@yh-ui/ai-sdk 0.1.21
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/LICENSE +21 -0
- package/README.md +309 -0
- package/dist/agent-enhanced.cjs +292 -0
- package/dist/agent-enhanced.d.ts +143 -0
- package/dist/agent-enhanced.mjs +267 -0
- package/dist/cache-adapter.cjs +99 -0
- package/dist/cache-adapter.d.ts +42 -0
- package/dist/cache-adapter.mjs +95 -0
- package/dist/future.cjs +882 -0
- package/dist/future.d.ts +519 -0
- package/dist/future.mjs +765 -0
- package/dist/index.cjs +913 -0
- package/dist/index.d.ts +55 -0
- package/dist/index.mjs +217 -0
- package/dist/langchain.cjs +363 -0
- package/dist/langchain.d.ts +232 -0
- package/dist/langchain.mjs +319 -0
- package/dist/loaders.cjs +110 -0
- package/dist/loaders.d.ts +58 -0
- package/dist/loaders.mjs +76 -0
- package/dist/mcp-server.cjs +265 -0
- package/dist/mcp-server.d.ts +186 -0
- package/dist/mcp-server.mjs +234 -0
- package/dist/mcp.cjs +370 -0
- package/dist/mcp.d.ts +206 -0
- package/dist/mcp.mjs +354 -0
- package/dist/observability.cjs +150 -0
- package/dist/observability.d.ts +112 -0
- package/dist/observability.mjs +117 -0
- package/dist/rag-production.cjs +95 -0
- package/dist/rag-production.d.ts +43 -0
- package/dist/rag-production.mjs +85 -0
- package/dist/rate-limit.cjs +73 -0
- package/dist/rate-limit.d.ts +55 -0
- package/dist/rate-limit.mjs +51 -0
- package/dist/vector-store.cjs +63 -0
- package/dist/vector-store.d.ts +74 -0
- package/dist/vector-store.mjs +55 -0
- package/dist/vue/index.cjs +1023 -0
- package/dist/vue/index.d.ts +627 -0
- package/dist/vue/index.mjs +913 -0
- package/package.json +87 -0
package/dist/future.cjs
ADDED
|
@@ -0,0 +1,882 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.createAudioContent = createAudioContent;
|
|
7
|
+
exports.createChainOfThought = createChainOfThought;
|
|
8
|
+
exports.createContextCompressor = createContextCompressor;
|
|
9
|
+
exports.createCostTracker = createCostTracker;
|
|
10
|
+
exports.createImageContent = createImageContent;
|
|
11
|
+
exports.createImageUrlContent = createImageUrlContent;
|
|
12
|
+
exports.createJSONSchema = createJSONSchema;
|
|
13
|
+
exports.createMultiModalMessage = createMultiModalMessage;
|
|
14
|
+
exports.createPlanExecuteAgent = createPlanExecuteAgent;
|
|
15
|
+
exports.createRAGSystem = createRAGSystem;
|
|
16
|
+
exports.createSafetyFilter = createSafetyFilter;
|
|
17
|
+
exports.createTracer = createTracer;
|
|
18
|
+
exports.createVideoContent = createVideoContent;
|
|
19
|
+
exports.fromZodSchema = fromZodSchema;
|
|
20
|
+
exports.parseStructuredOutput = parseStructuredOutput;
|
|
21
|
+
exports.schema = void 0;
|
|
22
|
+
exports.useReActAgent = useReActAgent;
|
|
23
|
+
var _vue = require("vue");
|
|
24
|
+
function useReActAgent(config) {
|
|
25
|
+
const {
|
|
26
|
+
type: _type = "react",
|
|
27
|
+
maxIterations = 10,
|
|
28
|
+
maxToolCalls = 20,
|
|
29
|
+
returnReasoning = false,
|
|
30
|
+
tools = [],
|
|
31
|
+
stopConditions = [],
|
|
32
|
+
onError
|
|
33
|
+
} = config;
|
|
34
|
+
const steps = (0, _vue.ref)([]);
|
|
35
|
+
const isRunning = (0, _vue.ref)(false);
|
|
36
|
+
const currentOutput = (0, _vue.ref)("");
|
|
37
|
+
const toolCallCount = (0, _vue.ref)(0);
|
|
38
|
+
const addStep = step => {
|
|
39
|
+
steps.value.push({
|
|
40
|
+
...step,
|
|
41
|
+
id: `step-${Date.now()}-${Math.random().toString(36).slice(2)}`,
|
|
42
|
+
timestamp: /* @__PURE__ */new Date()
|
|
43
|
+
});
|
|
44
|
+
};
|
|
45
|
+
const checkStopConditions = output => {
|
|
46
|
+
for (const condition of stopConditions) {
|
|
47
|
+
switch (condition.type) {
|
|
48
|
+
case "contains":
|
|
49
|
+
if (condition.value && output.includes(condition.value)) {
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
break;
|
|
53
|
+
case "custom":
|
|
54
|
+
if (condition.value && condition.value(output)) {
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
break;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return false;
|
|
61
|
+
};
|
|
62
|
+
const executeTool = async (toolName, args) => {
|
|
63
|
+
const tool = tools.find(t => t.name === toolName);
|
|
64
|
+
if (!tool) {
|
|
65
|
+
throw new Error(`Tool not found: ${toolName}`);
|
|
66
|
+
}
|
|
67
|
+
addStep({
|
|
68
|
+
type: "action",
|
|
69
|
+
content: `Executing tool: ${toolName}`,
|
|
70
|
+
toolName,
|
|
71
|
+
toolInput: args
|
|
72
|
+
});
|
|
73
|
+
try {
|
|
74
|
+
const result = await tool.execute(args);
|
|
75
|
+
const resultStr = typeof result === "string" ? result : JSON.stringify(result);
|
|
76
|
+
addStep({
|
|
77
|
+
type: "observation",
|
|
78
|
+
content: resultStr,
|
|
79
|
+
toolName,
|
|
80
|
+
toolOutput: result
|
|
81
|
+
});
|
|
82
|
+
toolCallCount.value++;
|
|
83
|
+
return resultStr;
|
|
84
|
+
} catch (error) {
|
|
85
|
+
addStep({
|
|
86
|
+
type: "observation",
|
|
87
|
+
content: `Error: ${error instanceof Error ? error.message : String(error)}`,
|
|
88
|
+
toolName,
|
|
89
|
+
toolOutput: error
|
|
90
|
+
});
|
|
91
|
+
throw error;
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
const parseResponse = response => {
|
|
95
|
+
const thoughtMatch = response.match(/Thought:?\s*(.+)/i);
|
|
96
|
+
const actionMatch = response.match(/Action:?\s*(.+)/i);
|
|
97
|
+
const actionInputMatch = response.match(/Action Input:?\s*(.+)/i);
|
|
98
|
+
return {
|
|
99
|
+
thought: thoughtMatch ? thoughtMatch[1].trim() : response,
|
|
100
|
+
action: actionMatch ? actionMatch[1].trim() : void 0,
|
|
101
|
+
actionInput: actionInputMatch ? actionInputMatch[1].trim() : void 0
|
|
102
|
+
};
|
|
103
|
+
};
|
|
104
|
+
const run = async (input, executeFn) => {
|
|
105
|
+
if (isRunning.value) {
|
|
106
|
+
throw new Error("Agent is already running");
|
|
107
|
+
}
|
|
108
|
+
isRunning.value = true;
|
|
109
|
+
steps.value = [];
|
|
110
|
+
currentOutput.value = "";
|
|
111
|
+
toolCallCount.value = 0;
|
|
112
|
+
let iteration = 0;
|
|
113
|
+
let context = `Task: ${input}
|
|
114
|
+
|
|
115
|
+
`;
|
|
116
|
+
try {
|
|
117
|
+
while (iteration < maxIterations && toolCallCount.value < maxToolCalls) {
|
|
118
|
+
iteration++;
|
|
119
|
+
if (checkStopConditions(currentOutput.value)) {
|
|
120
|
+
break;
|
|
121
|
+
}
|
|
122
|
+
addStep({
|
|
123
|
+
type: "thought",
|
|
124
|
+
content: `Iteration ${iteration}: Thinking about how to proceed...`
|
|
125
|
+
});
|
|
126
|
+
const response = await executeFn(context);
|
|
127
|
+
const parsed = parseResponse(response);
|
|
128
|
+
currentOutput.value = parsed.thought;
|
|
129
|
+
if (parsed.action && parsed.actionInput) {
|
|
130
|
+
try {
|
|
131
|
+
const observation = await executeTool(parsed.action, JSON.parse(parsed.actionInput));
|
|
132
|
+
context += `Thought: ${parsed.thought}
|
|
133
|
+
Action: ${parsed.action}
|
|
134
|
+
Action Input: ${parsed.actionInput}
|
|
135
|
+
Observation: ${observation}
|
|
136
|
+
|
|
137
|
+
`;
|
|
138
|
+
} catch (error) {
|
|
139
|
+
context += `Thought: ${parsed.thought}
|
|
140
|
+
Action: ${parsed.action}
|
|
141
|
+
Action Input: ${parsed.actionInput}
|
|
142
|
+
Observation: Error - ${error instanceof Error ? error.message : String(error)}
|
|
143
|
+
|
|
144
|
+
`;
|
|
145
|
+
if (onError) {
|
|
146
|
+
await onError(error, steps.value[steps.value.length - 1]);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
} else {
|
|
150
|
+
addStep({
|
|
151
|
+
type: "result",
|
|
152
|
+
content: parsed.thought
|
|
153
|
+
});
|
|
154
|
+
break;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return {
|
|
158
|
+
output: currentOutput.value,
|
|
159
|
+
reasoning: returnReasoning ? steps.value : void 0,
|
|
160
|
+
toolCalls: toolCallCount.value,
|
|
161
|
+
finished: iteration >= maxIterations
|
|
162
|
+
};
|
|
163
|
+
} catch (error) {
|
|
164
|
+
return {
|
|
165
|
+
output: currentOutput.value,
|
|
166
|
+
reasoning: returnReasoning ? steps.value : void 0,
|
|
167
|
+
toolCalls: toolCallCount.value,
|
|
168
|
+
finished: false,
|
|
169
|
+
error: error instanceof Error ? error : new Error(String(error))
|
|
170
|
+
};
|
|
171
|
+
} finally {
|
|
172
|
+
isRunning.value = false;
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
return {
|
|
176
|
+
steps,
|
|
177
|
+
isRunning,
|
|
178
|
+
currentOutput,
|
|
179
|
+
toolCallCount,
|
|
180
|
+
run
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
function createPlanExecuteAgent(config) {
|
|
184
|
+
const {
|
|
185
|
+
tools = []
|
|
186
|
+
} = config;
|
|
187
|
+
const plans = (0, _vue.ref)([]);
|
|
188
|
+
const currentPlan = (0, _vue.ref)(null);
|
|
189
|
+
const results = (0, _vue.ref)({});
|
|
190
|
+
const executeTool = async (toolName, args) => {
|
|
191
|
+
const tool = tools.find(t => t.name === toolName);
|
|
192
|
+
if (!tool) {
|
|
193
|
+
throw new Error(`Tool not found: ${toolName}`);
|
|
194
|
+
}
|
|
195
|
+
return tool.execute(args);
|
|
196
|
+
};
|
|
197
|
+
const execute = async (task, llm) => {
|
|
198
|
+
const planPrompt = `\u5206\u89E3\u4EE5\u4E0B\u4EFB\u52A1\u4E3A\u591A\u4E2A\u53EF\u6267\u884C\u7684\u6B65\u9AA4\uFF0C\u8FD4\u56DE JSON \u6570\u7EC4\u683C\u5F0F\uFF1A
|
|
199
|
+
[{"step": "\u6B65\u9AA4\u63CF\u8FF0", "tool": "\u5DE5\u5177\u540D", "input": {"\u53C2\u6570": "\u503C"}}]
|
|
200
|
+
|
|
201
|
+
\u4EFB\u52A1: ${task}
|
|
202
|
+
|
|
203
|
+
\u53EF\u7528\u5DE5\u5177: ${tools.map(t => t.name).join(", ")}`;
|
|
204
|
+
const planResponse = await llm(planPrompt);
|
|
205
|
+
try {
|
|
206
|
+
const parsed = JSON.parse(planResponse.replace(/```json|```/g, "").trim());
|
|
207
|
+
plans.value = parsed.map((p, i) => ({
|
|
208
|
+
id: `plan-${i}`,
|
|
209
|
+
description: p.step,
|
|
210
|
+
status: "pending"
|
|
211
|
+
}));
|
|
212
|
+
} catch {
|
|
213
|
+
plans.value = [{
|
|
214
|
+
id: "plan-0",
|
|
215
|
+
description: planResponse,
|
|
216
|
+
status: "pending"
|
|
217
|
+
}];
|
|
218
|
+
}
|
|
219
|
+
for (const plan of plans.value) {
|
|
220
|
+
currentPlan.value = plan.id;
|
|
221
|
+
plan.status = "pending";
|
|
222
|
+
try {
|
|
223
|
+
const execPrompt = `\u6839\u636E\u5F53\u524D\u6B65\u9AA4\u751F\u6210\u5DE5\u5177\u8C03\u7528\uFF1A
|
|
224
|
+
|
|
225
|
+
\u6B65\u9AA4: ${plan.description}
|
|
226
|
+
\u4E0A\u4E0B\u6587: ${JSON.stringify(results.value)}
|
|
227
|
+
|
|
228
|
+
\u8FD4\u56DE\u683C\u5F0F: {"tool": "\u5DE5\u5177\u540D", "input": {"\u53C2\u6570": "\u503C"}}`;
|
|
229
|
+
const execResponse = await llm(execPrompt);
|
|
230
|
+
const exec = JSON.parse(execResponse.replace(/```json|```/g, "").trim());
|
|
231
|
+
if (exec.tool) {
|
|
232
|
+
const result = await executeTool(exec.tool, exec.input || {});
|
|
233
|
+
results.value[plan.id] = result;
|
|
234
|
+
plan.status = "completed";
|
|
235
|
+
} else {
|
|
236
|
+
results.value[plan.id] = execResponse;
|
|
237
|
+
plan.status = "completed";
|
|
238
|
+
}
|
|
239
|
+
} catch (error) {
|
|
240
|
+
plan.status = "failed";
|
|
241
|
+
results.value[plan.id] = {
|
|
242
|
+
error: error instanceof Error ? error.message : String(error)
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
const summaryPrompt = `\u6839\u636E\u4EE5\u4E0B\u6267\u884C\u7ED3\u679C\uFF0C\u7528\u81EA\u7136\u8BED\u8A00\u603B\u7ED3\u56DE\u7B54\u7528\u6237\uFF1A
|
|
247
|
+
|
|
248
|
+
\u4EFB\u52A1: ${task}
|
|
249
|
+
\u6267\u884C\u7ED3\u679C: ${JSON.stringify(results.value)}
|
|
250
|
+
|
|
251
|
+
\u8BF7\u7528\u4E2D\u6587\u56DE\u7B54\uFF1A`;
|
|
252
|
+
const finalResult = await llm(summaryPrompt);
|
|
253
|
+
return {
|
|
254
|
+
result: finalResult,
|
|
255
|
+
plan: plans.value,
|
|
256
|
+
results: results.value
|
|
257
|
+
};
|
|
258
|
+
};
|
|
259
|
+
return {
|
|
260
|
+
plans,
|
|
261
|
+
currentPlan,
|
|
262
|
+
results,
|
|
263
|
+
execute
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
function createMultiModalMessage(role, contents) {
|
|
267
|
+
return {
|
|
268
|
+
role,
|
|
269
|
+
content: contents
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
function createImageContent(source, value, mimeType) {
|
|
273
|
+
return {
|
|
274
|
+
type: "image",
|
|
275
|
+
...(source === "url" ? {
|
|
276
|
+
url: value
|
|
277
|
+
} : {
|
|
278
|
+
base64: value
|
|
279
|
+
}),
|
|
280
|
+
mimeType: mimeType || (source === "base64" ? "image/png" : void 0)
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
function createImageUrlContent(url, detail) {
|
|
284
|
+
return {
|
|
285
|
+
type: "image_url",
|
|
286
|
+
url,
|
|
287
|
+
mimeType: detail
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
function createAudioContent(base64, mimeType = "audio/m4a") {
|
|
291
|
+
return {
|
|
292
|
+
type: "audio",
|
|
293
|
+
base64,
|
|
294
|
+
mimeType
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
function createVideoContent(base64, mimeType = "video/mp4") {
|
|
298
|
+
return {
|
|
299
|
+
type: "video",
|
|
300
|
+
base64,
|
|
301
|
+
mimeType
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
function createRAGSystem(config) {
|
|
305
|
+
const {
|
|
306
|
+
knowledgeBaseId,
|
|
307
|
+
topK = 3,
|
|
308
|
+
similarityThreshold = 0.5,
|
|
309
|
+
includeSources = true,
|
|
310
|
+
strategy = "similarity"
|
|
311
|
+
} = config;
|
|
312
|
+
const vectorStore = /* @__PURE__ */new Map();
|
|
313
|
+
const addDocuments = async documents => {
|
|
314
|
+
const chunks = documents.map((doc, i) => ({
|
|
315
|
+
id: `chunk-${Date.now()}-${i}`,
|
|
316
|
+
content: doc.content,
|
|
317
|
+
metadata: doc.metadata || {},
|
|
318
|
+
// 简化:实际应该调用 embedding API
|
|
319
|
+
score: Math.random()
|
|
320
|
+
}));
|
|
321
|
+
if (knowledgeBaseId) {
|
|
322
|
+
const existing = vectorStore.get(knowledgeBaseId) || [];
|
|
323
|
+
vectorStore.set(knowledgeBaseId, [...existing, ...chunks]);
|
|
324
|
+
}
|
|
325
|
+
return chunks;
|
|
326
|
+
};
|
|
327
|
+
const retrieve = async (query2, k = topK) => {
|
|
328
|
+
if (!knowledgeBaseId) return [];
|
|
329
|
+
const chunks = vectorStore.get(knowledgeBaseId) || [];
|
|
330
|
+
const sorted = [...chunks].sort((a, b) => (b.score || 0) - (a.score || 0)).slice(0, k);
|
|
331
|
+
return sorted.filter(c => (c.score || 0) >= similarityThreshold);
|
|
332
|
+
};
|
|
333
|
+
const query = async (question, llm) => {
|
|
334
|
+
const relevantDocs = await retrieve(question);
|
|
335
|
+
if (relevantDocs.length === 0) {
|
|
336
|
+
return {
|
|
337
|
+
answer: "\u62B1\u6B49\uFF0C\u77E5\u8BC6\u5E93\u4E2D\u6CA1\u6709\u627E\u5230\u76F8\u5173\u4FE1\u606F\u3002",
|
|
338
|
+
sources: [],
|
|
339
|
+
contextUsed: ""
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
const context = relevantDocs.map((doc, i) => `[\u6587\u6863 ${i + 1}]
|
|
343
|
+
${doc.content}`).join("\n\n");
|
|
344
|
+
const prompt = `\u57FA\u4E8E\u4EE5\u4E0B\u77E5\u8BC6\u5E93\u5185\u5BB9\uFF0C\u7528\u4E2D\u6587\u56DE\u7B54\u7528\u6237\u7684\u95EE\u9898\u3002\u5982\u679C\u77E5\u8BC6\u5E93\u4E2D\u7684\u4FE1\u606F\u4E0D\u80FD\u56DE\u7B54\u95EE\u9898\uFF0C\u8BF7\u8BF4\u660E\u3002
|
|
345
|
+
|
|
346
|
+
\u77E5\u8BC6\u5E93\u5185\u5BB9:
|
|
347
|
+
${context}
|
|
348
|
+
|
|
349
|
+
\u7528\u6237\u95EE\u9898: ${question}
|
|
350
|
+
|
|
351
|
+
\u8BF7\u7ED9\u51FA\u56DE\u7B54\uFF1A`;
|
|
352
|
+
const answer = await llm(prompt);
|
|
353
|
+
return {
|
|
354
|
+
answer,
|
|
355
|
+
sources: includeSources ? relevantDocs.map(doc => ({
|
|
356
|
+
content: doc.content.slice(0, 200) + "...",
|
|
357
|
+
metadata: doc.metadata,
|
|
358
|
+
score: doc.score || 0
|
|
359
|
+
})) : [],
|
|
360
|
+
contextUsed: context.slice(0, 500)
|
|
361
|
+
};
|
|
362
|
+
};
|
|
363
|
+
const clear = () => {
|
|
364
|
+
if (knowledgeBaseId) {
|
|
365
|
+
vectorStore.delete(knowledgeBaseId);
|
|
366
|
+
}
|
|
367
|
+
};
|
|
368
|
+
return {
|
|
369
|
+
addDocuments,
|
|
370
|
+
retrieve,
|
|
371
|
+
query,
|
|
372
|
+
clear,
|
|
373
|
+
config: {
|
|
374
|
+
topK,
|
|
375
|
+
similarityThreshold,
|
|
376
|
+
strategy
|
|
377
|
+
}
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
function createChainOfThought(config = {
|
|
381
|
+
mode: "standard"
|
|
382
|
+
}) {
|
|
383
|
+
const {
|
|
384
|
+
mode = "standard",
|
|
385
|
+
maxDepth = 5,
|
|
386
|
+
showConfidence = false
|
|
387
|
+
} = config;
|
|
388
|
+
const reasoningSteps = (0, _vue.ref)([]);
|
|
389
|
+
const think = async (problem, llm) => {
|
|
390
|
+
reasoningSteps.value = [];
|
|
391
|
+
const prompt = mode === "standard" ? `\u9010\u6B65\u601D\u8003\u5E76\u7ED9\u51FA\u7B54\u6848\uFF1A${problem}` : mode === "chain" ? `\u6309\u6B65\u9AA4\u5206\u6790\uFF1A${problem}` : mode === "tree" ? `\u7528\u6811\u72B6\u7ED3\u6784\u5206\u6790\uFF1A${problem}` : `\u7528\u8868\u683C\u5F62\u5F0F\u5206\u6790\uFF1A${problem}`;
|
|
392
|
+
const response = await llm(prompt);
|
|
393
|
+
const lines = response.split("\n").filter(l => l.trim());
|
|
394
|
+
reasoningSteps.value = lines.map((line, i) => ({
|
|
395
|
+
id: `reason-${i}`,
|
|
396
|
+
content: line.replace(/^\d+[.)::、]\s*/, ""),
|
|
397
|
+
type: i === lines.length - 1 ? "conclusion" : "analysis"
|
|
398
|
+
}));
|
|
399
|
+
return {
|
|
400
|
+
result: response,
|
|
401
|
+
reasoning: reasoningSteps.value
|
|
402
|
+
};
|
|
403
|
+
};
|
|
404
|
+
const addStep = step => {
|
|
405
|
+
reasoningSteps.value.push({
|
|
406
|
+
...step,
|
|
407
|
+
id: `reason-${Date.now()}-${Math.random().toString(36).slice(2)}`
|
|
408
|
+
});
|
|
409
|
+
};
|
|
410
|
+
const clear = () => {
|
|
411
|
+
reasoningSteps.value = [];
|
|
412
|
+
};
|
|
413
|
+
return {
|
|
414
|
+
think,
|
|
415
|
+
addStep,
|
|
416
|
+
clear,
|
|
417
|
+
reasoningSteps,
|
|
418
|
+
config: {
|
|
419
|
+
mode,
|
|
420
|
+
maxDepth,
|
|
421
|
+
showConfidence
|
|
422
|
+
}
|
|
423
|
+
};
|
|
424
|
+
}
|
|
425
|
+
function createContextCompressor(config) {
|
|
426
|
+
const {
|
|
427
|
+
strategy = "summary",
|
|
428
|
+
targetTokens = 2e3,
|
|
429
|
+
preserveKeyInfo = []
|
|
430
|
+
} = config;
|
|
431
|
+
const estimateTokens = text => Math.ceil(text.length / 4);
|
|
432
|
+
const compress = async (content, llm) => {
|
|
433
|
+
const isArray = Array.isArray(content);
|
|
434
|
+
const text = isArray ? content.map(m => `${m.role}: ${m.content}`).join("\n") : content;
|
|
435
|
+
const originalTokens = estimateTokens(text);
|
|
436
|
+
if (originalTokens <= targetTokens) {
|
|
437
|
+
return {
|
|
438
|
+
compressedContent: text,
|
|
439
|
+
originalTokens,
|
|
440
|
+
compressedTokens: originalTokens,
|
|
441
|
+
compressionRatio: 1,
|
|
442
|
+
extractedKeyInfo: preserveKeyInfo
|
|
443
|
+
};
|
|
444
|
+
}
|
|
445
|
+
let compressed;
|
|
446
|
+
switch (strategy) {
|
|
447
|
+
case "summary":
|
|
448
|
+
{
|
|
449
|
+
if (!llm) {
|
|
450
|
+
const ratio = targetTokens / originalTokens;
|
|
451
|
+
compressed = text.slice(0, Math.floor(text.length * ratio));
|
|
452
|
+
} else {
|
|
453
|
+
const summaryPrompt = `\u5C06\u4EE5\u4E0B\u5185\u5BB9\u538B\u7F29\u5230\u7EA6 ${targetTokens} \u5B57\u7B26\uFF0C\u4FDD\u7559\u5173\u952E\u4FE1\u606F\uFF1A
|
|
454
|
+
|
|
455
|
+
${text}`;
|
|
456
|
+
compressed = await llm(summaryPrompt);
|
|
457
|
+
}
|
|
458
|
+
break;
|
|
459
|
+
}
|
|
460
|
+
case "extract":
|
|
461
|
+
{
|
|
462
|
+
const sentences = text.split(/[。!?\n]/).filter(s => s.trim());
|
|
463
|
+
const keySentences = sentences.slice(0, Math.floor(sentences.length * (targetTokens / originalTokens)));
|
|
464
|
+
compressed = keySentences.join("\u3002") + "\u3002";
|
|
465
|
+
break;
|
|
466
|
+
}
|
|
467
|
+
case "prune":
|
|
468
|
+
{
|
|
469
|
+
const lines = text.split("\n");
|
|
470
|
+
const seen = /* @__PURE__ */new Set();
|
|
471
|
+
const pruned = lines.filter(line => {
|
|
472
|
+
const key = line.slice(0, 50);
|
|
473
|
+
if (seen.has(key)) return false;
|
|
474
|
+
seen.add(key);
|
|
475
|
+
return true;
|
|
476
|
+
});
|
|
477
|
+
compressed = pruned.join("\n").slice(0, targetTokens * 4);
|
|
478
|
+
break;
|
|
479
|
+
}
|
|
480
|
+
default:
|
|
481
|
+
compressed = text.slice(0, targetTokens * 4);
|
|
482
|
+
}
|
|
483
|
+
const compressedTokens = estimateTokens(compressed);
|
|
484
|
+
return {
|
|
485
|
+
compressedContent: compressed,
|
|
486
|
+
originalTokens,
|
|
487
|
+
compressedTokens,
|
|
488
|
+
compressionRatio: compressedTokens / originalTokens,
|
|
489
|
+
extractedKeyInfo: preserveKeyInfo
|
|
490
|
+
};
|
|
491
|
+
};
|
|
492
|
+
return {
|
|
493
|
+
compress,
|
|
494
|
+
estimateTokens,
|
|
495
|
+
config: {
|
|
496
|
+
strategy,
|
|
497
|
+
targetTokens,
|
|
498
|
+
preserveKeyInfo
|
|
499
|
+
}
|
|
500
|
+
};
|
|
501
|
+
}
|
|
502
|
+
function createCostTracker(config = {}) {
|
|
503
|
+
const {
|
|
504
|
+
monthlyBudget = 100,
|
|
505
|
+
maxTokensPerRequest = 1e5,
|
|
506
|
+
warningThreshold = 0.8
|
|
507
|
+
} = config;
|
|
508
|
+
const dailyUsage = {};
|
|
509
|
+
const totalUsage = {
|
|
510
|
+
prompt: 0,
|
|
511
|
+
completion: 0,
|
|
512
|
+
total: 0
|
|
513
|
+
};
|
|
514
|
+
const PRICING = {
|
|
515
|
+
"gpt-4": {
|
|
516
|
+
prompt: 30,
|
|
517
|
+
completion: 60
|
|
518
|
+
},
|
|
519
|
+
"gpt-4-turbo": {
|
|
520
|
+
prompt: 10,
|
|
521
|
+
completion: 30
|
|
522
|
+
},
|
|
523
|
+
"gpt-3.5-turbo": {
|
|
524
|
+
prompt: 0.5,
|
|
525
|
+
completion: 1.5
|
|
526
|
+
},
|
|
527
|
+
"claude-3-opus": {
|
|
528
|
+
prompt: 15,
|
|
529
|
+
completion: 75
|
|
530
|
+
},
|
|
531
|
+
"claude-3-sonnet": {
|
|
532
|
+
prompt: 3,
|
|
533
|
+
completion: 15
|
|
534
|
+
},
|
|
535
|
+
"gemini-pro": {
|
|
536
|
+
prompt: 0.5,
|
|
537
|
+
completion: 1.5
|
|
538
|
+
}
|
|
539
|
+
};
|
|
540
|
+
const track = (usage, _model = "gpt-4") => {
|
|
541
|
+
const today = (/* @__PURE__ */new Date()).toISOString().split("T")[0];
|
|
542
|
+
if (!dailyUsage[today]) {
|
|
543
|
+
dailyUsage[today] = {
|
|
544
|
+
prompt: 0,
|
|
545
|
+
completion: 0
|
|
546
|
+
};
|
|
547
|
+
}
|
|
548
|
+
dailyUsage[today].prompt += usage.prompt;
|
|
549
|
+
dailyUsage[today].completion += usage.completion;
|
|
550
|
+
totalUsage.prompt += usage.prompt;
|
|
551
|
+
totalUsage.completion += usage.completion;
|
|
552
|
+
totalUsage.total += usage.prompt + usage.completion;
|
|
553
|
+
};
|
|
554
|
+
const calculateCost = (usage, model) => {
|
|
555
|
+
const pricing = PRICING[model] || PRICING["gpt-4"];
|
|
556
|
+
return pricing.prompt * usage.prompt / 1e6 + pricing.completion * usage.completion / 1e6;
|
|
557
|
+
};
|
|
558
|
+
const getStatus = () => {
|
|
559
|
+
const totalCost = calculateCost(totalUsage, "gpt-4");
|
|
560
|
+
const budgetRemaining = monthlyBudget - totalCost;
|
|
561
|
+
return {
|
|
562
|
+
totalCost,
|
|
563
|
+
dailyCost: Object.fromEntries(Object.entries(dailyUsage).map(([date, usage]) => [date, calculateCost({
|
|
564
|
+
prompt: usage.prompt,
|
|
565
|
+
completion: usage.completion,
|
|
566
|
+
total: 0
|
|
567
|
+
}, "gpt-4")])),
|
|
568
|
+
usage: {
|
|
569
|
+
...totalUsage
|
|
570
|
+
},
|
|
571
|
+
budget: {
|
|
572
|
+
monthlyBudget,
|
|
573
|
+
warningThreshold
|
|
574
|
+
},
|
|
575
|
+
remaining: budgetRemaining
|
|
576
|
+
};
|
|
577
|
+
};
|
|
578
|
+
const isOverBudget = () => {
|
|
579
|
+
const status = getStatus();
|
|
580
|
+
return status.remaining < 0;
|
|
581
|
+
};
|
|
582
|
+
const shouldWarn = () => {
|
|
583
|
+
const status = getStatus();
|
|
584
|
+
return status.totalCost >= monthlyBudget * warningThreshold;
|
|
585
|
+
};
|
|
586
|
+
const checkRequestLimit = tokens => {
|
|
587
|
+
if (tokens > maxTokensPerRequest) {
|
|
588
|
+
return {
|
|
589
|
+
allowed: false,
|
|
590
|
+
reason: `\u8BF7\u6C42 token \u6570 ${tokens} \u8D85\u8FC7\u9650\u5236 ${maxTokensPerRequest}`
|
|
591
|
+
};
|
|
592
|
+
}
|
|
593
|
+
const status = getStatus();
|
|
594
|
+
const estimatedCost = tokens / 1e6 * 30;
|
|
595
|
+
if (status.remaining - estimatedCost < 0) {
|
|
596
|
+
return {
|
|
597
|
+
allowed: false,
|
|
598
|
+
reason: "\u9884\u7B97\u4E0D\u8DB3"
|
|
599
|
+
};
|
|
600
|
+
}
|
|
601
|
+
return {
|
|
602
|
+
allowed: true
|
|
603
|
+
};
|
|
604
|
+
};
|
|
605
|
+
const reset = () => {
|
|
606
|
+
Object.keys(dailyUsage).forEach(key => delete dailyUsage[key]);
|
|
607
|
+
totalUsage.prompt = 0;
|
|
608
|
+
totalUsage.completion = 0;
|
|
609
|
+
totalUsage.total = 0;
|
|
610
|
+
};
|
|
611
|
+
return {
|
|
612
|
+
track,
|
|
613
|
+
calculateCost,
|
|
614
|
+
getStatus,
|
|
615
|
+
isOverBudget,
|
|
616
|
+
shouldWarn,
|
|
617
|
+
checkRequestLimit,
|
|
618
|
+
reset,
|
|
619
|
+
pricing: PRICING,
|
|
620
|
+
config: {
|
|
621
|
+
monthlyBudget,
|
|
622
|
+
maxTokensPerRequest,
|
|
623
|
+
warningThreshold
|
|
624
|
+
}
|
|
625
|
+
};
|
|
626
|
+
}
|
|
627
|
+
function createTracer() {
|
|
628
|
+
const spans = (0, _vue.ref)([]);
|
|
629
|
+
const events = (0, _vue.ref)([]);
|
|
630
|
+
const activeSpans = /* @__PURE__ */new Map();
|
|
631
|
+
const startSpan = (name, attributes = {}) => {
|
|
632
|
+
const id = `span-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
633
|
+
const span = {
|
|
634
|
+
id,
|
|
635
|
+
name,
|
|
636
|
+
startTime: /* @__PURE__ */new Date(),
|
|
637
|
+
events: [],
|
|
638
|
+
attributes,
|
|
639
|
+
children: []
|
|
640
|
+
};
|
|
641
|
+
spans.value.push(span);
|
|
642
|
+
activeSpans.set(id, span);
|
|
643
|
+
addEvent({
|
|
644
|
+
type: "custom",
|
|
645
|
+
data: {
|
|
646
|
+
action: "span_start",
|
|
647
|
+
name
|
|
648
|
+
}
|
|
649
|
+
});
|
|
650
|
+
return id;
|
|
651
|
+
};
|
|
652
|
+
const endSpan = (id, attributes = {}) => {
|
|
653
|
+
const span = activeSpans.get(id);
|
|
654
|
+
if (span) {
|
|
655
|
+
span.endTime = /* @__PURE__ */new Date();
|
|
656
|
+
span.attributes = {
|
|
657
|
+
...span.attributes,
|
|
658
|
+
...attributes
|
|
659
|
+
};
|
|
660
|
+
activeSpans.delete(id);
|
|
661
|
+
addEvent({
|
|
662
|
+
type: "custom",
|
|
663
|
+
data: {
|
|
664
|
+
action: "span_end",
|
|
665
|
+
name: span.name,
|
|
666
|
+
duration: span.endTime.getTime() - span.startTime.getTime()
|
|
667
|
+
}
|
|
668
|
+
});
|
|
669
|
+
}
|
|
670
|
+
};
|
|
671
|
+
const addEvent = event => {
|
|
672
|
+
events.value.push({
|
|
673
|
+
...event,
|
|
674
|
+
id: `event-${Date.now()}-${Math.random().toString(36).slice(2)}`,
|
|
675
|
+
timestamp: /* @__PURE__ */new Date()
|
|
676
|
+
});
|
|
677
|
+
};
|
|
678
|
+
const recordRequest = (config, spanId) => {
|
|
679
|
+
const event = {
|
|
680
|
+
id: `req-${Date.now()}`,
|
|
681
|
+
type: "request",
|
|
682
|
+
timestamp: /* @__PURE__ */new Date(),
|
|
683
|
+
data: config,
|
|
684
|
+
parentId: spanId
|
|
685
|
+
};
|
|
686
|
+
events.value.push(event);
|
|
687
|
+
};
|
|
688
|
+
const recordResponse = (response, duration, spanId) => {
|
|
689
|
+
const event = {
|
|
690
|
+
id: `res-${Date.now()}`,
|
|
691
|
+
type: "response",
|
|
692
|
+
timestamp: /* @__PURE__ */new Date(),
|
|
693
|
+
data: {
|
|
694
|
+
response,
|
|
695
|
+
duration
|
|
696
|
+
},
|
|
697
|
+
parentId: spanId
|
|
698
|
+
};
|
|
699
|
+
events.value.push(event);
|
|
700
|
+
};
|
|
701
|
+
const recordError = (error, context, spanId) => {
|
|
702
|
+
const event = {
|
|
703
|
+
id: `err-${Date.now()}`,
|
|
704
|
+
type: "error",
|
|
705
|
+
timestamp: /* @__PURE__ */new Date(),
|
|
706
|
+
data: {
|
|
707
|
+
message: error.message,
|
|
708
|
+
stack: error.stack,
|
|
709
|
+
...context
|
|
710
|
+
},
|
|
711
|
+
parentId: spanId
|
|
712
|
+
};
|
|
713
|
+
events.value.push(event);
|
|
714
|
+
};
|
|
715
|
+
const getEvents = () => events.value;
|
|
716
|
+
const getSpans = () => spans.value;
|
|
717
|
+
const clear = () => {
|
|
718
|
+
spans.value = [];
|
|
719
|
+
events.value = [];
|
|
720
|
+
activeSpans.clear();
|
|
721
|
+
};
|
|
722
|
+
const exportJSON = () => JSON.stringify({
|
|
723
|
+
spans: spans.value,
|
|
724
|
+
events: events.value
|
|
725
|
+
}, null, 2);
|
|
726
|
+
return {
|
|
727
|
+
startSpan,
|
|
728
|
+
endSpan,
|
|
729
|
+
addEvent,
|
|
730
|
+
recordRequest,
|
|
731
|
+
recordResponse,
|
|
732
|
+
recordError,
|
|
733
|
+
getEvents,
|
|
734
|
+
getSpans,
|
|
735
|
+
clear,
|
|
736
|
+
exportJSON
|
|
737
|
+
};
|
|
738
|
+
}
|
|
739
|
+
function createSafetyFilter(config) {
|
|
740
|
+
const {
|
|
741
|
+
rules = []
|
|
742
|
+
} = config;
|
|
743
|
+
const check = async content => {
|
|
744
|
+
const violations = [];
|
|
745
|
+
for (const rule of rules) {
|
|
746
|
+
let passed = true;
|
|
747
|
+
let replacedContent = content;
|
|
748
|
+
if (rule.pattern) {
|
|
749
|
+
const regex = typeof rule.pattern === "string" ? new RegExp(rule.pattern, "gi") : rule.pattern;
|
|
750
|
+
passed = !regex.test(content);
|
|
751
|
+
replacedContent = content.replace(regex, "***");
|
|
752
|
+
}
|
|
753
|
+
if (rule.customCheck && passed) {
|
|
754
|
+
passed = !(await rule.customCheck(content));
|
|
755
|
+
}
|
|
756
|
+
if (!passed) {
|
|
757
|
+
violations.push({
|
|
758
|
+
rule,
|
|
759
|
+
content,
|
|
760
|
+
action: rule.action === "replace" && replacedContent !== content ? "replaced" : rule.action === "block" ? "blocked" : "warned",
|
|
761
|
+
replacedContent: rule.action === "replace" ? replacedContent : void 0
|
|
762
|
+
});
|
|
763
|
+
if (rule.action === "block") {
|
|
764
|
+
break;
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
return {
|
|
769
|
+
passed: violations.length === 0 || violations.every(v => v.action !== "blocked"),
|
|
770
|
+
violations
|
|
771
|
+
};
|
|
772
|
+
};
|
|
773
|
+
const addRule = rule => {
|
|
774
|
+
rules.push(rule);
|
|
775
|
+
};
|
|
776
|
+
const removeRule = ruleId => {
|
|
777
|
+
const index = rules.findIndex(r => r.id === ruleId);
|
|
778
|
+
if (index > -1) {
|
|
779
|
+
rules.splice(index, 1);
|
|
780
|
+
}
|
|
781
|
+
};
|
|
782
|
+
const createPresetRules = type => {
|
|
783
|
+
const presets = {
|
|
784
|
+
strict: [{
|
|
785
|
+
id: "s1",
|
|
786
|
+
name: "\u653F\u6CBB\u654F\u611F",
|
|
787
|
+
type: "content_filter",
|
|
788
|
+
pattern: "\u653F\u6CBB|\u9886\u5BFC\u4EBA",
|
|
789
|
+
action: "block"
|
|
790
|
+
}, {
|
|
791
|
+
id: "s2",
|
|
792
|
+
name: "\u66B4\u529B\u5185\u5BB9",
|
|
793
|
+
type: "content_filter",
|
|
794
|
+
pattern: "\u66B4\u529B|\u8840\u8165",
|
|
795
|
+
action: "block"
|
|
796
|
+
}, {
|
|
797
|
+
id: "s3",
|
|
798
|
+
name: "\u6076\u610F\u8F6F\u4EF6",
|
|
799
|
+
type: "content_filter",
|
|
800
|
+
pattern: "\u75C5\u6BD2|\u6728\u9A6C",
|
|
801
|
+
action: "block"
|
|
802
|
+
}],
|
|
803
|
+
moderate: [{
|
|
804
|
+
id: "m1",
|
|
805
|
+
name: "\u653F\u6CBB\u654F\u611F",
|
|
806
|
+
type: "content_filter",
|
|
807
|
+
pattern: "\u653F\u6CBB|\u9886\u5BFC\u4EBA",
|
|
808
|
+
action: "warn"
|
|
809
|
+
}, {
|
|
810
|
+
id: "m2",
|
|
811
|
+
name: "\u66B4\u529B\u5185\u5BB9",
|
|
812
|
+
type: "content_filter",
|
|
813
|
+
pattern: "\u66B4\u529B|\u8840\u8165",
|
|
814
|
+
action: "warn"
|
|
815
|
+
}],
|
|
816
|
+
lenient: [{
|
|
817
|
+
id: "l1",
|
|
818
|
+
name: "\u6076\u610F\u5185\u5BB9",
|
|
819
|
+
type: "content_filter",
|
|
820
|
+
pattern: "\u75C5\u6BD2|\u6728\u9A6C",
|
|
821
|
+
action: "block"
|
|
822
|
+
}]
|
|
823
|
+
};
|
|
824
|
+
rules.push(...presets[type]);
|
|
825
|
+
};
|
|
826
|
+
return {
|
|
827
|
+
check,
|
|
828
|
+
addRule,
|
|
829
|
+
removeRule,
|
|
830
|
+
createPresetRules,
|
|
831
|
+
rules
|
|
832
|
+
};
|
|
833
|
+
}
|
|
834
|
+
function fromZodSchema(schema2) {
|
|
835
|
+
return {
|
|
836
|
+
type: "object",
|
|
837
|
+
schema: schema2,
|
|
838
|
+
toJSONSchema: () => schema2
|
|
839
|
+
};
|
|
840
|
+
}
|
|
841
|
+
function createJSONSchema(definition) {
|
|
842
|
+
return definition;
|
|
843
|
+
}
|
|
844
|
+
const schema = exports.schema = {
|
|
845
|
+
string: description => ({
|
|
846
|
+
type: "string",
|
|
847
|
+
description
|
|
848
|
+
}),
|
|
849
|
+
number: description => ({
|
|
850
|
+
type: "number",
|
|
851
|
+
description
|
|
852
|
+
}),
|
|
853
|
+
boolean: description => ({
|
|
854
|
+
type: "boolean",
|
|
855
|
+
description
|
|
856
|
+
}),
|
|
857
|
+
enum: (values, description) => ({
|
|
858
|
+
type: "string",
|
|
859
|
+
enum: values,
|
|
860
|
+
description
|
|
861
|
+
}),
|
|
862
|
+
array: items => ({
|
|
863
|
+
type: "array",
|
|
864
|
+
items
|
|
865
|
+
}),
|
|
866
|
+
object: (properties, required = []) => ({
|
|
867
|
+
type: "object",
|
|
868
|
+
properties,
|
|
869
|
+
required
|
|
870
|
+
})
|
|
871
|
+
};
|
|
872
|
+
function parseStructuredOutput(output, _schema) {
|
|
873
|
+
try {
|
|
874
|
+
const jsonMatch = output.match(/\{[\s\S]*\}/);
|
|
875
|
+
if (jsonMatch) {
|
|
876
|
+
return JSON.parse(jsonMatch[0]);
|
|
877
|
+
}
|
|
878
|
+
} catch {
|
|
879
|
+
return null;
|
|
880
|
+
}
|
|
881
|
+
return null;
|
|
882
|
+
}
|