flowmind 1.0.1 → 1.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/README_CN.md CHANGED
@@ -94,7 +94,13 @@ npm install -g flowmind
94
94
  ### 初始化
95
95
 
96
96
  ```bash
97
+ # 基础初始化
97
98
  flowmind init
99
+
100
+ # 带 AI 模型初始化 (推荐)
101
+ flowmind init --ai openai
102
+ flowmind init --ai anthropic
103
+ flowmind init --ai ollama
98
104
  ```
99
105
 
100
106
  > 一次配置,永久生效。配置资源连接、学习偏好、输出格式,无需每次重复设置。
@@ -113,6 +119,248 @@ FlowMind: [自动使用顺序列表格式] ✓
113
119
 
114
120
  ---
115
121
 
122
+ ## 📖 使用方式
123
+
124
+ FlowMind 支持 4 种使用方式,满足不同场景需求:
125
+
126
+ ### 方式1: CLI 独立使用
127
+
128
+ 最简单的使用方式,无需 AI 模型,直接通过命令行调用。
129
+
130
+ ```bash
131
+ # 单次执行
132
+ flowmind "查询 traceId abc123 的日志"
133
+ flowmind "审查代码质量"
134
+ flowmind "验证订单数据"
135
+
136
+ # 交互模式
137
+ flowmind
138
+
139
+ # 指定技能执行
140
+ flowmind process --skill log-audit "查询最近1小时的错误日志"
141
+ ```
142
+
143
+ **特点:**
144
+ - ✅ 无需 AI 模型
145
+ - ✅ 基于规则引擎匹配
146
+ - ✅ 支持学习和记忆
147
+ - ✅ 离线可用
148
+
149
+ ---
150
+
151
+ ### 方式2: AI 模型直接接入
152
+
153
+ FlowMind 内置 AI 模型接入层,可直接调用 OpenAI、Anthropic、Ollama 等模型。
154
+
155
+ #### 配置 AI 模型
156
+
157
+ **方式 A:通过 CLI 初始化(推荐)**
158
+
159
+ ```bash
160
+ # 配置 OpenAI
161
+ flowmind init --ai openai
162
+ # 会提示输入 API Key
163
+
164
+ # 配置 Anthropic
165
+ flowmind init --ai anthropic
166
+
167
+ # 配置 Ollama (本地模型)
168
+ flowmind init --ai ollama
169
+ ```
170
+
171
+ **方式 B:手动配置**
172
+
173
+ 创建 `~/.flowmind/ai-config.json`:
174
+
175
+ ```json
176
+ {
177
+ "ai": {
178
+ "enabled": true,
179
+ "defaultProvider": "openai",
180
+ "fallbackToRules": true,
181
+ "providers": {
182
+ "openai": {
183
+ "apiKey": "sk-your-api-key",
184
+ "model": "gpt-4",
185
+ "temperature": 0.3
186
+ },
187
+ "anthropic": {
188
+ "apiKey": "sk-ant-your-api-key",
189
+ "model": "claude-3-sonnet-20240229"
190
+ },
191
+ "ollama": {
192
+ "baseUrl": "http://localhost:11434",
193
+ "model": "llama2"
194
+ }
195
+ },
196
+ "features": {
197
+ "intentUnderstanding": true,
198
+ "parameterExtraction": true,
199
+ "skillSelection": true,
200
+ "resultSummary": true,
201
+ "learningFeedback": true
202
+ }
203
+ }
204
+ }
205
+ ```
206
+
207
+ **方式 C:环境变量**
208
+
209
+ ```bash
210
+ export OPENAI_API_KEY=sk-your-api-key
211
+ export ANTHROPIC_API_KEY=sk-ant-your-api-key
212
+ ```
213
+
214
+ #### 测试 AI 连接
215
+
216
+ ```bash
217
+ # 测试默认 Provider
218
+ flowmind ai --test
219
+
220
+ # 测试指定 Provider
221
+ flowmind ai --test openai
222
+ flowmind ai --test anthropic
223
+ ```
224
+
225
+ #### 使用 AI 增强功能
226
+
227
+ ```bash
228
+ # AI 会理解意图、提取参数、选择技能、生成摘要
229
+ flowmind "帮我查一下最近1小时用户服务的错误日志"
230
+
231
+ # AI 会分析复杂的多步骤任务
232
+ flowmind "排查线上问题:用户下单失败,需要查看日志、检查数据库、分析原因"
233
+ ```
234
+
235
+ **特点:**
236
+ - ✅ 自然语言理解
237
+ - ✅ 智能参数提取
238
+ - ✅ 结果摘要生成
239
+ - ✅ 降级到规则引擎
240
+
241
+ ---
242
+
243
+ ### 方式3: Claude Code 集成(MCP Server)
244
+
245
+ 让 Claude Code 直接调用 FlowMind 的内部流程。
246
+
247
+ #### 步骤 1:安装 FlowMind
248
+
249
+ ```bash
250
+ npm install -g flowmind
251
+ ```
252
+
253
+ #### 步骤 2:配置 MCP Server
254
+
255
+ 在项目根目录创建 `.claude/settings.local.json`:
256
+
257
+ ```json
258
+ {
259
+ "mcpServers": {
260
+ "flowmind": {
261
+ "command": "flowmind-mcp",
262
+ "args": [],
263
+ "env": {
264
+ "OPENAI_API_KEY": "${OPENAI_API_KEY}"
265
+ }
266
+ }
267
+ }
268
+ }
269
+ ```
270
+
271
+ 或者使用完整路径:
272
+
273
+ ```json
274
+ {
275
+ "mcpServers": {
276
+ "flowmind": {
277
+ "command": "node",
278
+ "args": ["/path/to/flowmind/mcp/server.js"]
279
+ }
280
+ }
281
+ }
282
+ ```
283
+
284
+ #### 步骤 3:在 Claude Code 中使用
285
+
286
+ ```
287
+ 你:帮我查询最近1小时的错误日志
288
+
289
+ Claude:我来调用 FlowMind 帮你查询...
290
+ [调用 flowmind_process 工具]
291
+
292
+ 你:审查一下这个项目的代码质量
293
+
294
+ Claude:我来使用 FlowMind 的代码审查技能...
295
+ [调用 flowmind_skill_code-review 工具]
296
+ ```
297
+
298
+ #### 可用的 MCP 工具
299
+
300
+ | 工具名称 | 描述 |
301
+ |---------|------|
302
+ | `flowmind_process` | 处理请求的主入口 |
303
+ | `flowmind_list_skills` | 列出所有可用技能 |
304
+ | `flowmind_get_skill` | 获取技能详情 |
305
+ | `flowmind_ai_status` | 查看 AI 状态 |
306
+ | `flowmind_learning_stats` | 查看学习统计 |
307
+ | `flowmind_skill_<name>` | 执行特定技能 |
308
+
309
+ **特点:**
310
+ - ✅ Claude Code 直接调用
311
+ - ✅ 无需额外配置 MCP Server
312
+ - ✅ 保留学习和记忆功能
313
+ - ✅ 支持所有 FlowMind 技能
314
+
315
+ ---
316
+
317
+ ### 方式4: Codex 集成(JSON 输出)
318
+
319
+ 通过 JSON 输出与 Codex 集成。
320
+
321
+ ```bash
322
+ # 获取技能列表 (JSON 格式)
323
+ flowmind skills --json
324
+
325
+ # 获取技能详情
326
+ flowmind skill log-audit --json
327
+
328
+ # 执行并输出 JSON
329
+ flowmind process --json "查询日志"
330
+ ```
331
+
332
+ **Codex 脚本示例:**
333
+
334
+ ```python
335
+ import subprocess
336
+ import json
337
+
338
+ def flowmind_query(query):
339
+ result = subprocess.run(
340
+ ['flowmind', 'process', '--json', query],
341
+ capture_output=True,
342
+ text=True
343
+ )
344
+ return json.loads(result.stdout)
345
+
346
+ # 使用
347
+ result = flowmind_query("查询 traceId abc123 的日志")
348
+ print(result)
349
+ ```
350
+
351
+ ---
352
+
353
+ ### 使用方式对比
354
+
355
+ | 方式 | 适用场景 | 需要 AI | 需要 MCP | 特点 |
356
+ |------|---------|---------|----------|------|
357
+ | CLI 独立使用 | 快速执行、脚本集成 | ❌ | ❌ | 简单直接 |
358
+ | AI 模型接入 | 智能理解、复杂任务 | ✅ | ❌ | 自然语言 |
359
+ | Claude Code | 智能对话、多步骤 | ✅ | ✅ | 深度集成 |
360
+ | Codex 集成 | 自动化、CI/CD | ❌ | ❌ | 程序化调用 |
361
+
362
+ ---
363
+
116
364
  ## 🧠 工作原理
