@easbot/ollama-sdk 0.3.3 → 0.3.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +4 -4
- package/README.md +5 -5
- package/dist/index.cjs +19 -18
- package/dist/index.d.cts +3 -14
- package/dist/index.d.ts +3 -14
- package/dist/index.mjs +19 -18
- package/package.json +3 -3
package/README.en.md
CHANGED
|
@@ -142,7 +142,7 @@ const model3 = new NativeOllamaLanguageModel('llama3.1:8b');
|
|
|
142
142
|
|
|
143
143
|
### Tool Definition Format
|
|
144
144
|
|
|
145
|
-
Tool definitions follow the AI SDK
|
|
145
|
+
Tool definitions follow the AI SDK v3 specification, using the `inputSchema` field:
|
|
146
146
|
|
|
147
147
|
```typescript
|
|
148
148
|
const tools = {
|
|
@@ -348,7 +348,7 @@ For complete usage examples, please refer to:
|
|
|
348
348
|
|
|
349
349
|
### `NativeOllamaLanguageModel`
|
|
350
350
|
|
|
351
|
-
Native Ollama language model implementation, fully compatible with AI SDK
|
|
351
|
+
Native Ollama language model implementation, fully compatible with AI SDK v3.
|
|
352
352
|
|
|
353
353
|
**Constructor:**
|
|
354
354
|
|
|
@@ -395,7 +395,7 @@ const generateResult = await model.doGenerate({
|
|
|
395
395
|
|
|
396
396
|
## Event Stream
|
|
397
397
|
|
|
398
|
-
This SDK generates a complete AI SDK
|
|
398
|
+
This SDK generates a complete AI SDK v3 event stream, including:
|
|
399
399
|
|
|
400
400
|
### Basic Events
|
|
401
401
|
|
|
@@ -522,7 +522,7 @@ Ollama HTTP API
|
|
|
522
522
|
### Features
|
|
523
523
|
|
|
524
524
|
- **Zero Dependencies**: No dependency on `ai-sdk-ollama` or other third-party libraries
|
|
525
|
-
- **Complete Implementation**: Fully compliant with AI SDK
|
|
525
|
+
- **Complete Implementation**: Fully compliant with AI SDK v3 specification
|
|
526
526
|
- **High Performance**: Batch event queue, timely state cleanup
|
|
527
527
|
- **Debuggable**: Structured logging, trace ID tracking
|
|
528
528
|
|
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
# @easbot/ollama-sdk
|
|
4
4
|
|
|
5
|
-
AI SDK
|
|
5
|
+
AI SDK v3 兼容的 Ollama Provider,自动生成完整的事件流。
|
|
6
6
|
|
|
7
7
|
## 特性
|
|
8
8
|
|
|
@@ -142,7 +142,7 @@ const model3 = new NativeOllamaLanguageModel('llama3.1:8b');
|
|
|
142
142
|
|
|
143
143
|
### 工具定义格式
|
|
144
144
|
|
|
145
|
-
工具定义遵循 AI SDK
|
|
145
|
+
工具定义遵循 AI SDK v3 规范,使用 `inputSchema` 字段:
|
|
146
146
|
|
|
147
147
|
```typescript
|
|
148
148
|
const tools = {
|
|
@@ -348,7 +348,7 @@ const tools = {
|
|
|
348
348
|
|
|
349
349
|
### `NativeOllamaLanguageModel`
|
|
350
350
|
|
|
351
|
-
原生 Ollama 语言模型实现,完全兼容 AI SDK
|
|
351
|
+
原生 Ollama 语言模型实现,完全兼容 AI SDK v3。
|
|
352
352
|
|
|
353
353
|
**构造函数:**
|
|
354
354
|
|
|
@@ -395,7 +395,7 @@ const generateResult = await model.doGenerate({
|
|
|
395
395
|
|
|
396
396
|
## 事件流
|
|
397
397
|
|
|
398
|
-
本 SDK 生成完整的 AI SDK
|
|
398
|
+
本 SDK 生成完整的 AI SDK v3 事件流,包括:
|
|
399
399
|
|
|
400
400
|
### 基本事件
|
|
401
401
|
|
|
@@ -522,7 +522,7 @@ Ollama HTTP API
|
|
|
522
522
|
### 特点
|
|
523
523
|
|
|
524
524
|
- **零依赖**: 不依赖 `ai-sdk-ollama` 或其他第三方库
|
|
525
|
-
- **完整实现**: 完全符合 AI SDK
|
|
525
|
+
- **完整实现**: 完全符合 AI SDK v3 规范
|
|
526
526
|
- **高性能**: 批量事件队列、及时状态清理
|
|
527
527
|
- **可调试**: 结构化日志、trace ID 追踪
|
|
528
528
|
|
package/dist/index.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
'use strict';var utils=require('@easbot/utils');var
|
|
2
|
-
`);n=
|
|
3
|
-
`);o&&t.push({role:"user",content:o});break}case "assistant":{let o="",a=[];for(let n of e.content)if(n.type==="text")o+=n.text;else if(n.type==="tool-call"){let l=n;a.push({id:l.toolCallId,type:"function",function:{name:l.toolName,arguments:JSON.stringify(l.input)}});}t.push({role:"assistant",content:o||null,tool_calls:a.length>0?a:void 0});break}case "tool":for(let o of e.content){let a=o.output,n;switch(a.type){case "text":case "error-text":n=a.value;break;case "content":case "json":case "error-json":n=JSON.stringify(a.value);break;default:n=String(a.value);break}t.push({role:"tool",tool_call_id:o.toolCallId,content:n});}break}}catch(o){x.warn("Failed to convert message",{messageRole:e.role,error:o instanceof Error?o.message:String(o)});}return t}var q=class{constructor(t,e={}){r(this,"specificationVersion","v3");r(this,"provider","ollama");r(this,"modelId");r(this,"defaultObjectGenerationMode","json");r(this,"supportedUrls",{});r(this,"client");this.modelId=t,this.client=new D(e.baseURL);}async generate(t){return this.doGenerate(t)}async stream(t){return this.doStream(t)}async doStream(t){let e=V();x.debug("Stream request started",{traceId:e,modelId:this.modelId,hasTools:!!t.tools&&t.tools.length>0,toolCount:t.tools?.length||0,messageCount:t.prompt.length});let o=Z(t.prompt),a=Y({tools:t.tools}),n=JSON.stringify({model:this.modelId,messages:o,options:w,...a}),l=null,c=null,u=m=>{l&&l.enqueue(m),c&&c.enqueue(m);},b=async()=>{try{let m=!0,M=!1,L=!1,E="",p="",N=!1,P=[],d=[],j=()=>{if(d.length>0){for(let v of d)u(v);d.length=0;}},y=null;for await(let v of this.client.streamChat({model:this.modelId,messages:o,options:w,...a})){if(y&&y.chunkCount++,m){m=!1;let k={type:"response-metadata",id:V(),modelId:this.modelId,timestamp:new Date(v.created_at)};u(k),y&&y.eventCount++;}if(v.message?.tool_calls){L&&(d.push({type:"reasoning-end",id:"reasoning-0"}),L=!1),M&&(d.push({type:"text-end",id:"txt-0"}),M=!1);for(let k of v.message.tool_calls){if(!k.id||!k.function?.name){let $=k.id?"function.name":"id";x.error("Invalid tool call: missing field",{traceId:e,missingField:$,toolCall:void 0}),d.push({type:"error",error:`Invalid tool call: missing ${$}`});continue}let f=k.id,C=k.function.name,h=K(k.function.arguments),S=P.find($=>$.id===f);S?(S.function.arguments+=h,x.debug("Tool call arguments accumulated",{traceId:e,toolCallId:f,toolName:C,deltaLength:h.length,totalLength:S.function.arguments.length,isComplete:U(S.function.arguments)}),h&&d.push({type:"tool-input-delta",id:f,delta:h})):(S={id:f,type:"function",function:{name:C,arguments:h},hasFinished:!1},P.push(S),y&&y.toolCallCount++,x.debug("Tool call received",{traceId:e,toolCallId:f,toolName:C,argumentsLength:h.length,isComplete:U(h)}),d.push({type:"tool-input-start",id:f,toolName:C}),h&&d.push({type:"tool-input-delta",id:f,delta:h}));let W=U(S.function.arguments);!S.hasFinished&&W&&(x.debug("Tool call arguments complete",{traceId:e,toolCallId:f,toolName:C,isComplete:W,argumentsLength:S.function.arguments.length}),d.push({type:"tool-input-end",id:f}),d.push({type:"tool-call",toolCallId:f,toolName:C,input:S.function.arguments}),S.hasFinished=!0);}j(),y&&(y.eventCount+=d.length);}if(v.message?.content){let k=v.message.content;for(p+=k;p.length>0;)if(N){let f=p.indexOf("</think>");if(f===-1){p.length>0&&d.push({type:"reasoning-delta",id:"reasoning-0",delta:p}),p="";break}else {if(f>0){let C=p.substring(0,f);d.push({type:"reasoning-delta",id:"reasoning-0",delta:C});}d.push({type:"reasoning-end",id:"reasoning-0"}),L=!1,N=!1,p=p.substring(f+8);}}else {let f=p.indexOf("<think>");if(f===-1){p.length>0&&(M||(M=!0,d.push({type:"text-start",id:"txt-0"})),d.push({type:"text-delta",id:"txt-0",delta:p}),E+=p),p="";break}else {if(f>0){let C=p.substring(0,f);M||(M=!0,d.push({type:"text-start",id:"txt-0"})),d.push({type:"text-delta",id:"txt-0",delta:C}),E+=C,d.push({type:"text-end",id:"txt-0"}),M=!1;}N=!0,p=p.substring(f+7),L||(L=!0,d.push({type:"reasoning-start",id:"reasoning-0"}));}}}if(j(),y&&(y.eventCount+=d.length),v.done){let k=P.filter(h=>!h.hasFinished);for(let h of k)d.push({type:"tool-input-end",id:h.id}),d.push({type:"tool-call",toolCallId:h.id,toolName:h.function.name,input:h.function.arguments});p.length>0&&(N?(d.push({type:"reasoning-delta",id:"reasoning-0",delta:p}),d.push({type:"reasoning-end",id:"reasoning-0"})):(M||(M=!0,d.push({type:"text-start",id:"txt-0"})),d.push({type:"text-delta",id:"txt-0",delta:p}),E+=p)),M&&d.push({type:"text-end",id:"txt-0"});let C=P.length>0?"tool-calls":"stop";if(d.push({type:"finish",finishReason:C,usage:{inputTokens:{total:v.prompt_eval_count||0,noCache:void 0,cacheRead:void 0,cacheWrite:void 0},outputTokens:{total:v.eval_count||0,text:void 0,reasoning:void 0}},providerMetadata:{ollama:{totalDuration:v.total_duration||0,loadDuration:v.load_duration||0,promptEvalDuration:v.prompt_eval_duration||0,evalDuration:v.eval_duration||0}}}),j(),y&&(y.eventCount+=d.length),y);P.length=0;}}}catch(m){x.error("Stream processing error",{traceId:e,error:m instanceof Error?m.message:String(m),stack:void 0}),u({type:"error",error:m instanceof Error?m.message:String(m)}),u({type:"finish",finishReason:"error",usage:{inputTokens:{total:0,noCache:void 0,cacheRead:void 0,cacheWrite:void 0},outputTokens:{total:0,text:void 0,reasoning:void 0}}});}finally{l&&l.close(),c&&c.close();}},O=new ReadableStream({start(m){l=m;}}),i=new ReadableStream({start(m){c=m;}});b();async function*g(m){let M=m.getReader();try{for(;;){let{done:L,value:E}=await M.read();if(L)break;yield E;}}finally{M.releaseLock();}}return {stream:O,fullStream:g(i),request:{body:n},response:{}}}async doGenerate(t){let e=V();x.debug("Generate request started",{traceId:e,modelId:this.modelId,hasTools:!!t.tools&&t.tools.length>0,toolCount:t.tools?.length||0,messageCount:t.prompt.length});let o=Z(t.prompt),a=Y({tools:t.tools}),n=await this.client.chat({model:this.modelId,messages:o,options:w,...a}),l=[];if(n.message?.content&&l.push({type:"text",text:n.message.content}),n.message?.tool_calls){x.debug("Tool calls received in generate",{traceId:e,toolCallCount:n.message.tool_calls.length});for(let b of n.message.tool_calls){let O=b.id||V(),i=b.function.name,g=K(b.function.arguments);x.debug("Processing tool call in generate",{traceId:e,toolCallId:O,toolName:i,argumentsLength:g.length,isComplete:U(g)}),l.push({type:"tool-call",toolCallId:O,toolName:i,input:g});}}let c=!!(n.message?.tool_calls&&n.message.tool_calls.length>0),u=Q(n.done??false,c,"stop");return x.debug("Generate request completed",{traceId:e,finishReason:u,contentParts:l.length,hasToolCalls:c,inputTokens:n.prompt_eval_count||0,outputTokens:n.eval_count||0}),{content:l,finishReason:u,usage:{inputTokens:{total:n.prompt_eval_count||0,noCache:void 0,cacheRead:void 0,cacheWrite:void 0},outputTokens:{total:n.eval_count||0,text:void 0,reasoning:void 0}},providerMetadata:{ollama:{totalDuration:n.total_duration||0,loadDuration:n.load_duration||0,promptEvalDuration:n.prompt_eval_duration||0,evalDuration:n.eval_duration||0}},request:{body:JSON.stringify({model:this.modelId,messages:o,options:w,...a})},response:{}}}};var _=class{constructor(t,e={}){r(this,"specificationVersion","v3");r(this,"provider","ollama");r(this,"modelId");r(this,"defaultObjectGenerationMode","json");r(this,"supportedUrls",{});r(this,"nativeModel");this.modelId=t,this.nativeModel=new q(t,{baseURL:e.baseURL||"http://localhost:11434"});}doGenerate(t){return this.nativeModel.doGenerate(t)}doStream(t){return this.nativeModel.doStream(t)}async generate(t){return this.nativeModel.generate(t)}async stream(t){return this.nativeModel.stream(t)}};var A=class{constructor(t,e={}){r(this,"specificationVersion","v3");r(this,"provider","ollama");r(this,"modelId");r(this,"maxEmbeddingsPerCall");r(this,"supportsParallelCalls",true);r(this,"baseURL");this.modelId=t,this.baseURL=e.baseURL||"http://localhost:11434";}async doEmbed(t){let{values:e,abortSignal:o}=t,a=utils.Log.create({service:"ollama-embedding"});if(!e||e.length===0)return a.warn("Empty values array provided",{modelId:this.modelId}),{embeddings:[],usage:{tokens:0},warnings:[]};a.debug("Generating text embeddings",{modelId:this.modelId,valuesCount:e.length,baseURL:this.baseURL});try{let n=await Promise.all(e.map(c=>this.generateSingleEmbedding(c,o))),l=e.reduce((c,u)=>c+this.estimateTokens(u),0);return a.debug("Text embeddings generated successfully",{modelId:this.modelId,embeddingsCount:n.length,totalTokens:l}),{embeddings:n,usage:{tokens:l},warnings:[]}}catch(n){throw a.error("Text embedding generation failed",{modelId:this.modelId,error:n instanceof Error?n.message:String(n),stack:void 0}),n}}async generateSingleEmbedding(t,e){let o=`${this.baseURL}/api/embeddings`;try{let a=await fetch(o,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({model:this.modelId,prompt:t}),signal:e});if(!a.ok){let l=await a.text();throw new Error(`Ollama embedding API error (${a.status}): ${l}`)}let n=await a.json();if(!n.embedding||!Array.isArray(n.embedding))throw new Error("Invalid response format from Ollama embedding API");return n.embedding}catch(a){throw a instanceof TypeError&&a.message.includes("fetch")?new Error(`Failed to connect to Ollama server at ${this.baseURL}: ${a.message}`):a}}estimateTokens(t){let e=t.match(/[a-zA-Z]/g)?.length||0,o=t.match(/[\u4e00-\u9fa5]/g)?.length||0,a=t.length-e-o;return Math.ceil(e/4)+o+Math.ceil(a*.5)}};var F=class{constructor(t,e,o={}){r(this,"specificationVersion","v3");r(this,"provider","ollama");r(this,"modelId");r(this,"languageModel");r(this,"options");r(this,"log",utils.Log.create({service:"ollama-sdk",module:"reranking-model"}));this.modelId=t,this.languageModel=new _(t,e),this.options={totalScore:o.totalScore??1,useEnhancedPrompt:o.useEnhancedPrompt??true,promptLanguage:o.promptLanguage??"en"},this.log.debug("OllamaRerankingModel created",{modelId:t,totalScore:this.options.totalScore,useEnhancedPrompt:this.options.useEnhancedPrompt,promptLanguage:this.options.promptLanguage});}async doRerank(t){let{query:e,documents:o,topN:a}=t,n;Array.isArray(o)?n=o:o.type==="text"?n=o.values.map((u,b)=>({content:u,id:`doc_${b+1}`})):n=o.values;let l=a??n.length;if(n.length===0)return {ranking:[],warnings:[]};try{let u=this.buildRerankPrompt(e,n),O=(await this.languageModel.doGenerate({prompt:[{role:"user",content:[{type:"text",text:u}]}],maxOutputTokens:500,temperature:.1})).content.find(g=>g.type==="text")?.text||"",i=this.parseRerankResult(O,n,l);return {ranking:i.results.map(g=>({index:g.index,relevanceScore:g.score,document:g.document})),warnings:i.warnings.map(g=>({type:"other",message:g}))}}catch(u){return this.log.error("Reranking failed",{error:u.message}),{ranking:n.map((O,i)=>({index:i,relevanceScore:this.options.totalScore*(1-i/n.length),document:O})),warnings:[{type:"other",message:`Reranking failed, using original order: ${u.message}`}]}}}buildRerankPrompt(t,e){let o=e.map((a,n)=>{let l=a.id||`doc_${n+1}`,c=a.content.slice(0,300);return `${n+1}. [ID: ${l}] ${c}`}).join(`
|
|
1
|
+
'use strict';var utils=require('@easbot/utils');var B=Object.defineProperty;var Q=(s,t,e)=>t in s?B(s,t,{enumerable:true,configurable:true,writable:true,value:e}):s[t]=e;var r=(s,t,e)=>Q(s,typeof t!="symbol"?t+"":t,e);var T=class{constructor(t="http://localhost:11434"){r(this,"baseURL",t);}async*streamChat(t){let e=await fetch(`${this.baseURL}/api/chat`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({...t,stream:true})});if(!e.ok)throw new Error(`Ollama API error: ${e.status} ${e.statusText}`);if(!e.body)throw new Error("Response body is null");let o=e.body.getReader(),a=new TextDecoder,n="";try{for(;;){let{done:i,value:y}=await o.read();if(i){if(n.trim())try{yield JSON.parse(n);}catch{}break}n+=a.decode(y,{stream:!0});let g=n.split(`
|
|
2
|
+
`);n=g.pop()||"";for(let u of g){let c=u.trim();if(c)try{yield JSON.parse(c);}catch{}}}}finally{o.releaseLock();}}async chat(t){let e=await fetch(`${this.baseURL}/api/chat`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({...t,stream:false})});if(!e.ok)throw new Error(`Ollama API error: ${e.status} ${e.statusText}`);return e.json()}};var P={numCtx:262144,temperature:.7,topK:40,topP:.9,repeatPenalty:1.1,numPredict:32e3},K=["numCtx","repeatPenalty","numPredict"];var R=class extends Error{constructor(e,o){super(e);r(this,"cause",o);this.name="OllamaError",Object.setPrototypeOf(this,new.target.prototype);}},F=class extends R{constructor(e,o,a){super(e,a);r(this,"url",o);this.name="ConnectionError";}},j=class extends R{constructor(e,o){super(`Model not found: ${e}`,o);r(this,"modelId",e);this.name="ModelNotFoundError";}},q=class extends R{constructor(e,o,a,n){super(e,n);r(this,"field",o);r(this,"value",a);this.name="ValidationError";}},G=class extends R{constructor(e,o,a){super(e,a);r(this,"timeoutMs",o);this.name="TimeoutError";}},I=class extends R{constructor(e,o,a){super(`Invalid tool definition for "${e}": missing ${o}`,a);r(this,"toolName",e);r(this,"missingField",o);this.name="InvalidToolDefinitionError";}};function A(s,t,e){let o;return t?o="tool-calls":e==="length"?o="length":s?o="stop":o="other",{unified:o,raw:e}}var C=utils.Log.create({service:"ollama-sdk",module:"native-language-model"});function N(){return `${Date.now()}-${Math.random().toString(36).substring(2,9)}`}function V(s){if(!s||s.trim().length===0)return false;try{return JSON.parse(s),!0}catch{return false}}function z(s){return typeof s=="string"?s:JSON.stringify(s)}function W(s){return !s.tools||s.tools.length===0?{}:{tools:s.tools.map(t=>{if(!t.name)throw new I(t.name||"unknown","name");let e=t.inputSchema||t.parameters;if(!e)throw new I(t.name,"inputSchema");return {type:"function",function:{name:t.name,description:t.description,parameters:e}}})}}function Y(s){let t=[];for(let e of s)try{switch(e.role){case "system":t.push({role:"system",content:e.content});break;case "user":{let o=e.content.filter(a=>a.type==="text").map(a=>a.text).join(`
|
|
3
|
+
`);o&&t.push({role:"user",content:o});break}case "assistant":{let o="",a=[];for(let n of e.content)if(n.type==="text")o+=n.text;else if(n.type==="tool-call"){let i=n;a.push({id:i.toolCallId,type:"function",function:{name:i.toolName,arguments:JSON.stringify(i.input)}});}t.push({role:"assistant",content:o||null,tool_calls:a.length>0?a:void 0});break}case "tool":for(let o of e.content){let a=o.output,n;switch(a.type){case "text":case "error-text":n=a.value;break;case "content":case "json":case "error-json":n=JSON.stringify(a.value);break;default:n=String(a.value);break}t.push({role:"tool",tool_call_id:o.toolCallId,content:n});}break}}catch(o){C.warn("Failed to convert message",{messageRole:e.role,error:o instanceof Error?o.message:String(o)});}return t}var D=class{constructor(t,e={}){r(this,"specificationVersion","v3");r(this,"provider","ollama");r(this,"modelId");r(this,"defaultObjectGenerationMode","json");r(this,"supportedUrls",{});r(this,"client");this.modelId=t,this.client=new T(e.baseURL);}async doStream(t){let e=N();C.debug("Stream request started",{traceId:e,modelId:this.modelId,hasTools:!!t.tools&&t.tools.length>0,toolCount:t.tools?.length||0,messageCount:t.prompt.length});let o=Y(t.prompt),a=W({tools:t.tools}),n=null,i=u=>{n&&n.enqueue(u);},y=async()=>{try{let u=!0,c=!1,l=!1,p="",m="",w=!1,_=[],d=[],U=()=>{if(d.length>0){for(let v of d)i(v);d.length=0;}},b=null;for await(let v of this.client.streamChat({model:this.modelId,messages:o,options:P,...a})){if(b&&b.chunkCount++,u){u=!1;let M={type:"response-metadata",id:N(),modelId:this.modelId,timestamp:new Date(v.created_at)};i(M),b&&b.eventCount++;}if(v.message?.tool_calls){l&&(d.push({type:"reasoning-end",id:"reasoning-0"}),l=!1),c&&(d.push({type:"text-end",id:"txt-0"}),c=!1);for(let M of v.message.tool_calls){if(!M.id||!M.function?.name){let E=M.id?"function.name":"id";C.error("Invalid tool call: missing field",{traceId:e,missingField:E,toolCall:void 0}),d.push({type:"error",error:`Invalid tool call: missing ${E}`});continue}let h=M.id,O=M.function.name,f=z(M.function.arguments),k=_.find(E=>E.id===h);k?(k.function.arguments+=f,C.debug("Tool call arguments accumulated",{traceId:e,toolCallId:h,toolName:O,deltaLength:f.length,totalLength:k.function.arguments.length,isComplete:V(k.function.arguments)}),f&&d.push({type:"tool-input-delta",id:h,delta:f})):(k={id:h,type:"function",function:{name:O,arguments:f},hasFinished:!1},_.push(k),b&&b.toolCallCount++,C.debug("Tool call received",{traceId:e,toolCallId:h,toolName:O,argumentsLength:f.length,isComplete:V(f)}),d.push({type:"tool-input-start",id:h,toolName:O}),f&&d.push({type:"tool-input-delta",id:h,delta:f}));let J=V(k.function.arguments);!k.hasFinished&&J&&(C.debug("Tool call arguments complete",{traceId:e,toolCallId:h,toolName:O,isComplete:J,argumentsLength:k.function.arguments.length}),d.push({type:"tool-input-end",id:h}),d.push({type:"tool-call",toolCallId:h,toolName:O,input:k.function.arguments}),k.hasFinished=!0);}U(),b&&(b.eventCount+=d.length);}if(v.message?.content){let M=v.message.content;for(m+=M;m.length>0;)if(w){let h=m.indexOf("</think>");if(h===-1){m.length>0&&d.push({type:"reasoning-delta",id:"reasoning-0",delta:m}),m="";break}else {if(h>0){let O=m.substring(0,h);d.push({type:"reasoning-delta",id:"reasoning-0",delta:O});}d.push({type:"reasoning-end",id:"reasoning-0"}),l=!1,w=!1,m=m.substring(h+8);}}else {let h=m.indexOf("<think>");if(h===-1){m.length>0&&(c||(c=!0,d.push({type:"text-start",id:"txt-0"})),d.push({type:"text-delta",id:"txt-0",delta:m}),p+=m),m="";break}else {if(h>0){let O=m.substring(0,h);c||(c=!0,d.push({type:"text-start",id:"txt-0"})),d.push({type:"text-delta",id:"txt-0",delta:O}),p+=O,d.push({type:"text-end",id:"txt-0"}),c=!1;}w=!0,m=m.substring(h+7),l||(l=!0,d.push({type:"reasoning-start",id:"reasoning-0"}));}}}if(U(),b&&(b.eventCount+=d.length),v.done){let M=_.filter(f=>!f.hasFinished);for(let f of M)d.push({type:"tool-input-end",id:f.id}),d.push({type:"tool-call",toolCallId:f.id,toolName:f.function.name,input:f.function.arguments});m.length>0&&(w?(d.push({type:"reasoning-delta",id:"reasoning-0",delta:m}),d.push({type:"reasoning-end",id:"reasoning-0"})):(c||(c=!0,d.push({type:"text-start",id:"txt-0"})),d.push({type:"text-delta",id:"txt-0",delta:m}),p+=m)),c&&d.push({type:"text-end",id:"txt-0"});let h=_.length>0,O=A(!0,h,"stop");if(d.push({type:"finish",finishReason:O,usage:{inputTokens:{total:v.prompt_eval_count||0,noCache:void 0,cacheRead:void 0,cacheWrite:void 0},outputTokens:{total:v.eval_count||0,text:void 0,reasoning:void 0}},providerMetadata:{ollama:{totalDuration:v.total_duration||0,loadDuration:v.load_duration||0,promptEvalDuration:v.prompt_eval_duration||0,evalDuration:v.eval_duration||0}}}),U(),b&&(b.eventCount+=d.length),b);_.length=0;}}}catch(u){C.error("Stream processing error",{traceId:e,error:u instanceof Error?u.message:String(u),stack:void 0}),i({type:"error",error:u instanceof Error?u.message:String(u)}),i({type:"finish",finishReason:A(false,false,"error"),usage:{inputTokens:{total:0,noCache:void 0,cacheRead:void 0,cacheWrite:void 0},outputTokens:{total:0,text:void 0,reasoning:void 0}}});}finally{n&&n.close();}},g=new ReadableStream({start(u){n=u;}});return y(),{stream:g}}async doGenerate(t){let e=N();C.debug("Generate request started",{traceId:e,modelId:this.modelId,hasTools:!!t.tools&&t.tools.length>0,toolCount:t.tools?.length||0,messageCount:t.prompt.length});let o=Y(t.prompt),a=W({tools:t.tools}),n=await this.client.chat({model:this.modelId,messages:o,options:P,...a}),i=[];if(n.message?.content&&i.push({type:"text",text:n.message.content}),n.message?.tool_calls){C.debug("Tool calls received in generate",{traceId:e,toolCallCount:n.message.tool_calls.length});for(let u of n.message.tool_calls){let c=u.id||N(),l=u.function.name,p=z(u.function.arguments);C.debug("Processing tool call in generate",{traceId:e,toolCallId:c,toolName:l,argumentsLength:p.length,isComplete:V(p)}),i.push({type:"tool-call",toolCallId:c,toolName:l,input:p});}}let y=!!(n.message?.tool_calls&&n.message.tool_calls.length>0),g=A(n.done??false,y,"stop");return C.debug("Generate request completed",{traceId:e,finishReason:g,contentParts:i.length,hasToolCalls:y,inputTokens:n.prompt_eval_count||0,outputTokens:n.eval_count||0}),{content:i,finishReason:g,usage:{inputTokens:{total:n.prompt_eval_count||0,noCache:void 0,cacheRead:void 0,cacheWrite:void 0},outputTokens:{total:n.eval_count||0,text:void 0,reasoning:void 0}},providerMetadata:{ollama:{totalDuration:n.total_duration||0,loadDuration:n.load_duration||0,promptEvalDuration:n.prompt_eval_duration||0,evalDuration:n.eval_duration||0}},warnings:[],response:{id:e,timestamp:new Date(n.created_at||new Date().toISOString()),modelId:this.modelId}}}};var L=class{constructor(t,e={}){r(this,"specificationVersion","v3");r(this,"provider","ollama");r(this,"modelId");r(this,"defaultObjectGenerationMode","json");r(this,"supportedUrls",{});r(this,"nativeModel");this.modelId=t,this.nativeModel=new D(t,{baseURL:e.baseURL||"http://localhost:11434"});}doGenerate(t){return this.nativeModel.doGenerate(t)}doStream(t){return this.nativeModel.doStream(t)}};var S=class{constructor(t,e={}){r(this,"specificationVersion","v3");r(this,"provider","ollama");r(this,"modelId");r(this,"maxEmbeddingsPerCall");r(this,"supportsParallelCalls",true);r(this,"baseURL");this.modelId=t,this.baseURL=e.baseURL||"http://localhost:11434";}async doEmbed(t){let{values:e,abortSignal:o}=t,a=utils.Log.create({service:"ollama-embedding"});if(!e||e.length===0)return a.warn("Empty values array provided",{modelId:this.modelId}),{embeddings:[],usage:{tokens:0},warnings:[]};a.debug("Generating text embeddings",{modelId:this.modelId,valuesCount:e.length,baseURL:this.baseURL});try{let n=await Promise.all(e.map(y=>this.generateSingleEmbedding(y,o))),i=e.reduce((y,g)=>y+this.estimateTokens(g),0);return a.debug("Text embeddings generated successfully",{modelId:this.modelId,embeddingsCount:n.length,totalTokens:i}),{embeddings:n,usage:{tokens:i},warnings:[]}}catch(n){throw a.error("Text embedding generation failed",{modelId:this.modelId,error:n instanceof Error?n.message:String(n),stack:void 0}),n}}async generateSingleEmbedding(t,e){let o=`${this.baseURL}/api/embeddings`;try{let a=await fetch(o,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({model:this.modelId,prompt:t}),signal:e});if(!a.ok){let i=await a.text();throw new Error(`Ollama embedding API error (${a.status}): ${i}`)}let n=await a.json();if(!n.embedding||!Array.isArray(n.embedding))throw new Error("Invalid response format from Ollama embedding API");return n.embedding}catch(a){throw a instanceof TypeError&&a.message.includes("fetch")?new Error(`Failed to connect to Ollama server at ${this.baseURL}: ${a.message}`):a}}estimateTokens(t){let e=t.match(/[a-zA-Z]/g)?.length||0,o=t.match(/[\u4e00-\u9fa5]/g)?.length||0,a=t.length-e-o;return Math.ceil(e/4)+o+Math.ceil(a*.5)}};var $=class{constructor(t,e,o={}){r(this,"specificationVersion","v3");r(this,"provider","ollama");r(this,"modelId");r(this,"languageModel");r(this,"options");r(this,"log",utils.Log.create({service:"ollama-sdk",module:"reranking-model"}));this.modelId=t,this.languageModel=new L(t,e),this.options={totalScore:o.totalScore??1,useEnhancedPrompt:o.useEnhancedPrompt??true,promptLanguage:o.promptLanguage??"en"},this.log.debug("OllamaRerankingModel created",{modelId:t,totalScore:this.options.totalScore,useEnhancedPrompt:this.options.useEnhancedPrompt,promptLanguage:this.options.promptLanguage});}async doRerank(t){let{query:e,documents:o,topN:a}=t,n;Array.isArray(o)?n=o:o.type==="text"?n=o.values.map((g,u)=>({content:g,id:`doc_${u+1}`})):n=o.values;let i=a??n.length;if(n.length===0)return {ranking:[],warnings:[]};try{let g=this.buildRerankPrompt(e,n),c=(await this.languageModel.doGenerate({prompt:[{role:"user",content:[{type:"text",text:g}]}],maxOutputTokens:500,temperature:.1})).content.find(p=>p.type==="text")?.text||"";this.log.debug("Rerank LLM raw output",{query:e,textContent:c,documentsCount:n.length});let l=this.parseRerankResult(c,n,i);return {ranking:l.results.map(p=>({index:p.index,relevanceScore:p.score})),warnings:l.warnings.map(p=>({type:"other",message:p}))}}catch(g){return this.log.error("Reranking failed",{error:g.message}),{ranking:n.map((c,l)=>({index:l,relevanceScore:n.length>1?this.options.totalScore*(1-.9*l/(n.length-1)):this.options.totalScore,document:c})),warnings:[{type:"other",message:`Reranking failed, using original order: ${g.message}`}]}}}buildRerankPrompt(t,e){let o=e.map((a,n)=>{let i=a.id||`doc_${n+1}`,y=a.content.slice(0,300);return `${n+1}. [ID: ${i}] ${y}`}).join(`
|
|
4
4
|
|
|
5
5
|
`);if(this.options.promptLanguage==="en")return `You are a professional information retrieval reranking expert. Please rank the following documents according to the query.
|
|
6
6
|
|
|
@@ -13,18 +13,16 @@ Please rank the documents according to the following requirements:
|
|
|
13
13
|
1. Carefully analyze the user's query intent and key information needs
|
|
14
14
|
2. Evaluate each document's relevance to the query
|
|
15
15
|
3. Consider the document's completeness, accuracy, and usefulness
|
|
16
|
-
4. Return the
|
|
17
|
-
5. Most relevant documents
|
|
16
|
+
4. Return ONLY the document numbers (1, 2, 3, ...) in order from MOST relevant to LEAST relevant, separated by commas
|
|
17
|
+
5. Most relevant documents MUST be at the front
|
|
18
|
+
6. Every document must appear exactly once in your output
|
|
18
19
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
- If totalScore is 5: scores might be: 0.1, 0.25, 0.5, 0.03, 0.02
|
|
20
|
+
IMPORTANT:
|
|
21
|
+
- You MUST actually reorder the documents based on relevance to the query
|
|
22
|
+
- Do NOT output the original order unless it happens to be the correct relevance order
|
|
23
|
+
- Output format: just the numbers separated by commas, nothing else
|
|
24
24
|
|
|
25
|
-
Example output format: 2,5,1,4,3
|
|
26
|
-
|
|
27
|
-
Please only output the ranked document numbers separated by commas, do not include the actual scores.`;{let a=this.options.totalScore===1?"1.0":`${this.options.totalScore}`;return `\u4F60\u662F\u4E00\u4E2A\u4E13\u4E1A\u7684\u4FE1\u606F\u68C0\u7D22\u91CD\u6392\u5E8F\u4E13\u5BB6\u3002\u8BF7\u6839\u636E\u7528\u6237\u67E5\u8BE2\u5BF9\u6587\u6863\u8FDB\u884C\u76F8\u5173\u6027\u6392\u5E8F\u3002
|
|
25
|
+
Example output format: 2,5,1,4,3 (where document 2 is most relevant to the query)`;{this.options.totalScore===1?"1.0":`${this.options.totalScore}`;return `\u4F60\u662F\u4E00\u4E2A\u4E13\u4E1A\u7684\u4FE1\u606F\u68C0\u7D22\u91CD\u6392\u5E8F\u4E13\u5BB6\u3002\u8BF7\u6839\u636E\u7528\u6237\u67E5\u8BE2\u5BF9\u6587\u6863\u8FDB\u884C\u76F8\u5173\u6027\u6392\u5E8F\u3002
|
|
28
26
|
|
|
29
27
|
\u7528\u6237\u67E5\u8BE2\uFF1A${t}
|
|
30
28
|
|
|
@@ -35,10 +33,13 @@ ${o}
|
|
|
35
33
|
1. \u4ED4\u7EC6\u5206\u6790\u7528\u6237\u67E5\u8BE2\u7684\u610F\u56FE\u548C\u5173\u952E\u4FE1\u606F\u9700\u6C42
|
|
36
34
|
2. \u8BC4\u4F30\u6BCF\u4E2A\u6587\u6863\u4E0E\u67E5\u8BE2\u7684\u76F8\u5173\u6027
|
|
37
35
|
3. \u8003\u8651\u6587\u6863\u7684\u5B8C\u6574\u6027\u3001\u51C6\u786E\u6027\u548C\u5B9E\u7528\u6027
|
|
38
|
-
4. \
|
|
39
|
-
5. \u6700\u76F8\u5173\u7684\u6587\u6863\u6392\u5728\u6700\u524D\u9762
|
|
40
|
-
6. \
|
|
36
|
+
4. \u53EA\u8F93\u51FA\u6587\u6863\u7F16\u53F7\uFF081, 2, 3, ...\uFF09\uFF0C\u6309"\u6700\u76F8\u5173"\u5230"\u6700\u4E0D\u76F8\u5173"\u987A\u5E8F\u6392\u5217\uFF0C\u7528\u9017\u53F7\u5206\u9694
|
|
37
|
+
5. \u6700\u76F8\u5173\u7684\u6587\u6863\u5FC5\u987B\u6392\u5728\u6700\u524D\u9762
|
|
38
|
+
6. \u6BCF\u4E2A\u6587\u6863\u5FC5\u987B\u51FA\u73B0\u4E14\u4EC5\u51FA\u73B0\u4E00\u6B21
|
|
41
39
|
|
|
42
|
-
\
|
|
40
|
+
\u91CD\u8981\u63D0\u793A\uFF1A
|
|
41
|
+
- \u5FC5\u987B\u6839\u636E\u4E0E\u67E5\u8BE2\u7684\u76F8\u5173\u6027\u5B9E\u9645\u91CD\u65B0\u6392\u5E8F\u6587\u6863
|
|
42
|
+
- \u9664\u975E\u539F\u59CB\u987A\u5E8F\u6070\u597D\u5C31\u662F\u6B63\u786E\u7684\u76F8\u5173\u6027\u6392\u5E8F\uFF0C\u5426\u5219\u4E0D\u8981\u8F93\u51FA\u539F\u59CB\u987A\u5E8F
|
|
43
|
+
- \u8F93\u51FA\u683C\u5F0F\uFF1A\u4EC5\u5305\u542B\u7528\u9017\u53F7\u5206\u9694\u7684\u7F16\u53F7\uFF0C\u4E0D\u8981\u6709\u5176\u4ED6\u5185\u5BB9
|
|
43
44
|
|
|
44
|
-
\
|
|
45
|
+
\u793A\u4F8B\u8F93\u51FA\u683C\u5F0F\uFF1A2,5,1,4,3\uFF08\u5176\u4E2D\u6587\u6863 2 \u4E0E\u67E5\u8BE2\u6700\u76F8\u5173\uFF09`}}parseRerankResult(t,e,o){let a=[];try{let n=t.match(/\d+/g)?.map(l=>parseInt(l,10)-1).filter(l=>l>=0&&l<e.length)||[],i=[],y=new Set;for(let l of n)y.has(l)||(y.add(l),i.push(l));let g=[];for(let l=0;l<i.length;l++){let p=i[l];if(p!==void 0&&p>=0&&p<e.length){let m=e[p];m&&g.push({index:p,score:i.length>1?this.options.totalScore*(1-.9*l/(i.length-1)):this.options.totalScore,document:m});}}let u=new Set(i);for(let l=0;l<e.length;l++)if(!u.has(l)){let p=this.options.totalScore*.1;g.push({index:l,score:p,document:e[l]});}let c=o?g.slice(0,o):g;return this.log.debug("Parsed rerank results",{extractedNumbers:n,uniqueIndices:i,resultCount:c.length,topK:o}),{results:c,warnings:a}}catch(n){return this.log.error("Failed to parse rerank result",{error:n.message,text:t}),{results:e.map((y,g)=>({index:g,score:e.length>1?this.options.totalScore*(1-.9*g/(e.length-1)):this.options.totalScore,document:y})),warnings:[`Failed to parse rerank result: ${n.message}`]}}}};function ee(s={}){return Object.assign(e=>new L(e,s),{languageModel:e=>new L(e,s),chat:e=>new L(e,s),embeddingModel:e=>new S(e,s),rerankingModel:(e,o)=>new $(e,s,o)})}var te="0.1.0";exports.ConnectionError=F;exports.ModelNotFoundError=j;exports.OLLAMA_DEFAULT_OPTIONS=P;exports.OLLAMA_SPECIFIC_PARAMS=K;exports.OllamaEmbeddingModel=S;exports.OllamaError=R;exports.OllamaLanguageModel=L;exports.TimeoutError=G;exports.VERSION=te;exports.ValidationError=q;exports.createOllama=ee;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { LanguageModelV3, LanguageModelV3CallOptions, EmbeddingModelV3, EmbeddingModelV3CallOptions, EmbeddingModelV3Result, RerankingModelV3 } from '@ai-sdk/provider';
|
|
1
|
+
import { LanguageModelV3, LanguageModelV3CallOptions, LanguageModelV3GenerateResult, LanguageModelV3StreamResult, EmbeddingModelV3, EmbeddingModelV3CallOptions, EmbeddingModelV3Result, RerankingModelV3 } from '@ai-sdk/provider';
|
|
2
2
|
|
|
3
3
|
type OllamaModelId = string;
|
|
4
4
|
interface OllamaConfig {
|
|
@@ -25,19 +25,8 @@ declare class OllamaLanguageModel implements LanguageModelV3 {
|
|
|
25
25
|
readonly supportedUrls: Record<string, RegExp[]>;
|
|
26
26
|
private nativeModel;
|
|
27
27
|
constructor(modelId: OllamaModelId, config?: OllamaConfig);
|
|
28
|
-
doGenerate(options: LanguageModelV3CallOptions):
|
|
29
|
-
doStream(options: LanguageModelV3CallOptions):
|
|
30
|
-
generate(options: LanguageModelV3CallOptions): Promise<any>;
|
|
31
|
-
stream(options: LanguageModelV3CallOptions): Promise<{
|
|
32
|
-
stream: ReadableStream<any>;
|
|
33
|
-
fullStream: AsyncIterable<any>;
|
|
34
|
-
request: {
|
|
35
|
-
body: string;
|
|
36
|
-
};
|
|
37
|
-
response: {
|
|
38
|
-
headers?: Record<string, string>;
|
|
39
|
-
};
|
|
40
|
-
}>;
|
|
28
|
+
doGenerate(options: LanguageModelV3CallOptions): PromiseLike<LanguageModelV3GenerateResult>;
|
|
29
|
+
doStream(options: LanguageModelV3CallOptions): PromiseLike<LanguageModelV3StreamResult>;
|
|
41
30
|
}
|
|
42
31
|
|
|
43
32
|
declare class OllamaEmbeddingModel implements EmbeddingModelV3 {
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { LanguageModelV3, LanguageModelV3CallOptions, EmbeddingModelV3, EmbeddingModelV3CallOptions, EmbeddingModelV3Result, RerankingModelV3 } from '@ai-sdk/provider';
|
|
1
|
+
import { LanguageModelV3, LanguageModelV3CallOptions, LanguageModelV3GenerateResult, LanguageModelV3StreamResult, EmbeddingModelV3, EmbeddingModelV3CallOptions, EmbeddingModelV3Result, RerankingModelV3 } from '@ai-sdk/provider';
|
|
2
2
|
|
|
3
3
|
type OllamaModelId = string;
|
|
4
4
|
interface OllamaConfig {
|
|
@@ -25,19 +25,8 @@ declare class OllamaLanguageModel implements LanguageModelV3 {
|
|
|
25
25
|
readonly supportedUrls: Record<string, RegExp[]>;
|
|
26
26
|
private nativeModel;
|
|
27
27
|
constructor(modelId: OllamaModelId, config?: OllamaConfig);
|
|
28
|
-
doGenerate(options: LanguageModelV3CallOptions):
|
|
29
|
-
doStream(options: LanguageModelV3CallOptions):
|
|
30
|
-
generate(options: LanguageModelV3CallOptions): Promise<any>;
|
|
31
|
-
stream(options: LanguageModelV3CallOptions): Promise<{
|
|
32
|
-
stream: ReadableStream<any>;
|
|
33
|
-
fullStream: AsyncIterable<any>;
|
|
34
|
-
request: {
|
|
35
|
-
body: string;
|
|
36
|
-
};
|
|
37
|
-
response: {
|
|
38
|
-
headers?: Record<string, string>;
|
|
39
|
-
};
|
|
40
|
-
}>;
|
|
28
|
+
doGenerate(options: LanguageModelV3CallOptions): PromiseLike<LanguageModelV3GenerateResult>;
|
|
29
|
+
doStream(options: LanguageModelV3CallOptions): PromiseLike<LanguageModelV3StreamResult>;
|
|
41
30
|
}
|
|
42
31
|
|
|
43
32
|
declare class OllamaEmbeddingModel implements EmbeddingModelV3 {
|
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {Log}from'@easbot/utils';var
|
|
2
|
-
`);n=
|
|
3
|
-
`);o&&t.push({role:"user",content:o});break}case "assistant":{let o="",a=[];for(let n of e.content)if(n.type==="text")o+=n.text;else if(n.type==="tool-call"){let l=n;a.push({id:l.toolCallId,type:"function",function:{name:l.toolName,arguments:JSON.stringify(l.input)}});}t.push({role:"assistant",content:o||null,tool_calls:a.length>0?a:void 0});break}case "tool":for(let o of e.content){let a=o.output,n;switch(a.type){case "text":case "error-text":n=a.value;break;case "content":case "json":case "error-json":n=JSON.stringify(a.value);break;default:n=String(a.value);break}t.push({role:"tool",tool_call_id:o.toolCallId,content:n});}break}}catch(o){x.warn("Failed to convert message",{messageRole:e.role,error:o instanceof Error?o.message:String(o)});}return t}var F=class{constructor(t,e={}){r(this,"specificationVersion","v3");r(this,"provider","ollama");r(this,"modelId");r(this,"defaultObjectGenerationMode","json");r(this,"supportedUrls",{});r(this,"client");this.modelId=t,this.client=new V(e.baseURL);}async generate(t){return this.doGenerate(t)}async stream(t){return this.doStream(t)}async doStream(t){let e=U();x.debug("Stream request started",{traceId:e,modelId:this.modelId,hasTools:!!t.tools&&t.tools.length>0,toolCount:t.tools?.length||0,messageCount:t.prompt.length});let o=H(t.prompt),a=Z({tools:t.tools}),n=JSON.stringify({model:this.modelId,messages:o,options:E,...a}),l=null,c=null,u=m=>{l&&l.enqueue(m),c&&c.enqueue(m);},b=async()=>{try{let m=!0,M=!1,w=!1,P="",p="",$=!1,T=[],d=[],J=()=>{if(d.length>0){for(let v of d)u(v);d.length=0;}},y=null;for await(let v of this.client.streamChat({model:this.modelId,messages:o,options:E,...a})){if(y&&y.chunkCount++,m){m=!1;let k={type:"response-metadata",id:U(),modelId:this.modelId,timestamp:new Date(v.created_at)};u(k),y&&y.eventCount++;}if(v.message?.tool_calls){w&&(d.push({type:"reasoning-end",id:"reasoning-0"}),w=!1),M&&(d.push({type:"text-end",id:"txt-0"}),M=!1);for(let k of v.message.tool_calls){if(!k.id||!k.function?.name){let D=k.id?"function.name":"id";x.error("Invalid tool call: missing field",{traceId:e,missingField:D,toolCall:void 0}),d.push({type:"error",error:`Invalid tool call: missing ${D}`});continue}let f=k.id,C=k.function.name,h=Y(k.function.arguments),S=T.find(D=>D.id===f);S?(S.function.arguments+=h,x.debug("Tool call arguments accumulated",{traceId:e,toolCallId:f,toolName:C,deltaLength:h.length,totalLength:S.function.arguments.length,isComplete:q(S.function.arguments)}),h&&d.push({type:"tool-input-delta",id:f,delta:h})):(S={id:f,type:"function",function:{name:C,arguments:h},hasFinished:!1},T.push(S),y&&y.toolCallCount++,x.debug("Tool call received",{traceId:e,toolCallId:f,toolName:C,argumentsLength:h.length,isComplete:q(h)}),d.push({type:"tool-input-start",id:f,toolName:C}),h&&d.push({type:"tool-input-delta",id:f,delta:h}));let Q=q(S.function.arguments);!S.hasFinished&&Q&&(x.debug("Tool call arguments complete",{traceId:e,toolCallId:f,toolName:C,isComplete:Q,argumentsLength:S.function.arguments.length}),d.push({type:"tool-input-end",id:f}),d.push({type:"tool-call",toolCallId:f,toolName:C,input:S.function.arguments}),S.hasFinished=!0);}J(),y&&(y.eventCount+=d.length);}if(v.message?.content){let k=v.message.content;for(p+=k;p.length>0;)if($){let f=p.indexOf("</think>");if(f===-1){p.length>0&&d.push({type:"reasoning-delta",id:"reasoning-0",delta:p}),p="";break}else {if(f>0){let C=p.substring(0,f);d.push({type:"reasoning-delta",id:"reasoning-0",delta:C});}d.push({type:"reasoning-end",id:"reasoning-0"}),w=!1,$=!1,p=p.substring(f+8);}}else {let f=p.indexOf("<think>");if(f===-1){p.length>0&&(M||(M=!0,d.push({type:"text-start",id:"txt-0"})),d.push({type:"text-delta",id:"txt-0",delta:p}),P+=p),p="";break}else {if(f>0){let C=p.substring(0,f);M||(M=!0,d.push({type:"text-start",id:"txt-0"})),d.push({type:"text-delta",id:"txt-0",delta:C}),P+=C,d.push({type:"text-end",id:"txt-0"}),M=!1;}$=!0,p=p.substring(f+7),w||(w=!0,d.push({type:"reasoning-start",id:"reasoning-0"}));}}}if(J(),y&&(y.eventCount+=d.length),v.done){let k=T.filter(h=>!h.hasFinished);for(let h of k)d.push({type:"tool-input-end",id:h.id}),d.push({type:"tool-call",toolCallId:h.id,toolName:h.function.name,input:h.function.arguments});p.length>0&&($?(d.push({type:"reasoning-delta",id:"reasoning-0",delta:p}),d.push({type:"reasoning-end",id:"reasoning-0"})):(M||(M=!0,d.push({type:"text-start",id:"txt-0"})),d.push({type:"text-delta",id:"txt-0",delta:p}),P+=p)),M&&d.push({type:"text-end",id:"txt-0"});let C=T.length>0?"tool-calls":"stop";if(d.push({type:"finish",finishReason:C,usage:{inputTokens:{total:v.prompt_eval_count||0,noCache:void 0,cacheRead:void 0,cacheWrite:void 0},outputTokens:{total:v.eval_count||0,text:void 0,reasoning:void 0}},providerMetadata:{ollama:{totalDuration:v.total_duration||0,loadDuration:v.load_duration||0,promptEvalDuration:v.prompt_eval_duration||0,evalDuration:v.eval_duration||0}}}),J(),y&&(y.eventCount+=d.length),y);T.length=0;}}}catch(m){x.error("Stream processing error",{traceId:e,error:m instanceof Error?m.message:String(m),stack:void 0}),u({type:"error",error:m instanceof Error?m.message:String(m)}),u({type:"finish",finishReason:"error",usage:{inputTokens:{total:0,noCache:void 0,cacheRead:void 0,cacheWrite:void 0},outputTokens:{total:0,text:void 0,reasoning:void 0}}});}finally{l&&l.close(),c&&c.close();}},O=new ReadableStream({start(m){l=m;}}),i=new ReadableStream({start(m){c=m;}});b();async function*g(m){let M=m.getReader();try{for(;;){let{done:w,value:P}=await M.read();if(w)break;yield P;}}finally{M.releaseLock();}}return {stream:O,fullStream:g(i),request:{body:n},response:{}}}async doGenerate(t){let e=U();x.debug("Generate request started",{traceId:e,modelId:this.modelId,hasTools:!!t.tools&&t.tools.length>0,toolCount:t.tools?.length||0,messageCount:t.prompt.length});let o=H(t.prompt),a=Z({tools:t.tools}),n=await this.client.chat({model:this.modelId,messages:o,options:E,...a}),l=[];if(n.message?.content&&l.push({type:"text",text:n.message.content}),n.message?.tool_calls){x.debug("Tool calls received in generate",{traceId:e,toolCallCount:n.message.tool_calls.length});for(let b of n.message.tool_calls){let O=b.id||U(),i=b.function.name,g=Y(b.function.arguments);x.debug("Processing tool call in generate",{traceId:e,toolCallId:O,toolName:i,argumentsLength:g.length,isComplete:q(g)}),l.push({type:"tool-call",toolCallId:O,toolName:i,input:g});}}let c=!!(n.message?.tool_calls&&n.message.tool_calls.length>0),u=K(n.done??false,c,"stop");return x.debug("Generate request completed",{traceId:e,finishReason:u,contentParts:l.length,hasToolCalls:c,inputTokens:n.prompt_eval_count||0,outputTokens:n.eval_count||0}),{content:l,finishReason:u,usage:{inputTokens:{total:n.prompt_eval_count||0,noCache:void 0,cacheRead:void 0,cacheWrite:void 0},outputTokens:{total:n.eval_count||0,text:void 0,reasoning:void 0}},providerMetadata:{ollama:{totalDuration:n.total_duration||0,loadDuration:n.load_duration||0,promptEvalDuration:n.prompt_eval_duration||0,evalDuration:n.eval_duration||0}},request:{body:JSON.stringify({model:this.modelId,messages:o,options:E,...a})},response:{}}}};var I=class{constructor(t,e={}){r(this,"specificationVersion","v3");r(this,"provider","ollama");r(this,"modelId");r(this,"defaultObjectGenerationMode","json");r(this,"supportedUrls",{});r(this,"nativeModel");this.modelId=t,this.nativeModel=new F(t,{baseURL:e.baseURL||"http://localhost:11434"});}doGenerate(t){return this.nativeModel.doGenerate(t)}doStream(t){return this.nativeModel.doStream(t)}async generate(t){return this.nativeModel.generate(t)}async stream(t){return this.nativeModel.stream(t)}};var N=class{constructor(t,e={}){r(this,"specificationVersion","v3");r(this,"provider","ollama");r(this,"modelId");r(this,"maxEmbeddingsPerCall");r(this,"supportsParallelCalls",true);r(this,"baseURL");this.modelId=t,this.baseURL=e.baseURL||"http://localhost:11434";}async doEmbed(t){let{values:e,abortSignal:o}=t,a=Log.create({service:"ollama-embedding"});if(!e||e.length===0)return a.warn("Empty values array provided",{modelId:this.modelId}),{embeddings:[],usage:{tokens:0},warnings:[]};a.debug("Generating text embeddings",{modelId:this.modelId,valuesCount:e.length,baseURL:this.baseURL});try{let n=await Promise.all(e.map(c=>this.generateSingleEmbedding(c,o))),l=e.reduce((c,u)=>c+this.estimateTokens(u),0);return a.debug("Text embeddings generated successfully",{modelId:this.modelId,embeddingsCount:n.length,totalTokens:l}),{embeddings:n,usage:{tokens:l},warnings:[]}}catch(n){throw a.error("Text embedding generation failed",{modelId:this.modelId,error:n instanceof Error?n.message:String(n),stack:void 0}),n}}async generateSingleEmbedding(t,e){let o=`${this.baseURL}/api/embeddings`;try{let a=await fetch(o,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({model:this.modelId,prompt:t}),signal:e});if(!a.ok){let l=await a.text();throw new Error(`Ollama embedding API error (${a.status}): ${l}`)}let n=await a.json();if(!n.embedding||!Array.isArray(n.embedding))throw new Error("Invalid response format from Ollama embedding API");return n.embedding}catch(a){throw a instanceof TypeError&&a.message.includes("fetch")?new Error(`Failed to connect to Ollama server at ${this.baseURL}: ${a.message}`):a}}estimateTokens(t){let e=t.match(/[a-zA-Z]/g)?.length||0,o=t.match(/[\u4e00-\u9fa5]/g)?.length||0,a=t.length-e-o;return Math.ceil(e/4)+o+Math.ceil(a*.5)}};var j=class{constructor(t,e,o={}){r(this,"specificationVersion","v3");r(this,"provider","ollama");r(this,"modelId");r(this,"languageModel");r(this,"options");r(this,"log",Log.create({service:"ollama-sdk",module:"reranking-model"}));this.modelId=t,this.languageModel=new I(t,e),this.options={totalScore:o.totalScore??1,useEnhancedPrompt:o.useEnhancedPrompt??true,promptLanguage:o.promptLanguage??"en"},this.log.debug("OllamaRerankingModel created",{modelId:t,totalScore:this.options.totalScore,useEnhancedPrompt:this.options.useEnhancedPrompt,promptLanguage:this.options.promptLanguage});}async doRerank(t){let{query:e,documents:o,topN:a}=t,n;Array.isArray(o)?n=o:o.type==="text"?n=o.values.map((u,b)=>({content:u,id:`doc_${b+1}`})):n=o.values;let l=a??n.length;if(n.length===0)return {ranking:[],warnings:[]};try{let u=this.buildRerankPrompt(e,n),O=(await this.languageModel.doGenerate({prompt:[{role:"user",content:[{type:"text",text:u}]}],maxOutputTokens:500,temperature:.1})).content.find(g=>g.type==="text")?.text||"",i=this.parseRerankResult(O,n,l);return {ranking:i.results.map(g=>({index:g.index,relevanceScore:g.score,document:g.document})),warnings:i.warnings.map(g=>({type:"other",message:g}))}}catch(u){return this.log.error("Reranking failed",{error:u.message}),{ranking:n.map((O,i)=>({index:i,relevanceScore:this.options.totalScore*(1-i/n.length),document:O})),warnings:[{type:"other",message:`Reranking failed, using original order: ${u.message}`}]}}}buildRerankPrompt(t,e){let o=e.map((a,n)=>{let l=a.id||`doc_${n+1}`,c=a.content.slice(0,300);return `${n+1}. [ID: ${l}] ${c}`}).join(`
|
|
1
|
+
import {Log}from'@easbot/utils';var Q=Object.defineProperty;var K=(s,t,e)=>t in s?Q(s,t,{enumerable:true,configurable:true,writable:true,value:e}):s[t]=e;var r=(s,t,e)=>K(s,typeof t!="symbol"?t+"":t,e);var P=class{constructor(t="http://localhost:11434"){r(this,"baseURL",t);}async*streamChat(t){let e=await fetch(`${this.baseURL}/api/chat`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({...t,stream:true})});if(!e.ok)throw new Error(`Ollama API error: ${e.status} ${e.statusText}`);if(!e.body)throw new Error("Response body is null");let o=e.body.getReader(),a=new TextDecoder,n="";try{for(;;){let{done:i,value:y}=await o.read();if(i){if(n.trim())try{yield JSON.parse(n);}catch{}break}n+=a.decode(y,{stream:!0});let g=n.split(`
|
|
2
|
+
`);n=g.pop()||"";for(let u of g){let c=u.trim();if(c)try{yield JSON.parse(c);}catch{}}}}finally{o.releaseLock();}}async chat(t){let e=await fetch(`${this.baseURL}/api/chat`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({...t,stream:false})});if(!e.ok)throw new Error(`Ollama API error: ${e.status} ${e.statusText}`);return e.json()}};var A={numCtx:262144,temperature:.7,topK:40,topP:.9,repeatPenalty:1.1,numPredict:32e3},Z=["numCtx","repeatPenalty","numPredict"];var _=class extends Error{constructor(e,o){super(e);r(this,"cause",o);this.name="OllamaError",Object.setPrototypeOf(this,new.target.prototype);}},j=class extends _{constructor(e,o,a){super(e,a);r(this,"url",o);this.name="ConnectionError";}},q=class extends _{constructor(e,o){super(`Model not found: ${e}`,o);r(this,"modelId",e);this.name="ModelNotFoundError";}},G=class extends _{constructor(e,o,a,n){super(e,n);r(this,"field",o);r(this,"value",a);this.name="ValidationError";}},J=class extends _{constructor(e,o,a){super(e,a);r(this,"timeoutMs",o);this.name="TimeoutError";}},S=class extends _{constructor(e,o,a){super(`Invalid tool definition for "${e}": missing ${o}`,a);r(this,"toolName",e);r(this,"missingField",o);this.name="InvalidToolDefinitionError";}};function N(s,t,e){let o;return t?o="tool-calls":e==="length"?o="length":s?o="stop":o="other",{unified:o,raw:e}}var C=Log.create({service:"ollama-sdk",module:"native-language-model"});function V(){return `${Date.now()}-${Math.random().toString(36).substring(2,9)}`}function D(s){if(!s||s.trim().length===0)return false;try{return JSON.parse(s),!0}catch{return false}}function W(s){return typeof s=="string"?s:JSON.stringify(s)}function Y(s){return !s.tools||s.tools.length===0?{}:{tools:s.tools.map(t=>{if(!t.name)throw new S(t.name||"unknown","name");let e=t.inputSchema||t.parameters;if(!e)throw new S(t.name,"inputSchema");return {type:"function",function:{name:t.name,description:t.description,parameters:e}}})}}function B(s){let t=[];for(let e of s)try{switch(e.role){case "system":t.push({role:"system",content:e.content});break;case "user":{let o=e.content.filter(a=>a.type==="text").map(a=>a.text).join(`
|
|
3
|
+
`);o&&t.push({role:"user",content:o});break}case "assistant":{let o="",a=[];for(let n of e.content)if(n.type==="text")o+=n.text;else if(n.type==="tool-call"){let i=n;a.push({id:i.toolCallId,type:"function",function:{name:i.toolName,arguments:JSON.stringify(i.input)}});}t.push({role:"assistant",content:o||null,tool_calls:a.length>0?a:void 0});break}case "tool":for(let o of e.content){let a=o.output,n;switch(a.type){case "text":case "error-text":n=a.value;break;case "content":case "json":case "error-json":n=JSON.stringify(a.value);break;default:n=String(a.value);break}t.push({role:"tool",tool_call_id:o.toolCallId,content:n});}break}}catch(o){C.warn("Failed to convert message",{messageRole:e.role,error:o instanceof Error?o.message:String(o)});}return t}var $=class{constructor(t,e={}){r(this,"specificationVersion","v3");r(this,"provider","ollama");r(this,"modelId");r(this,"defaultObjectGenerationMode","json");r(this,"supportedUrls",{});r(this,"client");this.modelId=t,this.client=new P(e.baseURL);}async doStream(t){let e=V();C.debug("Stream request started",{traceId:e,modelId:this.modelId,hasTools:!!t.tools&&t.tools.length>0,toolCount:t.tools?.length||0,messageCount:t.prompt.length});let o=B(t.prompt),a=Y({tools:t.tools}),n=null,i=u=>{n&&n.enqueue(u);},y=async()=>{try{let u=!0,c=!1,l=!1,p="",m="",E=!1,I=[],d=[],F=()=>{if(d.length>0){for(let v of d)i(v);d.length=0;}},b=null;for await(let v of this.client.streamChat({model:this.modelId,messages:o,options:A,...a})){if(b&&b.chunkCount++,u){u=!1;let M={type:"response-metadata",id:V(),modelId:this.modelId,timestamp:new Date(v.created_at)};i(M),b&&b.eventCount++;}if(v.message?.tool_calls){l&&(d.push({type:"reasoning-end",id:"reasoning-0"}),l=!1),c&&(d.push({type:"text-end",id:"txt-0"}),c=!1);for(let M of v.message.tool_calls){if(!M.id||!M.function?.name){let T=M.id?"function.name":"id";C.error("Invalid tool call: missing field",{traceId:e,missingField:T,toolCall:void 0}),d.push({type:"error",error:`Invalid tool call: missing ${T}`});continue}let h=M.id,O=M.function.name,f=W(M.function.arguments),k=I.find(T=>T.id===h);k?(k.function.arguments+=f,C.debug("Tool call arguments accumulated",{traceId:e,toolCallId:h,toolName:O,deltaLength:f.length,totalLength:k.function.arguments.length,isComplete:D(k.function.arguments)}),f&&d.push({type:"tool-input-delta",id:h,delta:f})):(k={id:h,type:"function",function:{name:O,arguments:f},hasFinished:!1},I.push(k),b&&b.toolCallCount++,C.debug("Tool call received",{traceId:e,toolCallId:h,toolName:O,argumentsLength:f.length,isComplete:D(f)}),d.push({type:"tool-input-start",id:h,toolName:O}),f&&d.push({type:"tool-input-delta",id:h,delta:f}));let z=D(k.function.arguments);!k.hasFinished&&z&&(C.debug("Tool call arguments complete",{traceId:e,toolCallId:h,toolName:O,isComplete:z,argumentsLength:k.function.arguments.length}),d.push({type:"tool-input-end",id:h}),d.push({type:"tool-call",toolCallId:h,toolName:O,input:k.function.arguments}),k.hasFinished=!0);}F(),b&&(b.eventCount+=d.length);}if(v.message?.content){let M=v.message.content;for(m+=M;m.length>0;)if(E){let h=m.indexOf("</think>");if(h===-1){m.length>0&&d.push({type:"reasoning-delta",id:"reasoning-0",delta:m}),m="";break}else {if(h>0){let O=m.substring(0,h);d.push({type:"reasoning-delta",id:"reasoning-0",delta:O});}d.push({type:"reasoning-end",id:"reasoning-0"}),l=!1,E=!1,m=m.substring(h+8);}}else {let h=m.indexOf("<think>");if(h===-1){m.length>0&&(c||(c=!0,d.push({type:"text-start",id:"txt-0"})),d.push({type:"text-delta",id:"txt-0",delta:m}),p+=m),m="";break}else {if(h>0){let O=m.substring(0,h);c||(c=!0,d.push({type:"text-start",id:"txt-0"})),d.push({type:"text-delta",id:"txt-0",delta:O}),p+=O,d.push({type:"text-end",id:"txt-0"}),c=!1;}E=!0,m=m.substring(h+7),l||(l=!0,d.push({type:"reasoning-start",id:"reasoning-0"}));}}}if(F(),b&&(b.eventCount+=d.length),v.done){let M=I.filter(f=>!f.hasFinished);for(let f of M)d.push({type:"tool-input-end",id:f.id}),d.push({type:"tool-call",toolCallId:f.id,toolName:f.function.name,input:f.function.arguments});m.length>0&&(E?(d.push({type:"reasoning-delta",id:"reasoning-0",delta:m}),d.push({type:"reasoning-end",id:"reasoning-0"})):(c||(c=!0,d.push({type:"text-start",id:"txt-0"})),d.push({type:"text-delta",id:"txt-0",delta:m}),p+=m)),c&&d.push({type:"text-end",id:"txt-0"});let h=I.length>0,O=N(!0,h,"stop");if(d.push({type:"finish",finishReason:O,usage:{inputTokens:{total:v.prompt_eval_count||0,noCache:void 0,cacheRead:void 0,cacheWrite:void 0},outputTokens:{total:v.eval_count||0,text:void 0,reasoning:void 0}},providerMetadata:{ollama:{totalDuration:v.total_duration||0,loadDuration:v.load_duration||0,promptEvalDuration:v.prompt_eval_duration||0,evalDuration:v.eval_duration||0}}}),F(),b&&(b.eventCount+=d.length),b);I.length=0;}}}catch(u){C.error("Stream processing error",{traceId:e,error:u instanceof Error?u.message:String(u),stack:void 0}),i({type:"error",error:u instanceof Error?u.message:String(u)}),i({type:"finish",finishReason:N(false,false,"error"),usage:{inputTokens:{total:0,noCache:void 0,cacheRead:void 0,cacheWrite:void 0},outputTokens:{total:0,text:void 0,reasoning:void 0}}});}finally{n&&n.close();}},g=new ReadableStream({start(u){n=u;}});return y(),{stream:g}}async doGenerate(t){let e=V();C.debug("Generate request started",{traceId:e,modelId:this.modelId,hasTools:!!t.tools&&t.tools.length>0,toolCount:t.tools?.length||0,messageCount:t.prompt.length});let o=B(t.prompt),a=Y({tools:t.tools}),n=await this.client.chat({model:this.modelId,messages:o,options:A,...a}),i=[];if(n.message?.content&&i.push({type:"text",text:n.message.content}),n.message?.tool_calls){C.debug("Tool calls received in generate",{traceId:e,toolCallCount:n.message.tool_calls.length});for(let u of n.message.tool_calls){let c=u.id||V(),l=u.function.name,p=W(u.function.arguments);C.debug("Processing tool call in generate",{traceId:e,toolCallId:c,toolName:l,argumentsLength:p.length,isComplete:D(p)}),i.push({type:"tool-call",toolCallId:c,toolName:l,input:p});}}let y=!!(n.message?.tool_calls&&n.message.tool_calls.length>0),g=N(n.done??false,y,"stop");return C.debug("Generate request completed",{traceId:e,finishReason:g,contentParts:i.length,hasToolCalls:y,inputTokens:n.prompt_eval_count||0,outputTokens:n.eval_count||0}),{content:i,finishReason:g,usage:{inputTokens:{total:n.prompt_eval_count||0,noCache:void 0,cacheRead:void 0,cacheWrite:void 0},outputTokens:{total:n.eval_count||0,text:void 0,reasoning:void 0}},providerMetadata:{ollama:{totalDuration:n.total_duration||0,loadDuration:n.load_duration||0,promptEvalDuration:n.prompt_eval_duration||0,evalDuration:n.eval_duration||0}},warnings:[],response:{id:e,timestamp:new Date(n.created_at||new Date().toISOString()),modelId:this.modelId}}}};var R=class{constructor(t,e={}){r(this,"specificationVersion","v3");r(this,"provider","ollama");r(this,"modelId");r(this,"defaultObjectGenerationMode","json");r(this,"supportedUrls",{});r(this,"nativeModel");this.modelId=t,this.nativeModel=new $(t,{baseURL:e.baseURL||"http://localhost:11434"});}doGenerate(t){return this.nativeModel.doGenerate(t)}doStream(t){return this.nativeModel.doStream(t)}};var w=class{constructor(t,e={}){r(this,"specificationVersion","v3");r(this,"provider","ollama");r(this,"modelId");r(this,"maxEmbeddingsPerCall");r(this,"supportsParallelCalls",true);r(this,"baseURL");this.modelId=t,this.baseURL=e.baseURL||"http://localhost:11434";}async doEmbed(t){let{values:e,abortSignal:o}=t,a=Log.create({service:"ollama-embedding"});if(!e||e.length===0)return a.warn("Empty values array provided",{modelId:this.modelId}),{embeddings:[],usage:{tokens:0},warnings:[]};a.debug("Generating text embeddings",{modelId:this.modelId,valuesCount:e.length,baseURL:this.baseURL});try{let n=await Promise.all(e.map(y=>this.generateSingleEmbedding(y,o))),i=e.reduce((y,g)=>y+this.estimateTokens(g),0);return a.debug("Text embeddings generated successfully",{modelId:this.modelId,embeddingsCount:n.length,totalTokens:i}),{embeddings:n,usage:{tokens:i},warnings:[]}}catch(n){throw a.error("Text embedding generation failed",{modelId:this.modelId,error:n instanceof Error?n.message:String(n),stack:void 0}),n}}async generateSingleEmbedding(t,e){let o=`${this.baseURL}/api/embeddings`;try{let a=await fetch(o,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({model:this.modelId,prompt:t}),signal:e});if(!a.ok){let i=await a.text();throw new Error(`Ollama embedding API error (${a.status}): ${i}`)}let n=await a.json();if(!n.embedding||!Array.isArray(n.embedding))throw new Error("Invalid response format from Ollama embedding API");return n.embedding}catch(a){throw a instanceof TypeError&&a.message.includes("fetch")?new Error(`Failed to connect to Ollama server at ${this.baseURL}: ${a.message}`):a}}estimateTokens(t){let e=t.match(/[a-zA-Z]/g)?.length||0,o=t.match(/[\u4e00-\u9fa5]/g)?.length||0,a=t.length-e-o;return Math.ceil(e/4)+o+Math.ceil(a*.5)}};var U=class{constructor(t,e,o={}){r(this,"specificationVersion","v3");r(this,"provider","ollama");r(this,"modelId");r(this,"languageModel");r(this,"options");r(this,"log",Log.create({service:"ollama-sdk",module:"reranking-model"}));this.modelId=t,this.languageModel=new R(t,e),this.options={totalScore:o.totalScore??1,useEnhancedPrompt:o.useEnhancedPrompt??true,promptLanguage:o.promptLanguage??"en"},this.log.debug("OllamaRerankingModel created",{modelId:t,totalScore:this.options.totalScore,useEnhancedPrompt:this.options.useEnhancedPrompt,promptLanguage:this.options.promptLanguage});}async doRerank(t){let{query:e,documents:o,topN:a}=t,n;Array.isArray(o)?n=o:o.type==="text"?n=o.values.map((g,u)=>({content:g,id:`doc_${u+1}`})):n=o.values;let i=a??n.length;if(n.length===0)return {ranking:[],warnings:[]};try{let g=this.buildRerankPrompt(e,n),c=(await this.languageModel.doGenerate({prompt:[{role:"user",content:[{type:"text",text:g}]}],maxOutputTokens:500,temperature:.1})).content.find(p=>p.type==="text")?.text||"";this.log.debug("Rerank LLM raw output",{query:e,textContent:c,documentsCount:n.length});let l=this.parseRerankResult(c,n,i);return {ranking:l.results.map(p=>({index:p.index,relevanceScore:p.score})),warnings:l.warnings.map(p=>({type:"other",message:p}))}}catch(g){return this.log.error("Reranking failed",{error:g.message}),{ranking:n.map((c,l)=>({index:l,relevanceScore:n.length>1?this.options.totalScore*(1-.9*l/(n.length-1)):this.options.totalScore,document:c})),warnings:[{type:"other",message:`Reranking failed, using original order: ${g.message}`}]}}}buildRerankPrompt(t,e){let o=e.map((a,n)=>{let i=a.id||`doc_${n+1}`,y=a.content.slice(0,300);return `${n+1}. [ID: ${i}] ${y}`}).join(`
|
|
4
4
|
|
|
5
5
|
`);if(this.options.promptLanguage==="en")return `You are a professional information retrieval reranking expert. Please rank the following documents according to the query.
|
|
6
6
|
|
|
@@ -13,18 +13,16 @@ Please rank the documents according to the following requirements:
|
|
|
13
13
|
1. Carefully analyze the user's query intent and key information needs
|
|
14
14
|
2. Evaluate each document's relevance to the query
|
|
15
15
|
3. Consider the document's completeness, accuracy, and usefulness
|
|
16
|
-
4. Return the
|
|
17
|
-
5. Most relevant documents
|
|
16
|
+
4. Return ONLY the document numbers (1, 2, 3, ...) in order from MOST relevant to LEAST relevant, separated by commas
|
|
17
|
+
5. Most relevant documents MUST be at the front
|
|
18
|
+
6. Every document must appear exactly once in your output
|
|
18
19
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
- If totalScore is 5: scores might be: 0.1, 0.25, 0.5, 0.03, 0.02
|
|
20
|
+
IMPORTANT:
|
|
21
|
+
- You MUST actually reorder the documents based on relevance to the query
|
|
22
|
+
- Do NOT output the original order unless it happens to be the correct relevance order
|
|
23
|
+
- Output format: just the numbers separated by commas, nothing else
|
|
24
24
|
|
|
25
|
-
Example output format: 2,5,1,4,3
|
|
26
|
-
|
|
27
|
-
Please only output the ranked document numbers separated by commas, do not include the actual scores.`;{let a=this.options.totalScore===1?"1.0":`${this.options.totalScore}`;return `\u4F60\u662F\u4E00\u4E2A\u4E13\u4E1A\u7684\u4FE1\u606F\u68C0\u7D22\u91CD\u6392\u5E8F\u4E13\u5BB6\u3002\u8BF7\u6839\u636E\u7528\u6237\u67E5\u8BE2\u5BF9\u6587\u6863\u8FDB\u884C\u76F8\u5173\u6027\u6392\u5E8F\u3002
|
|
25
|
+
Example output format: 2,5,1,4,3 (where document 2 is most relevant to the query)`;{this.options.totalScore===1?"1.0":`${this.options.totalScore}`;return `\u4F60\u662F\u4E00\u4E2A\u4E13\u4E1A\u7684\u4FE1\u606F\u68C0\u7D22\u91CD\u6392\u5E8F\u4E13\u5BB6\u3002\u8BF7\u6839\u636E\u7528\u6237\u67E5\u8BE2\u5BF9\u6587\u6863\u8FDB\u884C\u76F8\u5173\u6027\u6392\u5E8F\u3002
|
|
28
26
|
|
|
29
27
|
\u7528\u6237\u67E5\u8BE2\uFF1A${t}
|
|
30
28
|
|
|
@@ -35,10 +33,13 @@ ${o}
|
|
|
35
33
|
1. \u4ED4\u7EC6\u5206\u6790\u7528\u6237\u67E5\u8BE2\u7684\u610F\u56FE\u548C\u5173\u952E\u4FE1\u606F\u9700\u6C42
|
|
36
34
|
2. \u8BC4\u4F30\u6BCF\u4E2A\u6587\u6863\u4E0E\u67E5\u8BE2\u7684\u76F8\u5173\u6027
|
|
37
35
|
3. \u8003\u8651\u6587\u6863\u7684\u5B8C\u6574\u6027\u3001\u51C6\u786E\u6027\u548C\u5B9E\u7528\u6027
|
|
38
|
-
4. \
|
|
39
|
-
5. \u6700\u76F8\u5173\u7684\u6587\u6863\u6392\u5728\u6700\u524D\u9762
|
|
40
|
-
6. \
|
|
36
|
+
4. \u53EA\u8F93\u51FA\u6587\u6863\u7F16\u53F7\uFF081, 2, 3, ...\uFF09\uFF0C\u6309"\u6700\u76F8\u5173"\u5230"\u6700\u4E0D\u76F8\u5173"\u987A\u5E8F\u6392\u5217\uFF0C\u7528\u9017\u53F7\u5206\u9694
|
|
37
|
+
5. \u6700\u76F8\u5173\u7684\u6587\u6863\u5FC5\u987B\u6392\u5728\u6700\u524D\u9762
|
|
38
|
+
6. \u6BCF\u4E2A\u6587\u6863\u5FC5\u987B\u51FA\u73B0\u4E14\u4EC5\u51FA\u73B0\u4E00\u6B21
|
|
41
39
|
|
|
42
|
-
\
|
|
40
|
+
\u91CD\u8981\u63D0\u793A\uFF1A
|
|
41
|
+
- \u5FC5\u987B\u6839\u636E\u4E0E\u67E5\u8BE2\u7684\u76F8\u5173\u6027\u5B9E\u9645\u91CD\u65B0\u6392\u5E8F\u6587\u6863
|
|
42
|
+
- \u9664\u975E\u539F\u59CB\u987A\u5E8F\u6070\u597D\u5C31\u662F\u6B63\u786E\u7684\u76F8\u5173\u6027\u6392\u5E8F\uFF0C\u5426\u5219\u4E0D\u8981\u8F93\u51FA\u539F\u59CB\u987A\u5E8F
|
|
43
|
+
- \u8F93\u51FA\u683C\u5F0F\uFF1A\u4EC5\u5305\u542B\u7528\u9017\u53F7\u5206\u9694\u7684\u7F16\u53F7\uFF0C\u4E0D\u8981\u6709\u5176\u4ED6\u5185\u5BB9
|
|
43
44
|
|
|
44
|
-
\
|
|
45
|
+
\u793A\u4F8B\u8F93\u51FA\u683C\u5F0F\uFF1A2,5,1,4,3\uFF08\u5176\u4E2D\u6587\u6863 2 \u4E0E\u67E5\u8BE2\u6700\u76F8\u5173\uFF09`}}parseRerankResult(t,e,o){let a=[];try{let n=t.match(/\d+/g)?.map(l=>parseInt(l,10)-1).filter(l=>l>=0&&l<e.length)||[],i=[],y=new Set;for(let l of n)y.has(l)||(y.add(l),i.push(l));let g=[];for(let l=0;l<i.length;l++){let p=i[l];if(p!==void 0&&p>=0&&p<e.length){let m=e[p];m&&g.push({index:p,score:i.length>1?this.options.totalScore*(1-.9*l/(i.length-1)):this.options.totalScore,document:m});}}let u=new Set(i);for(let l=0;l<e.length;l++)if(!u.has(l)){let p=this.options.totalScore*.1;g.push({index:l,score:p,document:e[l]});}let c=o?g.slice(0,o):g;return this.log.debug("Parsed rerank results",{extractedNumbers:n,uniqueIndices:i,resultCount:c.length,topK:o}),{results:c,warnings:a}}catch(n){return this.log.error("Failed to parse rerank result",{error:n.message,text:t}),{results:e.map((y,g)=>({index:g,score:e.length>1?this.options.totalScore*(1-.9*g/(e.length-1)):this.options.totalScore,document:y})),warnings:[`Failed to parse rerank result: ${n.message}`]}}}};function te(s={}){return Object.assign(e=>new R(e,s),{languageModel:e=>new R(e,s),chat:e=>new R(e,s),embeddingModel:e=>new w(e,s),rerankingModel:(e,o)=>new U(e,s,o)})}var ne="0.1.0";export{j as ConnectionError,q as ModelNotFoundError,A as OLLAMA_DEFAULT_OPTIONS,Z as OLLAMA_SPECIFIC_PARAMS,w as OllamaEmbeddingModel,_ as OllamaError,R as OllamaLanguageModel,J as TimeoutError,ne as VERSION,G as ValidationError,te as createOllama};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@easbot/ollama-sdk",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.5",
|
|
4
4
|
"description": "Ollama provider for Vercel AI SDK - Run local LLMs with Ollama in your AI applications",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.cjs",
|
|
@@ -44,8 +44,8 @@
|
|
|
44
44
|
"ai": "^6.0.176",
|
|
45
45
|
"axios": "^1.16.1",
|
|
46
46
|
"zod": "^4.4.3",
|
|
47
|
-
"@easbot/types": "0.3.
|
|
48
|
-
"@easbot/utils": "0.3.
|
|
47
|
+
"@easbot/types": "0.3.5",
|
|
48
|
+
"@easbot/utils": "0.3.5"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"@biomejs/biome": "^2.4.14",
|