modelpact-providers 1.0.0 → 1.2.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/README.md +264 -11
- package/dist/index.d.ts +13 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -1
- package/dist/index.js.map +1 -1
- package/dist/ollama.d.ts +39 -0
- package/dist/ollama.d.ts.map +1 -0
- package/dist/ollama.js +442 -0
- package/dist/ollama.js.map +1 -0
- package/dist/openai.d.ts +60 -0
- package/dist/openai.d.ts.map +1 -0
- package/dist/openai.js +488 -0
- package/dist/openai.js.map +1 -0
- package/dist/prompt-api.d.ts +26 -0
- package/dist/prompt-api.d.ts.map +1 -0
- package/dist/prompt-api.js +261 -0
- package/dist/prompt-api.js.map +1 -0
- package/dist/webgpu.d.ts +73 -0
- package/dist/webgpu.d.ts.map +1 -0
- package/dist/webgpu.js +214 -0
- package/dist/webgpu.js.map +1 -0
- package/package.json +29 -5
package/dist/ollama.js
ADDED
|
@@ -0,0 +1,442 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ollama on a machine you can reach over HTTP.
|
|
3
|
+
*
|
|
4
|
+
* The daemon keeps nothing between requests: `/api/chat` is handed the whole
|
|
5
|
+
* conversation every time, which is what `request.history` is for. Three
|
|
6
|
+
* endpoints are the whole backend — `/api/tags` says what is downloaded,
|
|
7
|
+
* `/api/pull` downloads, `/api/chat` generates — and everything else the
|
|
8
|
+
* contract promises is the lifecycle's, back in `modelpact`.
|
|
9
|
+
*
|
|
10
|
+
* Shapes here were read off a running daemon, not off the docs: a chat stream
|
|
11
|
+
* is NDJSON whose last line carries the counts, a pull line carries `completed`
|
|
12
|
+
* and `total` per layer, and an error is an HTTP status with `{"error": "…"}`.
|
|
13
|
+
*/
|
|
14
|
+
import { AiError, contextUsage, createProvider, err, findTool, fraction, ndjsonLines, ok, runTool, tokens, } from "modelpact/backend";
|
|
15
|
+
const DEFAULTS = {
|
|
16
|
+
host: "http://127.0.0.1:11434",
|
|
17
|
+
contextWindow: 4096,
|
|
18
|
+
maxToolRounds: 8,
|
|
19
|
+
};
|
|
20
|
+
const asRecord = (value) => {
|
|
21
|
+
const isObject = typeof value === "object" && value !== null;
|
|
22
|
+
return isObject && !Array.isArray(value)
|
|
23
|
+
? value
|
|
24
|
+
: null;
|
|
25
|
+
};
|
|
26
|
+
const asString = (value) => typeof value === "string" ? value : null;
|
|
27
|
+
const asNumber = (value) => typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
28
|
+
const parseJson = (text) => {
|
|
29
|
+
try {
|
|
30
|
+
return JSON.parse(text);
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
const toEndpoint = (config) => ({
|
|
37
|
+
host: config.host ?? DEFAULTS.host,
|
|
38
|
+
// Bound, and not optional: in a browser `fetch` is a method of the window and
|
|
39
|
+
// throws `TypeError: Illegal invocation` once it is held on its own. Node
|
|
40
|
+
// does not care, so nothing but a page catches this (measured).
|
|
41
|
+
call: config.fetch ?? globalThis.fetch.bind(globalThis),
|
|
42
|
+
});
|
|
43
|
+
const postTo = (endpoint, path, body, signal) => endpoint.call(`${endpoint.host}${path}`, {
|
|
44
|
+
method: "POST",
|
|
45
|
+
headers: { "content-type": "application/json" },
|
|
46
|
+
body: JSON.stringify(body),
|
|
47
|
+
...(signal === undefined ? {} : { signal }),
|
|
48
|
+
});
|
|
49
|
+
/** The daemon says what went wrong in the body; a status alone would lose it. */
|
|
50
|
+
const failureFromResponse = async (response) => {
|
|
51
|
+
const text = await response.text().catch(() => "");
|
|
52
|
+
const errorText = asString(asRecord(parseJson(text))?.error);
|
|
53
|
+
const detail = errorText ?? `${response.status} from the daemon`;
|
|
54
|
+
// 400 is the daemon reading the request and refusing it, which is a bug on
|
|
55
|
+
// this side. Everything else is the daemon's own trouble.
|
|
56
|
+
return response.status === 400
|
|
57
|
+
? { kind: "invalid-input", detail }
|
|
58
|
+
: { kind: "failed", detail };
|
|
59
|
+
};
|
|
60
|
+
const listModels = async (endpoint) => {
|
|
61
|
+
const response = await endpoint.call(`${endpoint.host}/api/tags`);
|
|
62
|
+
if (!response.ok)
|
|
63
|
+
return [];
|
|
64
|
+
const listedModels = asRecord(await response.json().catch(() => null))?.models;
|
|
65
|
+
if (!Array.isArray(listedModels))
|
|
66
|
+
return [];
|
|
67
|
+
const names = listedModels.map((entry) => asString(asRecord(entry)?.model));
|
|
68
|
+
return names.filter((name) => name !== null);
|
|
69
|
+
};
|
|
70
|
+
const getAvailability = async (config) => {
|
|
71
|
+
const endpoint = toEndpoint(config);
|
|
72
|
+
let downloadedModels;
|
|
73
|
+
try {
|
|
74
|
+
downloadedModels = await listModels(endpoint);
|
|
75
|
+
}
|
|
76
|
+
catch (cause) {
|
|
77
|
+
// Nothing answering is not a failed request, it is no Ollama here.
|
|
78
|
+
return { kind: "unavailable", reason: { kind: "unsupported", cause } };
|
|
79
|
+
}
|
|
80
|
+
const isDownloaded = downloadedModels.includes(config.model);
|
|
81
|
+
return isDownloaded
|
|
82
|
+
? { kind: "ready" }
|
|
83
|
+
: { kind: "needs-download", started: false };
|
|
84
|
+
};
|
|
85
|
+
/**
|
|
86
|
+
* Pull progress is per layer, and layers are announced as the pull reaches
|
|
87
|
+
* them, so the denominator grows while it runs. The share can therefore stall,
|
|
88
|
+
* and `ProgressMonitor` drops it if it would step back. `success` is what
|
|
89
|
+
* makes the last report a 1, since that line carries no numbers.
|
|
90
|
+
*/
|
|
91
|
+
const readPullProgress = (reportProgress) => {
|
|
92
|
+
const layers = new Map();
|
|
93
|
+
return new TransformStream({
|
|
94
|
+
transform: (line, controller) => {
|
|
95
|
+
const parsedLine = asRecord(parseJson(line));
|
|
96
|
+
if (parsedLine === null)
|
|
97
|
+
return;
|
|
98
|
+
const errorText = asString(parsedLine.error);
|
|
99
|
+
if (errorText !== null)
|
|
100
|
+
throw new AiError({ kind: "failed", detail: errorText });
|
|
101
|
+
const digest = asString(parsedLine.digest);
|
|
102
|
+
const total = asNumber(parsedLine.total);
|
|
103
|
+
const completed = asNumber(parsedLine.completed) ?? 0;
|
|
104
|
+
if (digest !== null && total !== null && total > 0) {
|
|
105
|
+
layers.set(digest, { total, completed });
|
|
106
|
+
}
|
|
107
|
+
const isDone = asString(parsedLine.status) === "success";
|
|
108
|
+
const pulledShare = isDone ? 1 : getPulledShare(layers);
|
|
109
|
+
const progress = fraction(pulledShare);
|
|
110
|
+
if (progress !== null)
|
|
111
|
+
reportProgress(progress);
|
|
112
|
+
controller.enqueue(line);
|
|
113
|
+
},
|
|
114
|
+
});
|
|
115
|
+
};
|
|
116
|
+
const getPulledShare = (layers) => {
|
|
117
|
+
let total = 0;
|
|
118
|
+
let completed = 0;
|
|
119
|
+
for (const layer of layers.values()) {
|
|
120
|
+
total += layer.total;
|
|
121
|
+
completed += layer.completed;
|
|
122
|
+
}
|
|
123
|
+
return total === 0 ? 0 : completed / total;
|
|
124
|
+
};
|
|
125
|
+
const pullModel = async (endpoint, model, reportProgress) => {
|
|
126
|
+
const response = await postTo(endpoint, "/api/pull", { model, stream: true });
|
|
127
|
+
if (!response.ok)
|
|
128
|
+
return err(await failureFromResponse(response));
|
|
129
|
+
if (response.body === null)
|
|
130
|
+
return err({ kind: "failed", detail: "the pull sent no body" });
|
|
131
|
+
const lines = response.body
|
|
132
|
+
.pipeThrough(new TextDecoderStream())
|
|
133
|
+
.pipeThrough(ndjsonLines())
|
|
134
|
+
.pipeThrough(readPullProgress(reportProgress));
|
|
135
|
+
const reader = lines.getReader();
|
|
136
|
+
try {
|
|
137
|
+
// Read to the end: the transform above is where the reporting happens, and
|
|
138
|
+
// the body is not finished until it stops yielding.
|
|
139
|
+
for (;;) {
|
|
140
|
+
const chunk = await reader.read();
|
|
141
|
+
if (chunk.done)
|
|
142
|
+
return ok(null);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
catch (error) {
|
|
146
|
+
return err(error instanceof AiError
|
|
147
|
+
? error.failure
|
|
148
|
+
: { kind: "failed", detail: "the pull was interrupted", cause: error });
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
const toOllamaTools = (tools) => tools.map((tool) => ({
|
|
152
|
+
type: "function",
|
|
153
|
+
function: {
|
|
154
|
+
name: tool.name,
|
|
155
|
+
description: tool.description,
|
|
156
|
+
parameters: tool.inputSchema,
|
|
157
|
+
},
|
|
158
|
+
}));
|
|
159
|
+
/** A call carries `function.name` and `function.arguments`, an object; one without a name is skipped. */
|
|
160
|
+
const readToolCalls = (message) => {
|
|
161
|
+
const listedCalls = message?.tool_calls;
|
|
162
|
+
if (!Array.isArray(listedCalls))
|
|
163
|
+
return [];
|
|
164
|
+
const readCalls = [];
|
|
165
|
+
for (const listedCall of listedCalls) {
|
|
166
|
+
const calledFunction = asRecord(asRecord(listedCall)?.function);
|
|
167
|
+
const name = asString(calledFunction?.name);
|
|
168
|
+
if (name === null)
|
|
169
|
+
continue;
|
|
170
|
+
const callArguments = asRecord(calledFunction?.arguments) ?? {};
|
|
171
|
+
readCalls.push({ function: { name, arguments: callArguments } });
|
|
172
|
+
}
|
|
173
|
+
return readCalls;
|
|
174
|
+
};
|
|
175
|
+
const readWhole = async (stream) => {
|
|
176
|
+
const reader = stream.getReader();
|
|
177
|
+
const parts = [];
|
|
178
|
+
try {
|
|
179
|
+
for (;;) {
|
|
180
|
+
const chunk = await reader.read();
|
|
181
|
+
if (chunk.done)
|
|
182
|
+
return ok(parts.join(""));
|
|
183
|
+
parts.push(chunk.value);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
catch (error) {
|
|
187
|
+
return err(error instanceof AiError
|
|
188
|
+
? error.failure
|
|
189
|
+
: { kind: "failed", detail: "the chat stream broke", cause: error });
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
class OllamaModel {
|
|
193
|
+
#endpoint;
|
|
194
|
+
#model;
|
|
195
|
+
#contextWindow;
|
|
196
|
+
#system;
|
|
197
|
+
#tools;
|
|
198
|
+
#maxToolRounds;
|
|
199
|
+
#reportOverflow;
|
|
200
|
+
/** The last turn's counts, which is what the context holds now rather than a running sum. */
|
|
201
|
+
#usedTokens = 0;
|
|
202
|
+
constructor(config, options) {
|
|
203
|
+
this.#endpoint = toEndpoint(config);
|
|
204
|
+
this.#model = config.model;
|
|
205
|
+
this.#contextWindow = config.contextWindow ?? DEFAULTS.contextWindow;
|
|
206
|
+
this.#system = options.session.system;
|
|
207
|
+
this.#tools = options.request.tools ?? [];
|
|
208
|
+
this.#maxToolRounds = config.maxToolRounds ?? DEFAULTS.maxToolRounds;
|
|
209
|
+
this.#reportOverflow = options.reportOverflow;
|
|
210
|
+
}
|
|
211
|
+
generateStream = async (input, request) => {
|
|
212
|
+
const conversation = this.#toConversation(input, request);
|
|
213
|
+
const responseResult = await this.#chat(conversation, request, true);
|
|
214
|
+
if (!responseResult.ok)
|
|
215
|
+
return responseResult;
|
|
216
|
+
const body = responseResult.value.body;
|
|
217
|
+
if (body === null)
|
|
218
|
+
return err({ kind: "failed", detail: "the chat sent no body" });
|
|
219
|
+
return ok(this.#streamRounds(body, conversation, request));
|
|
220
|
+
};
|
|
221
|
+
generateWhole = async (input, request) => {
|
|
222
|
+
// A turn with tools is rounds, and rounds are the streaming path read to
|
|
223
|
+
// its end; only a plain turn has a whole-answer call worth a second shape.
|
|
224
|
+
if (this.#tools.length > 0) {
|
|
225
|
+
const streamResult = await this.generateStream(input, request);
|
|
226
|
+
return streamResult.ok ? readWhole(streamResult.value) : streamResult;
|
|
227
|
+
}
|
|
228
|
+
const conversation = this.#toConversation(input, request);
|
|
229
|
+
const responseResult = await this.#chat(conversation, request, false);
|
|
230
|
+
if (!responseResult.ok)
|
|
231
|
+
return responseResult;
|
|
232
|
+
const parsedBody = asRecord(await responseResult.value.json().catch(() => null));
|
|
233
|
+
if (parsedBody === null)
|
|
234
|
+
return err({ kind: "failed", detail: "the chat sent no JSON" });
|
|
235
|
+
const answerText = asString(asRecord(parsedBody.message)?.content);
|
|
236
|
+
if (answerText === null)
|
|
237
|
+
return err({ kind: "failed", detail: "the chat sent no message" });
|
|
238
|
+
this.#charge(parsedBody);
|
|
239
|
+
return ok(answerText);
|
|
240
|
+
};
|
|
241
|
+
usage = () => {
|
|
242
|
+
const used = tokens(this.#usedTokens) ?? ZERO_TOKENS;
|
|
243
|
+
return contextUsage(used, this.#contextWindow);
|
|
244
|
+
};
|
|
245
|
+
/**
|
|
246
|
+
* Nothing to release. The daemon unloads on its own timer, and telling it to
|
|
247
|
+
* unload here would take the model out from under whoever else is on it.
|
|
248
|
+
*/
|
|
249
|
+
dispose = () => undefined;
|
|
250
|
+
#toConversation(input, request) {
|
|
251
|
+
const askedMessage = { role: "user", content: input };
|
|
252
|
+
const conversation = [...request.history, askedMessage];
|
|
253
|
+
return this.#system === undefined
|
|
254
|
+
? conversation
|
|
255
|
+
: [{ role: "user", content: this.#system }, ...conversation];
|
|
256
|
+
}
|
|
257
|
+
async #chat(messages, request, stream) {
|
|
258
|
+
const body = {
|
|
259
|
+
model: this.#model,
|
|
260
|
+
messages,
|
|
261
|
+
stream,
|
|
262
|
+
options: { num_ctx: this.#contextWindow },
|
|
263
|
+
...(request.schema === undefined ? {} : { format: request.schema }),
|
|
264
|
+
...(this.#tools.length === 0
|
|
265
|
+
? {}
|
|
266
|
+
: { tools: toOllamaTools(this.#tools) }),
|
|
267
|
+
};
|
|
268
|
+
const response = await postTo(this.#endpoint, "/api/chat", body, request.signal);
|
|
269
|
+
return response.ok
|
|
270
|
+
? ok(response)
|
|
271
|
+
: err(await failureFromResponse(response));
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Rounds: an answer is read to its end, and where it ends in tool calls the
|
|
275
|
+
* calls are answered and the conversation sent again. Only text reaches the
|
|
276
|
+
* caller, so a turn that is all calls is silent until its last round.
|
|
277
|
+
* Bounded, because a model that keeps calling would spend the window on it:
|
|
278
|
+
* `granite4:350m` asks for the same listing until something stops it.
|
|
279
|
+
*/
|
|
280
|
+
#streamRounds(firstBody, firstConversation, request) {
|
|
281
|
+
let conversation = firstConversation;
|
|
282
|
+
let currentRound = this.#openRound(firstBody);
|
|
283
|
+
let roundsTaken = 0;
|
|
284
|
+
const advance = async (controller) => {
|
|
285
|
+
for (;;) {
|
|
286
|
+
const chunk = await currentRound.reader.read();
|
|
287
|
+
if (!chunk.done) {
|
|
288
|
+
controller.enqueue(chunk.value);
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
if (currentRound.toolCalls.length === 0) {
|
|
292
|
+
controller.close();
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
295
|
+
roundsTaken += 1;
|
|
296
|
+
if (roundsTaken > this.#maxToolRounds) {
|
|
297
|
+
throw new AiError({
|
|
298
|
+
kind: "failed",
|
|
299
|
+
detail: `the model called tools ${roundsTaken} times without answering`,
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
conversation = await this.#answerToolCalls(conversation, currentRound, request.signal);
|
|
303
|
+
const nextResult = await this.#chat(conversation, request, true);
|
|
304
|
+
if (!nextResult.ok)
|
|
305
|
+
throw new AiError(nextResult.error);
|
|
306
|
+
const nextBody = nextResult.value.body;
|
|
307
|
+
if (nextBody === null)
|
|
308
|
+
throw new AiError({
|
|
309
|
+
kind: "failed",
|
|
310
|
+
detail: "the chat sent no body",
|
|
311
|
+
});
|
|
312
|
+
currentRound = this.#openRound(nextBody);
|
|
313
|
+
}
|
|
314
|
+
};
|
|
315
|
+
return new ReadableStream({
|
|
316
|
+
pull: (controller) => advance(controller),
|
|
317
|
+
cancel: (reason) => currentRound.reader.cancel(reason),
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
/** Content out, calls and counts kept: the last line carries both `done` and the totals. */
|
|
321
|
+
#openRound(body) {
|
|
322
|
+
const contentParts = [];
|
|
323
|
+
const toolCalls = [];
|
|
324
|
+
const readLines = new TransformStream({
|
|
325
|
+
transform: (line, controller) => {
|
|
326
|
+
const parsedLine = asRecord(parseJson(line));
|
|
327
|
+
if (parsedLine === null)
|
|
328
|
+
return;
|
|
329
|
+
const errorText = asString(parsedLine.error);
|
|
330
|
+
if (errorText !== null)
|
|
331
|
+
throw new AiError({ kind: "failed", detail: errorText });
|
|
332
|
+
if (parsedLine.done === true)
|
|
333
|
+
this.#charge(parsedLine);
|
|
334
|
+
const message = asRecord(parsedLine.message);
|
|
335
|
+
toolCalls.push(...readToolCalls(message));
|
|
336
|
+
const delta = asString(message?.content) ?? "";
|
|
337
|
+
if (delta === "")
|
|
338
|
+
return;
|
|
339
|
+
contentParts.push(delta);
|
|
340
|
+
controller.enqueue(delta);
|
|
341
|
+
},
|
|
342
|
+
});
|
|
343
|
+
const deltas = body
|
|
344
|
+
.pipeThrough(new TextDecoderStream())
|
|
345
|
+
.pipeThrough(ndjsonLines())
|
|
346
|
+
.pipeThrough(readLines);
|
|
347
|
+
return { reader: deltas.getReader(), contentParts, toolCalls };
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* The model's call goes back as its own turn, then each answer with the
|
|
351
|
+
* `tool` role, which is what the daemon's template expects. A name the model
|
|
352
|
+
* made up is answered by name rather than failing the turn: the model can
|
|
353
|
+
* pick again, where a failed turn could not. A tool that throws cannot be
|
|
354
|
+
* answered for, and ends the turn.
|
|
355
|
+
*/
|
|
356
|
+
async #answerToolCalls(conversation, round, signal) {
|
|
357
|
+
const answered = [
|
|
358
|
+
...conversation,
|
|
359
|
+
{
|
|
360
|
+
role: "assistant",
|
|
361
|
+
content: round.contentParts.join(""),
|
|
362
|
+
tool_calls: round.toolCalls,
|
|
363
|
+
},
|
|
364
|
+
];
|
|
365
|
+
for (const call of round.toolCalls) {
|
|
366
|
+
const name = call.function.name;
|
|
367
|
+
const tool = findTool(this.#tools, name);
|
|
368
|
+
if (tool === undefined) {
|
|
369
|
+
answered.push({
|
|
370
|
+
role: "tool",
|
|
371
|
+
content: `there is no tool called "${name}"`,
|
|
372
|
+
tool_name: name,
|
|
373
|
+
});
|
|
374
|
+
continue;
|
|
375
|
+
}
|
|
376
|
+
const toolResult = await runTool(tool, call.function.arguments, signal);
|
|
377
|
+
if (!toolResult.ok)
|
|
378
|
+
throw new AiError(toolResult.error);
|
|
379
|
+
answered.push({
|
|
380
|
+
role: "tool",
|
|
381
|
+
content: toolResult.value,
|
|
382
|
+
tool_name: name,
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
return answered;
|
|
386
|
+
}
|
|
387
|
+
/**
|
|
388
|
+
* `prompt_eval_count` is the whole prompt, history included, so the two
|
|
389
|
+
* counts together are what the window holds after this turn. Summing across
|
|
390
|
+
* turns would count the history once per turn.
|
|
391
|
+
*/
|
|
392
|
+
#charge(finishedLine) {
|
|
393
|
+
const promptTokens = asNumber(finishedLine.prompt_eval_count) ?? 0;
|
|
394
|
+
const answerTokens = asNumber(finishedLine.eval_count) ?? 0;
|
|
395
|
+
this.#usedTokens = promptTokens + answerTokens;
|
|
396
|
+
if (this.#hasSpentTheWindow(finishedLine))
|
|
397
|
+
this.#reportOverflow();
|
|
398
|
+
}
|
|
399
|
+
/**
|
|
400
|
+
* A daemon that shifts context answers past `num_ctx` and the counts say so
|
|
401
|
+
* on their own. One that stops instead ends the turn with `done_reason:
|
|
402
|
+
* "length"` on counts that reach the window and go no further — the same
|
|
403
|
+
* overflow, told rather than counted. Both are read here because which one
|
|
404
|
+
* the daemon does is its build's to decide, not the caller's.
|
|
405
|
+
*
|
|
406
|
+
* `num_predict` is left unset, so `length` can only be the window; the count
|
|
407
|
+
* is checked anyway, in case a model file sets one.
|
|
408
|
+
*/
|
|
409
|
+
#hasSpentTheWindow(finishedLine) {
|
|
410
|
+
if (this.#usedTokens < this.#contextWindow)
|
|
411
|
+
return false;
|
|
412
|
+
return asString(finishedLine.done_reason) === "length";
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
const ZERO_TOKENS = tokens(0);
|
|
416
|
+
const connectOllama = async (config, options) => {
|
|
417
|
+
const endpoint = toEndpoint(config);
|
|
418
|
+
let downloadedModels;
|
|
419
|
+
try {
|
|
420
|
+
downloadedModels = await listModels(endpoint);
|
|
421
|
+
}
|
|
422
|
+
catch (cause) {
|
|
423
|
+
return err({ kind: "unsupported", cause });
|
|
424
|
+
}
|
|
425
|
+
if (!downloadedModels.includes(config.model)) {
|
|
426
|
+
const pullResult = await pullModel(endpoint, config.model, options.reportProgress);
|
|
427
|
+
if (!pullResult.ok)
|
|
428
|
+
return pullResult;
|
|
429
|
+
}
|
|
430
|
+
return ok(new OllamaModel(config, options));
|
|
431
|
+
};
|
|
432
|
+
export function makeOllamaProvider(config) {
|
|
433
|
+
const backend = {
|
|
434
|
+
name: "ollama",
|
|
435
|
+
modalities: ["text"],
|
|
436
|
+
tools: true,
|
|
437
|
+
availability: () => getAvailability(config),
|
|
438
|
+
connect: (options) => connectOllama(config, options),
|
|
439
|
+
};
|
|
440
|
+
return createProvider(backend);
|
|
441
|
+
}
|
|
442
|
+
//# sourceMappingURL=ollama.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ollama.js","sourceRoot":"","sources":["../src/ollama.ts"],"names":[],"mappings":"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"}
|
package/dist/openai.d.ts
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* An OpenAI-compatible server, which is a dialect rather than a company.
|
|
3
|
+
*
|
|
4
|
+
* `https://api.openai.com/v1` is the default and one instance of it. The same
|
|
5
|
+
* two endpoints answer on vLLM, llama.cpp, LM Studio, OpenRouter, Groq and
|
|
6
|
+
* Ollama's own compatibility layer, so `baseUrl` is the whole difference
|
|
7
|
+
* between them and `apiKey` is optional — a model on this machine wants no key,
|
|
8
|
+
* and a type that demanded one would be describing a service instead of a
|
|
9
|
+
* protocol.
|
|
10
|
+
*
|
|
11
|
+
* Two endpoints are the whole backend: `/models` says what is served,
|
|
12
|
+
* `/chat/completions` generates. There is no third, because there is nothing to
|
|
13
|
+
* download — the weights are the server's problem, which is why this is the one
|
|
14
|
+
* backend here that never answers `needs-download`.
|
|
15
|
+
*
|
|
16
|
+
* Shapes were read off the wire, not off the docs: a stream is Server-Sent
|
|
17
|
+
* Events whose last frame carries the counts, a tool call arrives in fragments
|
|
18
|
+
* keyed by `index` with its arguments as a JSON string rather than an object,
|
|
19
|
+
* and an error is an HTTP status with `{"error": {"message": "…"}}` — or with
|
|
20
|
+
* `{"error": "…"}`, which is what several compatible servers send instead.
|
|
21
|
+
*/
|
|
22
|
+
import { type AiProvider } from "modelpact/backend";
|
|
23
|
+
export interface OpenAiConfig {
|
|
24
|
+
/** The id as `/models` lists it, such as `gpt-4o-mini` or `qwen2.5-coder`. */
|
|
25
|
+
readonly model: string;
|
|
26
|
+
/**
|
|
27
|
+
* Up to and including the version segment, because that is where servers
|
|
28
|
+
* disagree: OpenAI serves `/v1`, LM Studio serves `/v1`, and a proxy can
|
|
29
|
+
* serve neither. A trailing slash is trimmed rather than doubled into the
|
|
30
|
+
* path.
|
|
31
|
+
*/
|
|
32
|
+
readonly baseUrl?: string;
|
|
33
|
+
/**
|
|
34
|
+
* Absent, no `Authorization` header is sent at all — which is what a local
|
|
35
|
+
* server wants, and what an unauthenticated one refuses. Note where this
|
|
36
|
+
* ends up: a key in a browser bundle is a key handed to everyone who loads
|
|
37
|
+
* the page. Point `baseUrl` at your own server there and keep the key on it.
|
|
38
|
+
*/
|
|
39
|
+
readonly apiKey?: string;
|
|
40
|
+
/**
|
|
41
|
+
* The window to measure against. Optional and defaulted to nothing on
|
|
42
|
+
* purpose: no OpenAI-compatible server reports the window it loaded a model
|
|
43
|
+
* with, so a number here is the caller's declaration and not a discovery.
|
|
44
|
+
* Absent, `usage()` answers `unknown` rather than inventing a denominator.
|
|
45
|
+
*
|
|
46
|
+
* Declared, it is also a budget: a transcript past it is an overflow, told
|
|
47
|
+
* by the counts rather than by the server. See `#hasSpentTheWindow`.
|
|
48
|
+
*/
|
|
49
|
+
readonly contextWindow?: number;
|
|
50
|
+
/** For a proxy, an extra header, or a test with no server behind it. */
|
|
51
|
+
readonly fetch?: typeof globalThis.fetch;
|
|
52
|
+
/**
|
|
53
|
+
* How many times one turn may come back with tool calls before it is failed.
|
|
54
|
+
* Per turn, not per session: a model that keeps asking spends the window on
|
|
55
|
+
* its own questions and never answers.
|
|
56
|
+
*/
|
|
57
|
+
readonly maxToolRounds?: number;
|
|
58
|
+
}
|
|
59
|
+
export declare function makeOpenAiProvider(config: OpenAiConfig): AiProvider;
|
|
60
|
+
//# sourceMappingURL=openai.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../src/openai.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,EAYL,KAAK,UAAU,EAUhB,MAAM,mBAAmB,CAAC;AAE3B,MAAM,WAAW,YAAY;IAC3B,8EAA8E;IAC9E,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB;;;;;OAKG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;;OAKG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB;;;;;;;;OAQG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,wEAAwE;IACxE,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;IACzC;;;;OAIG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;CACjC;AAgnBD,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,YAAY,GAAG,UAAU,CASnE"}
|