@agents-eco/reasoning 0.1.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/LICENSE +21 -0
- package/README.md +365 -0
- package/dist/backends/huggingface.d.ts +75 -0
- package/dist/backends/huggingface.d.ts.map +1 -0
- package/dist/backends/huggingface.js +158 -0
- package/dist/backends/huggingface.js.map +1 -0
- package/dist/backends/openai.d.ts +24 -0
- package/dist/backends/openai.d.ts.map +1 -0
- package/dist/backends/openai.js +83 -0
- package/dist/backends/openai.js.map +1 -0
- package/dist/engine.d.ts +63 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +132 -0
- package/dist/engine.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/strategies/cot.d.ts +18 -0
- package/dist/strategies/cot.d.ts.map +1 -0
- package/dist/strategies/cot.js +198 -0
- package/dist/strategies/cot.js.map +1 -0
- package/dist/strategies/react.d.ts +21 -0
- package/dist/strategies/react.d.ts.map +1 -0
- package/dist/strategies/react.js +331 -0
- package/dist/strategies/react.js.map +1 -0
- package/dist/strategies/tot.d.ts +25 -0
- package/dist/strategies/tot.d.ts.map +1 -0
- package/dist/strategies/tot.js +274 -0
- package/dist/strategies/tot.js.map +1 -0
- package/dist/types.d.ts +162 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/package.json +52 -0
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
const REACT_SYSTEM_SUFFIX = `
|
|
3
|
+
|
|
4
|
+
You are a reasoning agent that solves tasks step by step using the ReAct framework.
|
|
5
|
+
|
|
6
|
+
For each step, you MUST follow this format exactly:
|
|
7
|
+
|
|
8
|
+
Thought: <your reasoning about what to do next>
|
|
9
|
+
Action: <tool_name>
|
|
10
|
+
Action Input: <JSON arguments for the tool>
|
|
11
|
+
|
|
12
|
+
After receiving an observation, continue reasoning.
|
|
13
|
+
|
|
14
|
+
When you have enough information to answer, respond with:
|
|
15
|
+
|
|
16
|
+
Thought: <final reasoning>
|
|
17
|
+
Answer: <your final answer>
|
|
18
|
+
|
|
19
|
+
Rules:
|
|
20
|
+
- Always think before acting.
|
|
21
|
+
- Use tools when you need external information or computation.
|
|
22
|
+
- If a tool call fails, reflect on why and try a different approach.
|
|
23
|
+
- Be concise but thorough in your reasoning.
|
|
24
|
+
- If you are unsure, state your uncertainty.
|
|
25
|
+
`;
|
|
26
|
+
const REFLECTION_PROMPT = `
|
|
27
|
+
Reflect on your progress so far. Consider:
|
|
28
|
+
1. What have you learned from the steps taken?
|
|
29
|
+
2. Are you on the right track to solve the task?
|
|
30
|
+
3. What should you do differently?
|
|
31
|
+
4. How confident are you in your current approach?
|
|
32
|
+
|
|
33
|
+
Provide a brief reflection.
|
|
34
|
+
`;
|
|
35
|
+
const PLAN_PROMPT = `
|
|
36
|
+
Based on the task and your progress so far, create or revise your plan.
|
|
37
|
+
List the remaining steps needed to solve the task.
|
|
38
|
+
Be specific and actionable.
|
|
39
|
+
`;
|
|
40
|
+
/**
|
|
41
|
+
* ReAct (Reason + Act) strategy.
|
|
42
|
+
*
|
|
43
|
+
* Implements the multi-step reasoning loop from SmolAgents / Yao et al. 2022.
|
|
44
|
+
* Each step: Thought -> Action -> Observation, with optional reflection and planning.
|
|
45
|
+
*/
|
|
46
|
+
export class ReActStrategy {
|
|
47
|
+
name = "react";
|
|
48
|
+
async reason(task, systemPrompt, tools, config, backend) {
|
|
49
|
+
const startTime = Date.now();
|
|
50
|
+
const steps = [];
|
|
51
|
+
let totalPromptTokens = 0;
|
|
52
|
+
let totalCompletionTokens = 0;
|
|
53
|
+
let llmCalls = 0;
|
|
54
|
+
let toolCallCount = 0;
|
|
55
|
+
// Build system message
|
|
56
|
+
const fullSystemPrompt = systemPrompt + REACT_SYSTEM_SUFFIX + this.buildToolDescriptions(tools);
|
|
57
|
+
const messages = [
|
|
58
|
+
{ role: "system", content: fullSystemPrompt },
|
|
59
|
+
{ role: "user", content: task },
|
|
60
|
+
];
|
|
61
|
+
// Optional initial planning step
|
|
62
|
+
if (config.planning) {
|
|
63
|
+
const planStep = await this.planStep(messages, backend, config, steps.length);
|
|
64
|
+
if (planStep) {
|
|
65
|
+
steps.push(planStep);
|
|
66
|
+
messages.push({ role: "assistant", content: `Plan: ${planStep.content}` });
|
|
67
|
+
totalPromptTokens += planStep.tokens?.prompt ?? 0;
|
|
68
|
+
totalCompletionTokens += planStep.tokens?.completion ?? 0;
|
|
69
|
+
llmCalls++;
|
|
70
|
+
await config.hooks?.onPlan?.(planStep.content);
|
|
71
|
+
await config.hooks?.onStep?.(planStep);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
// ReAct loop
|
|
75
|
+
for (let i = 0; i < config.maxSteps; i++) {
|
|
76
|
+
const stepStart = Date.now();
|
|
77
|
+
// Get LLM completion
|
|
78
|
+
let response;
|
|
79
|
+
try {
|
|
80
|
+
response = await backend.complete(messages, {
|
|
81
|
+
temperature: config.temperature ?? 0.3,
|
|
82
|
+
maxTokens: 2048,
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
catch (err) {
|
|
86
|
+
const errorStep = this.makeStep(steps.length, "error", `LLM call failed: ${err}`, 0, stepStart);
|
|
87
|
+
steps.push(errorStep);
|
|
88
|
+
await config.hooks?.onError?.(err instanceof Error ? err : new Error(String(err)));
|
|
89
|
+
break;
|
|
90
|
+
}
|
|
91
|
+
llmCalls++;
|
|
92
|
+
totalPromptTokens += response.tokens?.prompt ?? 0;
|
|
93
|
+
totalCompletionTokens += response.tokens?.completion ?? 0;
|
|
94
|
+
const parsed = this.parseResponse(response.content);
|
|
95
|
+
// Handle final answer
|
|
96
|
+
if (parsed.answer) {
|
|
97
|
+
const answerStep = this.makeStep(steps.length, "answer", parsed.answer, 0.9, stepStart);
|
|
98
|
+
if (parsed.thought) {
|
|
99
|
+
const thoughtStep = this.makeStep(steps.length, "thought", parsed.thought, 0.7, stepStart);
|
|
100
|
+
steps.push(thoughtStep);
|
|
101
|
+
await config.hooks?.onThought?.(parsed.thought);
|
|
102
|
+
await config.hooks?.onStep?.(thoughtStep);
|
|
103
|
+
}
|
|
104
|
+
steps.push(answerStep);
|
|
105
|
+
messages.push({ role: "assistant", content: response.content });
|
|
106
|
+
await config.hooks?.onAnswer?.(parsed.answer);
|
|
107
|
+
await config.hooks?.onStep?.(answerStep);
|
|
108
|
+
return this.buildResult(parsed.answer, steps, startTime, totalPromptTokens, totalCompletionTokens, llmCalls, toolCallCount, true);
|
|
109
|
+
}
|
|
110
|
+
// Handle thought
|
|
111
|
+
if (parsed.thought) {
|
|
112
|
+
const thoughtStep = this.makeStep(steps.length, "thought", parsed.thought, 0.7, stepStart);
|
|
113
|
+
steps.push(thoughtStep);
|
|
114
|
+
await config.hooks?.onThought?.(parsed.thought);
|
|
115
|
+
await config.hooks?.onStep?.(thoughtStep);
|
|
116
|
+
if (config.verbose) {
|
|
117
|
+
console.log(`[Step ${steps.length}] Thought: ${parsed.thought}`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
// Handle action (tool call)
|
|
121
|
+
if (parsed.action && parsed.actionInput) {
|
|
122
|
+
const actionStep = this.makeStep(steps.length, "action", `${parsed.action}(${JSON.stringify(parsed.actionInput)})`, 0.7, stepStart, [{ name: parsed.action, arguments: parsed.actionInput }]);
|
|
123
|
+
steps.push(actionStep);
|
|
124
|
+
await config.hooks?.onAction?.(parsed.action, parsed.actionInput);
|
|
125
|
+
await config.hooks?.onStep?.(actionStep);
|
|
126
|
+
if (config.verbose) {
|
|
127
|
+
console.log(`[Step ${steps.length}] Action: ${parsed.action}(${JSON.stringify(parsed.actionInput)})`);
|
|
128
|
+
}
|
|
129
|
+
// Execute tool
|
|
130
|
+
const toolEntry = tools.get(parsed.action);
|
|
131
|
+
let observation;
|
|
132
|
+
let toolSuccess = true;
|
|
133
|
+
if (!toolEntry) {
|
|
134
|
+
observation = `Error: Tool '${parsed.action}' not found. Available tools: ${Array.from(tools.keys()).join(", ")}`;
|
|
135
|
+
toolSuccess = false;
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
try {
|
|
139
|
+
observation = await toolEntry.handler(parsed.actionInput);
|
|
140
|
+
toolCallCount++;
|
|
141
|
+
}
|
|
142
|
+
catch (err) {
|
|
143
|
+
observation = `Error executing tool '${parsed.action}': ${err}`;
|
|
144
|
+
toolSuccess = false;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
// Record observation
|
|
148
|
+
const obsStep = this.makeStep(steps.length, "observation", observation, toolSuccess ? 0.8 : 0.3, stepStart);
|
|
149
|
+
obsStep.toolResults = [{ name: parsed.action, content: observation, success: toolSuccess }];
|
|
150
|
+
steps.push(obsStep);
|
|
151
|
+
await config.hooks?.onObservation?.(observation);
|
|
152
|
+
await config.hooks?.onStep?.(obsStep);
|
|
153
|
+
if (config.verbose) {
|
|
154
|
+
console.log(`[Step ${steps.length}] Observation: ${observation.slice(0, 200)}`);
|
|
155
|
+
}
|
|
156
|
+
// Add to messages
|
|
157
|
+
messages.push({ role: "assistant", content: response.content });
|
|
158
|
+
messages.push({ role: "user", content: `Observation: ${observation}` });
|
|
159
|
+
}
|
|
160
|
+
else if (!parsed.answer) {
|
|
161
|
+
// No action and no answer — LLM gave unstructured response
|
|
162
|
+
messages.push({ role: "assistant", content: response.content });
|
|
163
|
+
messages.push({
|
|
164
|
+
role: "user",
|
|
165
|
+
content: "Please follow the format: Thought/Action/Action Input or Thought/Answer.",
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
// Optional reflection
|
|
169
|
+
if (config.reflection && (i + 1) % 3 === 0) {
|
|
170
|
+
const reflectionStep = await this.reflectStep(messages, backend, config, steps.length);
|
|
171
|
+
if (reflectionStep) {
|
|
172
|
+
steps.push(reflectionStep);
|
|
173
|
+
messages.push({ role: "assistant", content: `Reflection: ${reflectionStep.content}` });
|
|
174
|
+
totalPromptTokens += reflectionStep.tokens?.prompt ?? 0;
|
|
175
|
+
totalCompletionTokens += reflectionStep.tokens?.completion ?? 0;
|
|
176
|
+
llmCalls++;
|
|
177
|
+
await config.hooks?.onReflection?.(reflectionStep.content);
|
|
178
|
+
await config.hooks?.onStep?.(reflectionStep);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
// Optional plan revision
|
|
182
|
+
if (config.planning && config.planInterval && (i + 1) % config.planInterval === 0) {
|
|
183
|
+
const planStep = await this.planStep(messages, backend, config, steps.length);
|
|
184
|
+
if (planStep) {
|
|
185
|
+
steps.push(planStep);
|
|
186
|
+
messages.push({ role: "assistant", content: `Revised Plan: ${planStep.content}` });
|
|
187
|
+
totalPromptTokens += planStep.tokens?.prompt ?? 0;
|
|
188
|
+
totalCompletionTokens += planStep.tokens?.completion ?? 0;
|
|
189
|
+
llmCalls++;
|
|
190
|
+
await config.hooks?.onPlan?.(planStep.content);
|
|
191
|
+
await config.hooks?.onStep?.(planStep);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
// Max steps reached — force a final answer
|
|
196
|
+
messages.push({
|
|
197
|
+
role: "user",
|
|
198
|
+
content: "You have reached the maximum number of steps. Please provide your best answer now based on what you have learned.",
|
|
199
|
+
});
|
|
200
|
+
try {
|
|
201
|
+
const finalResponse = await backend.complete(messages, { temperature: 0.2, maxTokens: 1024 });
|
|
202
|
+
llmCalls++;
|
|
203
|
+
totalPromptTokens += finalResponse.tokens?.prompt ?? 0;
|
|
204
|
+
totalCompletionTokens += finalResponse.tokens?.completion ?? 0;
|
|
205
|
+
const parsed = this.parseResponse(finalResponse.content);
|
|
206
|
+
const answer = parsed.answer || finalResponse.content;
|
|
207
|
+
const answerStep = this.makeStep(steps.length, "answer", answer, 0.5, Date.now());
|
|
208
|
+
steps.push(answerStep);
|
|
209
|
+
return this.buildResult(answer, steps, startTime, totalPromptTokens, totalCompletionTokens, llmCalls, toolCallCount, true);
|
|
210
|
+
}
|
|
211
|
+
catch {
|
|
212
|
+
return this.buildResult("Failed to produce a final answer within the step limit.", steps, startTime, totalPromptTokens, totalCompletionTokens, llmCalls, toolCallCount, false);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
// ── Helpers ─────────────────────────────────────────
|
|
216
|
+
parseResponse(content) {
|
|
217
|
+
const result = {};
|
|
218
|
+
// Extract Thought
|
|
219
|
+
const thoughtMatch = content.match(/Thought:\s*([\s\S]*?)(?=\n(?:Action|Answer):|$)/i);
|
|
220
|
+
if (thoughtMatch)
|
|
221
|
+
result.thought = thoughtMatch[1].trim();
|
|
222
|
+
// Extract Answer
|
|
223
|
+
const answerMatch = content.match(/Answer:\s*([\s\S]*?)$/i);
|
|
224
|
+
if (answerMatch) {
|
|
225
|
+
result.answer = answerMatch[1].trim();
|
|
226
|
+
return result;
|
|
227
|
+
}
|
|
228
|
+
// Extract Action
|
|
229
|
+
const actionMatch = content.match(/Action:\s*(\S+)/i);
|
|
230
|
+
if (actionMatch)
|
|
231
|
+
result.action = actionMatch[1].trim();
|
|
232
|
+
// Extract Action Input
|
|
233
|
+
const inputMatch = content.match(/Action Input:\s*([\s\S]*?)(?=\n(?:Thought|Action|Answer):|$)/i);
|
|
234
|
+
if (inputMatch) {
|
|
235
|
+
try {
|
|
236
|
+
result.actionInput = JSON.parse(inputMatch[1].trim());
|
|
237
|
+
}
|
|
238
|
+
catch {
|
|
239
|
+
// Try to parse as key-value if not valid JSON
|
|
240
|
+
result.actionInput = { input: inputMatch[1].trim() };
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
return result;
|
|
244
|
+
}
|
|
245
|
+
buildToolDescriptions(tools) {
|
|
246
|
+
if (tools.size === 0)
|
|
247
|
+
return "\n\nYou have no tools available. Reason through the problem using your knowledge.";
|
|
248
|
+
const lines = ["\n\nAvailable tools:"];
|
|
249
|
+
for (const [name, { def }] of tools) {
|
|
250
|
+
lines.push(`- ${name}: ${def.description}`);
|
|
251
|
+
if (def.parameters && Object.keys(def.parameters).length > 0) {
|
|
252
|
+
lines.push(` Parameters: ${JSON.stringify(def.parameters)}`);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
return lines.join("\n");
|
|
256
|
+
}
|
|
257
|
+
async reflectStep(messages, backend, config, index) {
|
|
258
|
+
const start = Date.now();
|
|
259
|
+
try {
|
|
260
|
+
const reflectionMessages = [
|
|
261
|
+
...messages,
|
|
262
|
+
{ role: "user", content: REFLECTION_PROMPT },
|
|
263
|
+
];
|
|
264
|
+
const response = await backend.complete(reflectionMessages, { temperature: 0.4, maxTokens: 512 });
|
|
265
|
+
return {
|
|
266
|
+
id: randomUUID(),
|
|
267
|
+
index,
|
|
268
|
+
type: "reflection",
|
|
269
|
+
content: response.content,
|
|
270
|
+
confidence: 0.6,
|
|
271
|
+
durationMs: Date.now() - start,
|
|
272
|
+
tokens: response.tokens,
|
|
273
|
+
timestamp: new Date().toISOString(),
|
|
274
|
+
metadata: {},
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
catch {
|
|
278
|
+
return null;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
async planStep(messages, backend, config, index) {
|
|
282
|
+
const start = Date.now();
|
|
283
|
+
try {
|
|
284
|
+
const planMessages = [
|
|
285
|
+
...messages,
|
|
286
|
+
{ role: "user", content: PLAN_PROMPT },
|
|
287
|
+
];
|
|
288
|
+
const response = await backend.complete(planMessages, { temperature: 0.3, maxTokens: 512 });
|
|
289
|
+
return {
|
|
290
|
+
id: randomUUID(),
|
|
291
|
+
index,
|
|
292
|
+
type: "plan",
|
|
293
|
+
content: response.content,
|
|
294
|
+
confidence: 0.7,
|
|
295
|
+
durationMs: Date.now() - start,
|
|
296
|
+
tokens: response.tokens,
|
|
297
|
+
timestamp: new Date().toISOString(),
|
|
298
|
+
metadata: {},
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
catch {
|
|
302
|
+
return null;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
makeStep(index, type, content, confidence, startTime, toolCalls) {
|
|
306
|
+
return {
|
|
307
|
+
id: randomUUID(),
|
|
308
|
+
index,
|
|
309
|
+
type,
|
|
310
|
+
content,
|
|
311
|
+
confidence,
|
|
312
|
+
toolCalls,
|
|
313
|
+
durationMs: Date.now() - startTime,
|
|
314
|
+
timestamp: new Date().toISOString(),
|
|
315
|
+
metadata: {},
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
buildResult(answer, steps, startTime, promptTokens, completionTokens, llmCalls, toolCalls, success) {
|
|
319
|
+
return {
|
|
320
|
+
answer,
|
|
321
|
+
steps,
|
|
322
|
+
strategy: "react",
|
|
323
|
+
durationMs: Date.now() - startTime,
|
|
324
|
+
tokens: { prompt: promptTokens, completion: completionTokens, total: promptTokens + completionTokens },
|
|
325
|
+
llmCalls,
|
|
326
|
+
toolCalls,
|
|
327
|
+
success,
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
//# sourceMappingURL=react.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"react.js","sourceRoot":"","sources":["../../src/strategies/react.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { ReasoningStrategy, ReasoningConfig, ReasoningResult, ToolDef, ToolHandler, LLMBackend } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Tree-of-Thought (ToT) strategy.
|
|
4
|
+
*
|
|
5
|
+
* Explores multiple reasoning paths in a tree structure.
|
|
6
|
+
* Uses beam search to keep the top-k most promising branches.
|
|
7
|
+
* Each branch is scored by the LLM or a heuristic.
|
|
8
|
+
*/
|
|
9
|
+
export declare class TreeOfThoughtStrategy implements ReasoningStrategy {
|
|
10
|
+
readonly name: "tot";
|
|
11
|
+
reason(task: string, systemPrompt: string, tools: Map<string, {
|
|
12
|
+
def: ToolDef;
|
|
13
|
+
handler: ToolHandler;
|
|
14
|
+
}>, config: ReasoningConfig, backend: LLMBackend): Promise<ReasoningResult>;
|
|
15
|
+
private generateBranches;
|
|
16
|
+
private llmScore;
|
|
17
|
+
private heuristicScore;
|
|
18
|
+
private wordOverlap;
|
|
19
|
+
private solve;
|
|
20
|
+
private getPath;
|
|
21
|
+
private findBranch;
|
|
22
|
+
private findBranchById;
|
|
23
|
+
private buildResult;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=tot.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tot.d.ts","sourceRoot":"","sources":["../../src/strategies/tot.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,iBAAiB,EACjB,eAAe,EACf,eAAe,EAIf,OAAO,EACP,WAAW,EACX,UAAU,EAEX,MAAM,aAAa,CAAC;AA0BrB;;;;;;GAMG;AACH,qBAAa,qBAAsB,YAAW,iBAAiB;IAC7D,QAAQ,CAAC,IAAI,EAAG,KAAK,CAAU;IAEzB,MAAM,CACV,IAAI,EAAE,MAAM,EACZ,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE;QAAE,GAAG,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,WAAW,CAAA;KAAE,CAAC,EAC1D,MAAM,EAAE,eAAe,EACvB,OAAO,EAAE,UAAU,GAClB,OAAO,CAAC,eAAe,CAAC;YA4Hb,gBAAgB;YA2ChB,QAAQ;IAoBtB,OAAO,CAAC,cAAc;IAyBtB,OAAO,CAAC,WAAW;YAYL,KAAK;IA0BnB,OAAO,CAAC,OAAO;IAOf,OAAO,CAAC,UAAU;IAUlB,OAAO,CAAC,cAAc;IAStB,OAAO,CAAC,WAAW;CAoBpB"}
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
const TOT_GENERATE_PROMPT = `Given the problem and the current reasoning path, generate {branchFactor} distinct next reasoning steps.
|
|
3
|
+
Each step should explore a different approach or angle.
|
|
4
|
+
|
|
5
|
+
Format each as:
|
|
6
|
+
Option 1: <reasoning step>
|
|
7
|
+
Option 2: <reasoning step>
|
|
8
|
+
...
|
|
9
|
+
|
|
10
|
+
Be creative and consider diverse approaches.`;
|
|
11
|
+
const TOT_EVALUATE_PROMPT = `Evaluate the following reasoning step on a scale of 0.0 to 1.0.
|
|
12
|
+
Consider: logical soundness, relevance to the problem, likelihood of leading to a correct answer, and novelty.
|
|
13
|
+
|
|
14
|
+
Reasoning step: {thought}
|
|
15
|
+
|
|
16
|
+
Respond with only a number between 0.0 and 1.0.`;
|
|
17
|
+
const TOT_SOLVE_PROMPT = `Based on the following reasoning path, provide a final answer.
|
|
18
|
+
|
|
19
|
+
Reasoning path:
|
|
20
|
+
{path}
|
|
21
|
+
|
|
22
|
+
Final Answer:`;
|
|
23
|
+
/**
|
|
24
|
+
* Tree-of-Thought (ToT) strategy.
|
|
25
|
+
*
|
|
26
|
+
* Explores multiple reasoning paths in a tree structure.
|
|
27
|
+
* Uses beam search to keep the top-k most promising branches.
|
|
28
|
+
* Each branch is scored by the LLM or a heuristic.
|
|
29
|
+
*/
|
|
30
|
+
export class TreeOfThoughtStrategy {
|
|
31
|
+
name = "tot";
|
|
32
|
+
async reason(task, systemPrompt, tools, config, backend) {
|
|
33
|
+
const startTime = Date.now();
|
|
34
|
+
const steps = [];
|
|
35
|
+
let totalPromptTokens = 0;
|
|
36
|
+
let totalCompletionTokens = 0;
|
|
37
|
+
let llmCalls = 0;
|
|
38
|
+
const totConfig = config;
|
|
39
|
+
const branchFactor = totConfig.branchFactor ?? 3;
|
|
40
|
+
const maxDepth = totConfig.maxDepth ?? 4;
|
|
41
|
+
const beamWidth = totConfig.beamWidth ?? 2;
|
|
42
|
+
// Root node
|
|
43
|
+
const root = {
|
|
44
|
+
id: randomUUID(),
|
|
45
|
+
thought: task,
|
|
46
|
+
score: 1.0,
|
|
47
|
+
depth: 0,
|
|
48
|
+
children: [],
|
|
49
|
+
isTerminal: false,
|
|
50
|
+
};
|
|
51
|
+
// Beam search
|
|
52
|
+
let currentBeam = [root];
|
|
53
|
+
for (let depth = 1; depth <= maxDepth; depth++) {
|
|
54
|
+
const allCandidates = [];
|
|
55
|
+
for (const parent of currentBeam) {
|
|
56
|
+
// Generate branches
|
|
57
|
+
const path = this.getPath(root, parent.id);
|
|
58
|
+
const branches = await this.generateBranches(task, systemPrompt, path, branchFactor, backend);
|
|
59
|
+
llmCalls++;
|
|
60
|
+
totalPromptTokens += branches.tokens.prompt;
|
|
61
|
+
totalCompletionTokens += branches.tokens.completion;
|
|
62
|
+
// Score each branch
|
|
63
|
+
for (const thought of branches.thoughts) {
|
|
64
|
+
let score;
|
|
65
|
+
if (totConfig.scoringMethod === "heuristic") {
|
|
66
|
+
score = this.heuristicScore(thought, path);
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
const scoreResult = await this.llmScore(thought, backend);
|
|
70
|
+
score = scoreResult.score;
|
|
71
|
+
llmCalls++;
|
|
72
|
+
totalPromptTokens += scoreResult.tokens.prompt;
|
|
73
|
+
totalCompletionTokens += scoreResult.tokens.completion;
|
|
74
|
+
}
|
|
75
|
+
const branch = {
|
|
76
|
+
id: randomUUID(),
|
|
77
|
+
parentId: parent.id,
|
|
78
|
+
thought,
|
|
79
|
+
score,
|
|
80
|
+
depth,
|
|
81
|
+
children: [],
|
|
82
|
+
isTerminal: depth === maxDepth,
|
|
83
|
+
};
|
|
84
|
+
parent.children.push(branch);
|
|
85
|
+
allCandidates.push(branch);
|
|
86
|
+
// Record step
|
|
87
|
+
const step = {
|
|
88
|
+
id: randomUUID(),
|
|
89
|
+
index: steps.length,
|
|
90
|
+
type: "thought",
|
|
91
|
+
content: `[Depth ${depth}, Score ${score.toFixed(2)}] ${thought}`,
|
|
92
|
+
confidence: score,
|
|
93
|
+
durationMs: 0,
|
|
94
|
+
timestamp: new Date().toISOString(),
|
|
95
|
+
metadata: { depth, branchId: branch.id, parentId: parent.id },
|
|
96
|
+
};
|
|
97
|
+
steps.push(step);
|
|
98
|
+
await config.hooks?.onThought?.(thought);
|
|
99
|
+
await config.hooks?.onStep?.(step);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
// Beam selection: keep top-k branches
|
|
103
|
+
allCandidates.sort((a, b) => b.score - a.score);
|
|
104
|
+
currentBeam = allCandidates.slice(0, beamWidth);
|
|
105
|
+
if (config.verbose) {
|
|
106
|
+
console.log(`[ToT Depth ${depth}] ${allCandidates.length} candidates, kept top ${beamWidth}`);
|
|
107
|
+
for (const b of currentBeam) {
|
|
108
|
+
console.log(` Score ${b.score.toFixed(2)}: ${b.thought.slice(0, 80)}`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
// Get the best terminal branch and solve
|
|
113
|
+
const bestBranch = currentBeam[0];
|
|
114
|
+
if (!bestBranch) {
|
|
115
|
+
return this.buildResult("Unable to find a solution.", steps, startTime, totalPromptTokens, totalCompletionTokens, llmCalls, false);
|
|
116
|
+
}
|
|
117
|
+
const bestPath = this.getPath(root, bestBranch.id);
|
|
118
|
+
const solveResult = await this.solve(task, systemPrompt, bestPath, backend);
|
|
119
|
+
llmCalls++;
|
|
120
|
+
totalPromptTokens += solveResult.tokens.prompt;
|
|
121
|
+
totalCompletionTokens += solveResult.tokens.completion;
|
|
122
|
+
const answerStep = {
|
|
123
|
+
id: randomUUID(),
|
|
124
|
+
index: steps.length,
|
|
125
|
+
type: "answer",
|
|
126
|
+
content: solveResult.answer,
|
|
127
|
+
confidence: bestBranch.score,
|
|
128
|
+
durationMs: Date.now() - startTime,
|
|
129
|
+
timestamp: new Date().toISOString(),
|
|
130
|
+
metadata: { bestBranchId: bestBranch.id, pathLength: bestPath.length },
|
|
131
|
+
};
|
|
132
|
+
steps.push(answerStep);
|
|
133
|
+
await config.hooks?.onAnswer?.(solveResult.answer);
|
|
134
|
+
await config.hooks?.onStep?.(answerStep);
|
|
135
|
+
return this.buildResult(solveResult.answer, steps, startTime, totalPromptTokens, totalCompletionTokens, llmCalls, true);
|
|
136
|
+
}
|
|
137
|
+
// ── Branch Generation ───────────────────────────────
|
|
138
|
+
async generateBranches(task, systemPrompt, path, branchFactor, backend) {
|
|
139
|
+
const pathStr = path.length > 0
|
|
140
|
+
? `Current reasoning path:\n${path.map((p, i) => `${i + 1}. ${p}`).join("\n")}\n\n`
|
|
141
|
+
: "";
|
|
142
|
+
const prompt = TOT_GENERATE_PROMPT.replace("{branchFactor}", String(branchFactor));
|
|
143
|
+
const messages = [
|
|
144
|
+
{ role: "system", content: systemPrompt },
|
|
145
|
+
{ role: "user", content: `Problem: ${task}\n\n${pathStr}${prompt}` },
|
|
146
|
+
];
|
|
147
|
+
const response = await backend.complete(messages, { temperature: 0.8, maxTokens: 1024 });
|
|
148
|
+
// Parse options
|
|
149
|
+
const thoughts = [];
|
|
150
|
+
const optionPattern = /Option\s+\d+:\s*([\s\S]*?)(?=Option\s+\d+:|$)/gi;
|
|
151
|
+
let match;
|
|
152
|
+
while ((match = optionPattern.exec(response.content)) !== null) {
|
|
153
|
+
const text = match[1].trim();
|
|
154
|
+
if (text)
|
|
155
|
+
thoughts.push(text);
|
|
156
|
+
}
|
|
157
|
+
// Fallback: split by newlines if no options found
|
|
158
|
+
if (thoughts.length === 0) {
|
|
159
|
+
const lines = response.content.split("\n").filter((l) => l.trim().length > 10);
|
|
160
|
+
thoughts.push(...lines.slice(0, branchFactor));
|
|
161
|
+
}
|
|
162
|
+
return {
|
|
163
|
+
thoughts: thoughts.slice(0, branchFactor),
|
|
164
|
+
tokens: { prompt: response.tokens?.prompt ?? 0, completion: response.tokens?.completion ?? 0 },
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
// ── Scoring ─────────────────────────────────────────
|
|
168
|
+
async llmScore(thought, backend) {
|
|
169
|
+
const prompt = TOT_EVALUATE_PROMPT.replace("{thought}", thought);
|
|
170
|
+
const messages = [{ role: "user", content: prompt }];
|
|
171
|
+
try {
|
|
172
|
+
const response = await backend.complete(messages, { temperature: 0.1, maxTokens: 16 });
|
|
173
|
+
const scoreMatch = response.content.match(/(\d+\.?\d*)/);
|
|
174
|
+
const score = scoreMatch ? Math.max(0, Math.min(1, parseFloat(scoreMatch[1]))) : 0.5;
|
|
175
|
+
return {
|
|
176
|
+
score,
|
|
177
|
+
tokens: { prompt: response.tokens?.prompt ?? 0, completion: response.tokens?.completion ?? 0 },
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
catch {
|
|
181
|
+
return { score: 0.5, tokens: { prompt: 0, completion: 0 } };
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
heuristicScore(thought, path) {
|
|
185
|
+
let score = 0.5;
|
|
186
|
+
// Length bonus (not too short, not too long)
|
|
187
|
+
const words = thought.split(/\s+/).length;
|
|
188
|
+
if (words >= 10 && words <= 100)
|
|
189
|
+
score += 0.1;
|
|
190
|
+
// Novelty: penalize if too similar to existing path
|
|
191
|
+
for (const p of path) {
|
|
192
|
+
const overlap = this.wordOverlap(thought, p);
|
|
193
|
+
if (overlap > 0.8)
|
|
194
|
+
score -= 0.2;
|
|
195
|
+
}
|
|
196
|
+
// Structure bonus: contains reasoning indicators
|
|
197
|
+
const indicators = ["because", "therefore", "however", "if", "then", "since", "given"];
|
|
198
|
+
for (const ind of indicators) {
|
|
199
|
+
if (thought.toLowerCase().includes(ind)) {
|
|
200
|
+
score += 0.05;
|
|
201
|
+
break;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
return Math.max(0, Math.min(1, score));
|
|
205
|
+
}
|
|
206
|
+
wordOverlap(a, b) {
|
|
207
|
+
const wordsA = new Set(a.toLowerCase().split(/\s+/));
|
|
208
|
+
const wordsB = new Set(b.toLowerCase().split(/\s+/));
|
|
209
|
+
let overlap = 0;
|
|
210
|
+
for (const w of wordsA) {
|
|
211
|
+
if (wordsB.has(w))
|
|
212
|
+
overlap++;
|
|
213
|
+
}
|
|
214
|
+
return overlap / Math.max(wordsA.size, wordsB.size);
|
|
215
|
+
}
|
|
216
|
+
// ── Solve ───────────────────────────────────────────
|
|
217
|
+
async solve(task, systemPrompt, path, backend) {
|
|
218
|
+
const pathStr = path.map((p, i) => `${i + 1}. ${p}`).join("\n");
|
|
219
|
+
const prompt = TOT_SOLVE_PROMPT.replace("{path}", pathStr);
|
|
220
|
+
const messages = [
|
|
221
|
+
{ role: "system", content: systemPrompt },
|
|
222
|
+
{ role: "user", content: `Problem: ${task}\n\n${prompt}` },
|
|
223
|
+
];
|
|
224
|
+
const response = await backend.complete(messages, { temperature: 0.2, maxTokens: 1024 });
|
|
225
|
+
const answerMatch = response.content.match(/Final Answer:\s*([\s\S]*?)$/i);
|
|
226
|
+
const answer = answerMatch ? answerMatch[1].trim() : response.content.trim();
|
|
227
|
+
return {
|
|
228
|
+
answer,
|
|
229
|
+
tokens: { prompt: response.tokens?.prompt ?? 0, completion: response.tokens?.completion ?? 0 },
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
// ── Path Extraction ─────────────────────────────────
|
|
233
|
+
getPath(root, targetId) {
|
|
234
|
+
const path = [];
|
|
235
|
+
const found = this.findBranch(root, targetId, path);
|
|
236
|
+
if (found)
|
|
237
|
+
return path.map((id) => this.findBranchById(root, id)?.thought ?? "").filter(Boolean);
|
|
238
|
+
return [];
|
|
239
|
+
}
|
|
240
|
+
findBranch(node, targetId, path) {
|
|
241
|
+
path.push(node.id);
|
|
242
|
+
if (node.id === targetId)
|
|
243
|
+
return true;
|
|
244
|
+
for (const child of node.children) {
|
|
245
|
+
if (this.findBranch(child, targetId, path))
|
|
246
|
+
return true;
|
|
247
|
+
}
|
|
248
|
+
path.pop();
|
|
249
|
+
return false;
|
|
250
|
+
}
|
|
251
|
+
findBranchById(node, id) {
|
|
252
|
+
if (node.id === id)
|
|
253
|
+
return node;
|
|
254
|
+
for (const child of node.children) {
|
|
255
|
+
const found = this.findBranchById(child, id);
|
|
256
|
+
if (found)
|
|
257
|
+
return found;
|
|
258
|
+
}
|
|
259
|
+
return null;
|
|
260
|
+
}
|
|
261
|
+
buildResult(answer, steps, startTime, promptTokens, completionTokens, llmCalls, success) {
|
|
262
|
+
return {
|
|
263
|
+
answer,
|
|
264
|
+
steps,
|
|
265
|
+
strategy: "tot",
|
|
266
|
+
durationMs: Date.now() - startTime,
|
|
267
|
+
tokens: { prompt: promptTokens, completion: completionTokens, total: promptTokens + completionTokens },
|
|
268
|
+
llmCalls,
|
|
269
|
+
toolCalls: 0,
|
|
270
|
+
success,
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
//# sourceMappingURL=tot.js.map
|