diff --git a/.stats.yml b/.stats.yml index 0604d8f..1f37812 100644 --- a/.stats.yml +++ b/.stats.yml @@ -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 diff --git a/README.md b/README.md index ed3e5b8..df2290a 100644 --- a/README.md +++ b/README.md @@ -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. @@ -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); @@ -44,7 +46,9 @@ 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 = { @@ -52,7 +56,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', }; const chatCompletion: Groq.Chat.ChatCompletion = await groq.chat.completions.create(params); } @@ -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) { @@ -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, }); ``` @@ -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, }); ``` @@ -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')); @@ -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')); @@ -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 }), diff --git a/package.json b/package.json index 4bd8d0a..69cce33 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/src/core.ts b/src/core.ts index c2814ba..a0f7b4d 100644 --- a/src/core.ts +++ b/src/core.ts @@ -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, @@ -249,7 +249,17 @@ export abstract class APIClient { path: string, opts?: PromiseOrValue>, ): APIPromise { - 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 = AbstractPage>( @@ -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; @@ -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); @@ -735,7 +749,9 @@ export type Headers = Record; export type DefaultQuery = Record; export type KeysEnum = { [P in keyof Required]: true }; -export type RequestOptions | Readable> = { +export type RequestOptions< + Req = unknown | Record | Readable | BlobLike | ArrayBufferView | ArrayBuffer, +> = { method?: HTTPMethod; path?: string; query?: Req | undefined; @@ -749,6 +765,7 @@ export type RequestOptions | Readable> = signal?: AbortSignal | undefined | null; idempotencyKey?: string; + __binaryRequest?: boolean | undefined; __binaryResponse?: boolean | undefined; __streamClass?: typeof Stream; }; @@ -770,6 +787,7 @@ const requestOptionsKeys: KeysEnum = { signal: true, idempotencyKey: true, + __binaryRequest: true, __binaryResponse: true, __streamClass: true, }; @@ -783,10 +801,11 @@ export const isRequestOptions = (obj: unknown): obj is RequestOptions => { ); }; -export type FinalRequestOptions | Readable> = RequestOptions & { - method: HTTPMethod; - path: string; -}; +export type FinalRequestOptions | Readable | DataView> = + RequestOptions & { + method: HTTPMethod; + path: string; + }; declare const Deno: any; declare const EdgeRuntime: any; diff --git a/src/resources/chat/completions.ts b/src/resources/chat/completions.ts index bbc6d09..3b77850 100644 --- a/src/resources/chat/completions.ts +++ b/src/resources/chat/completions.ts @@ -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 { /** @@ -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`. @@ -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 @@ -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. * diff --git a/src/resources/embeddings.ts b/src/resources/embeddings.ts index 265bf41..0553ca4 100644 --- a/src/resources/embeddings.ts +++ b/src/resources/embeddings.ts @@ -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`. diff --git a/src/resources/shared.ts b/src/resources/shared.ts index 22473dc..8696bf4 100644 --- a/src/resources/shared.ts +++ b/src/resources/shared.ts @@ -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. * @@ -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. * diff --git a/tests/api-resources/chat/completions.test.ts b/tests/api-resources/chat/completions.test.ts index f4e5c72..24181af 100644 --- a/tests/api-resources/chat/completions.test.ts +++ b/tests/api-resources/chat/completions.test.ts @@ -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(); @@ -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', @@ -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', }); });