Skip to content

Commit

Permalink
feat(api): Tool calling features
Browse files Browse the repository at this point in the history
Add parallel tool calling option to chat completions
Allow 'required' as a function call option
  • Loading branch information
stainless-app[bot] authored and gradenr committed Jun 11, 2024
1 parent 3b235dd commit e257ab7
Show file tree
Hide file tree
Showing 8 changed files with 65 additions and 45 deletions.
2 changes: 1 addition & 1 deletion .stats.yml
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
configured_endpoints: 7
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/groqcloud%2Fgroqcloud-0f93f9ac6d4ad16dacaddd7608e104374c83f3bd9d0b9ed4c0273eb27ed998b7.yml
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/groqcloud%2Fgroqcloud-a4c1214ecaa24ad37fbb3c12b8392787ebe0fd51c5e7e08bdf25d7608dc7900b.yml
26 changes: 15 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Groq Node API Library

[![NPM version](https://img.shields.io/npm/v/groq-sdk.svg)](https://npmjs.org/package/groq-sdk)
[![NPM version](https://img.shields.io/npm/v/groq-sdk.svg)](https://npmjs.org/package/groq-sdk) ![npm bundle size](https://img.shields.io/bundlephobia/minzip/groq-sdk)

This library provides convenient access to the Groq REST API from server-side TypeScript or JavaScript.

Expand All @@ -22,12 +22,14 @@ The full API of this library can be found in [api.md](api.md).
```js
import Groq from 'groq-sdk';

const groq = new Groq();
const groq = new Groq({
apiKey: process.env['GROQ_API_KEY'], // This is the default and can be omitted
});

async function main() {
const chatCompletion = await groq.chat.completions.create({
messages: [{ role: 'user', content: 'Explain the importance of low latency LLMs' }],
model: 'mixtral-8x7b-32768',
model: 'llama3-8b-8192',
});

console.log(chatCompletion.choices[0].message.content);
Expand All @@ -44,15 +46,17 @@ This library includes TypeScript definitions for all request params and response
```ts
import Groq from 'groq-sdk';

const groq = new Groq();
const groq = new Groq({
apiKey: process.env['GROQ_API_KEY'], // This is the default and can be omitted
});

async function main() {
const params: Groq.Chat.CompletionCreateParams = {
messages: [
{ role: 'system', content: 'You are a helpful assistant.' },
{ role: 'user', content: 'Explain the importance of low latency LLMs' },
],
model: 'mixtral-8x7b-32768',
model: 'llama3-8b-8192',
};
const chatCompletion: Groq.Chat.ChatCompletion = await groq.chat.completions.create(params);
}
Expand All @@ -77,7 +81,7 @@ async function main() {
{ role: 'system', content: 'You are a helpful assistant.' },
{ role: 'user', content: 'Explain the importance of low latency LLMs' },
],
model: 'mixtral-8x7b-32768',
model: 'llama3-8b-8192',
})
.catch(async (err) => {
if (err instanceof Groq.APIError) {
Expand Down Expand Up @@ -122,7 +126,7 @@ const groq = new Groq({
});

// Or, configure per-request:
await groq.chat.completions.create({ messages: [{ role: 'system', content: 'You are a helpful assistant.' }, { role: 'user', content: 'Explain the importance of low latency LLMs' }], model: 'mixtral-8x7b-32768' }, {
await groq.chat.completions.create({ messages: [{ role: 'system', content: 'You are a helpful assistant.' }, { role: 'user', content: 'Explain the importance of low latency LLMs' }], model: 'llama3-8b-8192' }, {
maxRetries: 5,
});
```
Expand All @@ -139,7 +143,7 @@ const groq = new Groq({
});

// Override per-request:
await groq.chat.completions.create({ messages: [{ role: 'system', content: 'You are a helpful assistant.' }, { role: 'user', content: 'Explain the importance of low latency LLMs' }], model: 'mixtral-8x7b-32768' }, {
await groq.chat.completions.create({ messages: [{ role: 'system', content: 'You are a helpful assistant.' }, { role: 'user', content: 'Explain the importance of low latency LLMs' }], model: 'llama3-8b-8192' }, {
timeout: 5 * 1000,
});
```
Expand All @@ -166,7 +170,7 @@ const response = await groq.chat.completions
{ role: 'system', content: 'You are a helpful assistant.' },
{ role: 'user', content: 'Explain the importance of low latency LLMs' },
],
model: 'mixtral-8x7b-32768',
model: 'llama3-8b-8192',
})
.asResponse();
console.log(response.headers.get('X-My-Header'));
Expand All @@ -178,7 +182,7 @@ const { data: chatCompletion, response: raw } = await groq.chat.completions
{ role: 'system', content: 'You are a helpful assistant.' },
{ role: 'user', content: 'Explain the importance of low latency LLMs' },
],
model: 'mixtral-8x7b-32768',
model: 'llama3-8b-8192',
})
.withResponse();
console.log(raw.headers.get('X-My-Header'));
Expand Down Expand Up @@ -292,7 +296,7 @@ await groq.chat.completions.create(
{ role: 'system', content: 'You are a helpful assistant.' },
{ role: 'user', content: 'Explain the importance of low latency LLMs' },
],
model: 'mixtral-8x7b-32768',
model: 'llama3-8b-8192',
},
{
httpAgent: new http.Agent({ keepAlive: false }),
Expand Down
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
"scripts": {
"test": "./scripts/test",
"build": "./scripts/build",
"prepack": "echo 'to pack, run yarn build && (cd dist; yarn pack)' && exit 1",
"prepublishOnly": "echo 'to publish, run yarn build && (cd dist; yarn publish)' && exit 1",
"format": "prettier --write --cache --cache-strategy metadata . !dist",
"prepare": "if ./scripts/utils/check-is-in-git-install.sh; then ./scripts/build; fi",
Expand Down
35 changes: 27 additions & 8 deletions src/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import {
type HeadersInit,
} from './_shims/index';
export { type Response };
import { isMultipartBody } from './uploads';
import { BlobLike, isBlobLike, isMultipartBody } from './uploads';
export {
maybeMultipartFormRequestOptions,
multipartFormRequestOptions,
Expand Down Expand Up @@ -249,7 +249,17 @@ export abstract class APIClient {
path: string,
opts?: PromiseOrValue<RequestOptions<Req>>,
): APIPromise<Rsp> {
return this.request(Promise.resolve(opts).then((opts) => ({ method, path, ...opts })));
return this.request(
Promise.resolve(opts).then(async (opts) => {
const body =
opts && isBlobLike(opts?.body) ? new DataView(await opts.body.arrayBuffer())
: opts?.body instanceof DataView ? opts.body
: opts?.body instanceof ArrayBuffer ? new DataView(opts.body)
: opts && ArrayBuffer.isView(opts?.body) ? new DataView(opts.body.buffer)
: opts?.body;
return { method, path, ...opts, body };
}),
);
}

getAPIList<Item, PageClass extends AbstractPage<Item> = AbstractPage<Item>>(
Expand All @@ -271,6 +281,8 @@ export abstract class APIClient {
const encoded = encoder.encode(body);
return encoded.length.toString();
}
} else if (ArrayBuffer.isView(body)) {
return body.byteLength.toString();
}

return null;
Expand All @@ -280,7 +292,9 @@ export abstract class APIClient {
const { method, path, query, headers: headers = {} } = options;

const body =
isMultipartBody(options.body) ? options.body.body
ArrayBuffer.isView(options.body) || (options.__binaryRequest && typeof options.body === 'string') ?
options.body
: isMultipartBody(options.body) ? options.body.body
: options.body ? JSON.stringify(options.body, null, 2)
: null;
const contentLength = this.calculateContentLength(body);
Expand Down Expand Up @@ -735,7 +749,9 @@ export type Headers = Record<string, string | null | undefined>;
export type DefaultQuery = Record<string, string | undefined>;
export type KeysEnum<T> = { [P in keyof Required<T>]: true };

export type RequestOptions<Req = unknown | Record<string, unknown> | Readable> = {
export type RequestOptions<
Req = unknown | Record<string, unknown> | Readable | BlobLike | ArrayBufferView | ArrayBuffer,
> = {
method?: HTTPMethod;
path?: string;
query?: Req | undefined;
Expand All @@ -749,6 +765,7 @@ export type RequestOptions<Req = unknown | Record<string, unknown> | Readable> =
signal?: AbortSignal | undefined | null;
idempotencyKey?: string;

__binaryRequest?: boolean | undefined;
__binaryResponse?: boolean | undefined;
__streamClass?: typeof Stream;
};
Expand All @@ -770,6 +787,7 @@ const requestOptionsKeys: KeysEnum<RequestOptions> = {
signal: true,
idempotencyKey: true,

__binaryRequest: true,
__binaryResponse: true,
__streamClass: true,
};
Expand All @@ -783,10 +801,11 @@ export const isRequestOptions = (obj: unknown): obj is RequestOptions => {
);
};

export type FinalRequestOptions<Req = unknown | Record<string, unknown> | Readable> = RequestOptions<Req> & {
method: HTTPMethod;
path: string;
};
export type FinalRequestOptions<Req = unknown | Record<string, unknown> | Readable | DataView> =
RequestOptions<Req> & {
method: HTTPMethod;
path: string;
};

declare const Deno: any;
declare const EdgeRuntime: any;
Expand Down
15 changes: 10 additions & 5 deletions src/resources/chat/completions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -623,7 +623,7 @@ export interface ChatCompletionTool {
* `none` is the default when no tools are present. `auto` is the default if tools
* are present.
*/
export type ChatCompletionToolChoiceOption = 'none' | 'auto' | ChatCompletionNamedToolChoice;
export type ChatCompletionToolChoiceOption = 'none' | 'auto' | 'required' | ChatCompletionNamedToolChoice;

export interface ChatCompletionToolMessageParam {
/**
Expand Down Expand Up @@ -695,7 +695,7 @@ export interface ChatCompletionCreateParamsBase {
* `none` is the default when no functions are present. `auto` is the default if
* functions are present.
*/
function_call?: 'none' | 'auto' | ChatCompletionFunctionCallOption | null;
function_call?: 'none' | 'auto' | 'required' | ChatCompletionFunctionCallOption | null;

/**
* Deprecated in favor of `tools`.
Expand Down Expand Up @@ -726,11 +726,16 @@ export interface ChatCompletionCreateParamsBase {

/**
* How many chat completion choices to generate for each input message. Note that
* you will be charged based on the number of generated tokens across all of the
* choices. Keep `n` as `1` to minimize costs.
* the current moment, only n=1 is supported. Other values will result in a 400
* response.
*/
n?: number | null;

/**
* Whether to enable parallel function calling during tool use.
*/
parallel_tool_calls?: boolean | null;

/**
* Number between -2.0 and 2.0. Positive values penalize new tokens based on
* whether they appear in the text so far, increasing the model's likelihood to
Expand Down Expand Up @@ -841,7 +846,7 @@ export namespace CompletionCreateParams {

/**
* The parameters the functions accepts, described as a JSON Schema object. See the
* [guide](/docs/guides/text-generation/function-calling) for examples, and the
* docs on [tool use](/docs/tool-use) for examples, and the
* [JSON Schema reference](https://json-schema.org/understanding-json-schema/) for
* documentation about the format.
*
Expand Down
2 changes: 1 addition & 1 deletion src/resources/embeddings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ export interface EmbeddingCreateParams {
/**
* ID of the model to use.
*/
model: string;
model: (string & {}) | 'nomic-embed-text-v1_5';

/**
* The format to return the embeddings in. Can only be `float` or `base64`.
Expand Down
4 changes: 2 additions & 2 deletions src/resources/shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export interface FunctionDefinition {

/**
* The parameters the functions accepts, described as a JSON Schema object. See the
* [guide](/docs/guides/text-generation/function-calling) for examples, and the
* docs on [tool use](/docs/tool-use) for examples, and the
* [JSON Schema reference](https://json-schema.org/understanding-json-schema/) for
* documentation about the format.
*
Expand All @@ -36,7 +36,7 @@ export interface FunctionDefinition {

/**
* The parameters the functions accepts, described as a JSON Schema object. See the
* [guide](/docs/guides/text-generation/function-calling) for examples, and the
* docs on [tool use](/docs/tool-use) for examples, and the
* [JSON Schema reference](https://json-schema.org/understanding-json-schema/) for
* documentation about the format.
*
Expand Down
25 changes: 9 additions & 16 deletions tests/api-resources/chat/completions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,7 @@ const groq = new Groq({
describe('resource completions', () => {
test('create: only required params', async () => {
const responsePromise = groq.chat.completions.create({
messages: [
{ content: 'string', role: 'system' },
{ content: 'string', role: 'system' },
{ content: 'string', role: 'system' },
],
messages: [{ content: 'string', role: 'system' }],
model: 'string',
});
const rawResponse = await responsePromise.asResponse();
Expand All @@ -29,11 +25,7 @@ describe('resource completions', () => {

test('create: required and optional params', async () => {
const response = await groq.chat.completions.create({
messages: [
{ content: 'string', role: 'system', name: 'string', tool_call_id: 'string' },
{ content: 'string', role: 'system', name: 'string', tool_call_id: 'string' },
{ content: 'string', role: 'system', name: 'string', tool_call_id: 'string' },
],
messages: [{ content: 'string', role: 'system', name: 'string' }],
model: 'string',
frequency_penalty: -2,
function_call: 'none',
Expand All @@ -46,20 +38,21 @@ describe('resource completions', () => {
logprobs: true,
max_tokens: 0,
n: 1,
parallel_tool_calls: true,
presence_penalty: -2,
response_format: { type: 'string' },
response_format: { type: 'json_object' },
seed: 0,
stop: '\n',
stream: true,
temperature: 0,
temperature: 1,
tool_choice: 'none',
tools: [
{ function: { description: 'string', name: 'string', parameters: { foo: 'bar' } }, type: 'function' },
{ function: { description: 'string', name: 'string', parameters: { foo: 'bar' } }, type: 'function' },
{ function: { description: 'string', name: 'string', parameters: { foo: 'bar' } }, type: 'function' },
{ type: 'function', function: { description: 'string', name: 'string', parameters: { foo: 'bar' } } },
{ type: 'function', function: { description: 'string', name: 'string', parameters: { foo: 'bar' } } },
{ type: 'function', function: { description: 'string', name: 'string', parameters: { foo: 'bar' } } },
],
top_logprobs: 0,
top_p: 0,
top_p: 1,
user: 'string',
});
});
Expand Down

0 comments on commit e257ab7

Please sign in to comment.