@sisu-ai/adapter-ollama 10.0.1 → 11.0.0
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/dist/index.js +87 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as core from "@sisu-ai/core";
|
|
2
2
|
import { Ollama, } from "ollama";
|
|
3
|
+
const { firstConfigValue } = core;
|
|
4
|
+
function getCreateEmbeddingsClient() {
|
|
5
|
+
const candidate = core.createEmbeddingsClient;
|
|
6
|
+
if (typeof candidate === "function") {
|
|
7
|
+
return candidate;
|
|
8
|
+
}
|
|
9
|
+
return createEmbeddingsClientFallback;
|
|
10
|
+
}
|
|
11
|
+
const createEmbeddingsClient = getCreateEmbeddingsClient();
|
|
3
12
|
function resolveBaseUrl(explicitBaseUrl, envBaseUrl, fallback) {
|
|
4
13
|
const candidate = explicitBaseUrl || envBaseUrl;
|
|
5
14
|
return (candidate && candidate !== "/" ? candidate : fallback).replace(/\/$/, "");
|
|
@@ -22,6 +31,83 @@ export function ollamaEmbeddings(opts) {
|
|
|
22
31
|
},
|
|
23
32
|
});
|
|
24
33
|
}
|
|
34
|
+
function createEmbeddingsClientFallback(options) {
|
|
35
|
+
const clientName = options.clientName ?? "createEmbeddingsClient";
|
|
36
|
+
if (!options.baseUrl) {
|
|
37
|
+
throw new Error(`[${clientName}] baseUrl is required`);
|
|
38
|
+
}
|
|
39
|
+
const baseUrl = options.baseUrl.replace(/\/$/, "");
|
|
40
|
+
const path = options.path ?? "/v1/embeddings";
|
|
41
|
+
const authHeader = options.authHeader ?? "Authorization";
|
|
42
|
+
const authScheme = options.authScheme ?? "Bearer ";
|
|
43
|
+
return {
|
|
44
|
+
async embed(input, opts) {
|
|
45
|
+
if (!Array.isArray(input) || input.length === 0) {
|
|
46
|
+
throw new Error(`[${clientName}] input must contain at least one string`);
|
|
47
|
+
}
|
|
48
|
+
if (opts?.signal?.aborted) {
|
|
49
|
+
throw new Error(`[${clientName}] embedding request aborted`);
|
|
50
|
+
}
|
|
51
|
+
const model = opts?.model ?? options.model;
|
|
52
|
+
if (!model) {
|
|
53
|
+
throw new Error(`[${clientName}] model is required`);
|
|
54
|
+
}
|
|
55
|
+
const response = await fetch(`${baseUrl}${path}`, {
|
|
56
|
+
method: "POST",
|
|
57
|
+
headers: {
|
|
58
|
+
"Content-Type": "application/json",
|
|
59
|
+
Accept: "application/json",
|
|
60
|
+
...(options.apiKey
|
|
61
|
+
? { [authHeader]: `${authScheme}${options.apiKey}` }
|
|
62
|
+
: {}),
|
|
63
|
+
...(options.headers ?? {}),
|
|
64
|
+
},
|
|
65
|
+
body: JSON.stringify(options.buildBody?.({ input, model }) ?? {
|
|
66
|
+
model,
|
|
67
|
+
input,
|
|
68
|
+
}),
|
|
69
|
+
signal: opts?.signal,
|
|
70
|
+
});
|
|
71
|
+
const raw = await response.text();
|
|
72
|
+
if (!response.ok) {
|
|
73
|
+
throw new Error(`[${clientName}] API error: ${response.status} ${response.statusText} - ${extractEmbeddingsErrorDetails(raw)}`);
|
|
74
|
+
}
|
|
75
|
+
let embeddings;
|
|
76
|
+
try {
|
|
77
|
+
embeddings =
|
|
78
|
+
options.parseResponse?.(raw) ??
|
|
79
|
+
parseOpenAICompatibleEmbeddingsResponse(raw);
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
const message = error instanceof Error ? error.message : "unknown parse error";
|
|
83
|
+
throw new Error(`[${clientName}] Failed to parse embeddings response: ${message}`);
|
|
84
|
+
}
|
|
85
|
+
if (embeddings.length !== input.length) {
|
|
86
|
+
throw new Error(`[${clientName}] Expected ${input.length} embeddings, received ${embeddings.length}`);
|
|
87
|
+
}
|
|
88
|
+
return embeddings;
|
|
89
|
+
},
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
function parseOpenAICompatibleEmbeddingsResponse(raw) {
|
|
93
|
+
const parsed = JSON.parse(raw);
|
|
94
|
+
return (parsed.data ?? []).map((entry) => entry.embedding ?? []);
|
|
95
|
+
}
|
|
96
|
+
function extractEmbeddingsErrorDetails(raw) {
|
|
97
|
+
try {
|
|
98
|
+
const parsed = JSON.parse(raw);
|
|
99
|
+
if (typeof parsed.error === "string")
|
|
100
|
+
return parsed.error;
|
|
101
|
+
if (parsed.error?.message)
|
|
102
|
+
return parsed.error.message;
|
|
103
|
+
if (parsed.message)
|
|
104
|
+
return parsed.message;
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
return raw;
|
|
108
|
+
}
|
|
109
|
+
return raw;
|
|
110
|
+
}
|
|
25
111
|
export function ollamaAdapter(opts) {
|
|
26
112
|
const envBase = firstConfigValue(["BASE_URL", "OLLAMA_BASE_URL"]);
|
|
27
113
|
const baseUrl = resolveBaseUrl(opts.baseUrl, envBase, "http://localhost:11434");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sisu-ai/adapter-ollama",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "11.0.0",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -21,10 +21,10 @@
|
|
|
21
21
|
"url": "https://github.com/finger-gun/sisu/issues"
|
|
22
22
|
},
|
|
23
23
|
"peerDependencies": {
|
|
24
|
-
"@sisu-ai/core": "^2.
|
|
24
|
+
"@sisu-ai/core": "^2.5.0"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
|
-
"@sisu-ai/core": "2.
|
|
27
|
+
"@sisu-ai/core": "2.5.0"
|
|
28
28
|
},
|
|
29
29
|
"keywords": [
|
|
30
30
|
"sisu",
|