@ztimson/ai-utils 0.1.14 → 0.1.16
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 +8 -4
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +165 -157
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { createWorker as S } from "tesseract.js";
|
|
2
|
-
import { objectMap as
|
|
2
|
+
import { objectMap as _, JSONAttemptParse as w, findByProp as b, JSONSanitize as y, Http as j, consoleInterceptor as T, fn as q, ASet as v } from "@ztimson/utils";
|
|
3
3
|
import { Anthropic as P } from "@anthropic-ai/sdk";
|
|
4
|
-
import { Ollama as
|
|
5
|
-
import { OpenAI as
|
|
4
|
+
import { Ollama as A } from "ollama";
|
|
5
|
+
import { OpenAI as E } from "openai";
|
|
6
6
|
import x from "node:fs/promises";
|
|
7
7
|
import O from "node:path";
|
|
8
8
|
import * as g from "@tensorflow/tfjs";
|
|
@@ -16,18 +16,24 @@ class L extends k {
|
|
|
16
16
|
}
|
|
17
17
|
client;
|
|
18
18
|
toStandard(t) {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
19
|
+
const e = [];
|
|
20
|
+
for (let n = 0; n < t.length; n++) {
|
|
21
|
+
const i = t[n];
|
|
22
|
+
if (typeof i.content != "string" && (i.role == "assistant" ? i.content.filter((o) => o.type == "tool_use").forEach((o) => {
|
|
23
|
+
e.push({ role: "tool", id: o.id, name: o.name, args: o.input });
|
|
24
|
+
}) : i.role == "user" && i.content.filter((o) => o.type == "tool_result").forEach((o) => {
|
|
25
|
+
const p = e.find((c) => c.id == o.tool_use_id);
|
|
26
|
+
p && (p[o.is_error ? "error" : "content"] = o.content);
|
|
27
|
+
}), i.content = i.content.filter((o) => o.type == "text").map((o) => o.text).join(`
|
|
28
|
+
|
|
29
|
+
`)), i.content) {
|
|
30
|
+
const o = e.at(-1);
|
|
31
|
+
o && o.role == "assistant" && i.role == "assistant" ? o.content += `
|
|
27
32
|
|
|
28
|
-
`)
|
|
33
|
+
` + i.content : e.push({ role: i.role, content: i.content });
|
|
34
|
+
}
|
|
29
35
|
}
|
|
30
|
-
return
|
|
36
|
+
return e;
|
|
31
37
|
}
|
|
32
38
|
fromStandard(t) {
|
|
33
39
|
for (let e = 0; e < t.length; e++)
|
|
@@ -43,76 +49,78 @@ class L extends k {
|
|
|
43
49
|
return t;
|
|
44
50
|
}
|
|
45
51
|
ask(t, e = {}) {
|
|
46
|
-
const n = new AbortController(),
|
|
47
|
-
let
|
|
48
|
-
e.compress && (
|
|
52
|
+
const n = new AbortController(), i = new Promise(async (o, p) => {
|
|
53
|
+
let c = this.fromStandard([...e.history || [], { role: "user", content: t }]);
|
|
54
|
+
e.compress && (c = await this.ai.llm.compress(c, e.compress.max, e.compress.min, e));
|
|
49
55
|
const m = {
|
|
50
56
|
model: e.model || this.model,
|
|
51
57
|
max_tokens: e.max_tokens || this.ai.options.max_tokens || 4096,
|
|
52
58
|
system: e.system || this.ai.options.system || "",
|
|
53
59
|
temperature: e.temperature || this.ai.options.temperature || 0.7,
|
|
54
|
-
tools: (e.tools || this.ai.options.tools || []).map((
|
|
55
|
-
name:
|
|
56
|
-
description:
|
|
60
|
+
tools: (e.tools || this.ai.options.tools || []).map((a) => ({
|
|
61
|
+
name: a.name,
|
|
62
|
+
description: a.description,
|
|
57
63
|
input_schema: {
|
|
58
64
|
type: "object",
|
|
59
|
-
properties:
|
|
60
|
-
required:
|
|
65
|
+
properties: a.args ? _(a.args, (r, d) => ({ ...d, required: void 0 })) : {},
|
|
66
|
+
required: a.args ? Object.entries(a.args).filter((r) => r[1].required).map((r) => r[0]) : []
|
|
61
67
|
},
|
|
62
68
|
fn: void 0
|
|
63
69
|
})),
|
|
64
|
-
messages:
|
|
70
|
+
messages: c,
|
|
65
71
|
stream: !!e.stream
|
|
66
72
|
};
|
|
67
|
-
let
|
|
73
|
+
let l, s = !0;
|
|
68
74
|
do {
|
|
69
|
-
if (
|
|
70
|
-
|
|
71
|
-
|
|
75
|
+
if (l = await this.client.messages.create(m), e.stream) {
|
|
76
|
+
s || e.stream({ text: `
|
|
77
|
+
|
|
78
|
+
` }), s = !1, l.content = [];
|
|
79
|
+
for await (const r of l) {
|
|
72
80
|
if (n.signal.aborted) break;
|
|
73
81
|
if (r.type === "content_block_start")
|
|
74
|
-
r.content_block.type === "text" ?
|
|
82
|
+
r.content_block.type === "text" ? l.content.push({ type: "text", text: "" }) : r.content_block.type === "tool_use" && l.content.push({ type: "tool_use", id: r.content_block.id, name: r.content_block.name, input: "" });
|
|
75
83
|
else if (r.type === "content_block_delta")
|
|
76
84
|
if (r.delta.type === "text_delta") {
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
} else r.delta.type === "input_json_delta" && (
|
|
85
|
+
const d = r.delta.text;
|
|
86
|
+
l.content.at(-1).text += d, e.stream({ text: d });
|
|
87
|
+
} else r.delta.type === "input_json_delta" && (l.content.at(-1).input += r.delta.partial_json);
|
|
80
88
|
else if (r.type === "content_block_stop") {
|
|
81
|
-
const
|
|
82
|
-
|
|
89
|
+
const d = l.content.at(-1);
|
|
90
|
+
d.input != null && (d.input = d.input ? w(d.input, {}) : {});
|
|
83
91
|
} else if (r.type === "message_stop")
|
|
84
92
|
break;
|
|
85
93
|
}
|
|
86
94
|
}
|
|
87
|
-
const
|
|
88
|
-
if (
|
|
89
|
-
|
|
90
|
-
const r = await Promise.all(
|
|
91
|
-
const
|
|
92
|
-
if (!
|
|
95
|
+
const a = l.content.filter((r) => r.type === "tool_use");
|
|
96
|
+
if (a.length && !n.signal.aborted) {
|
|
97
|
+
c.push({ role: "assistant", content: l.content });
|
|
98
|
+
const r = await Promise.all(a.map(async (d) => {
|
|
99
|
+
const f = e.tools?.find(b("name", d.name));
|
|
100
|
+
if (!f) return { tool_use_id: d.id, is_error: !0, content: "Tool not found" };
|
|
93
101
|
try {
|
|
94
|
-
const
|
|
95
|
-
return { type: "tool_result", tool_use_id:
|
|
96
|
-
} catch (
|
|
97
|
-
return { type: "tool_result", tool_use_id:
|
|
102
|
+
const h = await f.fn(d.input, this.ai);
|
|
103
|
+
return { type: "tool_result", tool_use_id: d.id, content: y(h) };
|
|
104
|
+
} catch (h) {
|
|
105
|
+
return { type: "tool_result", tool_use_id: d.id, is_error: !0, content: h?.message || h?.toString() || "Unknown" };
|
|
98
106
|
}
|
|
99
107
|
}));
|
|
100
|
-
|
|
108
|
+
c.push({ role: "user", content: r }), m.messages = c;
|
|
101
109
|
}
|
|
102
|
-
} while (!n.signal.aborted &&
|
|
103
|
-
e.stream && e.stream({ done: !0 }),
|
|
110
|
+
} while (!n.signal.aborted && l.content.some((a) => a.type === "tool_use"));
|
|
111
|
+
e.stream && e.stream({ done: !0 }), o(this.toStandard([...c, {
|
|
104
112
|
role: "assistant",
|
|
105
|
-
content:
|
|
113
|
+
content: l.content.filter((a) => a.type == "text").map((a) => a.text).join(`
|
|
106
114
|
|
|
107
115
|
`)
|
|
108
116
|
}]));
|
|
109
117
|
});
|
|
110
|
-
return Object.assign(
|
|
118
|
+
return Object.assign(i, { abort: () => n.abort() });
|
|
111
119
|
}
|
|
112
120
|
}
|
|
113
121
|
class R extends k {
|
|
114
122
|
constructor(t, e, n) {
|
|
115
|
-
super(), this.ai = t, this.host = e, this.model = n, this.client = new
|
|
123
|
+
super(), this.ai = t, this.host = e, this.model = n, this.client = new A({ host: e });
|
|
116
124
|
}
|
|
117
125
|
client;
|
|
118
126
|
toStandard(t) {
|
|
@@ -129,10 +137,10 @@ class R extends k {
|
|
|
129
137
|
return t.map((e) => e.role != "tool" ? e : { role: "tool", tool_name: e.name, content: e.error || e.content });
|
|
130
138
|
}
|
|
131
139
|
ask(t, e = {}) {
|
|
132
|
-
const n = new AbortController(),
|
|
133
|
-
let
|
|
134
|
-
m[0].roll == "system" && (
|
|
135
|
-
const
|
|
140
|
+
const n = new AbortController(), i = new Promise(async (o, p) => {
|
|
141
|
+
let c = e.system || this.ai.options.system, m = this.fromStandard([...e.history || [], { role: "user", content: t }]);
|
|
142
|
+
m[0].roll == "system" && (c ? m.shift() : c = m.shift()), e.compress && (m = await this.ai.llm.compress(m, e.compress.max, e.compress.min)), e.system && m.unshift({ role: "system", content: c });
|
|
143
|
+
const l = {
|
|
136
144
|
model: e.model || this.model,
|
|
137
145
|
messages: m,
|
|
138
146
|
stream: !!e.stream,
|
|
@@ -141,66 +149,66 @@ class R extends k {
|
|
|
141
149
|
temperature: e.temperature || this.ai.options.temperature || 0.7,
|
|
142
150
|
num_predict: e.max_tokens || this.ai.options.max_tokens || 4096
|
|
143
151
|
},
|
|
144
|
-
tools: (e.tools || this.ai.options.tools || []).map((
|
|
152
|
+
tools: (e.tools || this.ai.options.tools || []).map((a) => ({
|
|
145
153
|
type: "function",
|
|
146
154
|
function: {
|
|
147
|
-
name:
|
|
148
|
-
description:
|
|
155
|
+
name: a.name,
|
|
156
|
+
description: a.description,
|
|
149
157
|
parameters: {
|
|
150
158
|
type: "object",
|
|
151
|
-
properties:
|
|
152
|
-
required:
|
|
159
|
+
properties: a.args ? _(a.args, (r, d) => ({ ...d, required: void 0 })) : {},
|
|
160
|
+
required: a.args ? Object.entries(a.args).filter((r) => r[1].required).map((r) => r[0]) : []
|
|
153
161
|
}
|
|
154
162
|
}
|
|
155
163
|
}))
|
|
156
164
|
};
|
|
157
|
-
let
|
|
165
|
+
let s;
|
|
158
166
|
do {
|
|
159
|
-
if (
|
|
160
|
-
|
|
161
|
-
for await (const
|
|
162
|
-
if (n.signal.aborted || (
|
|
167
|
+
if (s = await this.client.chat(l), e.stream) {
|
|
168
|
+
s.message = { role: "assistant", content: "", tool_calls: [] };
|
|
169
|
+
for await (const a of s)
|
|
170
|
+
if (n.signal.aborted || (a.message?.content && (s.message.content += a.message.content, e.stream({ text: a.message.content })), a.message?.tool_calls && (s.message.tool_calls = a.message.tool_calls), a.done)) break;
|
|
163
171
|
}
|
|
164
|
-
if (
|
|
165
|
-
m.push(
|
|
166
|
-
const
|
|
167
|
-
const
|
|
168
|
-
if (!
|
|
169
|
-
const f = typeof
|
|
172
|
+
if (s.message?.tool_calls?.length && !n.signal.aborted) {
|
|
173
|
+
m.push(s.message);
|
|
174
|
+
const a = await Promise.all(s.message.tool_calls.map(async (r) => {
|
|
175
|
+
const d = (e.tools || this.ai.options.tools)?.find(b("name", r.function.name));
|
|
176
|
+
if (!d) return { role: "tool", tool_name: r.function.name, content: '{"error": "Tool not found"}' };
|
|
177
|
+
const f = typeof r.function.arguments == "string" ? w(r.function.arguments, {}) : r.function.arguments;
|
|
170
178
|
try {
|
|
171
|
-
const h = await
|
|
172
|
-
return { role: "tool", tool_name:
|
|
179
|
+
const h = await d.fn(f, this.ai);
|
|
180
|
+
return { role: "tool", tool_name: r.function.name, args: f, content: y(h) };
|
|
173
181
|
} catch (h) {
|
|
174
|
-
return { role: "tool", tool_name:
|
|
182
|
+
return { role: "tool", tool_name: r.function.name, args: f, content: y({ error: h?.message || h?.toString() || "Unknown" }) };
|
|
175
183
|
}
|
|
176
184
|
}));
|
|
177
|
-
m.push(...
|
|
185
|
+
m.push(...a), l.messages = m;
|
|
178
186
|
}
|
|
179
|
-
} while (!n.signal.aborted &&
|
|
180
|
-
e.stream && e.stream({ done: !0 }),
|
|
187
|
+
} while (!n.signal.aborted && s.message?.tool_calls?.length);
|
|
188
|
+
e.stream && e.stream({ done: !0 }), o(this.toStandard([...m, { role: "assistant", content: s.message?.content }]));
|
|
181
189
|
});
|
|
182
|
-
return Object.assign(
|
|
190
|
+
return Object.assign(i, { abort: () => n.abort() });
|
|
183
191
|
}
|
|
184
192
|
}
|
|
185
|
-
class
|
|
193
|
+
class J extends k {
|
|
186
194
|
constructor(t, e, n) {
|
|
187
|
-
super(), this.ai = t, this.apiToken = e, this.model = n, this.client = new
|
|
195
|
+
super(), this.ai = t, this.apiToken = e, this.model = n, this.client = new E({ apiKey: e });
|
|
188
196
|
}
|
|
189
197
|
client;
|
|
190
198
|
toStandard(t) {
|
|
191
199
|
for (let e = 0; e < t.length; e++) {
|
|
192
200
|
const n = t[e];
|
|
193
201
|
if (n.role === "assistant" && n.tool_calls) {
|
|
194
|
-
const
|
|
202
|
+
const i = n.tool_calls.map((o) => ({
|
|
195
203
|
role: "tool",
|
|
196
|
-
id:
|
|
197
|
-
name:
|
|
198
|
-
args: w(
|
|
204
|
+
id: o.id,
|
|
205
|
+
name: o.function.name,
|
|
206
|
+
args: w(o.function.arguments, {})
|
|
199
207
|
}));
|
|
200
|
-
t.splice(e, 1, ...
|
|
208
|
+
t.splice(e, 1, ...i), e += i.length - 1;
|
|
201
209
|
} else if (n.role === "tool" && n.content) {
|
|
202
|
-
const
|
|
203
|
-
|
|
210
|
+
const i = t.find((o) => n.tool_call_id == o.id);
|
|
211
|
+
i && (n.content.includes('"error":') ? i.error = n.content : i.content = n.content), t.splice(e, 1), e--;
|
|
204
212
|
}
|
|
205
213
|
}
|
|
206
214
|
return t;
|
|
@@ -219,61 +227,61 @@ class I extends k {
|
|
|
219
227
|
}) : e.push(n), e), []);
|
|
220
228
|
}
|
|
221
229
|
ask(t, e = {}) {
|
|
222
|
-
const n = new AbortController(),
|
|
223
|
-
let
|
|
224
|
-
e.compress && (
|
|
230
|
+
const n = new AbortController(), i = new Promise(async (o, p) => {
|
|
231
|
+
let c = this.fromStandard([...e.history || [], { role: "user", content: t }]);
|
|
232
|
+
e.compress && (c = await this.ai.llm.compress(c, e.compress.max, e.compress.min, e));
|
|
225
233
|
const m = {
|
|
226
234
|
model: e.model || this.model,
|
|
227
|
-
messages:
|
|
235
|
+
messages: c,
|
|
228
236
|
stream: !!e.stream,
|
|
229
237
|
max_tokens: e.max_tokens || this.ai.options.max_tokens || 4096,
|
|
230
238
|
temperature: e.temperature || this.ai.options.temperature || 0.7,
|
|
231
|
-
tools: (e.tools || this.ai.options.tools || []).map((
|
|
239
|
+
tools: (e.tools || this.ai.options.tools || []).map((s) => ({
|
|
232
240
|
type: "function",
|
|
233
241
|
function: {
|
|
234
|
-
name:
|
|
235
|
-
description:
|
|
242
|
+
name: s.name,
|
|
243
|
+
description: s.description,
|
|
236
244
|
parameters: {
|
|
237
245
|
type: "object",
|
|
238
|
-
properties:
|
|
239
|
-
required:
|
|
246
|
+
properties: s.args ? _(s.args, (a, r) => ({ ...r, required: void 0 })) : {},
|
|
247
|
+
required: s.args ? Object.entries(s.args).filter((a) => a[1].required).map((a) => a[0]) : []
|
|
240
248
|
}
|
|
241
249
|
}
|
|
242
250
|
}))
|
|
243
251
|
};
|
|
244
|
-
let
|
|
252
|
+
let l;
|
|
245
253
|
do {
|
|
246
|
-
if (
|
|
247
|
-
|
|
248
|
-
for await (const
|
|
254
|
+
if (l = await this.client.chat.completions.create(m), e.stream) {
|
|
255
|
+
l.choices = [];
|
|
256
|
+
for await (const a of l) {
|
|
249
257
|
if (n.signal.aborted) break;
|
|
250
|
-
|
|
258
|
+
a.choices[0].delta.content && e.stream({ text: a.choices[0].delta.content });
|
|
251
259
|
}
|
|
252
260
|
}
|
|
253
|
-
const
|
|
254
|
-
if (
|
|
255
|
-
|
|
256
|
-
const
|
|
257
|
-
const
|
|
258
|
-
if (!
|
|
261
|
+
const s = l.choices[0].message.tool_calls || [];
|
|
262
|
+
if (s.length && !n.signal.aborted) {
|
|
263
|
+
c.push(l.choices[0].message);
|
|
264
|
+
const a = await Promise.all(s.map(async (r) => {
|
|
265
|
+
const d = e.tools?.find(b("name", r.function.name));
|
|
266
|
+
if (!d) return { role: "tool", tool_call_id: r.id, content: '{"error": "Tool not found"}' };
|
|
259
267
|
try {
|
|
260
|
-
const f = w(
|
|
261
|
-
return { role: "tool", tool_call_id:
|
|
268
|
+
const f = w(r.function.arguments, {}), h = await d.fn(f, this.ai);
|
|
269
|
+
return { role: "tool", tool_call_id: r.id, content: y(h) };
|
|
262
270
|
} catch (f) {
|
|
263
|
-
return { role: "tool", tool_call_id:
|
|
271
|
+
return { role: "tool", tool_call_id: r.id, content: y({ error: f?.message || f?.toString() || "Unknown" }) };
|
|
264
272
|
}
|
|
265
273
|
}));
|
|
266
|
-
|
|
274
|
+
c.push(...a), m.messages = c;
|
|
267
275
|
}
|
|
268
|
-
} while (!n.signal.aborted &&
|
|
269
|
-
e.stream && e.stream({ done: !0 }),
|
|
276
|
+
} while (!n.signal.aborted && l.choices?.[0]?.message?.tool_calls?.length);
|
|
277
|
+
e.stream && e.stream({ done: !0 }), o(this.toStandard([...c, { role: "assistant", content: l.choices[0].message.content || "" }]));
|
|
270
278
|
});
|
|
271
|
-
return Object.assign(
|
|
279
|
+
return Object.assign(i, { abort: () => n.abort() });
|
|
272
280
|
}
|
|
273
281
|
}
|
|
274
|
-
class
|
|
282
|
+
class W {
|
|
275
283
|
constructor(t, e) {
|
|
276
|
-
this.ai = t, this.options = e, e.anthropic?.token && (this.providers.anthropic = new L(this.ai, e.anthropic.token, e.anthropic.model)), e.ollama?.host && (this.providers.ollama = new R(this.ai, e.ollama.host, e.ollama.model)), e.openAi?.token && (this.providers.openAi = new
|
|
284
|
+
this.ai = t, this.options = e, e.anthropic?.token && (this.providers.anthropic = new L(this.ai, e.anthropic.token, e.anthropic.model)), e.ollama?.host && (this.providers.ollama = new R(this.ai, e.ollama.host, e.ollama.model)), e.openAi?.token && (this.providers.openAi = new J(this.ai, e.openAi.token, e.openAi.model));
|
|
277
285
|
}
|
|
278
286
|
providers = {};
|
|
279
287
|
/**
|
|
@@ -295,17 +303,17 @@ class J {
|
|
|
295
303
|
* @param {LLMRequest} options LLM options
|
|
296
304
|
* @returns {Promise<LLMMessage[]>} New chat history will summary at index 0
|
|
297
305
|
*/
|
|
298
|
-
async compress(t, e, n,
|
|
306
|
+
async compress(t, e, n, i) {
|
|
299
307
|
if (this.estimateTokens(t) < e) return t;
|
|
300
|
-
let
|
|
301
|
-
for (let
|
|
302
|
-
if (
|
|
308
|
+
let o = 0, p = 0;
|
|
309
|
+
for (let s of t.toReversed())
|
|
310
|
+
if (p += this.estimateTokens(s.content), p < n) o++;
|
|
303
311
|
else break;
|
|
304
|
-
if (t.length <=
|
|
305
|
-
const
|
|
306
|
-
return [{ role: "assistant", content: `Conversation Summary: ${await this.summarize(m.map((
|
|
312
|
+
if (t.length <= o) return t;
|
|
313
|
+
const c = o == 0 ? [] : t.slice(-o), m = (o == 0 ? t : t.slice(0, -o)).filter((s) => s.role === "assistant" || s.role === "user");
|
|
314
|
+
return [{ role: "assistant", content: `Conversation Summary: ${await this.summarize(m.map((s) => `${s.role}: ${s.content}`).join(`
|
|
307
315
|
|
|
308
|
-
`), 250,
|
|
316
|
+
`), 250, i)}` }, ...c];
|
|
309
317
|
}
|
|
310
318
|
/**
|
|
311
319
|
* Estimate variable as tokens
|
|
@@ -337,12 +345,12 @@ class J {
|
|
|
337
345
|
* @returns {Promise<string>} Summary
|
|
338
346
|
*/
|
|
339
347
|
summarize(t, e, n) {
|
|
340
|
-
return this.ask(t, { system: `Generate a brief summary <= ${e} tokens. Output nothing else`, temperature: 0.3, ...n }).then((
|
|
348
|
+
return this.ask(t, { system: `Generate a brief summary <= ${e} tokens. Output nothing else`, temperature: 0.3, ...n }).then((i) => i.pop()?.content || null);
|
|
341
349
|
}
|
|
342
350
|
}
|
|
343
351
|
class X {
|
|
344
352
|
constructor(t) {
|
|
345
|
-
this.options = t, this.llm = new
|
|
353
|
+
this.options = t, this.llm = new W(this, t), this.options.whisper?.binary && (this.whisperModel = this.options.whisper?.model.endsWith(".bin") ? this.options.whisper?.model : this.options.whisper?.model + ".bin", this.downloadAsrModel());
|
|
346
354
|
}
|
|
347
355
|
downloads = {};
|
|
348
356
|
whisperModel;
|
|
@@ -358,12 +366,12 @@ class X {
|
|
|
358
366
|
if (!this.options.whisper?.binary) throw new Error("Whisper not configured");
|
|
359
367
|
let n = () => {
|
|
360
368
|
};
|
|
361
|
-
return { response: new Promise((
|
|
362
|
-
this.downloadAsrModel(e).then((
|
|
369
|
+
return { response: new Promise((o, p) => {
|
|
370
|
+
this.downloadAsrModel(e).then((c) => {
|
|
363
371
|
let m = "";
|
|
364
|
-
const
|
|
365
|
-
n = () =>
|
|
366
|
-
|
|
372
|
+
const l = M(this.options.whisper?.binary, ["-nt", "-np", "-m", c, "-f", t], { stdio: ["ignore", "pipe", "ignore"] });
|
|
373
|
+
n = () => l.kill("SIGTERM"), l.on("error", (s) => p(s)), l.stdout.on("data", (s) => m += s.toString()), l.on("close", (s) => {
|
|
374
|
+
s === 0 ? o(m.trim() || null) : p(new Error(`Exit code ${s}`));
|
|
367
375
|
});
|
|
368
376
|
});
|
|
369
377
|
}), abort: n };
|
|
@@ -378,7 +386,7 @@ class X {
|
|
|
378
386
|
if (!this.options.whisper?.binary) throw new Error("Whisper not configured");
|
|
379
387
|
t.endsWith(".bin") || (t += ".bin");
|
|
380
388
|
const e = O.join(this.options.whisper.path, t);
|
|
381
|
-
return
|
|
389
|
+
return await x.stat(e).then(() => !0).catch(() => !1) ? e : this.downloads[t] ? this.downloads[t] : (this.downloads[t] = fetch(`https://huggingface.co/ggerganov/whisper.cpp/resolve/main/${t}`).then((n) => n.arrayBuffer()).then((n) => Buffer.from(n)).then(async (n) => (await x.writeFile(e, n), delete this.downloads[t], e)), this.downloads[t]);
|
|
382
390
|
}
|
|
383
391
|
/**
|
|
384
392
|
* Convert image to text using Optical Character Recognition
|
|
@@ -393,8 +401,8 @@ class X {
|
|
|
393
401
|
},
|
|
394
402
|
response: new Promise(async (n) => {
|
|
395
403
|
e = await S("eng");
|
|
396
|
-
const { data:
|
|
397
|
-
await e.terminate(), n(
|
|
404
|
+
const { data: i } = await e.recognize(t);
|
|
405
|
+
await e.terminate(), n(i.text.trim() || null);
|
|
398
406
|
})
|
|
399
407
|
};
|
|
400
408
|
}
|
|
@@ -406,19 +414,19 @@ class X {
|
|
|
406
414
|
*/
|
|
407
415
|
semanticSimilarity(t, ...e) {
|
|
408
416
|
if (e.length < 2) throw new Error("Requires at least 2 strings to compare");
|
|
409
|
-
const n = (
|
|
410
|
-
if (
|
|
411
|
-
const
|
|
412
|
-
return
|
|
413
|
-
},
|
|
414
|
-
return { avg:
|
|
417
|
+
const n = (c, m = 10) => c.toLowerCase().split("").map((l, s) => l.charCodeAt(0) * (s + 1) % m / m).slice(0, m), i = (c, m) => {
|
|
418
|
+
if (c.length !== m.length) throw new Error("Vectors must be same length");
|
|
419
|
+
const l = g.tensor1d(c), s = g.tensor1d(m), a = g.dot(l, s), r = g.norm(l), d = g.norm(s);
|
|
420
|
+
return r.dataSync()[0] === 0 || d.dataSync()[0] === 0 ? 0 : a.dataSync()[0] / (r.dataSync()[0] * d.dataSync()[0]);
|
|
421
|
+
}, o = n(t), p = e.map((c) => n(c)).map((c) => i(o, c));
|
|
422
|
+
return { avg: p.reduce((c, m) => c + m, 0) / p.length, max: Math.max(...p), similarities: p };
|
|
415
423
|
}
|
|
416
424
|
}
|
|
417
|
-
const
|
|
425
|
+
const I = {
|
|
418
426
|
name: "cli",
|
|
419
427
|
description: "Use the command line interface, returns any output",
|
|
420
428
|
args: { command: { type: "string", description: "Command to run", required: !0 } },
|
|
421
|
-
fn: (
|
|
429
|
+
fn: (u) => U`${u.command}`
|
|
422
430
|
}, Y = {
|
|
423
431
|
name: "get_datetime",
|
|
424
432
|
description: "Get current date and time",
|
|
@@ -431,15 +439,15 @@ const W = {
|
|
|
431
439
|
language: { type: "string", description: "Execution language", enum: ["cli", "node", "python"], required: !0 },
|
|
432
440
|
code: { type: "string", description: "Code to execute", required: !0 }
|
|
433
441
|
},
|
|
434
|
-
fn: async (
|
|
442
|
+
fn: async (u, t) => {
|
|
435
443
|
try {
|
|
436
|
-
switch (
|
|
444
|
+
switch (u.type) {
|
|
437
445
|
case "bash":
|
|
438
|
-
return await
|
|
446
|
+
return await I.fn({ command: u.code }, t);
|
|
439
447
|
case "node":
|
|
440
|
-
return await N.fn({ code:
|
|
448
|
+
return await N.fn({ code: u.code }, t);
|
|
441
449
|
case "python":
|
|
442
|
-
return await z.fn({ code:
|
|
450
|
+
return await z.fn({ code: u.code }, t);
|
|
443
451
|
}
|
|
444
452
|
} catch (e) {
|
|
445
453
|
return { error: e?.message || e.toString() };
|
|
@@ -454,15 +462,15 @@ const W = {
|
|
|
454
462
|
headers: { type: "object", description: "HTTP headers to send", default: {} },
|
|
455
463
|
body: { type: "object", description: "HTTP body to send" }
|
|
456
464
|
},
|
|
457
|
-
fn: (
|
|
465
|
+
fn: (u) => new j({ url: u.url, headers: u.headers }).request({ method: u.method || "GET", body: u.body })
|
|
458
466
|
}, N = {
|
|
459
467
|
name: "exec_javascript",
|
|
460
468
|
description: "Execute commonjs javascript",
|
|
461
469
|
args: {
|
|
462
470
|
code: { type: "string", description: "CommonJS javascript", required: !0 }
|
|
463
471
|
},
|
|
464
|
-
fn: async (
|
|
465
|
-
const t = T(null), e = await q({ console: t },
|
|
472
|
+
fn: async (u) => {
|
|
473
|
+
const t = T(null), e = await q({ console: t }, u.code, !0).catch((n) => t.output.error.push(n));
|
|
466
474
|
return { ...t.output, return: e, stdout: void 0, stderr: void 0 };
|
|
467
475
|
}
|
|
468
476
|
}, z = {
|
|
@@ -471,7 +479,7 @@ const W = {
|
|
|
471
479
|
args: {
|
|
472
480
|
code: { type: "string", description: "CommonJS javascript", required: !0 }
|
|
473
481
|
},
|
|
474
|
-
fn: async (
|
|
482
|
+
fn: async (u) => ({ result: $`python -c "${u.code}"` })
|
|
475
483
|
}, te = {
|
|
476
484
|
name: "search",
|
|
477
485
|
description: "Use a search engine to find relevant URLs, should be changed with fetch to scrape sources",
|
|
@@ -479,28 +487,28 @@ const W = {
|
|
|
479
487
|
query: { type: "string", description: "Search string", required: !0 },
|
|
480
488
|
length: { type: "string", description: "Number of results to return", default: 5 }
|
|
481
489
|
},
|
|
482
|
-
fn: async (
|
|
483
|
-
const t = await fetch(`https://html.duckduckgo.com/html/?q=${encodeURIComponent(
|
|
490
|
+
fn: async (u) => {
|
|
491
|
+
const t = await fetch(`https://html.duckduckgo.com/html/?q=${encodeURIComponent(u.query)}`, {
|
|
484
492
|
headers: { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)", "Accept-Language": "en-US,en;q=0.9" }
|
|
485
|
-
}).then((
|
|
493
|
+
}).then((o) => o.text());
|
|
486
494
|
let e, n = /<a .*?href="(.+?)".+?<\/a>/g;
|
|
487
|
-
const
|
|
495
|
+
const i = new v();
|
|
488
496
|
for (; (e = n.exec(t)) !== null; ) {
|
|
489
|
-
let
|
|
490
|
-
if (
|
|
497
|
+
let o = /uddg=(.+)&?/.exec(decodeURIComponent(e[1]))?.[1];
|
|
498
|
+
if (o && (o = decodeURIComponent(o)), o && i.add(o), i.size >= (u.length || 5)) break;
|
|
491
499
|
}
|
|
492
|
-
return
|
|
500
|
+
return i;
|
|
493
501
|
}
|
|
494
502
|
};
|
|
495
503
|
export {
|
|
496
504
|
X as Ai,
|
|
497
505
|
L as Anthropic,
|
|
498
|
-
|
|
506
|
+
I as CliTool,
|
|
499
507
|
Y as DateTimeTool,
|
|
500
508
|
Z as ExecTool,
|
|
501
509
|
ee as FetchTool,
|
|
502
510
|
N as JSTool,
|
|
503
|
-
|
|
511
|
+
W as LLM,
|
|
504
512
|
z as PythonTool,
|
|
505
513
|
te as SearchTool
|
|
506
514
|
};
|