From 0a5bbd8082915bcc8c4686d34fec5d5f034ebd9c Mon Sep 17 00:00:00 2001 From: Dimitri Kennedy Date: Wed, 12 Jun 2024 23:39:49 -0400 Subject: [PATCH] Non-oai usage meta + non-oai client types (#182) --- .changeset/light-chefs-clean.md | 5 +++ bun.lockb | Bin 287174 -> 287771 bytes package.json | 6 ++-- src/instructor.ts | 57 ++++++++++++++++++++++++++++---- src/lib/index.ts | 42 +++++++++++++++++++++++ src/types/index.ts | 6 ++-- tests/anthropic.test.ts | 33 ++++++++++-------- tests/stream.test.ts | 1 - 8 files changed, 123 insertions(+), 27 deletions(-) create mode 100644 .changeset/light-chefs-clean.md diff --git a/.changeset/light-chefs-clean.md b/.changeset/light-chefs-clean.md new file mode 100644 index 00000000..845ad9cf --- /dev/null +++ b/.changeset/light-chefs-clean.md @@ -0,0 +1,5 @@ +--- +"@instructor-ai/instructor": minor +--- + +update client types to better support non oai clients + updates to allow for passing usage properties into meta from non-oai clients diff --git a/bun.lockb b/bun.lockb index d9d61e146237b2a4e6837ed26f6e6d52a7f2a947..981b7ec2ae5ff199edc453a2bb0cdc39f7ebd61f 100755 GIT binary patch delta 41767 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 delta 41578 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 GnE?RIYy9v4 diff --git a/package.json b/package.json index d358e689..6d4bee0c 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,7 @@ "zod": ">=3.22.4" }, "devDependencies": { - "@anthropic-ai/sdk": "latest", + "@anthropic-ai/sdk": "0.22.0", "@changesets/changelog-github": "^0.5.0", "@changesets/cli": "^2.27.1", "@ianvs/prettier-plugin-sort-imports": "4.1.0", @@ -75,8 +75,8 @@ "eslint-plugin-only-warn": "^1.1.0", "eslint-plugin-prettier": "^5.1.2", "husky": "^8.0.3", - "llm-polyglot": "1.0.0", - "openai": "latest", + "llm-polyglot": "2.0.0", + "openai": "4.50.0", "prettier": "latest", "ts-inference-check": "^0.3.0", "tsup": "^8.0.1", diff --git a/src/instructor.ts b/src/instructor.ts index c6bd97ff..6b7313b0 100644 --- a/src/instructor.ts +++ b/src/instructor.ts @@ -22,11 +22,12 @@ import { PROVIDER_SUPPORTED_MODES_BY_MODEL, PROVIDERS } from "./constants/providers" +import { iterableTee } from "./lib" import { ClientTypeChatCompletionParams, CompletionMeta } from "./types" const MAX_RETRIES_DEFAULT = 0 -class Instructor { +class Instructor { readonly client: OpenAILikeClient readonly mode: Mode readonly provider: Provider @@ -46,7 +47,17 @@ class Instructor { logger = undefined, retryAllErrors = false }: InstructorConfig) { - this.client = client + if (!isGenericClient(client) && !(client instanceof OpenAI)) { + throw new Error("Client does not match the required structure") + } + + if (client instanceof OpenAI) { + this.client = client as OpenAI + } else { + this.client = client as C & GenericClient + } + + // this.client = client this.mode = mode this.debug = debug this.retryAllErrors = retryAllErrors @@ -308,7 +319,9 @@ class Instructor { debug: this.debug ?? false }) - async function checkForUsage(reader: Stream) { + async function checkForUsage( + reader: Stream | AsyncIterable + ) { for await (const chunk of reader) { if ("usage" in chunk) { streamUsage = chunk.usage as CompletionMeta["usage"] @@ -345,6 +358,24 @@ class Instructor { }) } + //check if async iterator + if ( + this.provider !== "OAI" && + completionParams?.stream && + completion?.[Symbol.asyncIterator] + ) { + const [completion1, completion2] = await iterableTee( + completion as AsyncIterable, + 2 + ) + + checkForUsage(completion1) + + return OAIStream({ + res: completion2 + }) + } + return OAIStream({ res: completion as unknown as AsyncIterable }) @@ -419,7 +450,7 @@ class Instructor { } } -export type InstructorClient = Instructor & OpenAILikeClient +export type InstructorClient = Instructor & OpenAILikeClient /** * Creates an instance of the `Instructor` class. @@ -442,9 +473,7 @@ export type InstructorClient = Instructor & * @param args * @returns */ -export default function createInstructor( - args: InstructorConfig -): InstructorClient { +export default function createInstructor(args: InstructorConfig): InstructorClient { const instructor = new Instructor(args) const instructorWithProxy = new Proxy(instructor, { get: (target, prop, receiver) => { @@ -458,3 +487,17 @@ export default function createInstructor( return instructorWithProxy as InstructorClient } +//eslint-disable-next-line @typescript-eslint/no-explicit-any +function isGenericClient(client: any): client is GenericClient { + return ( + typeof client === "object" && + client !== null && + "baseURL" in client && + "chat" in client && + typeof client.chat === "object" && + "completions" in client.chat && + typeof client.chat.completions === "object" && + "create" in client.chat.completions && + typeof client.chat.completions.create === "function" + ) +} diff --git a/src/lib/index.ts b/src/lib/index.ts index a164ae0c..540da954 100644 --- a/src/lib/index.ts +++ b/src/lib/index.ts @@ -7,3 +7,45 @@ export function omit(keys: K[], obj: T): Om } return result } + +export async function iterableTee( + iterable: AsyncIterable, + n: number +): Promise[]> { + const buffers: T[][] = Array.from({ length: n }, () => []) + const resolvers: (() => void)[] = [] + const iterator = iterable[Symbol.asyncIterator]() + let done = false + + async function* reader(index: number) { + while (true) { + if (buffers[index].length > 0) { + yield buffers[index].shift()! + } else if (done) { + break + } else { + await new Promise(resolve => resolvers.push(resolve)) + } + } + } + + ;(async () => { + for await (const item of { + [Symbol.asyncIterator]: () => iterator + }) { + for (const buffer of buffers) { + buffer.push(item) + } + + while (resolvers.length > 0) { + resolvers.shift()!() + } + } + done = true + while (resolvers.length > 0) { + resolvers.shift()!() + } + })() + + return Array.from({ length: n }, (_, i) => reader(i)) +} diff --git a/src/types/index.ts b/src/types/index.ts index d2f32108..717fc6bf 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -39,7 +39,7 @@ export type GenericClient = { baseURL?: string chat?: { completions?: { - create?: (params: GenericCreateParams) => Promise + create?:

(params: P) => Promise } } } @@ -55,7 +55,7 @@ export type ClientType = : C extends GenericClient ? "generic" : never -export type OpenAILikeClient = C extends OpenAI ? OpenAI : C & GenericClient +export type OpenAILikeClient = OpenAI | (C & GenericClient) export type SupportedInstructorClient = GenericClient | OpenAI export type LogLevel = "debug" | "info" | "warn" | "error" @@ -68,7 +68,7 @@ export type Mode = ZMode export type ResponseModel = ZResponseModel export interface InstructorConfig { - client: OpenAILikeClient + client: C mode: Mode debug?: boolean logger?: (level: LogLevel, ...args: T) => void diff --git a/tests/anthropic.test.ts b/tests/anthropic.test.ts index 832eafe8..4625f592 100644 --- a/tests/anthropic.test.ts +++ b/tests/anthropic.test.ts @@ -118,15 +118,16 @@ describe("LLMClient Anthropic Provider - mode: TOOLS", () => { }) }) -describe("LLMClient Anthropic Provider - mode: MD_JSON", () => { +describe("LLMClient Anthropic Provider - mode: TOOLS - stream", () => { const instructor = Instructor({ client: anthropicClient, - mode: "MD_JSON" + mode: "TOOLS" }) test("basic completion", async () => { const completion = await instructor.chat.completions.create({ model: "claude-3-sonnet-20240229", + stream: true, max_tokens: 1000, messages: [ { @@ -135,17 +136,24 @@ describe("LLMClient Anthropic Provider - mode: MD_JSON", () => { } ], response_model: { - name: "get_name", + name: "extract_name", schema: z.object({ name: z.string() }) } }) - expect(omit(["_meta"], completion)).toEqual({ name: "Dimitri Kennedy" }) + let final = {} + + for await (const result of completion) { + final = result + } + + //@ts-expect-error ignore for testing + expect(omit(["_meta"], final)).toEqual({ name: "Dimitri Kennedy" }) }) - test("complex schema - streaming", async () => { + test("complex schema", async () => { const completion = await instructor.chat.completions.create({ model: "claude-3-sonnet-20240229", max_tokens: 1000, @@ -173,14 +181,15 @@ describe("LLMClient Anthropic Provider - mode: MD_JSON", () => { Programming Leadership Communication - - ` } ], response_model: { name: "process_user_data", schema: z.object({ + story: z + .string() + .describe("A long and mostly made up story about the user - minimum 500 words"), userDetails: z.object({ firstName: z.string(), lastName: z.string(), @@ -196,21 +205,19 @@ describe("LLMClient Anthropic Provider - mode: MD_JSON", () => { years: z.number().optional() }) ), - skills: z.array(z.string()), - summaryOfWorldWarOne: z - .string() - .describe("A detailed summary of World War One and its major events - min 500 words") + skills: z.array(z.string()) }) } }) let final = {} + for await (const result of completion) { final = result } - //@ts-expect-error - lazy - expect(omit(["_meta", "summaryOfWorldWarOne"], final)).toEqual({ + //@ts-expect-error ignore for testing + expect(omit(["_meta", "story"], final)).toEqual({ userDetails: { firstName: "John", lastName: "Doe", diff --git a/tests/stream.test.ts b/tests/stream.test.ts index 79c40633..a14c3bc8 100644 --- a/tests/stream.test.ts +++ b/tests/stream.test.ts @@ -59,7 +59,6 @@ async function extractUser() { let extraction: Extraction = {} for await (const result of extractionStream) { - console.log(result) try { extraction = result expect(result).toHaveProperty("users")