@cogniformai/instructor-stream
Version:
Streaming-first structured data extraction from LLMs with real-time updates
299 lines (291 loc) • 13 kB
text/typescript
import { z } from 'zod';
import OpenAI from 'openai';
import { Stream } from 'openai/streaming';
declare const MODE: {
readonly FUNCTIONS: "FUNCTIONS";
readonly TOOLS: "TOOLS";
readonly JSON: "JSON";
readonly MD_JSON: "MD_JSON";
readonly JSON_SCHEMA: "JSON_SCHEMA";
readonly THINKING_MD_JSON: "THINKING_MD_JSON";
};
type ActivePath = (string | number | undefined)[];
type CompletedPaths = ActivePath[];
type LogLevel = 'debug' | 'info' | 'warn' | 'error';
interface BaseCompletionMeta {
/** The path that is currently being generated */
_activePath: ActivePath;
/** This is a list of all paths that have been generated in the order they were generated */
_completedPaths: CompletedPaths;
/** Not sure of the use of this will need to look closer at it */
_isValid: boolean;
/** This is a convenient way to access states of the completions this can be dynamically set. */
_type?: string;
}
/** This may just get merged into BaseCompletionMeta */
type CompletionMeta = Partial<BaseCompletionMeta> & {
/** Usage statistics when available, only supports OpenAI currently */
usage?: OpenAI.CompletionUsage;
/** Free‑form "thinking" text streamed in THINKING_MD_JSON mode */
thinking?: string;
};
/**
* @description This is the updated streaming data shape.
* The advantage of having a shape like this is that it is better dx
* to separate the meta data from the actual data. This shape is
* also more consistent whether you return a single object or an array
* of objects. - This is the main reason for this fork.
*/
type StreamChunk<T> = {
data: Partial<T>[];
_meta: CompletionMeta;
};
/**
* Once the basic refactor is dont we will tackle creating a single
* interface for Intructor-Stream and use provider adapers instead
* This will hopefully make this more modular with an easier way to
* and more reliable way to use this library.
*/
type GenericCreateParams<M = unknown> = Omit<Partial<OpenAI.ChatCompletionCreateParams>, 'model' | 'messages'> & {
model: string;
messages: M[];
stream?: boolean;
max_tokens?: number | null;
[key: string]: unknown;
};
type GenericRequestOptions = Partial<OpenAI.RequestOptions> & {
[key: string]: unknown;
};
type GenericChatCompletion<T = unknown> = Partial<OpenAI.Chat.Completions.ChatCompletion> & {
[key: string]: unknown;
choices?: T;
};
type GenericChatCompletionStream<T = unknown> = AsyncIterable<Partial<OpenAI.Chat.Completions.ChatCompletionChunk> & {
[key: string]: unknown;
choices?: T;
}>;
type GenericClient = {
[key: string]: unknown;
baseURL?: string;
chat?: {
completions?: {
create?: <P extends GenericCreateParams>(params: P) => Promise<unknown>;
};
};
};
type ClientTypeChatCompletionParams<C> = C extends OpenAI ? OpenAI.ChatCompletionCreateParams : GenericCreateParams;
type ClientTypeChatCompletionRequestOptions<C> = C extends OpenAI ? OpenAI.RequestOptions : GenericRequestOptions;
type ClientType<C> = C extends OpenAI ? 'openai' : C extends GenericClient ? 'generic' : never;
type OpenAILikeClient<C> = OpenAI | (C & GenericClient);
type SupportedInstructorClient = GenericClient | OpenAI;
type ClientConfig = {
debug?: boolean;
};
type ParseParams = {
name: string;
description?: string;
};
type ResponseModel<T extends z.ZodType> = {
schema: T;
name: string;
description?: string;
};
type Mode = keyof typeof MODE | 'THINKING_MD_JSON';
interface InstructorConfig<C> {
client: C;
mode: Mode;
debug?: boolean;
logger?: <T extends unknown[]>(level: LogLevel, ...args: T) => void;
retryAllErrors?: boolean;
}
type InstructorChatCompletionParams<T extends z.ZodType> = {
response_model: ResponseModel<T>;
max_retries?: number;
};
type ChatCompletionCreateParamsWithModel<T extends z.ZodType> = InstructorChatCompletionParams<T> & GenericCreateParams;
type ReturnTypeBasedOnParams<C, P> = P extends {
stream: true;
response_model: ResponseModel<infer T>;
} ? AsyncGenerator<{
data: Partial<z.output<T>>[];
_meta: CompletionMeta;
}, void, unknown> : P extends {
response_model: ResponseModel<infer T>;
} ? Promise<{
data: z.output<T>[];
_meta: CompletionMeta;
}> : C extends OpenAI ? P extends {
stream: true;
} ? Stream<OpenAI.Chat.Completions.ChatCompletionChunk> : OpenAI.Chat.Completions.ChatCompletion : Promise<unknown>;
type ZodStreamCompletionParams<T extends z.ZodType> = {
response_model: {
schema: T;
};
data?: Record<string, unknown>;
completionPromise: (data?: Record<string, unknown>) => Promise<ReadableStream<Uint8Array>>;
};
type InferStreamType<T extends OpenAI.ChatCompletionCreateParams> = T extends {
stream: true;
} ? OpenAI.ChatCompletionCreateParamsStreaming : OpenAI.ChatCompletionCreateParamsNonStreaming;
type FunctionParamsReturnType<T extends OpenAI.ChatCompletionCreateParams> = T & {
function_call: OpenAI.ChatCompletionFunctionCallOption;
functions: OpenAI.FunctionDefinition[];
};
type ToolFunctionParamsReturnType<T extends OpenAI.ChatCompletionCreateParams> = T & {
tool_choice: OpenAI.ChatCompletionToolChoiceOption;
tools: OpenAI.ChatCompletionTool[];
};
type MessageBasedParamsReturnType<T extends OpenAI.ChatCompletionCreateParams> = T;
type JsonModeParamsReturnType<T extends OpenAI.ChatCompletionCreateParams> = T & {
response_format: {
type: 'json_object';
};
messages: OpenAI.ChatCompletionMessageParam[];
};
type JsonSchemaParamsReturnType<T extends Omit<OpenAI.ChatCompletionCreateParams, 'response_format'>> = T & {
response_format: {
type: 'json_object';
schema: unknown;
};
messages: OpenAI.ChatCompletionMessageParam[];
};
type ModeParamsReturnType<T extends OpenAI.ChatCompletionCreateParams, M extends Mode> = M extends typeof MODE.FUNCTIONS ? FunctionParamsReturnType<T> : M extends typeof MODE.TOOLS ? ToolFunctionParamsReturnType<T> : M extends typeof MODE.JSON ? JsonModeParamsReturnType<T> : M extends typeof MODE.JSON_SCHEMA ? JsonSchemaParamsReturnType<T> : M extends typeof MODE.MD_JSON ? MessageBasedParamsReturnType<T> : MessageBasedParamsReturnType<T>;
type ZCompletionMeta = BaseCompletionMeta;
type ZMode = keyof typeof MODE;
type ZResponseModel<T extends z.ZodType> = ResponseModel<T>;
declare const PROVIDERS: {
readonly OAI: "OAI";
readonly ANYSCALE: "ANYSCALE";
readonly TOGETHER: "TOGETHER";
readonly ANTHROPIC: "ANTHROPIC";
readonly GROQ: "GROQ";
readonly OTHER: "OTHER";
};
type Provider = keyof typeof PROVIDERS;
/**
* The Instructor class provides a unified interface for interacting with OpenAI-like clients,
* supporting both standard and streaming chat completions with schema validation and error handling.
* It manages provider-specific options, logging, and retry logic for robust API usage.
*/
declare class Instructor<C> {
readonly client: OpenAILikeClient<C>;
readonly mode: Mode;
readonly provider: Provider;
readonly debug: boolean;
readonly retryAllErrors: boolean;
readonly logger?: <T extends unknown[]>(level: LogLevel, ...args: T) => void;
/**
* Initializes a new Instructor instance for a given OpenAI-like client and configuration.
* Validates the client and sets up provider-specific options and logging.
*
* Args:
* client (OpenAILikeClient): The OpenAI-compatible client instance.
* mode (Mode): The operation mode for completions.
* debug (boolean, optional): Enables debug logging if true.
* logger (function, optional): Custom logger function.
* retryAllErrors (boolean, optional): If true, retries all errors.
*/
constructor({ client, mode, debug, logger, retryAllErrors, }: InstructorConfig<C>);
/**
* Validates the current provider and mode configuration.
* Logs warnings if the mode is not supported by the provider.
*/
private validateOptions;
/**
* Logs messages at the specified log level using the configured logger or console.
* Skips debug logs if debug mode is disabled.
*
* Args:
* level (LogLevel): The severity level of the log.
* ...args: Additional arguments to log.
*/
private log;
/**
* Executes a standard (non-streaming) chat completion with schema validation and retry logic.
* Returns the validated response data and associated metadata.
*
* Args:
* params (ChatCompletionCreateParamsWithModel): Parameters for the chat completion, including the response model.
* requestOptions (optional): Additional request options for the client.
*
* Returns:
* Promise<{ data: z.output<T>[]; _meta: CompletionMeta }>: The validated completion data and metadata.
*
* Raises:
* ValidationError: If the response does not match the schema.
* RetryableError: If a retryable error occurs during completion.
* NonRetryableError: If a non-retryable error occurs.
*/
private chatCompletionStandard;
/**
* Executes a streaming chat completion, yielding partial results as they arrive.
* Supports schema validation and collects usage metadata during the stream.
*
* Args:
* params (ChatCompletionCreateParamsWithModel): Parameters for the chat completion, including the response model.
* requestOptions (optional): Additional request options for the client.
*
* Returns:
* AsyncGenerator<{ data: Partial<z.output<T>>[]; _meta: CompletionMeta }, void, unknown>: An async generator yielding partial completion data and metadata.
*/
private chatCompletionStream;
/**
* Determines if the provided parameters include a response model for schema validation.
* Used to distinguish between typed and untyped completion requests.
*
* Args:
* params (ChatCompletionCreateParamsWithModel): The parameters to check.
*
* Returns:
* boolean: True if the parameters include a response model, false otherwise.
*/
private isChatCompletionCreateParamsWithModel;
/**
* Checks if the given parameters specify a standard streaming completion.
* Returns true if the 'stream' property is set to true.
*
* Args:
* params (OpenAI.ChatCompletionCreateParams): The parameters to check.
*
* Returns:
* boolean: True if streaming is enabled, false otherwise.
*/
private isStandardStream;
/**
* Provides a unified interface for creating chat completions, supporting both standard and streaming modes.
* Automatically selects the appropriate completion method based on the provided parameters.
*
* Args:
* params: The parameters for the chat completion, with or without a response model.
* requestOptions (optional): Additional request options for the client.
*
* Returns:
* Promise or AsyncGenerator: The completion result, type depends on the parameters.
*
* Raises:
* UnsupportedClientError: If the client does not support completions.
*/
chat: {
completions: {
create: <T extends z.ZodType, P extends T extends z.ZodType ? ChatCompletionCreateParamsWithModel<T> : ClientTypeChatCompletionParams<OpenAILikeClient<C>> & {
response_model: never;
}>(params: P, requestOptions?: ClientTypeChatCompletionRequestOptions<C>) => Promise<ReturnTypeBasedOnParams<typeof this.client, P>>;
};
};
}
type InstructorClient<C> = Instructor<C> & OpenAILikeClient<C>;
/**
* Creates an instance of the `Instructor` class.
* @returns {InstructorClient} The extended OpenAI client.
* @example import createInstructor from "@instructor-ai/instructor"
import OpenAI from "openai"
const OAI = new OpenAi({})
const client = createInstructor({
client: OAI,
mode: "TOOLS",
})
* @param args
* @returns
*/
declare function createInstructor<C>(args: InstructorConfig<C>): InstructorClient<C>;
export { type ActivePath, type BaseCompletionMeta, type ChatCompletionCreateParamsWithModel, type ClientConfig, type ClientType, type ClientTypeChatCompletionParams, type ClientTypeChatCompletionRequestOptions, type CompletedPaths, type CompletionMeta, type FunctionParamsReturnType, type GenericChatCompletion, type GenericChatCompletionStream, type GenericClient, type GenericCreateParams, type GenericRequestOptions, type InferStreamType, type InstructorChatCompletionParams, type InstructorClient, type InstructorConfig, type JsonModeParamsReturnType, type JsonSchemaParamsReturnType, type LogLevel, type MessageBasedParamsReturnType, type Mode, type ModeParamsReturnType, type OpenAILikeClient, type ParseParams, type ResponseModel, type ReturnTypeBasedOnParams, type StreamChunk, type SupportedInstructorClient, type ToolFunctionParamsReturnType, type ZCompletionMeta, type ZMode, type ZResponseModel, type ZodStreamCompletionParams, createInstructor as default };