117
365
 
118
366
  ### 1. 多源代码定位
package/bin/flowmind.js CHANGED
@@ -52,7 +52,8 @@ program
52
52
  program
53
53
  .command('init')
54
54
  .description('Initialize FlowMind in current directory')
55
- .action(async () => {
55
+ .option('--ai <provider>', 'Initialize with AI provider (openai/anthropic/glm/mimo/qwen/ernie/deepseek/ollama)')
56
+ .action(async (options) => {
56
57
  showBanner();
57
58
 
58
59
  const spinner = ora('Initializing FlowMind...').start();
@@ -68,7 +69,7 @@ program
68
69
  const configPath = path.join(configDir, 'config.json');
69
70
  if (!await fs.pathExists(configPath)) {
70
71
  const defaultConfig = {
71
- version: '1.0.0',
72
+ version: '1.1.0',
72
73
  learning: {
73
74
  enabled: true,
74
75
  autoApply: true,
@@ -89,17 +90,89 @@ program
89
90
  await fs.writeJson(configPath, defaultConfig, { spaces: 2 });
90
91
  }
91
92
 
93
+ // Initialize AI if requested
94
+ if (options.ai) {
95
+ spinner.text = 'Configuring AI provider...';
96
+ const aiConfigPath = path.join(configDir, 'ai-config.json');
97
+
98
+ let aiConfig = {};
99
+ if (await fs.pathExists(aiConfigPath)) {
100
+ aiConfig = await fs.readJson(aiConfigPath);
101
+ }
102
+
103
+ // Set default provider
104
+ aiConfig.ai = aiConfig.ai || {};
105
+ aiConfig.ai.defaultProvider = options.ai;
106
+ aiConfig.ai.enabled = true;
107
+
108
+ // Prompt for API key based on provider
109
+ const apiKeyProviders = {
110
+ 'openai': { key: 'apiKey', message: 'Enter OpenAI API key:', env: 'OPENAI_API_KEY' },
111
+ 'anthropic': { key: 'apiKey', message: 'Enter Anthropic API key:', env: 'ANTHROPIC_API_KEY' },
112
+ 'glm': { key: 'apiKey', message: 'Enter Zhipu AI API key:', env: 'ZHIPU_API_KEY' },
113
+ 'mimo': { key: 'apiKey', message: 'Enter MiMo API key:', env: 'MIMO_API_KEY' },
114
+ 'qwen': { key: 'apiKey', message: 'Enter DashScope API key:', env: 'DASHSCOPE_API_KEY' },
115
+ 'ernie': { key: 'apiKey', message: 'Enter Baidu API key:', env: 'BAIDU_API_KEY' },
116
+ 'deepseek': { key: 'apiKey', message: 'Enter DeepSeek API key:', env: 'DEEPSEEK_API_KEY' }
117
+ };
118
+
119
+ const providerConfig = apiKeyProviders[options.ai];
120
+ if (providerConfig) {
121
+ const { apiKey } = await inquirer.prompt([
122
+ {
123
+ type: 'password',
124
+ name: 'apiKey',
125
+ message: providerConfig.message,
126
+ mask: '*'
127
+ }
128
+ ]);
129
+
130
+ aiConfig.ai.providers = aiConfig.ai.providers || {};
131
+ aiConfig.ai.providers[options.ai] = {
132
+ ...aiConfig.ai.providers[options.ai],
133
+ apiKey: apiKey,
134
+ enabled: true
135
+ };
136
+
137
+ // For ERNIE, also prompt for secret key
138
+ if (options.ai === 'ernie') {
139
+ const { secretKey } = await inquirer.prompt([
140
+ {
141
+ type: 'password',
142
+ name: 'secretKey',
143
+ message: 'Enter Baidu Secret key:',
144
+ mask: '*'
145
+ }
146
+ ]);
147
+ aiConfig.ai.providers[options.ai].secretKey = secretKey;
148
+ }
149
+ }
150
+
151
+ await fs.writeJson(aiConfigPath, aiConfig, { spaces: 2 });
152
+ console.log(chalk.green(`\n✓ AI provider configured: ${options.ai}`));
153
+ }
154
+
92
155
  spinner.succeed('FlowMind initialized successfully!');
93
156
 
94
157
  console.log(chalk.green('\n✓ Configuration created at:'), configDir);
95
158
  console.log(chalk.green('✓ Learning system ready'));
96
159
  console.log(chalk.green('✓ Scene mapping ready'));
97
160
 
161
+ if (options.ai) {
162
+ console.log(chalk.green(`✓ AI provider configured: ${options.ai}`));
163
+ }
164
+
98
165
  console.log(chalk.cyan('\nNext steps:'));
99
166
  console.log(' 1. Run', chalk.yellow('flowmind'), 'to start interactive mode');
100
167
  console.log(' 2. Or use', chalk.yellow('flowmind "your request"'), 'for single commands');
101
168
  console.log(' 3. FlowMind will learn from your corrections automatically');
102
169
 
170
+ if (!options.ai) {
171
+ console.log(chalk.cyan('\nTo enable AI features:'));
172
+ console.log(' Run', chalk.yellow('flowmind init --ai openai'), 'or', chalk.yellow('flowmind init --ai anthropic'));
173
+ console.log(' Or configure manually:', chalk.yellow('~/.flowmind/ai-config.json'));
174
+ }
175
+
103
176
  } catch (error) {
104
177
  spinner.fail('Failed to initialize FlowMind');
105
178
  console.error(chalk.red(error.message));
@@ -404,6 +477,82 @@ program
404
477
  }
405
478
  });
406
479
 
480
+ // AI command
481
+ program
482
+ .command('ai')
483
+ .description('Manage AI model configuration')
484
+ .option('-s, --status', 'Show AI model status')
485
+ .option('-l, --list', 'List available providers')
486
+ .option('-c, --config', 'Show AI configuration')
487
+ .option('-t, --test [provider]', 'Test AI provider connection')
488
+ .option('-j, --json', 'Output as JSON')
489
+ .action(async (options) => {
490
+ try {
491
+ const fm = await initFlowMind();
492
+
493
+ if (options.status) {
494
+ const status = fm.getAIStatus();
495
+ if (options.json) {
496
+ console.log(JSON.stringify(status, null, 2));
497
+ } else {
498
+ displayAIStatus(status);
499
+ }
500
+ } else if (options.list) {
501
+ const status = fm.getAIStatus();
502
+ const providers = Object.entries(status.providers).map(([name, info]) => ({
503
+ name,
504
+ ...info
505
+ }));
506
+ if (options.json) {
507
+ console.log(JSON.stringify({ providers }, null, 2));
508
+ } else {
509
+ console.log(chalk.cyan('\nAI Providers:'));
510
+ for (const provider of providers) {
511
+ const status = provider.initialized ? chalk.green('✓') : chalk.red('✗');
512
+ console.log(` ${status} ${provider.name}`);
513
+ if (provider.info?.model) {
514
+ console.log(` Model: ${provider.info.model}`);
515
+ }
516
+ }
517
+ }
518
+ } else if (options.config) {
519
+ const config = fm.config.get('ai', {});
520
+ if (options.json) {
521
+ console.log(JSON.stringify({ ai: config }, null, 2));
522
+ } else {
523
+ console.log(chalk.cyan('\nAI Configuration:'));
524
+ console.log(JSON.stringify(config, null, 2));
525
+ }
526
+ } else if (options.test !== undefined) {
527
+ const providerName = options.test || fm.ai.defaultProvider;
528
+ const provider = fm.ai.getProvider(providerName);
529
+ if (!provider) {
530
+ console.error(chalk.red(`Provider not found: ${providerName}`));
531
+ return;
532
+ }
533
+ console.log(chalk.cyan(`\nTesting ${providerName}...`));
534
+ try {
535
+ const result = await provider.complete('Hello, this is a test.', { maxTokens: 50 });
536
+ console.log(chalk.green('✓ Connection successful'));
537
+ console.log(chalk.white('Response:'), result.substring(0, 100) + '...');
538
+ } catch (error) {
539
+ console.log(chalk.red('✗ Connection failed'));
540
+ console.error(chalk.red(error.message));
541
+ }
542
+ } else {
543
+ // Default to status
544
+ const status = fm.getAIStatus();
545
+ if (options.json) {
546
+ console.log(JSON.stringify(status, null, 2));
547
+ } else {
548
+ displayAIStatus(status);
549
+ }
550
+ }
551
+ } catch (error) {
552
+ console.error(chalk.red('Error:'), error.message);
553
+ }
554
+ });
555
+
407
556
  // Interactive mode
408
557
  async function runInteractiveMode(fm) {
409
558
  showBanner();
@@ -802,6 +951,39 @@ function displayResourceConfig(config) {
802
951
  console.log(chalk.cyan('└─────────────────────────────────────────────────────┘'));
803
952
  }
804
953
 
954
+ function displayAIStatus(status) {
955
+ console.log(chalk.cyan('\n┌─────────────────────────────────────────────────────┐'));
956
+ console.log(chalk.cyan('│ AI Model Status │'));
957
+ console.log(chalk.cyan('├─────────────────────────────────────────────────────┤'));
958
+
959
+ const initialized = status.initialized ? chalk.green('✓') : chalk.red('✗');
960
+ console.log(chalk.cyan(`│ Initialized: ${initialized}`));
961
+ console.log(chalk.cyan(`│ Default Provider: ${status.defaultProvider || 'None'}`));
962
+
963
+ console.log(chalk.cyan('├─────────────────────────────────────────────────────┤'));
964
+ console.log(chalk.cyan('│ Features:'));
965
+
966
+ const features = status.features || {};
967
+ for (const [feature, enabled] of Object.entries(features)) {
968
+ const statusIcon = enabled ? chalk.green('✓') : chalk.red('✗');
969
+ console.log(chalk.cyan(`│ ${statusIcon} ${feature}`));
970
+ }
971
+
972
+ console.log(chalk.cyan('├─────────────────────────────────────────────────────┤'));
973
+ console.log(chalk.cyan('│ Providers:'));
974
+
975
+ const providers = status.providers || {};
976
+ for (const [name, info] of Object.entries(providers)) {
977
+ const statusIcon = info.initialized ? chalk.green('✓') : chalk.red('✗');
978
+ console.log(chalk.cyan(`│ ${statusIcon} ${name}`));
979
+ if (info.info?.model) {
980
+ console.log(chalk.cyan(`│ Model: ${info.info.model}`));
981
+ }
982
+ }
983
+
984
+ console.log(chalk.cyan('└─────────────────────────────────────────────────────┘'));
985
+ }
986
+
805
987
  function formatFileSize(bytes) {
806
988
  if (bytes === 0) return '0 B';
807
989
  const k = 1024;
@@ -0,0 +1,64 @@
1
+ {
2
+ "ai": {
3
+ "enabled": true,
4
+ "defaultProvider": "glm",
5
+ "fallbackToRules": true,
6
+ "providers": {
7
+ "openai": {
8
+ "apiKey": "${OPENAI_API_KEY}",
9
+ "model": "gpt-4",
10
+ "temperature": 0.3,
11
+ "maxTokens": 2000
12
+ },
13
+ "anthropic": {
14
+ "apiKey": "${ANTHROPIC_API_KEY}",
15
+ "model": "claude-3-sonnet-20240229",
16
+ "maxTokens": 2000,
17
+ "temperature": 0.3
18
+ },
19
+ "glm": {
20
+ "apiKey": "${ZHIPU_API_KEY}",
21
+ "model": "glm-4-flash",
22
+ "temperature": 0.3,
23
+ "maxTokens": 2000
24
+ },
25
+ "mimo": {
26
+ "apiKey": "${MIMO_API_KEY}",
27
+ "model": "mimo-7b",
28
+ "temperature": 0.3,
29
+ "maxTokens": 2000
30
+ },
31
+ "qwen": {
32
+ "apiKey": "${DASHSCOPE_API_KEY}",
33
+ "model": "qwen-turbo",
34
+ "temperature": 0.3,
35
+ "maxTokens": 2000
36
+ },
37
+ "ernie": {
38
+ "apiKey": "${BAIDU_API_KEY}",
39
+ "secretKey": "${BAIDU_SECRET_KEY}",
40
+ "model": "ernie-4.0-turbo-8k",
41
+ "temperature": 0.3,
42
+ "maxTokens": 2000
43
+ },
44
+ "deepseek": {
45
+ "apiKey": "${DEEPSEEK_API_KEY}",
46
+ "model": "deepseek-chat",
47
+ "temperature": 0.3,
48
+ "maxTokens": 2000
49
+ },
50
+ "ollama": {
51
+ "baseUrl": "http://localhost:11434",
52
+ "model": "llama2",
53
+ "temperature": 0.3
54
+ }
55
+ },
56
+ "features": {
57
+ "intentUnderstanding": true,
58
+ "parameterExtraction": true,
59
+ "skillSelection": true,
60
+ "resultSummary": true,
61
+ "learningFeedback": true
62
+ }
63
+ }
64
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "mcpServers": {
3
+ "flowmind": {
4
+ "command": "node",
5
+ "args": ["/path/to/flowmind/mcp/server.js"],
6
+ "env": {
7
+ "OPENAI_API_KEY": "${OPENAI_API_KEY}",
8
+ "ANTHROPIC_API_KEY": "${ANTHROPIC_API_KEY}"
9
+ }
10
+ }
11
+ }
12
+ }
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Base Model - AI 模型抽象基类
3
+ * 所有模型 Provider 必须继承此类并实现抽象方法
4
+ */
5
+
6
+ class BaseModel {
7
+ constructor(name, config = {}) {
8
+ this.name = name;
9
+ this.config = config;
10
+ this.initialized = false;
11
+ }
12
+
13
+ /**
14
+ * 初始化模型
15
+ * @returns {Promise<void>}
16
+ */
17
+ async init() {
18
+ throw new Error('init() must be implemented by subclass');
19
+ }
20
+
21
+ /**
22
+ * 发送聊天请求
23
+ * @param {Array} messages - 消息数组 [{role, content}]
24
+ * @param {Object} options - 请求选项
25
+ * @returns {Promise<string>} 模型响应
26
+ */
27
+ async chat(messages, options = {}) {
28
+ throw new Error('chat() must be implemented by subclass');
29
+ }
30
+
31
+ /**
32
+ * 发送补全请求
33
+ * @param {string} prompt - 提示词
34
+ * @param {Object} options - 请求选项
35
+ * @returns {Promise<string>} 模型响应
36
+ */
37
+ async complete(prompt, options = {}) {
38
+ throw new Error('complete() must be implemented by subclass');
39
+ }
40
+
41
+ /**
42
+ * 检查模型是否可用
43
+ * @returns {Promise<boolean>}
44
+ */
45
+ async isAvailable() {
46
+ throw new Error('isAvailable() must be implemented by subclass');
47
+ }
48
+
49
+ /**
50
+ * 获取模型信息
51
+ * @returns {Object}
52
+ */
53
+ getInfo() {
54
+ return {
55
+ name: this.name,
56
+ provider: this.constructor.name,
57
+ initialized: this.initialized
58
+ };
59
+ }
60
+
61
+ /**
62
+ * 验证配置
63
+ * @returns {boolean}
64
+ */
65
+ validateConfig() {
66
+ return true;
67
+ }
68
+ }
69
+
70
+ module.exports = BaseModel;
@@ -0,0 +1,29 @@
1
+ /**
2
+ * AI Module - AI 模型接入层入口
3
+ */
4
+
5
+ const ModelManager = require('./model-manager');
6
+ const BaseModel = require('./base-model');
7
+ const OpenAIProvider = require('./providers/openai');
8
+ const AnthropicProvider = require('./providers/anthropic');
9
+ const OllamaProvider = require('./providers/ollama');
10
+ const GLMProvider = require('./providers/glm');
11
+ const MiMoProvider = require('./providers/mimo');
12
+ const QwenProvider = require('./providers/qwen');
13
+ const ERNIEProvider = require('./providers/ernie');
14
+ const DeepSeekProvider = require('./providers/deepseek');
15
+ const prompts = require('./prompts');
16
+
17
+ module.exports = {
18
+ ModelManager,
19
+ BaseModel,
20
+ OpenAIProvider,
21
+ AnthropicProvider,
22
+ OllamaProvider,
23
+ GLMProvider,
24
+ MiMoProvider,
25
+ QwenProvider,
26
+ ERNIEProvider,
27
+ DeepSeekProvider,
28
+ prompts
29
+ };