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.
@@ -0,0 +1,111 @@
1
+ /**
2
+ * ERNIE Provider - 百度文心一言模型接入
3
+ * 支持 ERNIE-4.0-Turbo-8K、ERNIE-3.5-8K 等模型
4
+ */
5
+
6
+ const BaseModel = require('../base-model');
7
+
8
+ class ERNIEProvider extends BaseModel {
9
+ constructor(config = {}) {
10
+ super('ernie', config);
11
+ this.apiKey = config.apiKey || process.env.BAIDU_API_KEY;
12
+ this.secretKey = config.secretKey || process.env.BAIDU_SECRET_KEY;
13
+ this.model = config.model || 'ernie-4.0-turbo-8k';
14
+ this.baseUrl = config.baseUrl || 'https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop';
15
+ this.temperature = config.temperature ?? 0.3;
16
+ this.maxTokens = config.maxTokens ?? 2000;
17
+ this.accessToken = null;
18
+ }
19
+
20
+ async init() {
21
+ if (!this.apiKey || !this.secretKey) {
22
+ throw new Error('Baidu API key and secret key are required. Set BAIDU_API_KEY and BAIDU_SECRET_KEY environment variables or provide in config.');
23
+ }
24
+ await this.refreshAccessToken();
25
+ this.initialized = true;
26
+ }
27
+
28
+ async refreshAccessToken() {
29
+ const response = await fetch(
30
+ `https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=${this.apiKey}&client_secret=${this.secretKey}`,
31
+ { method: 'POST' }
32
+ );
33
+
34
+ if (!response.ok) {
35
+ throw new Error('Failed to get Baidu access token');
36
+ }
37
+
38
+ const data = await response.json();
39
+ this.accessToken = data.access_token;
40
+ }
41
+
42
+ validateConfig() {
43
+ return !!this.apiKey && !!this.secretKey;
44
+ }
45
+
46
+ async chat(messages, options = {}) {
47
+ if (!this.initialized) {
48
+ await this.init();
49
+ }
50
+
51
+ const model = options.model || this.model;
52
+ const endpoint = this.getEndpoint(model);
53
+
54
+ const response = await fetch(`${this.baseUrl}${endpoint}?access_token=${this.accessToken}`, {
55
+ method: 'POST',
56
+ headers: {
57
+ 'Content-Type': 'application/json'
58
+ },
59
+ body: JSON.stringify({
60
+ messages: messages,
61
+ temperature: options.temperature ?? this.temperature,
62
+ max_output_tokens: options.maxTokens ?? this.maxTokens
63
+ })
64
+ });
65
+
66
+ if (!response.ok) {
67
+ const error = await response.text();
68
+ throw new Error(`ERNIE API error: ${response.status} - ${error}`);
69
+ }
70
+
71
+ const data = await response.json();
72
+ return data.result;
73
+ }
74
+
75
+ getEndpoint(model) {
76
+ const endpoints = {
77
+ 'ernie-4.0-turbo-8k': '/chat/ernie-4.0-turbo-8k',
78
+ 'ernie-4.0-8k': '/chat/ernie-4.0-8k',
79
+ 'ernie-3.5-8k': '/chat/ernie-3.5-8k',
80
+ 'ernie-3.5-4k-0205': '/chat/ernie-3.5-4k-0205',
81
+ 'ernie-speed-8k': '/chat/ernie-speed-8k',
82
+ 'ernie-lite-8k': '/chat/ernie-lite-8k'
83
+ };
84
+ return endpoints[model] || `/chat/${model}`;
85
+ }
86
+
87
+ async complete(prompt, options = {}) {
88
+ return this.chat([{ role: 'user', content: prompt }], options);
89
+ }
90
+
91
+ async isAvailable() {
92
+ try {
93
+ if (!this.apiKey || !this.secretKey) return false;
94
+ await this.refreshAccessToken();
95
+ return true;
96
+ } catch {
97
+ return false;
98
+ }
99
+ }
100
+
101
+ getInfo() {
102
+ return {
103
+ ...super.getInfo(),
104
+ model: this.model,
105
+ baseUrl: this.baseUrl,
106
+ provider: 'Baidu'
107
+ };
108
+ }
109
+ }
110
+
111
+ module.exports = ERNIEProvider;
@@ -0,0 +1,80 @@
1
+ /**
2
+ * GLM Provider - 智谱AI GLM 模型接入
3
+ * 支持 GLM-4、GLM-4-Flash、ChatGLM 等模型
4
+ */
5
+
6
+ const BaseModel = require('../base-model');
7
+
8
+ class GLMProvider extends BaseModel {
9
+ constructor(config = {}) {
10
+ super('glm', config);
11
+ this.apiKey = config.apiKey || process.env.ZHIPU_API_KEY;
12
+ this.model = config.model || 'glm-4-flash';
13
+ this.baseUrl = config.baseUrl || 'https://open.bigmodel.cn/api/paas/v4';
14
+ this.temperature = config.temperature ?? 0.3;
15
+ this.maxTokens = config.maxTokens ?? 2000;
16
+ }
17
+
18
+ async init() {
19
+ if (!this.apiKey) {
20
+ throw new Error('Zhipu API key is required. Set ZHIPU_API_KEY environment variable or provide in config.');
21
+ }
22
+ this.initialized = true;
23
+ }
24
+
25
+ validateConfig() {
26
+ return !!this.apiKey;
27
+ }
28
+
29
+ async chat(messages, options = {}) {
30
+ if (!this.initialized) {
31
+ await this.init();
32
+ }
33
+
34
+ const response = await fetch(`${this.baseUrl}/chat/completions`, {
35
+ method: 'POST',
36
+ headers: {
37
+ 'Content-Type': 'application/json',
38
+ 'Authorization': `Bearer ${this.apiKey}`
39
+ },
40
+ body: JSON.stringify({
41
+ model: options.model || this.model,
42
+ messages: messages,
43
+ temperature: options.temperature ?? this.temperature,
44
+ max_tokens: options.maxTokens ?? this.maxTokens
45
+ })
46
+ });
47
+
48
+ if (!response.ok) {
49
+ const error = await response.text();
50
+ throw new Error(`GLM API error: ${response.status} - ${error}`);
51
+ }
52
+
53
+ const data = await response.json();
54
+ return data.choices[0].message.content;
55
+ }
56
+
57
+ async complete(prompt, options = {}) {
58
+ return this.chat([{ role: 'user', content: prompt }], options);
59
+ }
60
+
61
+ async isAvailable() {
62
+ try {
63
+ if (!this.apiKey) return false;
64
+ return true;
65
+ } catch {
66
+ return false;
67
+ }
68
+ }
69
+
70
+ getInfo() {
71
+ return {
72
+ ...super.getInfo(),
73
+ model: this.model,
74
+ baseUrl: this.baseUrl,
75
+ provider: 'Zhipu AI'
76
+ };
77
+ }
78
+ }
79
+
80
+ module.exports = GLMProvider;
@@ -0,0 +1,80 @@
1
+ /**
2
+ * MiMo Provider - 小米 MiMo 模型接入
3
+ * 支持 MiMo-7B 等模型
4
+ */
5
+
6
+ const BaseModel = require('../base-model');
7
+
8
+ class MiMoProvider extends BaseModel {
9
+ constructor(config = {}) {
10
+ super('mimo', config);
11
+ this.apiKey = config.apiKey || process.env.MIMO_API_KEY;
12
+ this.model = config.model || 'mimo-7b';
13
+ this.baseUrl = config.baseUrl || 'https://api.mimo.ai/v1';
14
+ this.temperature = config.temperature ?? 0.3;
15
+ this.maxTokens = config.maxTokens ?? 2000;
16
+ }
17
+
18
+ async init() {
19
+ if (!this.apiKey) {
20
+ throw new Error('MiMo API key is required. Set MIMO_API_KEY environment variable or provide in config.');
21
+ }
22
+ this.initialized = true;
23
+ }
24
+
25
+ validateConfig() {
26
+ return !!this.apiKey;
27
+ }
28
+
29
+ async chat(messages, options = {}) {
30
+ if (!this.initialized) {
31
+ await this.init();
32
+ }
33
+
34
+ const response = await fetch(`${this.baseUrl}/chat/completions`, {
35
+ method: 'POST',
36
+ headers: {
37
+ 'Content-Type': 'application/json',
38
+ 'Authorization': `Bearer ${this.apiKey}`
39
+ },
40
+ body: JSON.stringify({
41
+ model: options.model || this.model,
42
+ messages: messages,
43
+ temperature: options.temperature ?? this.temperature,
44
+ max_tokens: options.maxTokens ?? this.maxTokens
45
+ })
46
+ });
47
+
48
+ if (!response.ok) {
49
+ const error = await response.text();
50
+ throw new Error(`MiMo API error: ${response.status} - ${error}`);
51
+ }
52
+
53
+ const data = await response.json();
54
+ return data.choices[0].message.content;
55
+ }
56
+
57
+ async complete(prompt, options = {}) {
58
+ return this.chat([{ role: 'user', content: prompt }], options);
59
+ }
60
+
61
+ async isAvailable() {
62
+ try {
63
+ if (!this.apiKey) return false;
64
+ return true;
65
+ } catch {
66
+ return false;
67
+ }
68
+ }
69
+
70
+ getInfo() {
71
+ return {
72
+ ...super.getInfo(),
73
+ model: this.model,
74
+ baseUrl: this.baseUrl,
75
+ provider: 'Xiaomi'
76
+ };
77
+ }
78
+ }
79
+
80
+ module.exports = MiMoProvider;
@@ -0,0 +1,147 @@
1
+ /**
2
+ * Ollama Provider - 本地模型接入
3
+ * 支持 Ollama 运行的本地模型(Llama2、Mistral、CodeLlama 等)
4
+ */
5
+
6
+ const BaseModel = require('../base-model');
7
+
8
+ class OllamaProvider extends BaseModel {
9
+ constructor(config = {}) {
10
+ super('ollama', config);
11
+ this.baseUrl = config.baseUrl || 'http://localhost:11434';
12
+ this.model = config.model || 'llama2';
13
+ this.temperature = config.temperature ?? 0.3;
14
+ }
15
+
16
+ async init() {
17
+ // 检查 Ollama 服务是否可用
18
+ const available = await this.isAvailable();
19
+ if (!available) {
20
+ throw new Error(`Ollama service is not available at ${this.baseUrl}. Please start Ollama first.`);
21
+ }
22
+ this.initialized = true;
23
+ }
24
+
25
+ validateConfig() {
26
+ return !!this.baseUrl && !!this.model;
27
+ }
28
+
29
+ async chat(messages, options = {}) {
30
+ if (!this.initialized) {
31
+ await this.init();
32
+ }
33
+
34
+ // 转换消息格式为 Ollama 格式
35
+ const prompt = this._convertMessagesToPrompt(messages);
36
+
37
+ const response = await fetch(`${this.baseUrl}/api/generate`, {
38
+ method: 'POST',
39
+ headers: {
40
+ 'Content-Type': 'application/json'
41
+ },
42
+ body: JSON.stringify({
43
+ model: options.model || this.model,
44
+ prompt: prompt,
45
+ stream: false,
46
+ options: {
47
+ temperature: options.temperature ?? this.temperature,
48
+ num_predict: options.maxTokens ?? 2000
49
+ }
50
+ })
51
+ });
52
+
53
+ if (!response.ok) {
54
+ const error = await response.text();
55
+ throw new Error(`Ollama API error: ${response.status} - ${error}`);
56
+ }
57
+
58
+ const data = await response.json();
59
+ return data.response;
60
+ }
61
+
62
+ async complete(prompt, options = {}) {
63
+ if (!this.initialized) {
64
+ await this.init();
65
+ }
66
+
67
+ const response = await fetch(`${this.baseUrl}/api/generate`, {
68
+ method: 'POST',
69
+ headers: {
70
+ 'Content-Type': 'application/json'
71
+ },
72
+ body: JSON.stringify({
73
+ model: options.model || this.model,
74
+ prompt: prompt,
75
+ stream: false,
76
+ options: {
77
+ temperature: options.temperature ?? this.temperature,
78
+ num_predict: options.maxTokens ?? 2000
79
+ }
80
+ })
81
+ });
82
+
83
+ if (!response.ok) {
84
+ const error = await response.text();
85
+ throw new Error(`Ollama API error: ${response.status} - ${error}`);
86
+ }
87
+
88
+ const data = await response.json();
89
+ return data.response;
90
+ }
91
+
92
+ async isAvailable() {
93
+ try {
94
+ const response = await fetch(`${this.baseUrl}/api/tags`, {
95
+ method: 'GET',
96
+ signal: AbortSignal.timeout(5000) // 5秒超时
97
+ });
98
+ return response.ok;
99
+ } catch {
100
+ return false;
101
+ }
102
+ }
103
+
104
+ /**
105
+ * 获取可用模型列表
106
+ * @returns {Promise<Array>}
107
+ */
108
+ async listModels() {
109
+ try {
110
+ const response = await fetch(`${this.baseUrl}/api/tags`);
111
+ if (!response.ok) return [];
112
+ const data = await response.json();
113
+ return data.models || [];
114
+ } catch {
115
+ return [];
116
+ }
117
+ }
118
+
119
+ /**
120
+ * 将消息数组转换为单个提示词
121
+ * @private
122
+ */
123
+ _convertMessagesToPrompt(messages) {
124
+ let prompt = '';
125
+ for (const msg of messages) {
126
+ if (msg.role === 'system') {
127
+ prompt += `[System]: ${msg.content}\n\n`;
128
+ } else if (msg.role === 'user') {
129
+ prompt += `[User]: ${msg.content}\n\n`;
130
+ } else if (msg.role === 'assistant') {
131
+ prompt += `[Assistant]: ${msg.content}\n\n`;
132
+ }
133
+ }
134
+ prompt += '[Assistant]: ';
135
+ return prompt;
136
+ }
137
+
138
+ getInfo() {
139
+ return {
140
+ ...super.getInfo(),
141
+ model: this.model,
142
+ baseUrl: this.baseUrl
143
+ };
144
+ }
145
+ }
146
+
147
+ module.exports = OllamaProvider;
@@ -0,0 +1,82 @@
1
+ /**
2
+ * OpenAI Provider - OpenAI GPT 模型接入
3
+ */
4
+
5
+ const BaseModel = require('../base-model');
6
+
7
+ class OpenAIProvider extends BaseModel {
8
+ constructor(config = {}) {
9
+ super('openai', config);
10
+ this.apiKey = config.apiKey || process.env.OPENAI_API_KEY;
11
+ this.model = config.model || 'gpt-4';
12
+ this.baseUrl = config.baseUrl || 'https://api.openai.com/v1';
13
+ this.temperature = config.temperature ?? 0.3;
14
+ this.maxTokens = config.maxTokens ?? 2000;
15
+ }
16
+
17
+ async init() {
18
+ if (!this.apiKey) {
19
+ throw new Error('OpenAI API key is required. Set OPENAI_API_KEY environment variable or provide in config.');
20
+ }
21
+ this.initialized = true;
22
+ }
23
+
24
+ validateConfig() {
25
+ return !!this.apiKey;
26
+ }
27
+
28
+ async chat(messages, options = {}) {
29
+ if (!this.initialized) {
30
+ await this.init();
31
+ }
32
+
33
+ const response = await fetch(`${this.baseUrl}/chat/completions`, {
34
+ method: 'POST',
35
+ headers: {
36
+ 'Content-Type': 'application/json',
37
+ 'Authorization': `Bearer ${this.apiKey}`
38
+ },
39
+ body: JSON.stringify({
40
+ model: options.model || this.model,
41
+ messages: messages,
42
+ temperature: options.temperature ?? this.temperature,
43
+ max_tokens: options.maxTokens ?? this.maxTokens,
44
+ response_format: options.responseFormat || undefined
45
+ })
46
+ });
47
+
48
+ if (!response.ok) {
49
+ const error = await response.text();
50
+ throw new Error(`OpenAI API error: ${response.status} - ${error}`);
51
+ }
52
+
53
+ const data = await response.json();
54
+ return data.choices[0].message.content;
55
+ }
56
+
57
+ async complete(prompt, options = {}) {
58
+ return this.chat([{ role: 'user', content: prompt }], options);
59
+ }
60
+
61
+ async isAvailable() {
62
+ try {
63
+ if (!this.apiKey) return false;
64
+ const response = await fetch(`${this.baseUrl}/models`, {
65
+ headers: { 'Authorization': `Bearer ${this.apiKey}` }
66
+ });
67
+ return response.ok;
68
+ } catch {
69
+ return false;
70
+ }
71
+ }
72
+
73
+ getInfo() {
74
+ return {
75
+ ...super.getInfo(),
76
+ model: this.model,
77
+ baseUrl: this.baseUrl
78
+ };
79
+ }
80
+ }
81
+
82
+ module.exports = OpenAIProvider;
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Qwen Provider - 阿里云通义千问模型接入
3
+ * 支持 Qwen-Turbo、Qwen-Plus、Qwen-Max 等模型
4
+ */
5
+
6
+ const BaseModel = require('../base-model');
7
+
8
+ class QwenProvider extends BaseModel {
9
+ constructor(config = {}) {
10
+ super('qwen', config);
11
+ this.apiKey = config.apiKey || process.env.DASHSCOPE_API_KEY;
12
+ this.model = config.model || 'qwen-turbo';
13
+ this.baseUrl = config.baseUrl || 'https://dashscope.aliyuncs.com/compatible-mode/v1';
14
+ this.temperature = config.temperature ?? 0.3;
15
+ this.maxTokens = config.maxTokens ?? 2000;
16
+ }
17
+
18
+ async init() {
19
+ if (!this.apiKey) {
20
+ throw new Error('DashScope API key is required. Set DASHSCOPE_API_KEY environment variable or provide in config.');
21
+ }
22
+ this.initialized = true;
23
+ }
24
+
25
+ validateConfig() {
26
+ return !!this.apiKey;
27
+ }
28
+
29
+ async chat(messages, options = {}) {
30
+ if (!this.initialized) {
31
+ await this.init();
32
+ }
33
+
34
+ const response = await fetch(`${this.baseUrl}/chat/completions`, {
35
+ method: 'POST',
36
+ headers: {
37
+ 'Content-Type': 'application/json',
38
+ 'Authorization': `Bearer ${this.apiKey}`
39
+ },
40
+ body: JSON.stringify({
41
+ model: options.model || this.model,
42
+ messages: messages,
43
+ temperature: options.temperature ?? this.temperature,
44
+ max_tokens: options.maxTokens ?? this.maxTokens
45
+ })
46
+ });
47
+
48
+ if (!response.ok) {
49
+ const error = await response.text();
50
+ throw new Error(`Qwen API error: ${response.status} - ${error}`);
51
+ }
52
+
53
+ const data = await response.json();
54
+ return data.choices[0].message.content;
55
+ }
56
+
57
+ async complete(prompt, options = {}) {
58
+ return this.chat([{ role: 'user', content: prompt }], options);
59
+ }
60
+
61
+ async isAvailable() {
62
+ try {
63
+ if (!this.apiKey) return false;
64
+ return true;
65
+ } catch {
66
+ return false;
67
+ }
68
+ }
69
+
70
+ getInfo() {
71
+ return {
72
+ ...super.getInfo(),
73
+ model: this.model,
74
+ baseUrl: this.baseUrl,
75
+ provider: 'Alibaba Cloud'
76
+ };
77
+ }
78
+ }
79
+
80
+ module.exports = QwenProvider;