@cogniformai/instructor-stream
Version:
Streaming-first structured data extraction from LLMs with real-time updates
48 lines (36 loc) • 12.4 kB
JavaScript
import{a as E,b as S,c as v,d as Q,e as _,f as X,g as ee,h as te}from"./chunk-MPEVFTMN.js";import z from"openai";import{Stream as V}from"openai/streaming";import{ZodError as j}from"zod";import{fromZodError as Y}from"zod-validation-error";function g(o,e){let t={};for(let r in e)e.hasOwnProperty(r)&&!o.includes(r)&&(t[r]=e[r]);return t}async function D(o,e){let t=Array.from({length:e},()=>[]),r=[],l=o[Symbol.asyncIterator](),p=!1,i=async function*(m){for(;;)if(t[m].length>0)yield t[m].shift();else{if(p)break;await new Promise(d=>r.push(d))}};return await(async()=>{for await(let m of{[Symbol.asyncIterator]:()=>l}){for(let d of t)d.push(m);for(;r.length>0;)r.shift()()}for(p=!0;r.length>0;)r.shift()()})(),Array.from({length:e},(m,d)=>i(d))}var O={FUNCTIONS:"FUNCTIONS",TOOLS:"TOOLS",JSON:"JSON",MD_JSON:"MD_JSON",JSON_SCHEMA:"JSON_SCHEMA",THINKING_MD_JSON:"THINKING_MD_JSON"};function L(o,e){let{name:t,description:r,...l}=o,p={name:t},i=[...e?.functions??[],{name:t,description:r??void 0,parameters:l}];return{...e,function_call:p,functions:i}}function H(o,e){let{name:t,description:r,...l}=o,p={type:"function",function:{name:t}},i=[{type:"function",function:{name:t,description:r,parameters:l}},...e.tools?.map(m=>({type:m.type,function:{name:m.function.name,description:m.function.description,parameters:m.function.parameters}}))??[]];return{...e,tool_choice:p,tools:i}}function x(o,e){return{...e,messages:[{role:"system",content:`
Given a user prompt, you will return fully valid JSON based on the following description and schema.
You will return no other prose. You will take into account any descriptions or required parameters within the schema
and return a valid and fully escaped JSON object that matches the schema and those instructions.
description: ${o.description}
json schema: ${JSON.stringify(o)}
`},...e.messages]}}function G(o,e){return{...e,messages:[{role:"system",content:`
Given a user prompt, you will return fully valid JSON based on the provided description and schema.
You will take into account any descriptions or required parameters within the schema
and return a valid and fully escaped JSON object that matches the schema and those instructions.
You will always return your full thought process in one <think> tag and then return the JSON response in a \`\`\`json block after the </think> tag. Never include any prose or thinking process outside of the <think> tag.
For example:
<think>
I am analyzing the input to extract the required information...
</think>
\`\`\`json
{
"result": "the actual json response"
}
\`\`\`
description: ${o.description}
json schema: ${JSON.stringify(o)}
`},...e.messages]}}function U(o,e){return{...e,response_format:{type:"json_object"},messages:[{role:"system",content:`
Given a user prompt, you will return fully valid JSON based on the following description and schema.
You will return no other prose. You will take into account any descriptions or required parameters within the schema
and return a valid and fully escaped JSON object that matches the schema and those instructions.
description: ${o.description}
json schema: ${JSON.stringify(o)}
`},...e.messages]}}function F(o,e){return{...e,response_format:{type:"json_object",schema:g(["name","description"],o)},messages:[{role:"system",content:`
Given a user prompt, you will return fully valid JSON based on the following description.
You will return no other prose. You will take into account any descriptions or required parameters within the schema
and return a valid and fully escaped JSON object that matches the schema and those instructions.
description: ${o.description}
`},...e.messages]}}import*as B from"zod";function M({response_model:{name:o,schema:e,description:t=""},mode:r,params:l}){let p=o.replace(/[^a-zA-Z0-9]/g,"_").replace(/\s/g,"_"),i=B.toJSONSchema(e);delete i.$schema;let m={name:p,description:t,...i};return r===O.FUNCTIONS?L(m,l):r===O.TOOLS?H(m,l):r===O.JSON?U(m,l):r===O.JSON_SCHEMA?F(m,l):r===O.MD_JSON?x(m,l):r===O.THINKING_MD_JSON?G(m,l):x(m,l)}var n=O,Z={[n.THINKING_MD_JSON]:v},s={OAI:"OAI",ANYSCALE:"ANYSCALE",TOGETHER:"TOGETHER",ANTHROPIC:"ANTHROPIC",GROQ:"GROQ",OTHER:"OTHER"},$={[s.OTHER]:[n.FUNCTIONS,n.TOOLS,n.JSON,n.JSON_SCHEMA,n.MD_JSON],[s.OAI]:[n.FUNCTIONS,n.TOOLS,n.JSON,n.MD_JSON],[s.ANYSCALE]:[n.TOOLS,n.JSON,n.JSON_SCHEMA,n.MD_JSON],[s.TOGETHER]:[n.TOOLS,n.JSON,n.JSON_SCHEMA,n.MD_JSON],[s.ANTHROPIC]:[n.MD_JSON,n.TOOLS],[s.GROQ]:[n.TOOLS,n.FUNCTIONS,n.MD_JSON]},T={[s.ANYSCALE]:"api.endpoints.anyscale",[s.TOGETHER]:"api.together.xyz",[s.OAI]:"api.openai.com",[s.ANTHROPIC]:"api.anthropic.com",[s.GROQ]:"api.groq.com"},k={[s.GROQ]:{[n.TOOLS]:function(e){return e.tools&&e.tools.some(t=>t)&&e.stream&&console.warn("Streaming may not be supported when using tools in Groq, try MD_JSON instead"),e}},[s.ANYSCALE]:{[n.JSON_SCHEMA]:function(e){return e.response_format&&"additionalProperties"in e.response_format.schema?{...e,response_format:{...e.response_format,schema:g(["additionalProperties"],e.response_format.schema)}}:e},[n.TOOLS]:function(e){return e.tools&&e.tools.some(t=>t.function?.parameters)?{...e,tools:e.tools.map(t=>t.function?.parameters?{...t,function:{...t.function,parameters:g(["additionalProperties"],t.function.parameters)}}:t)}:e}},[s.OAI]:{},[s.TOGETHER]:{},[s.ANTHROPIC]:{},[s.OTHER]:{}},Ie={[s.OTHER]:{[n.FUNCTIONS]:["*"],[n.TOOLS]:["*"],[n.JSON]:["*"],[n.MD_JSON]:["*"],[n.JSON_SCHEMA]:["*"],[n.THINKING_MD_JSON]:["*"]},[s.OAI]:{[n.FUNCTIONS]:["*"],[n.TOOLS]:["*"],[n.JSON]:["*"],[n.MD_JSON]:["*"]},[s.TOGETHER]:{[n.MD_JSON]:["*"]},[s.ANYSCALE]:{[n.MD_JSON]:["*"]},[s.ANTHROPIC]:{[n.MD_JSON]:["*"],[n.TOOLS]:["*"]},[s.GROQ]:{[n.TOOLS]:["*"],[n.MD_JSON]:["*"],[n.THINKING_MD_JSON]:["deepseek-r1-distill-llama-70b"]}};var y=class extends Error{constructor(t,r){super(t);this.cause=r;this.name="InstructorError"}},C=class extends y{constructor(e="Unsupported client type",t){super(e,t),this.name="UnsupportedClientError"}},A=class extends y{constructor(e,t){super(e,t),this.name="RetryableError"}},w=class extends y{constructor(e,t){super(e,t),this.name="NonRetryableError"}},R=class extends y{constructor(t,r){super("ValidationError",r);this.issues=t;this.name="ValidationError"}};var K=0,b=class{constructor({client:e,mode:t,debug:r=!1,logger:l=void 0,retryAllErrors:p=!1}){this.debug=!1;this.retryAllErrors=!1;this.chat={completions:{create:async(e,t)=>{if(this.isChatCompletionCreateParamsWithModel(e))return e.stream?this.chatCompletionStream(e,t):this.chatCompletionStandard(e,t);if(this.client.chat?.completions?.create)return this.isStandardStream(e)?await this.client.chat.completions.create(e,t):await this.client.chat.completions.create(e,t);throw new C("Completion method is undefined")}}};if(!q(e)&&!(e instanceof z))throw new C("Client does not match the required structure");e instanceof z?this.client=e:this.client=e,this.mode=t,this.debug=r,this.retryAllErrors=p,this.logger=l??void 0,this.provider=typeof this.client?.baseURL=="string"?this.client?.baseURL.includes(T.ANYSCALE)?s.ANYSCALE:this.client?.baseURL.includes(T.TOGETHER)?s.TOGETHER:this.client?.baseURL.includes(T.OAI)?s.OAI:this.client?.baseURL.includes(T.ANTHROPIC)?s.ANTHROPIC:this.client?.baseURL.includes(T.GROQ)?s.GROQ:s.OTHER:s.OTHER,this.validateOptions()}validateOptions(){let e=$[this.provider].includes(this.mode);this.provider===s.OTHER&&this.log("debug","Unknown provider - cant validate options."),e||this.log("warn",`Mode ${this.mode} may not be supported by provider ${this.provider}`)}log(e,...t){if(this.logger&&this.logger(e,...t),!this.debug&&e==="debug")return;let r=new Date().toISOString();switch(e){case"debug":console.debug(`[Instructor:DEBUG] ${r}:`,...t);break;case"info":console.info(`[Instructor:INFO] ${r}:`,...t);break;case"warn":console.warn(`[Instructor:WARN] ${r}:`,...t);break;case"error":console.error(`[Instructor:ERROR] ${r}:`,...t);break}}async chatCompletionStandard({max_retries:e=K,response_model:t,...r},l){let p=0,i="",m=null,d=k?.[this.provider]?.[this.mode],f=M({params:{...r,stream:r.stream??!1},mode:this.mode,response_model:t});typeof d=="function"&&(f=d(f));let N=async()=>{let c=f;i?.length>0&&(c={...f,messages:[...f.messages,...m?[m]:[],{role:"user",content:`Please correct the function call; errors encountered:
${i}`}]});let a;try{if(this.client.chat?.completions?.create)a=await this.client.chat.completions.create({...c,stream:!1},l);else throw new C("Unsupported client type -- no completion method found.");this.log("debug","raw standard completion response: ",a)}catch(h){throw this.log("error",`Error making completion call - mode: ${this.mode} | Client base URL: ${this.client.baseURL} | with params:`,c,"raw error",h),new A(h instanceof Error?h.message:"Error making completion call",h)}let I=(Z?.[this.mode]??E)(a);try{let h=I.json??I;return{data:[JSON.parse(h)],_meta:{usage:a?.usage??void 0,thinking:I?.thinking??void 0}}}catch(h){throw this.log("error","failed to parse completion",I,this.mode,"attempt: ",p,"max attempts: ",e),new A("Failed to parse completion",h)}},u=async()=>{try{let c=await N(),a=await t.schema.safeParseAsync(c.data[0]);if(this.log("debug",t.name,"Completion validation: ",a),!a.success)if("error"in a&&a.error instanceof j){m={role:"assistant",content:JSON.stringify(c)};try{if(a.error&&Array.isArray(a.error.issues)&&a.error.issues.length>0)try{let P=a.error;i=Y(P)?.message??"Validation failed with issues"}catch{i=a.error.issues?.[0]?.message??"Validation failed with issues"}else i="Validation failed: error structure missing or invalid",this.log("debug","Validation error structure:",JSON.stringify(a.error))}catch(P){i=`Validation failed: ${a.error?.issues?.[0]?.message??"unknown validation error"}`,this.log("debug","fromZodError failed:",P),this.log("debug","Original validation error:",JSON.stringify(a.error))}throw new R(a.error.issues,a.error)}else throw new w("Validation failed",a.error);return{data:[a.data],_meta:c?._meta??{}}}catch(c){if(!this.retryAllErrors&&!(c instanceof R))throw c;if(p<e)return this.log("debug",`response model: ${t.name} - Retrying, attempt: `,p),this.log("warn",`response model: ${t.name} - Validation issues: `,i," - Attempt: ",p," - Max attempts: ",e),p++,await u();throw this.log("debug",`response model: ${t.name} - Max attempts reached: ${p}`),this.log("error",`response model: ${t.name} - Validation issues: `,i),c}};return u()}async*chatCompletionStream({max_retries:e,response_model:t,...r},l){e&&this.log("warn","max_retries is not supported for streaming completions");let p=k?.[this.provider]?.[this.mode],i=M({params:{...r,stream:!0},response_model:t,mode:this.mode});typeof p=="function"&&(i=p(i));let m=new _({debug:this.debug??!1}),d=async u=>{for await(let c of u)"usage"in c&&(f=c.usage)},f,N=await m.create({completionPromise:async()=>{if(this.client.chat?.completions?.create){let u=await this.client.chat.completions.create({...i,stream:!0},l);if(this.log("debug","raw stream completion response: ",u),this.provider==="OAI"&&i?.stream&&"stream_options"in i&&u instanceof V){let[c,a]=u.tee();return d(c),S({res:a})}if(this.provider!=="OAI"&&i?.stream&&u?.[Symbol.asyncIterator]){let[c,a]=await D(u,2);return d(c),S({res:a})}return S({res:u})}else throw new C("Unsupported client type")},response_model:{schema:t.schema}});for await(let u of N)yield{data:u.data,_meta:{usage:f??void 0,...u?._meta??{}}}}isChatCompletionCreateParamsWithModel(e){return"response_model"in e}isStandardStream(e){return"stream"in e&&e.stream===!0}};function J(o){let e=new b(o);return new Proxy(e,{get:(r,l,p)=>l in r?Reflect.get(r,l,p):Reflect.get(r.client,l,p)})}function q(o){return typeof o=="object"&&o!==null&&"chat"in o&&typeof o.chat=="object"&&o.chat!==null&&"completions"in o.chat&&typeof o.chat.completions=="object"&&o.chat.completions!==null&&"create"in o.chat.completions&&typeof o.chat.completions.create=="function"}var ze=J;export{ee as consumeLanggraphChannels,Q as createFunctionStreamingAdapter,ze as default,te as iterableToReadableStream,X as langgraphAdapter};
//# sourceMappingURL=index.js.map