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