@louloulinx/metagpt 0.1.3
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/.eslintrc.json +23 -0
- package/.prettierrc +7 -0
- package/LICENSE +21 -0
- package/README-CN.md +754 -0
- package/README.md +238 -0
- package/bun.lock +1023 -0
- package/doc/TutorialAssistant.md +114 -0
- package/doc/VercelLLMProvider.md +164 -0
- package/eslint.config.js +55 -0
- package/examples/data-interpreter-example.ts +173 -0
- package/examples/qwen-direct-example.ts +60 -0
- package/examples/qwen-example.ts +62 -0
- package/examples/tutorial-assistant-example.ts +97 -0
- package/jest.config.ts +22 -0
- package/output/tutorials/Go/350/257/255/350/250/200/347/274/226/347/250/213/346/225/231/347/250/213_2025-02-25T09-35-15-436Z.md +2208 -0
- package/output/tutorials/Rust/346/225/231/347/250/213_2025-02-25T08-27-27-632Z.md +1967 -0
- package/output/tutorials//345/246/202/344/275/225/344/275/277/347/224/250TypeScript/345/274/200/345/217/221Node.js/345/272/224/347/224/250_2025-02-25T08-14-39-605Z.md +1721 -0
- package/output/tutorials//346/225/260/345/255/227/347/273/217/346/265/216/345/255/246/346/225/231/347/250/213_2025-02-25T10-45-03-605Z.md +902 -0
- package/output/tutorials//346/232/250/345/215/227/345/244/247/345/255/246/346/225/260/345/255/227/347/273/217/346/265/216/345/255/246/345/244/215/350/257/225/350/265/204/346/226/231_2025-02-25T11-16-59-133Z.md +719 -0
- package/package.json +58 -0
- package/plan-cn.md +321 -0
- package/plan.md +154 -0
- package/src/actions/analyze-task.ts +65 -0
- package/src/actions/base-action.ts +103 -0
- package/src/actions/di/execute-nb-code.ts +247 -0
- package/src/actions/di/write-analysis-code.ts +234 -0
- package/src/actions/write-tutorial.ts +232 -0
- package/src/config/browser.ts +33 -0
- package/src/config/config.ts +345 -0
- package/src/config/embedding.ts +26 -0
- package/src/config/llm.ts +36 -0
- package/src/config/mermaid.ts +37 -0
- package/src/config/omniparse.ts +25 -0
- package/src/config/redis.ts +34 -0
- package/src/config/s3.ts +33 -0
- package/src/config/search.ts +30 -0
- package/src/config/workspace.ts +20 -0
- package/src/index.ts +40 -0
- package/src/management/team.ts +168 -0
- package/src/memory/longterm.ts +218 -0
- package/src/memory/manager.ts +160 -0
- package/src/memory/types.ts +100 -0
- package/src/memory/working.ts +154 -0
- package/src/monitoring/system.ts +413 -0
- package/src/monitoring/types.ts +230 -0
- package/src/plugin/manager.ts +79 -0
- package/src/plugin/types.ts +114 -0
- package/src/provider/vercel-llm.ts +314 -0
- package/src/rag/base-rag.ts +194 -0
- package/src/rag/document-qa.ts +102 -0
- package/src/roles/base-role.ts +155 -0
- package/src/roles/data-interpreter.ts +360 -0
- package/src/roles/engineer.ts +1 -0
- package/src/roles/tutorial-assistant.ts +217 -0
- package/src/skills/base-skill.ts +144 -0
- package/src/skills/code-review.ts +120 -0
- package/src/tools/base-tool.ts +155 -0
- package/src/tools/file-system.ts +204 -0
- package/src/tools/tool-recommend.d.ts +14 -0
- package/src/tools/tool-recommend.ts +31 -0
- package/src/types/action.ts +38 -0
- package/src/types/config.ts +129 -0
- package/src/types/document.ts +354 -0
- package/src/types/llm.ts +64 -0
- package/src/types/memory.ts +36 -0
- package/src/types/message.ts +193 -0
- package/src/types/rag.ts +86 -0
- package/src/types/role.ts +67 -0
- package/src/types/skill.ts +71 -0
- package/src/types/task.ts +32 -0
- package/src/types/team.ts +55 -0
- package/src/types/tool.ts +77 -0
- package/src/types/workflow.ts +133 -0
- package/src/utils/common.ts +73 -0
- package/src/utils/yaml.ts +67 -0
- package/src/websocket/browser-client.ts +187 -0
- package/src/websocket/client.ts +186 -0
- package/src/websocket/server.ts +169 -0
- package/src/websocket/types.ts +125 -0
- package/src/workflow/executor.ts +193 -0
- package/src/workflow/executors/action-executor.ts +72 -0
- package/src/workflow/executors/condition-executor.ts +118 -0
- package/src/workflow/executors/parallel-executor.ts +201 -0
- package/src/workflow/executors/role-executor.ts +76 -0
- package/src/workflow/executors/sequence-executor.ts +196 -0
- package/tests/actions.test.ts +105 -0
- package/tests/benchmark/performance.test.ts +147 -0
- package/tests/config/config.test.ts +115 -0
- package/tests/config.test.ts +106 -0
- package/tests/e2e/setup.ts +74 -0
- package/tests/e2e/workflow.test.ts +88 -0
- package/tests/llm.test.ts +84 -0
- package/tests/memory/memory.test.ts +164 -0
- package/tests/memory.test.ts +63 -0
- package/tests/monitoring/monitoring.test.ts +225 -0
- package/tests/plugin/plugin.test.ts +183 -0
- package/tests/provider/bailian-llm.test.ts +98 -0
- package/tests/rag.test.ts +162 -0
- package/tests/roles.test.ts +88 -0
- package/tests/skills.test.ts +166 -0
- package/tests/team.test.ts +143 -0
- package/tests/tools.test.ts +170 -0
- package/tests/types/document.test.ts +181 -0
- package/tests/types/message.test.ts +122 -0
- package/tests/utils/yaml.test.ts +110 -0
- package/tests/utils.test.ts +74 -0
- package/tests/websocket/browser-client.test.ts +1 -0
- package/tests/websocket/websocket.test.ts +42 -0
- package/tests/workflow/parallel-executor.test.ts +224 -0
- package/tests/workflow/sequence-executor.test.ts +207 -0
- package/tests/workflow.test.ts +290 -0
- package/tsconfig.json +27 -0
- package/typedoc.json +25 -0
@@ -0,0 +1,247 @@
|
|
1
|
+
import { exec } from 'child_process';
|
2
|
+
import * as fs from 'fs/promises';
|
3
|
+
import * as path from 'path';
|
4
|
+
import { v4 as uuidv4 } from 'uuid';
|
5
|
+
import type { LLMProvider } from '../../types/llm';
|
6
|
+
|
7
|
+
/**
|
8
|
+
* 执行Notebook代码动作
|
9
|
+
*/
|
10
|
+
export class ExecuteNbCode {
|
11
|
+
private llm: LLMProvider;
|
12
|
+
private tempDir: string = 'temp';
|
13
|
+
private process: any = null;
|
14
|
+
private commonDependencies = ['pandas', 'numpy', 'matplotlib', 'seaborn', 'scikit-learn'];
|
15
|
+
|
16
|
+
constructor(llm: LLMProvider) {
|
17
|
+
this.llm = llm;
|
18
|
+
console.log('[ExecuteNbCode] Initializing ExecuteNbCode');
|
19
|
+
|
20
|
+
// Ensure temp directory exists
|
21
|
+
this.ensureTempDir();
|
22
|
+
}
|
23
|
+
|
24
|
+
/**
|
25
|
+
* 确保临时目录存在
|
26
|
+
*/
|
27
|
+
private async ensureTempDir(): Promise<void> {
|
28
|
+
try {
|
29
|
+
await fs.mkdir(this.tempDir, { recursive: true });
|
30
|
+
console.log(`[ExecuteNbCode] Temporary directory created: ${this.tempDir}`);
|
31
|
+
} catch (error) {
|
32
|
+
console.error('[ExecuteNbCode] Error creating temporary directory:', error);
|
33
|
+
}
|
34
|
+
}
|
35
|
+
|
36
|
+
/**
|
37
|
+
* 执行代码
|
38
|
+
*/
|
39
|
+
async run(code: string): Promise<[string, boolean]> {
|
40
|
+
console.log('[ExecuteNbCode] Starting code execution');
|
41
|
+
console.log('[ExecuteNbCode] Code length:', code.length, 'bytes');
|
42
|
+
|
43
|
+
try {
|
44
|
+
// Check for required dependencies
|
45
|
+
console.log('[ExecuteNbCode] Checking for required dependencies');
|
46
|
+
const missingDeps = await this.checkDependencies(code);
|
47
|
+
|
48
|
+
if (missingDeps.length > 0) {
|
49
|
+
console.log(`[ExecuteNbCode] Missing dependencies detected: ${missingDeps.join(', ')}`);
|
50
|
+
const installInstructions = this.getInstallInstructions(missingDeps);
|
51
|
+
return [installInstructions, false];
|
52
|
+
}
|
53
|
+
|
54
|
+
// Create a temporary Python file
|
55
|
+
const filename = `${uuidv4()}.py`;
|
56
|
+
const filepath = path.join(this.tempDir, filename);
|
57
|
+
|
58
|
+
console.log(`[ExecuteNbCode] Writing code to ${filepath}`);
|
59
|
+
await fs.writeFile(filepath, code);
|
60
|
+
console.log(`[ExecuteNbCode] Code written to temporary file, size: ${(await fs.stat(filepath)).size} bytes`);
|
61
|
+
|
62
|
+
// Execute the code
|
63
|
+
console.log('[ExecuteNbCode] Executing Python code');
|
64
|
+
const [result, success] = await this.executePython(filepath);
|
65
|
+
|
66
|
+
// Clean up
|
67
|
+
try {
|
68
|
+
await fs.unlink(filepath);
|
69
|
+
console.log(`[ExecuteNbCode] Removed temporary file: ${filepath}`);
|
70
|
+
} catch (cleanupError) {
|
71
|
+
console.warn(`[ExecuteNbCode] Failed to remove temporary file: ${filepath}`, cleanupError);
|
72
|
+
}
|
73
|
+
|
74
|
+
if (success) {
|
75
|
+
console.log(`[ExecuteNbCode] Execution successful, output length: ${result.length} bytes`);
|
76
|
+
} else {
|
77
|
+
console.error(`[ExecuteNbCode] Execution failed: ${result.substring(0, 200)}...`);
|
78
|
+
}
|
79
|
+
|
80
|
+
return [result, success];
|
81
|
+
} catch (error) {
|
82
|
+
console.error('[ExecuteNbCode] Error executing code:', error);
|
83
|
+
return [`Error executing code: ${error}`, false];
|
84
|
+
}
|
85
|
+
}
|
86
|
+
|
87
|
+
/**
|
88
|
+
* 检查代码中使用的依赖是否已安装
|
89
|
+
*/
|
90
|
+
private async checkDependencies(code: string): Promise<string[]> {
|
91
|
+
console.log('[ExecuteNbCode] Analyzing code for import statements');
|
92
|
+
const importRegex = /import\s+([a-zA-Z0-9_,\s]+)(?:\s+as\s+[a-zA-Z0-9_]+)?|from\s+([a-zA-Z0-9_.]+)\s+import/g;
|
93
|
+
const matches = [...code.matchAll(importRegex)];
|
94
|
+
|
95
|
+
// Extract module names
|
96
|
+
const moduleSet = new Set<string>();
|
97
|
+
for (const match of matches) {
|
98
|
+
if (match[1]) {
|
99
|
+
// import X, Y, Z
|
100
|
+
const modules = match[1].split(',').map(m => m.trim().split('.')[0]);
|
101
|
+
modules.forEach(m => moduleSet.add(m));
|
102
|
+
} else if (match[2]) {
|
103
|
+
// from X import Y
|
104
|
+
moduleSet.add(match[2].split('.')[0]);
|
105
|
+
}
|
106
|
+
}
|
107
|
+
|
108
|
+
console.log(`[ExecuteNbCode] Detected modules: ${Array.from(moduleSet).join(', ')}`);
|
109
|
+
|
110
|
+
// Check if modules are installed
|
111
|
+
const missingDeps: string[] = [];
|
112
|
+
for (const module of moduleSet) {
|
113
|
+
// Skip standard library modules
|
114
|
+
if (['os', 'sys', 'time', 'datetime', 'json', 'math', 'random', 're'].includes(module)) {
|
115
|
+
continue;
|
116
|
+
}
|
117
|
+
|
118
|
+
// Check if module is installed
|
119
|
+
const isInstalled = await this.isModuleInstalled(module);
|
120
|
+
if (!isInstalled) {
|
121
|
+
missingDeps.push(module);
|
122
|
+
}
|
123
|
+
}
|
124
|
+
|
125
|
+
return missingDeps;
|
126
|
+
}
|
127
|
+
|
128
|
+
/**
|
129
|
+
* 检查模块是否已安装
|
130
|
+
*/
|
131
|
+
private async isModuleInstalled(moduleName: string): Promise<boolean> {
|
132
|
+
return new Promise((resolve) => {
|
133
|
+
console.log(`[ExecuteNbCode] Checking if module is installed: ${moduleName}`);
|
134
|
+
const command = `python -c "import ${moduleName}" 2>/dev/null`;
|
135
|
+
|
136
|
+
exec(command, (error) => {
|
137
|
+
if (error) {
|
138
|
+
console.log(`[ExecuteNbCode] Module ${moduleName} is not installed`);
|
139
|
+
resolve(false);
|
140
|
+
return;
|
141
|
+
}
|
142
|
+
|
143
|
+
console.log(`[ExecuteNbCode] Module ${moduleName} is installed`);
|
144
|
+
resolve(true);
|
145
|
+
});
|
146
|
+
});
|
147
|
+
}
|
148
|
+
|
149
|
+
/**
|
150
|
+
* 获取安装说明
|
151
|
+
*/
|
152
|
+
private getInstallInstructions(missingDeps: string[]): string {
|
153
|
+
const pipCommand = `pip install ${missingDeps.join(' ')}`;
|
154
|
+
|
155
|
+
return `
|
156
|
+
## Missing Dependencies Detected
|
157
|
+
|
158
|
+
The following Python packages are required but not installed:
|
159
|
+
\`\`\`
|
160
|
+
${missingDeps.join('\n')}
|
161
|
+
\`\`\`
|
162
|
+
|
163
|
+
Please install these dependencies using pip:
|
164
|
+
\`\`\`
|
165
|
+
${pipCommand}
|
166
|
+
\`\`\`
|
167
|
+
|
168
|
+
After installing the dependencies, try running the analysis again.
|
169
|
+
|
170
|
+
Original Python Code:
|
171
|
+
\`\`\`python
|
172
|
+
${this.getFirstLinesOfCode()}
|
173
|
+
\`\`\`
|
174
|
+
...
|
175
|
+
`;
|
176
|
+
}
|
177
|
+
|
178
|
+
/**
|
179
|
+
* 获取要显示的代码的前几行
|
180
|
+
*/
|
181
|
+
private getFirstLinesOfCode(): string {
|
182
|
+
// This would typically show the first few lines of the code
|
183
|
+
// Since we don't have the code at this point, we'll return a placeholder
|
184
|
+
return "# The generated code requires additional Python packages\n# Please install them using the pip command above";
|
185
|
+
}
|
186
|
+
|
187
|
+
/**
|
188
|
+
* 执行Python代码
|
189
|
+
*/
|
190
|
+
private executePython(filepath: string): Promise<[string, boolean]> {
|
191
|
+
return new Promise((resolve) => {
|
192
|
+
const command = `python ${filepath}`;
|
193
|
+
|
194
|
+
console.log(`[ExecuteNbCode] Running command: ${command}`);
|
195
|
+
|
196
|
+
this.process = exec(command, (error, stdout, stderr) => {
|
197
|
+
if (error) {
|
198
|
+
console.error(`[ExecuteNbCode] Execution error: ${error.message}`);
|
199
|
+
|
200
|
+
// Check if the error is due to missing dependencies
|
201
|
+
if (stderr.includes('ModuleNotFoundError: No module named')) {
|
202
|
+
const match = stderr.match(/ModuleNotFoundError: No module named '([^']+)'/);
|
203
|
+
if (match && match[1]) {
|
204
|
+
const missingModule = match[1];
|
205
|
+
const installCmd = `pip install ${missingModule}`;
|
206
|
+
const errorMsg = `
|
207
|
+
## Missing Dependency: ${missingModule}
|
208
|
+
|
209
|
+
Python cannot find the required module: \`${missingModule}\`
|
210
|
+
|
211
|
+
Please install it using pip:
|
212
|
+
\`\`\`
|
213
|
+
${installCmd}
|
214
|
+
\`\`\`
|
215
|
+
|
216
|
+
After installing the dependency, try running the analysis again.
|
217
|
+
`;
|
218
|
+
resolve([errorMsg, false]);
|
219
|
+
return;
|
220
|
+
}
|
221
|
+
}
|
222
|
+
|
223
|
+
resolve([`Execution error: ${error.message}\n${stderr}`, false]);
|
224
|
+
return;
|
225
|
+
}
|
226
|
+
|
227
|
+
if (stderr) {
|
228
|
+
console.warn(`[ExecuteNbCode] Stderr: ${stderr}`);
|
229
|
+
}
|
230
|
+
|
231
|
+
console.log(`[ExecuteNbCode] Execution successful, stdout length: ${stdout.length}`);
|
232
|
+
resolve([stdout, true]);
|
233
|
+
});
|
234
|
+
});
|
235
|
+
}
|
236
|
+
|
237
|
+
/**
|
238
|
+
* 终止执行
|
239
|
+
*/
|
240
|
+
async terminate(): Promise<void> {
|
241
|
+
if (this.process) {
|
242
|
+
console.log('[ExecuteNbCode] Terminating process');
|
243
|
+
this.process.kill();
|
244
|
+
this.process = null;
|
245
|
+
}
|
246
|
+
}
|
247
|
+
}
|
@@ -0,0 +1,234 @@
|
|
1
|
+
import { BaseAction } from '../base-action';
|
2
|
+
import type { ActionOutput } from '../../types/action';
|
3
|
+
import type { LLMProvider } from '../../types/llm';
|
4
|
+
import type { Message } from '../../types/message';
|
5
|
+
|
6
|
+
// Define data info prompt template
|
7
|
+
export const DATA_INFO = `
|
8
|
+
# Data Information
|
9
|
+
{info}
|
10
|
+
`;
|
11
|
+
|
12
|
+
/**
|
13
|
+
* ActionConfig配置接口
|
14
|
+
*/
|
15
|
+
export interface ActionConfig {
|
16
|
+
name?: string;
|
17
|
+
description?: string;
|
18
|
+
args?: Record<string, any>;
|
19
|
+
llm: LLMProvider;
|
20
|
+
memory?: any;
|
21
|
+
workingMemory?: any;
|
22
|
+
}
|
23
|
+
|
24
|
+
/**
|
25
|
+
* WriteAnalysisCode配置接口
|
26
|
+
*/
|
27
|
+
export interface WriteAnalysisCodeConfig extends ActionConfig {
|
28
|
+
llm: LLMProvider;
|
29
|
+
}
|
30
|
+
|
31
|
+
/**
|
32
|
+
* 编写数据分析代码动作
|
33
|
+
*/
|
34
|
+
export class WriteAnalysisCode extends BaseAction {
|
35
|
+
constructor(config: WriteAnalysisCodeConfig) {
|
36
|
+
super({
|
37
|
+
...config,
|
38
|
+
name: 'WriteAnalysisCode',
|
39
|
+
});
|
40
|
+
console.log('[WriteAnalysisCode] Initialized');
|
41
|
+
}
|
42
|
+
|
43
|
+
/**
|
44
|
+
* 运行动作
|
45
|
+
*/
|
46
|
+
async run(): Promise<ActionOutput> {
|
47
|
+
try {
|
48
|
+
console.log('[WriteAnalysisCode] Starting run method');
|
49
|
+
|
50
|
+
// Get arguments
|
51
|
+
const userRequirement = this.getArg<string>('user_requirement') || '';
|
52
|
+
const planStatus = this.getArg<string>('plan_status') || '';
|
53
|
+
const toolInfo = this.getArg<string>('tool_info') || '';
|
54
|
+
const workingMemory = this.getArg<Message[]>('working_memory') || [];
|
55
|
+
const useReflection = this.getArg<boolean>('use_reflection') || false;
|
56
|
+
|
57
|
+
console.log(`[WriteAnalysisCode] User requirement: ${userRequirement.substring(0, 50)}...`);
|
58
|
+
console.log(`[WriteAnalysisCode] Use reflection: ${useReflection}`);
|
59
|
+
|
60
|
+
// Format working memory
|
61
|
+
const workingMemoryText = workingMemory
|
62
|
+
.map(msg => `${msg.role}: ${msg.content}`)
|
63
|
+
.join('\n\n');
|
64
|
+
|
65
|
+
// Generate prompt
|
66
|
+
const prompt = this.generateCodePrompt(
|
67
|
+
userRequirement,
|
68
|
+
workingMemoryText,
|
69
|
+
planStatus,
|
70
|
+
toolInfo,
|
71
|
+
useReflection
|
72
|
+
);
|
73
|
+
|
74
|
+
console.log(`[WriteAnalysisCode] Generated prompt (${prompt.length} characters)`);
|
75
|
+
|
76
|
+
// Generate code with LLM
|
77
|
+
console.log('[WriteAnalysisCode] Calling LLM to generate code');
|
78
|
+
const result = await this.llm.generate(prompt);
|
79
|
+
|
80
|
+
// Extract Python code
|
81
|
+
const code = this.extractPythonCode(result);
|
82
|
+
console.log(`[WriteAnalysisCode] Generated code (${code.length} characters)`);
|
83
|
+
|
84
|
+
return this.createOutput(code, 'completed');
|
85
|
+
} catch (error) {
|
86
|
+
console.error('[WriteAnalysisCode] Error generating code:', error);
|
87
|
+
return this.createOutput(`Error generating code: ${error}`, 'failed');
|
88
|
+
}
|
89
|
+
}
|
90
|
+
|
91
|
+
/**
|
92
|
+
* 生成代码提示词
|
93
|
+
*/
|
94
|
+
private generateCodePrompt(
|
95
|
+
userRequirement: string,
|
96
|
+
workingMemory: string,
|
97
|
+
planStatus: string = '',
|
98
|
+
toolInfo: string = '',
|
99
|
+
useReflection: boolean = false
|
100
|
+
): string {
|
101
|
+
// Construct the prompt
|
102
|
+
let prompt = `# Data Analysis Task
|
103
|
+
## User Requirement
|
104
|
+
${userRequirement}
|
105
|
+
|
106
|
+
`;
|
107
|
+
|
108
|
+
// Add working memory if available
|
109
|
+
if (workingMemory) {
|
110
|
+
prompt += `## Context and History
|
111
|
+
${workingMemory}
|
112
|
+
|
113
|
+
`;
|
114
|
+
}
|
115
|
+
|
116
|
+
// Add plan status if available
|
117
|
+
if (planStatus) {
|
118
|
+
prompt += `## Current Plan Status
|
119
|
+
${planStatus}
|
120
|
+
|
121
|
+
`;
|
122
|
+
}
|
123
|
+
|
124
|
+
// Add tool info if available
|
125
|
+
if (toolInfo) {
|
126
|
+
prompt += `## Available Tools
|
127
|
+
${toolInfo}
|
128
|
+
|
129
|
+
`;
|
130
|
+
}
|
131
|
+
|
132
|
+
// Reflection instructions if enabled
|
133
|
+
if (useReflection) {
|
134
|
+
prompt += `## Reflection
|
135
|
+
Please review the previous code and execution results. Identify errors and issues, and make improvements.
|
136
|
+
|
137
|
+
`;
|
138
|
+
}
|
139
|
+
|
140
|
+
// Final instructions
|
141
|
+
prompt += `## Instructions
|
142
|
+
Please write clean, efficient Python code to analyze the data according to the user requirement.
|
143
|
+
Use pandas, numpy, matplotlib, and other data science libraries as appropriate.
|
144
|
+
Include comments to explain your code.
|
145
|
+
Make sure your code is complete and executable.
|
146
|
+
Do not include markdown annotations, just write the Python code directly.
|
147
|
+
|
148
|
+
`;
|
149
|
+
|
150
|
+
return prompt;
|
151
|
+
}
|
152
|
+
|
153
|
+
/**
|
154
|
+
* 从LLM响应中提取Python代码
|
155
|
+
*/
|
156
|
+
private extractPythonCode(text: string): string {
|
157
|
+
// Try to extract code from markdown code blocks
|
158
|
+
const pythonBlockRegex = /```(?:python)?\s*([\s\S]*?)```/g;
|
159
|
+
const matches = text.match(pythonBlockRegex);
|
160
|
+
|
161
|
+
if (matches && matches.length > 0) {
|
162
|
+
// Extract code from the first code block
|
163
|
+
const codeBlock = matches[0];
|
164
|
+
return codeBlock.replace(/```(?:python)?\s*/, '').replace(/```$/, '').trim();
|
165
|
+
}
|
166
|
+
|
167
|
+
// If no code blocks found, assume the entire text is code
|
168
|
+
return text.trim();
|
169
|
+
}
|
170
|
+
}
|
171
|
+
|
172
|
+
/**
|
173
|
+
* CheckData配置接口
|
174
|
+
*/
|
175
|
+
export interface CheckDataConfig extends ActionConfig {
|
176
|
+
llm: LLMProvider;
|
177
|
+
}
|
178
|
+
|
179
|
+
/**
|
180
|
+
* 检查数据动作
|
181
|
+
*/
|
182
|
+
export class CheckData extends BaseAction {
|
183
|
+
constructor(config: CheckDataConfig) {
|
184
|
+
super({
|
185
|
+
...config,
|
186
|
+
name: 'CheckData',
|
187
|
+
});
|
188
|
+
console.log('[CheckData] Initialized');
|
189
|
+
}
|
190
|
+
|
191
|
+
/**
|
192
|
+
* 运行动作
|
193
|
+
*/
|
194
|
+
async run(): Promise<ActionOutput> {
|
195
|
+
try {
|
196
|
+
console.log('[CheckData] Starting run method');
|
197
|
+
|
198
|
+
// In a full implementation, this would need to accept a plan and
|
199
|
+
// create code to check the data based on the plan
|
200
|
+
|
201
|
+
// For simplicity, we'll just return a basic data check script
|
202
|
+
const code = `
|
203
|
+
import pandas as pd
|
204
|
+
import numpy as np
|
205
|
+
|
206
|
+
# Check if dataset exists
|
207
|
+
try:
|
208
|
+
# Try to read a potential dataset (this is just a placeholder)
|
209
|
+
df = pd.read_csv('data.csv')
|
210
|
+
|
211
|
+
# Display basic information about the dataset
|
212
|
+
print("Dataset Information:")
|
213
|
+
print(f"Shape: {df.shape}")
|
214
|
+
print("\\nFirst 5 rows:")
|
215
|
+
print(df.head())
|
216
|
+
print("\\nData types:")
|
217
|
+
print(df.dtypes)
|
218
|
+
print("\\nSummary statistics:")
|
219
|
+
print(df.describe())
|
220
|
+
print("\\nMissing values:")
|
221
|
+
print(df.isnull().sum())
|
222
|
+
except Exception as e:
|
223
|
+
print(f"Error loading dataset: {e}")
|
224
|
+
print("No dataset available for analysis.")
|
225
|
+
`;
|
226
|
+
|
227
|
+
console.log('[CheckData] Generated basic data check code');
|
228
|
+
return this.createOutput(code, 'completed');
|
229
|
+
} catch (error) {
|
230
|
+
console.error('[CheckData] Error generating data check code:', error);
|
231
|
+
return this.createOutput(`Error generating data check code: ${error}`, 'failed');
|
232
|
+
}
|
233
|
+
}
|
234
|
+
}
|
@@ -0,0 +1,232 @@
|
|
1
|
+
import { z } from 'zod';
|
2
|
+
import type { ActionOutput } from '../types/action';
|
3
|
+
import type { LLMProvider } from '../types/llm';
|
4
|
+
import { BaseAction } from './base-action';
|
5
|
+
|
6
|
+
/**
|
7
|
+
* 动作配置接口
|
8
|
+
*/
|
9
|
+
export interface ActionConfig {
|
10
|
+
name?: string;
|
11
|
+
description?: string;
|
12
|
+
args?: Record<string, any>;
|
13
|
+
llm: LLMProvider;
|
14
|
+
memory?: any;
|
15
|
+
workingMemory?: any;
|
16
|
+
}
|
17
|
+
|
18
|
+
/**
|
19
|
+
* 目录结构类型定义
|
20
|
+
*/
|
21
|
+
export type Directory = {
|
22
|
+
title: string;
|
23
|
+
directory: Array<Record<string, string[]>>;
|
24
|
+
};
|
25
|
+
|
26
|
+
/**
|
27
|
+
* 目录结构模式验证
|
28
|
+
*/
|
29
|
+
export const DirectorySchema = z.object({
|
30
|
+
title: z.string(),
|
31
|
+
directory: z.array(z.record(z.string(), z.array(z.string()))),
|
32
|
+
});
|
33
|
+
|
34
|
+
/**
|
35
|
+
* 教程目录生成动作配置
|
36
|
+
*/
|
37
|
+
export interface WriteDirectoryConfig extends ActionConfig {
|
38
|
+
language?: string;
|
39
|
+
}
|
40
|
+
|
41
|
+
/**
|
42
|
+
* 教程目录生成动作
|
43
|
+
*/
|
44
|
+
export class WriteDirectory extends BaseAction {
|
45
|
+
language: string;
|
46
|
+
|
47
|
+
constructor(config: WriteDirectoryConfig) {
|
48
|
+
super({
|
49
|
+
...config,
|
50
|
+
name: 'WriteDirectory',
|
51
|
+
});
|
52
|
+
this.language = config.language || 'Chinese';
|
53
|
+
console.log(`[WriteDirectory] Initialized with language: ${this.language}`);
|
54
|
+
}
|
55
|
+
|
56
|
+
/**
|
57
|
+
* 执行动作,生成教程目录结构
|
58
|
+
*/
|
59
|
+
async run(): Promise<ActionOutput> {
|
60
|
+
try {
|
61
|
+
console.log('[WriteDirectory] Starting run() method');
|
62
|
+
const topic = this.getArg<string>('topic') || '';
|
63
|
+
console.log(`[WriteDirectory] Topic: "${topic}"`);
|
64
|
+
|
65
|
+
if (!topic) {
|
66
|
+
console.warn('[WriteDirectory] Topic is required but not provided');
|
67
|
+
return this.createOutput('Topic is required', 'failed');
|
68
|
+
}
|
69
|
+
|
70
|
+
const prompt = this.generateDirectoryPrompt(topic);
|
71
|
+
console.log(`[WriteDirectory] Generated prompt (${prompt.length} characters)`);
|
72
|
+
console.log('[WriteDirectory] Calling LLM to generate directory structure');
|
73
|
+
|
74
|
+
const result = await this.llm.generate(prompt);
|
75
|
+
console.log(`[WriteDirectory] Received response from LLM (${result.length} characters)`);
|
76
|
+
|
77
|
+
// 解析JSON结果
|
78
|
+
try {
|
79
|
+
console.log('[WriteDirectory] Parsing LLM response as JSON');
|
80
|
+
const jsonStr = result.replace(/```json|```/g, '').trim();
|
81
|
+
console.log(`[WriteDirectory] Cleaned JSON string: ${jsonStr.substring(0, 100)}...`);
|
82
|
+
|
83
|
+
const parsed = JSON.parse(jsonStr);
|
84
|
+
console.log('[WriteDirectory] JSON parsed successfully');
|
85
|
+
|
86
|
+
const directory = DirectorySchema.parse(parsed);
|
87
|
+
console.log(`[WriteDirectory] Directory schema validated: ${directory.title} with ${directory.directory.length} sections`);
|
88
|
+
|
89
|
+
return this.createOutput(
|
90
|
+
JSON.stringify(directory),
|
91
|
+
'completed',
|
92
|
+
directory
|
93
|
+
);
|
94
|
+
} catch (e) {
|
95
|
+
console.error('[WriteDirectory] Failed to parse directory structure JSON:', e);
|
96
|
+
console.log('[WriteDirectory] Original LLM response:', result);
|
97
|
+
|
98
|
+
// 返回默认结构
|
99
|
+
const defaultDirectory: Directory = {
|
100
|
+
title: `Tutorial for ${topic}`,
|
101
|
+
directory: [
|
102
|
+
{ "Introduction": ["Overview", "Prerequisites"] },
|
103
|
+
{ "Main Content": ["Basic Concepts", "Advanced Usage"] },
|
104
|
+
{ "Conclusion": ["Summary", "Next Steps"] }
|
105
|
+
]
|
106
|
+
};
|
107
|
+
|
108
|
+
console.log('[WriteDirectory] Using default directory structure instead');
|
109
|
+
return this.createOutput(
|
110
|
+
JSON.stringify(defaultDirectory),
|
111
|
+
'completed',
|
112
|
+
defaultDirectory
|
113
|
+
);
|
114
|
+
}
|
115
|
+
} catch (error) {
|
116
|
+
console.error('[WriteDirectory] Error generating directory:', error);
|
117
|
+
if (error instanceof Error) {
|
118
|
+
await this.handleException(error);
|
119
|
+
}
|
120
|
+
return this.createOutput(`Failed to generate directory: ${error}`, 'failed');
|
121
|
+
}
|
122
|
+
}
|
123
|
+
|
124
|
+
/**
|
125
|
+
* 生成目录结构的提示词
|
126
|
+
* @param topic 教程主题
|
127
|
+
* @returns 提示词
|
128
|
+
*/
|
129
|
+
private generateDirectoryPrompt(topic: string): string {
|
130
|
+
const language = this.language === 'Chinese' ? '中文' : 'English';
|
131
|
+
return `请为主题"${topic}"创建一个完整的教程目录结构。目录应该结构清晰、内容全面、逻辑连贯。
|
132
|
+
|
133
|
+
请使用以下JSON格式输出目录结构:
|
134
|
+
{
|
135
|
+
"title": "教程标题",
|
136
|
+
"directory": [
|
137
|
+
{"第一章标题": ["1.1 小节标题", "1.2 小节标题", ...]},
|
138
|
+
{"第二章标题": ["2.1 小节标题", "2.2 小节标题", ...]},
|
139
|
+
...
|
140
|
+
]
|
141
|
+
}
|
142
|
+
|
143
|
+
请确保输出是有效的JSON格式,目录结构要反映${language}教程的完整性、系统性和专业性。`;
|
144
|
+
}
|
145
|
+
}
|
146
|
+
|
147
|
+
/**
|
148
|
+
* 教程内容生成动作配置
|
149
|
+
*/
|
150
|
+
export interface WriteContentConfig extends ActionConfig {
|
151
|
+
language?: string;
|
152
|
+
directory: Record<string, string[]>;
|
153
|
+
}
|
154
|
+
|
155
|
+
/**
|
156
|
+
* 教程内容生成动作
|
157
|
+
*/
|
158
|
+
export class WriteContent extends BaseAction {
|
159
|
+
language: string;
|
160
|
+
directory: Record<string, string[]>;
|
161
|
+
|
162
|
+
constructor(config: WriteContentConfig) {
|
163
|
+
super({
|
164
|
+
...config,
|
165
|
+
name: 'WriteContent',
|
166
|
+
});
|
167
|
+
this.language = config.language || 'Chinese';
|
168
|
+
this.directory = config.directory;
|
169
|
+
|
170
|
+
const sectionTitle = Object.keys(this.directory)[0];
|
171
|
+
const subsections = this.directory[sectionTitle];
|
172
|
+
console.log(`[WriteContent] Initialized for section "${sectionTitle}" with ${subsections.length} subsections`);
|
173
|
+
}
|
174
|
+
|
175
|
+
/**
|
176
|
+
* 执行动作,生成教程内容
|
177
|
+
*/
|
178
|
+
async run(): Promise<ActionOutput> {
|
179
|
+
try {
|
180
|
+
console.log('[WriteContent] Starting run() method');
|
181
|
+
|
182
|
+
const topic = this.getArg<string>('topic') || '';
|
183
|
+
console.log(`[WriteContent] Topic: "${topic}"`);
|
184
|
+
|
185
|
+
if (!topic) {
|
186
|
+
console.warn('[WriteContent] Topic is required but not provided');
|
187
|
+
return this.createOutput('Topic is required', 'failed');
|
188
|
+
}
|
189
|
+
|
190
|
+
const sectionTitle = Object.keys(this.directory)[0];
|
191
|
+
console.log(`[WriteContent] Generating content for section: "${sectionTitle}"`);
|
192
|
+
|
193
|
+
const prompt = this.generateContentPrompt(topic);
|
194
|
+
console.log(`[WriteContent] Generated prompt (${prompt.length} characters)`);
|
195
|
+
console.log('[WriteContent] Calling LLM to generate content');
|
196
|
+
|
197
|
+
const result = await this.llm.generate(prompt);
|
198
|
+
console.log(`[WriteContent] Received response from LLM (${result.length} characters)`);
|
199
|
+
|
200
|
+
return this.createOutput(result.trim(), 'completed');
|
201
|
+
} catch (error) {
|
202
|
+
console.error('[WriteContent] Error generating content:', error);
|
203
|
+
if (error instanceof Error) {
|
204
|
+
await this.handleException(error);
|
205
|
+
}
|
206
|
+
return this.createOutput(`Failed to generate content: ${error}`, 'failed');
|
207
|
+
}
|
208
|
+
}
|
209
|
+
|
210
|
+
/**
|
211
|
+
* 生成内容的提示词
|
212
|
+
* @param topic 教程主题
|
213
|
+
* @returns 提示词
|
214
|
+
*/
|
215
|
+
private generateContentPrompt(topic: string): string {
|
216
|
+
const language = this.language === 'Chinese' ? '中文' : 'English';
|
217
|
+
const sectionTitle = Object.keys(this.directory)[0];
|
218
|
+
const subsections = this.directory[sectionTitle];
|
219
|
+
|
220
|
+
return `请为主题"${topic}"下的"${sectionTitle}"章节编写详细内容。请包含以下小节:${subsections.join('、')}。
|
221
|
+
|
222
|
+
要求:
|
223
|
+
1. 使用${language}编写
|
224
|
+
2. 严格遵循Markdown语法,布局整洁规范
|
225
|
+
3. 内容应该专业、详细、通俗易懂
|
226
|
+
4. 提供实用的信息和示例
|
227
|
+
5. 每个小节都应该有适当的标题(使用## 和 ###)
|
228
|
+
6. 总字数应该在1000-2000字之间
|
229
|
+
|
230
|
+
请直接输出Markdown内容,不需要有额外的注释。`;
|
231
|
+
}
|
232
|
+
}
|