@astack-tech/integrations 0.1.1-beta.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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Archer (qddegtya)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1 @@
1
+ > @astack-tech/integrations
package/dist/index.cjs ADDED
@@ -0,0 +1,221 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var src_exports = {};
32
+ __export(src_exports, {
33
+ ModelProvider: () => model_provider_exports
34
+ });
35
+ module.exports = __toCommonJS(src_exports);
36
+
37
+ // src/model-provider/index.ts
38
+ var model_provider_exports = {};
39
+ __export(model_provider_exports, {
40
+ Deepseek: () => deepseek_default
41
+ });
42
+
43
+ // src/model-provider/deepseek/index.ts
44
+ var import_core = require("@astack-tech/core");
45
+ var import_openai = __toESM(require("openai"), 1);
46
+ var Deepseek = class extends import_core.Component {
47
+ constructor(config) {
48
+ super({});
49
+ this.client = new import_openai.default({
50
+ apiKey: config.apiKey,
51
+ baseURL: config.baseURL || "https://api.deepseek.com/v1"
52
+ });
53
+ this.model = config.model || "deepseek-chat";
54
+ this.temperature = config.temperature ?? 0.7;
55
+ this.maxTokens = config.maxTokens;
56
+ this.topP = config.topP;
57
+ this.systemPrompt = config.systemPrompt;
58
+ if (config.rawTools && config.rawTools.length > 0) {
59
+ this.tools = config.rawTools.map((tool) => ({
60
+ type: "function",
61
+ function: {
62
+ name: tool.name,
63
+ description: tool.description,
64
+ parameters: tool.parameters || {}
65
+ }
66
+ }));
67
+ } else {
68
+ this.tools = config.tools;
69
+ }
70
+ import_core.Component.Port.I("prompt").attach(this);
71
+ import_core.Component.Port.I("messages").attach(this);
72
+ import_core.Component.Port.O("completion").attach(this);
73
+ import_core.Component.Port.O("message").attach(this);
74
+ }
75
+ /**
76
+ * 生成文本完成
77
+ * @param prompt 提示文本
78
+ * @returns 生成的文本
79
+ */
80
+ async generateCompletion(prompt) {
81
+ const messages = [];
82
+ if (this.systemPrompt) {
83
+ messages.push({
84
+ role: "system",
85
+ content: this.systemPrompt
86
+ });
87
+ }
88
+ messages.push({
89
+ role: "user",
90
+ content: prompt
91
+ });
92
+ const requestParams = {
93
+ model: this.model,
94
+ messages,
95
+ temperature: this.temperature,
96
+ max_tokens: this.maxTokens,
97
+ top_p: this.topP
98
+ };
99
+ if (this.tools && this.tools.length > 0) {
100
+ requestParams.tools = this.tools;
101
+ }
102
+ const response = await this.client.chat.completions.create(requestParams);
103
+ if (response.choices[0].message.tool_calls && response.choices[0].message.tool_calls.length > 0) {
104
+ return JSON.stringify(response.choices[0].message);
105
+ }
106
+ return response.choices[0].message.content || "";
107
+ }
108
+ /**
109
+ * 处理对话消息
110
+ * @param messages 对话消息数组
111
+ * @param options 可选的调用选项,包含临时工具列表
112
+ * @returns 生成的响应消息
113
+ */
114
+ async chatCompletion(messages, options) {
115
+ const formattedMessages = [];
116
+ if (this.systemPrompt) {
117
+ formattedMessages.push({
118
+ role: "system",
119
+ content: this.systemPrompt
120
+ });
121
+ }
122
+ formattedMessages.push(
123
+ ...messages.map((msg) => {
124
+ const formattedMsg = {
125
+ role: msg.role,
126
+ content: msg.content
127
+ };
128
+ if (msg.role === "tool" && msg.tool_call_id) {
129
+ formattedMsg.tool_call_id = msg.tool_call_id;
130
+ }
131
+ return formattedMsg;
132
+ })
133
+ );
134
+ const requestParams = {
135
+ model: this.model,
136
+ messages: formattedMessages,
137
+ temperature: this.temperature,
138
+ max_tokens: this.maxTokens,
139
+ top_p: this.topP
140
+ };
141
+ const toolsToUse = options?.temporaryTools || this.tools;
142
+ if (toolsToUse && toolsToUse.length > 0) {
143
+ const formattedTools = toolsToUse.map((tool) => {
144
+ const typedTool = tool;
145
+ if (typedTool.type === "function") {
146
+ return tool;
147
+ }
148
+ return {
149
+ type: "function",
150
+ function: {
151
+ name: typedTool.name,
152
+ description: typedTool.description,
153
+ parameters: typedTool.parameters || {}
154
+ }
155
+ };
156
+ });
157
+ requestParams.tools = formattedTools;
158
+ }
159
+ const response = await this.client.chat.completions.create(requestParams);
160
+ const responseMessage = response.choices[0].message;
161
+ const result = {
162
+ role: "assistant",
163
+ content: responseMessage.content || ""
164
+ };
165
+ if (responseMessage.tool_calls && responseMessage.tool_calls.length > 0) {
166
+ result.tool_calls = responseMessage.tool_calls.map((toolCall) => ({
167
+ id: toolCall.id,
168
+ tool_name: toolCall.function.name,
169
+ arguments: JSON.parse(toolCall.function.arguments || "{}")
170
+ }));
171
+ }
172
+ return result;
173
+ }
174
+ /**
175
+ * 在独立模式下运行组件
176
+ * @param input 输入参数,可以是提示文本或对话消息数组
177
+ * @returns 生成的文本或响应消息
178
+ */
179
+ async run(input) {
180
+ if (typeof input === "string") {
181
+ return this.generateCompletion(input);
182
+ } else {
183
+ return this.chatCompletion(input);
184
+ }
185
+ }
186
+ /**
187
+ * 在流水线中运行组件
188
+ * @param $i 输入端口
189
+ * @param $o 输出端口
190
+ */
191
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
192
+ _transform($i, $o) {
193
+ $i("prompt").receive(async (prompt) => {
194
+ try {
195
+ const completion = await this.generateCompletion(prompt);
196
+ $o("completion").send(completion);
197
+ } catch (error) {
198
+ console.error("Deepseek API \u8C03\u7528\u9519\u8BEF:", error);
199
+ $o("completion").send("API \u8C03\u7528\u9519\u8BEF");
200
+ }
201
+ });
202
+ $i("messages").receive(async (messages) => {
203
+ try {
204
+ const responseMessage = await this.chatCompletion(messages);
205
+ $o("message").send(responseMessage);
206
+ } catch (error) {
207
+ console.error("Deepseek API \u8C03\u7528\u9519\u8BEF:", error);
208
+ $o("message").send({
209
+ role: "assistant",
210
+ content: "API \u8C03\u7528\u9519\u8BEF"
211
+ });
212
+ }
213
+ });
214
+ }
215
+ };
216
+ var deepseek_default = Deepseek;
217
+ // Annotate the CommonJS export names for ESM import in node:
218
+ 0 && (module.exports = {
219
+ ModelProvider
220
+ });
221
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/model-provider/index.ts","../src/model-provider/deepseek/index.ts"],"sourcesContent":["/**\n * Astack 集成包\n *\n * 提供与各种外部服务和平台的集成组件\n */\n\n// 导出模型提供者组件\nexport * as ModelProvider from './model-provider';\n","export {\n default as Deepseek,\n type Message as DeepseekMessage,\n type ToolCall as DeepseekToolCall,\n type DeepseekConfig,\n type MessageRole as DeepseekMessageRole,\n} from './deepseek';\n","import { Component } from '@astack-tech/core';\nimport OpenAI from 'openai';\n\n/**\n * Deepseek 模型提供者配置\n */\nexport interface DeepseekConfig {\n /**\n * API 密钥\n */\n apiKey: string;\n\n /**\n * 使用的模型名称\n * 默认为 'deepseek-chat'\n */\n model?: string;\n\n /**\n * 自定义 API 基础 URL\n * 默认为 Deepseek 官方 API 地址\n */\n baseURL?: string;\n\n /**\n * 温度参数,控制输出的随机性\n */\n temperature?: number;\n\n /**\n * 最大生成的 token 数\n */\n maxTokens?: number;\n\n /**\n * 采样概率\n */\n topP?: number;\n\n /**\n * 系统提示消息\n */\n systemPrompt?: string;\n\n /**\n * 工具实例数组,直接传递工具实例\n * 每个工具应具有 name、description 和 parameters 属性\n */\n rawTools?: Array<{\n name: string;\n description: string;\n parameters?: Record<string, unknown>;\n }>;\n\n /**\n * API 格式的工具定义数组,与 rawTools 二选一\n * 使用 OpenAI 兼容的工具定义格式\n */\n tools?: unknown[];\n}\n\n/**\n * 消息角色类型\n */\nexport type MessageRole = 'system' | 'user' | 'assistant' | 'tool';\n\n/**\n * 工具调用\n */\nexport interface ToolCall {\n /**\n * 工具调用 ID\n */\n id?: string;\n\n /**\n * 工具名称\n */\n tool_name: string;\n\n /**\n * 工具调用参数\n */\n arguments: Record<string, unknown>;\n}\n\n/**\n * 对话消息类型\n */\nexport interface Message {\n /**\n * 消息角色\n */\n role: MessageRole;\n\n /**\n * 消息内容\n */\n content?: string;\n\n /**\n * 工具调用\n */\n tool_calls?: ToolCall[];\n\n /**\n * 工具调用 ID,用于工具响应消息\n */\n tool_call_id?: string;\n}\n\n/**\n * Deepseek 组件\n *\n * 使用 OpenAI 兼容接口调用 Deepseek 模型\n *\n * 输入:\n * - prompt: 文本提示\n * - messages: 对话消息数组\n *\n * 输出:\n * - completion: 生成的文本完成\n * - message: 生成的响应消息\n */\nclass Deepseek extends Component {\n // OpenAI 客户端实例\n private client: OpenAI;\n\n // 配置选项\n private model: string;\n private temperature: number;\n private maxTokens?: number;\n private topP?: number;\n private systemPrompt?: string;\n private tools?: unknown[];\n\n constructor(config: DeepseekConfig) {\n super({});\n\n // 配置客户端\n this.client = new OpenAI({\n apiKey: config.apiKey,\n baseURL: config.baseURL || 'https://api.deepseek.com/v1',\n });\n\n // 保存基本配置\n this.model = config.model || 'deepseek-chat';\n this.temperature = config.temperature ?? 0.7;\n this.maxTokens = config.maxTokens;\n this.topP = config.topP;\n this.systemPrompt = config.systemPrompt;\n\n // 处理工具配置,优先使用 rawTools\n if (config.rawTools && config.rawTools.length > 0) {\n // 将工具实例转换为 API 格式\n this.tools = config.rawTools.map(tool => ({\n type: 'function',\n function: {\n name: tool.name,\n description: tool.description,\n parameters: tool.parameters || {},\n },\n }));\n } else {\n // 使用直接提供的 API 格式工具\n this.tools = config.tools;\n }\n\n // 重命名端口\n Component.Port.I('prompt').attach(this);\n Component.Port.I('messages').attach(this);\n Component.Port.O('completion').attach(this);\n Component.Port.O('message').attach(this);\n }\n\n /**\n * 生成文本完成\n * @param prompt 提示文本\n * @returns 生成的文本\n */\n async generateCompletion(prompt: string): Promise<string> {\n const messages: Array<OpenAI.Chat.ChatCompletionMessageParam> = [];\n\n // 添加系统提示\n if (this.systemPrompt) {\n messages.push({\n role: 'system',\n content: this.systemPrompt,\n });\n }\n\n // 添加用户提示\n messages.push({\n role: 'user',\n content: prompt,\n });\n\n // 创建请求参数\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const requestParams: any = {\n model: this.model,\n messages,\n temperature: this.temperature,\n max_tokens: this.maxTokens,\n top_p: this.topP,\n };\n\n // 如果有工具定义,添加到请求中\n if (this.tools && this.tools.length > 0) {\n requestParams.tools = this.tools;\n }\n\n // 调用 API\n const response = await this.client.chat.completions.create(requestParams);\n\n // 处理工具调用结果\n if (\n response.choices[0].message.tool_calls &&\n response.choices[0].message.tool_calls.length > 0\n ) {\n return JSON.stringify(response.choices[0].message);\n }\n\n return response.choices[0].message.content || '';\n }\n\n /**\n * 处理对话消息\n * @param messages 对话消息数组\n * @param options 可选的调用选项,包含临时工具列表\n * @returns 生成的响应消息\n */\n async chatCompletion(\n messages: Message[],\n options?: { temporaryTools?: unknown[] }\n ): Promise<Message> {\n // 转换消息格式\n const formattedMessages: Array<OpenAI.Chat.ChatCompletionMessageParam> = [];\n\n // 添加系统提示\n if (this.systemPrompt) {\n formattedMessages.push({\n role: 'system',\n content: this.systemPrompt,\n });\n }\n\n // 添加用户提供的消息\n formattedMessages.push(\n ...messages.map(msg => {\n // 基本消息结构\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const formattedMsg: any = {\n role: msg.role,\n content: msg.content,\n };\n\n // 如果有工具调用 ID,添加到消息中\n if (msg.role === 'tool' && msg.tool_call_id) {\n formattedMsg.tool_call_id = msg.tool_call_id;\n }\n\n return formattedMsg;\n })\n );\n\n // 创建请求参数\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const requestParams: any = {\n model: this.model,\n messages: formattedMessages,\n temperature: this.temperature,\n max_tokens: this.maxTokens,\n top_p: this.topP,\n };\n\n // 决定使用哪些工具\n // 如果提供了临时工具,优先使用临时工具\n const toolsToUse = options?.temporaryTools || this.tools;\n\n // 如果有工具定义,添加到请求中\n if (toolsToUse && toolsToUse.length > 0) {\n // 检查工具格式并转换,确保符合 Deepseek API 要求\n const formattedTools = toolsToUse.map(tool => {\n // 使用类型断言来处理 unknown 类型\n type ToolType = {\n type?: string;\n name?: string;\n description?: string;\n parameters?: Record<string, unknown>;\n };\n\n const typedTool = tool as ToolType;\n\n // 如果工具已经是 API 格式,直接返回\n if (typedTool.type === 'function') {\n return tool;\n }\n\n // 如果是简单工具实例,转换为 API 格式\n return {\n type: 'function',\n function: {\n name: typedTool.name,\n description: typedTool.description,\n parameters: typedTool.parameters || {},\n },\n };\n });\n\n requestParams.tools = formattedTools;\n }\n\n // 调用 API\n const response = await this.client.chat.completions.create(requestParams);\n\n // 解析响应\n const responseMessage = response.choices[0].message;\n\n // 转换为内部消息格式\n const result: Message = {\n role: 'assistant',\n content: responseMessage.content || '',\n };\n\n // 如果有工具调用,添加到结果中\n if (responseMessage.tool_calls && responseMessage.tool_calls.length > 0) {\n result.tool_calls = responseMessage.tool_calls.map(toolCall => ({\n id: toolCall.id,\n tool_name: toolCall.function.name,\n arguments: JSON.parse(toolCall.function.arguments || '{}'),\n }));\n }\n\n return result;\n }\n\n /**\n * 在独立模式下运行组件\n * @param input 输入参数,可以是提示文本或对话消息数组\n * @returns 生成的文本或响应消息\n */\n async run(input: string | Message[]): Promise<string | Message> {\n if (typeof input === 'string') {\n return this.generateCompletion(input);\n } else {\n return this.chatCompletion(input);\n }\n }\n\n /**\n * 在流水线中运行组件\n * @param $i 输入端口\n * @param $o 输出端口\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n _transform($i: any, $o: any) {\n // 处理文本提示输入\n $i('prompt').receive(async (prompt: string) => {\n try {\n const completion = await this.generateCompletion(prompt);\n $o('completion').send(completion);\n } catch (error) {\n console.error('Deepseek API 调用错误:', error);\n $o('completion').send('API 调用错误');\n }\n });\n\n // 处理对话消息输入\n $i('messages').receive(async (messages: Message[]) => {\n try {\n const responseMessage = await this.chatCompletion(messages);\n $o('message').send(responseMessage);\n } catch (error) {\n console.error('Deepseek API 调用错误:', error);\n $o('message').send({\n role: 'assistant',\n content: 'API 调用错误',\n });\n }\n });\n }\n}\n\n// 默认导出组件\nexport default Deepseek;\n"],"mappings":"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","names":["OpenAI"]}
@@ -0,0 +1,2 @@
1
+ export { i as ModelProvider } from './model-provider/index.cjs';
2
+ import '@astack-tech/core';
@@ -0,0 +1,2 @@
1
+ export { i as ModelProvider } from './model-provider/index.js';
2
+ import '@astack-tech/core';
package/dist/index.js ADDED
@@ -0,0 +1,190 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __export = (target, all) => {
3
+ for (var name in all)
4
+ __defProp(target, name, { get: all[name], enumerable: true });
5
+ };
6
+
7
+ // src/model-provider/index.ts
8
+ var model_provider_exports = {};
9
+ __export(model_provider_exports, {
10
+ Deepseek: () => deepseek_default
11
+ });
12
+
13
+ // src/model-provider/deepseek/index.ts
14
+ import { Component } from "@astack-tech/core";
15
+ import OpenAI from "openai";
16
+ var Deepseek = class extends Component {
17
+ constructor(config) {
18
+ super({});
19
+ this.client = new OpenAI({
20
+ apiKey: config.apiKey,
21
+ baseURL: config.baseURL || "https://api.deepseek.com/v1"
22
+ });
23
+ this.model = config.model || "deepseek-chat";
24
+ this.temperature = config.temperature ?? 0.7;
25
+ this.maxTokens = config.maxTokens;
26
+ this.topP = config.topP;
27
+ this.systemPrompt = config.systemPrompt;
28
+ if (config.rawTools && config.rawTools.length > 0) {
29
+ this.tools = config.rawTools.map((tool) => ({
30
+ type: "function",
31
+ function: {
32
+ name: tool.name,
33
+ description: tool.description,
34
+ parameters: tool.parameters || {}
35
+ }
36
+ }));
37
+ } else {
38
+ this.tools = config.tools;
39
+ }
40
+ Component.Port.I("prompt").attach(this);
41
+ Component.Port.I("messages").attach(this);
42
+ Component.Port.O("completion").attach(this);
43
+ Component.Port.O("message").attach(this);
44
+ }
45
+ /**
46
+ * 生成文本完成
47
+ * @param prompt 提示文本
48
+ * @returns 生成的文本
49
+ */
50
+ async generateCompletion(prompt) {
51
+ const messages = [];
52
+ if (this.systemPrompt) {
53
+ messages.push({
54
+ role: "system",
55
+ content: this.systemPrompt
56
+ });
57
+ }
58
+ messages.push({
59
+ role: "user",
60
+ content: prompt
61
+ });
62
+ const requestParams = {
63
+ model: this.model,
64
+ messages,
65
+ temperature: this.temperature,
66
+ max_tokens: this.maxTokens,
67
+ top_p: this.topP
68
+ };
69
+ if (this.tools && this.tools.length > 0) {
70
+ requestParams.tools = this.tools;
71
+ }
72
+ const response = await this.client.chat.completions.create(requestParams);
73
+ if (response.choices[0].message.tool_calls && response.choices[0].message.tool_calls.length > 0) {
74
+ return JSON.stringify(response.choices[0].message);
75
+ }
76
+ return response.choices[0].message.content || "";
77
+ }
78
+ /**
79
+ * 处理对话消息
80
+ * @param messages 对话消息数组
81
+ * @param options 可选的调用选项,包含临时工具列表
82
+ * @returns 生成的响应消息
83
+ */
84
+ async chatCompletion(messages, options) {
85
+ const formattedMessages = [];
86
+ if (this.systemPrompt) {
87
+ formattedMessages.push({
88
+ role: "system",
89
+ content: this.systemPrompt
90
+ });
91
+ }
92
+ formattedMessages.push(
93
+ ...messages.map((msg) => {
94
+ const formattedMsg = {
95
+ role: msg.role,
96
+ content: msg.content
97
+ };
98
+ if (msg.role === "tool" && msg.tool_call_id) {
99
+ formattedMsg.tool_call_id = msg.tool_call_id;
100
+ }
101
+ return formattedMsg;
102
+ })
103
+ );
104
+ const requestParams = {
105
+ model: this.model,
106
+ messages: formattedMessages,
107
+ temperature: this.temperature,
108
+ max_tokens: this.maxTokens,
109
+ top_p: this.topP
110
+ };
111
+ const toolsToUse = options?.temporaryTools || this.tools;
112
+ if (toolsToUse && toolsToUse.length > 0) {
113
+ const formattedTools = toolsToUse.map((tool) => {
114
+ const typedTool = tool;
115
+ if (typedTool.type === "function") {
116
+ return tool;
117
+ }
118
+ return {
119
+ type: "function",
120
+ function: {
121
+ name: typedTool.name,
122
+ description: typedTool.description,
123
+ parameters: typedTool.parameters || {}
124
+ }
125
+ };
126
+ });
127
+ requestParams.tools = formattedTools;
128
+ }
129
+ const response = await this.client.chat.completions.create(requestParams);
130
+ const responseMessage = response.choices[0].message;
131
+ const result = {
132
+ role: "assistant",
133
+ content: responseMessage.content || ""
134
+ };
135
+ if (responseMessage.tool_calls && responseMessage.tool_calls.length > 0) {
136
+ result.tool_calls = responseMessage.tool_calls.map((toolCall) => ({
137
+ id: toolCall.id,
138
+ tool_name: toolCall.function.name,
139
+ arguments: JSON.parse(toolCall.function.arguments || "{}")
140
+ }));
141
+ }
142
+ return result;
143
+ }
144
+ /**
145
+ * 在独立模式下运行组件
146
+ * @param input 输入参数,可以是提示文本或对话消息数组
147
+ * @returns 生成的文本或响应消息
148
+ */
149
+ async run(input) {
150
+ if (typeof input === "string") {
151
+ return this.generateCompletion(input);
152
+ } else {
153
+ return this.chatCompletion(input);
154
+ }
155
+ }
156
+ /**
157
+ * 在流水线中运行组件
158
+ * @param $i 输入端口
159
+ * @param $o 输出端口
160
+ */
161
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
162
+ _transform($i, $o) {
163
+ $i("prompt").receive(async (prompt) => {
164
+ try {
165
+ const completion = await this.generateCompletion(prompt);
166
+ $o("completion").send(completion);
167
+ } catch (error) {
168
+ console.error("Deepseek API \u8C03\u7528\u9519\u8BEF:", error);
169
+ $o("completion").send("API \u8C03\u7528\u9519\u8BEF");
170
+ }
171
+ });
172
+ $i("messages").receive(async (messages) => {
173
+ try {
174
+ const responseMessage = await this.chatCompletion(messages);
175
+ $o("message").send(responseMessage);
176
+ } catch (error) {
177
+ console.error("Deepseek API \u8C03\u7528\u9519\u8BEF:", error);
178
+ $o("message").send({
179
+ role: "assistant",
180
+ content: "API \u8C03\u7528\u9519\u8BEF"
181
+ });
182
+ }
183
+ });
184
+ }
185
+ };
186
+ var deepseek_default = Deepseek;
187
+ export {
188
+ model_provider_exports as ModelProvider
189
+ };
190
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/model-provider/index.ts","../src/model-provider/deepseek/index.ts"],"sourcesContent":["export {\n default as Deepseek,\n type Message as DeepseekMessage,\n type ToolCall as DeepseekToolCall,\n type DeepseekConfig,\n type MessageRole as DeepseekMessageRole,\n} from './deepseek';\n","import { Component } from '@astack-tech/core';\nimport OpenAI from 'openai';\n\n/**\n * Deepseek 模型提供者配置\n */\nexport interface DeepseekConfig {\n /**\n * API 密钥\n */\n apiKey: string;\n\n /**\n * 使用的模型名称\n * 默认为 'deepseek-chat'\n */\n model?: string;\n\n /**\n * 自定义 API 基础 URL\n * 默认为 Deepseek 官方 API 地址\n */\n baseURL?: string;\n\n /**\n * 温度参数,控制输出的随机性\n */\n temperature?: number;\n\n /**\n * 最大生成的 token 数\n */\n maxTokens?: number;\n\n /**\n * 采样概率\n */\n topP?: number;\n\n /**\n * 系统提示消息\n */\n systemPrompt?: string;\n\n /**\n * 工具实例数组,直接传递工具实例\n * 每个工具应具有 name、description 和 parameters 属性\n */\n rawTools?: Array<{\n name: string;\n description: string;\n parameters?: Record<string, unknown>;\n }>;\n\n /**\n * API 格式的工具定义数组,与 rawTools 二选一\n * 使用 OpenAI 兼容的工具定义格式\n */\n tools?: unknown[];\n}\n\n/**\n * 消息角色类型\n */\nexport type MessageRole = 'system' | 'user' | 'assistant' | 'tool';\n\n/**\n * 工具调用\n */\nexport interface ToolCall {\n /**\n * 工具调用 ID\n */\n id?: string;\n\n /**\n * 工具名称\n */\n tool_name: string;\n\n /**\n * 工具调用参数\n */\n arguments: Record<string, unknown>;\n}\n\n/**\n * 对话消息类型\n */\nexport interface Message {\n /**\n * 消息角色\n */\n role: MessageRole;\n\n /**\n * 消息内容\n */\n content?: string;\n\n /**\n * 工具调用\n */\n tool_calls?: ToolCall[];\n\n /**\n * 工具调用 ID,用于工具响应消息\n */\n tool_call_id?: string;\n}\n\n/**\n * Deepseek 组件\n *\n * 使用 OpenAI 兼容接口调用 Deepseek 模型\n *\n * 输入:\n * - prompt: 文本提示\n * - messages: 对话消息数组\n *\n * 输出:\n * - completion: 生成的文本完成\n * - message: 生成的响应消息\n */\nclass Deepseek extends Component {\n // OpenAI 客户端实例\n private client: OpenAI;\n\n // 配置选项\n private model: string;\n private temperature: number;\n private maxTokens?: number;\n private topP?: number;\n private systemPrompt?: string;\n private tools?: unknown[];\n\n constructor(config: DeepseekConfig) {\n super({});\n\n // 配置客户端\n this.client = new OpenAI({\n apiKey: config.apiKey,\n baseURL: config.baseURL || 'https://api.deepseek.com/v1',\n });\n\n // 保存基本配置\n this.model = config.model || 'deepseek-chat';\n this.temperature = config.temperature ?? 0.7;\n this.maxTokens = config.maxTokens;\n this.topP = config.topP;\n this.systemPrompt = config.systemPrompt;\n\n // 处理工具配置,优先使用 rawTools\n if (config.rawTools && config.rawTools.length > 0) {\n // 将工具实例转换为 API 格式\n this.tools = config.rawTools.map(tool => ({\n type: 'function',\n function: {\n name: tool.name,\n description: tool.description,\n parameters: tool.parameters || {},\n },\n }));\n } else {\n // 使用直接提供的 API 格式工具\n this.tools = config.tools;\n }\n\n // 重命名端口\n Component.Port.I('prompt').attach(this);\n Component.Port.I('messages').attach(this);\n Component.Port.O('completion').attach(this);\n Component.Port.O('message').attach(this);\n }\n\n /**\n * 生成文本完成\n * @param prompt 提示文本\n * @returns 生成的文本\n */\n async generateCompletion(prompt: string): Promise<string> {\n const messages: Array<OpenAI.Chat.ChatCompletionMessageParam> = [];\n\n // 添加系统提示\n if (this.systemPrompt) {\n messages.push({\n role: 'system',\n content: this.systemPrompt,\n });\n }\n\n // 添加用户提示\n messages.push({\n role: 'user',\n content: prompt,\n });\n\n // 创建请求参数\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const requestParams: any = {\n model: this.model,\n messages,\n temperature: this.temperature,\n max_tokens: this.maxTokens,\n top_p: this.topP,\n };\n\n // 如果有工具定义,添加到请求中\n if (this.tools && this.tools.length > 0) {\n requestParams.tools = this.tools;\n }\n\n // 调用 API\n const response = await this.client.chat.completions.create(requestParams);\n\n // 处理工具调用结果\n if (\n response.choices[0].message.tool_calls &&\n response.choices[0].message.tool_calls.length > 0\n ) {\n return JSON.stringify(response.choices[0].message);\n }\n\n return response.choices[0].message.content || '';\n }\n\n /**\n * 处理对话消息\n * @param messages 对话消息数组\n * @param options 可选的调用选项,包含临时工具列表\n * @returns 生成的响应消息\n */\n async chatCompletion(\n messages: Message[],\n options?: { temporaryTools?: unknown[] }\n ): Promise<Message> {\n // 转换消息格式\n const formattedMessages: Array<OpenAI.Chat.ChatCompletionMessageParam> = [];\n\n // 添加系统提示\n if (this.systemPrompt) {\n formattedMessages.push({\n role: 'system',\n content: this.systemPrompt,\n });\n }\n\n // 添加用户提供的消息\n formattedMessages.push(\n ...messages.map(msg => {\n // 基本消息结构\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const formattedMsg: any = {\n role: msg.role,\n content: msg.content,\n };\n\n // 如果有工具调用 ID,添加到消息中\n if (msg.role === 'tool' && msg.tool_call_id) {\n formattedMsg.tool_call_id = msg.tool_call_id;\n }\n\n return formattedMsg;\n })\n );\n\n // 创建请求参数\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const requestParams: any = {\n model: this.model,\n messages: formattedMessages,\n temperature: this.temperature,\n max_tokens: this.maxTokens,\n top_p: this.topP,\n };\n\n // 决定使用哪些工具\n // 如果提供了临时工具,优先使用临时工具\n const toolsToUse = options?.temporaryTools || this.tools;\n\n // 如果有工具定义,添加到请求中\n if (toolsToUse && toolsToUse.length > 0) {\n // 检查工具格式并转换,确保符合 Deepseek API 要求\n const formattedTools = toolsToUse.map(tool => {\n // 使用类型断言来处理 unknown 类型\n type ToolType = {\n type?: string;\n name?: string;\n description?: string;\n parameters?: Record<string, unknown>;\n };\n\n const typedTool = tool as ToolType;\n\n // 如果工具已经是 API 格式,直接返回\n if (typedTool.type === 'function') {\n return tool;\n }\n\n // 如果是简单工具实例,转换为 API 格式\n return {\n type: 'function',\n function: {\n name: typedTool.name,\n description: typedTool.description,\n parameters: typedTool.parameters || {},\n },\n };\n });\n\n requestParams.tools = formattedTools;\n }\n\n // 调用 API\n const response = await this.client.chat.completions.create(requestParams);\n\n // 解析响应\n const responseMessage = response.choices[0].message;\n\n // 转换为内部消息格式\n const result: Message = {\n role: 'assistant',\n content: responseMessage.content || '',\n };\n\n // 如果有工具调用,添加到结果中\n if (responseMessage.tool_calls && responseMessage.tool_calls.length > 0) {\n result.tool_calls = responseMessage.tool_calls.map(toolCall => ({\n id: toolCall.id,\n tool_name: toolCall.function.name,\n arguments: JSON.parse(toolCall.function.arguments || '{}'),\n }));\n }\n\n return result;\n }\n\n /**\n * 在独立模式下运行组件\n * @param input 输入参数,可以是提示文本或对话消息数组\n * @returns 生成的文本或响应消息\n */\n async run(input: string | Message[]): Promise<string | Message> {\n if (typeof input === 'string') {\n return this.generateCompletion(input);\n } else {\n return this.chatCompletion(input);\n }\n }\n\n /**\n * 在流水线中运行组件\n * @param $i 输入端口\n * @param $o 输出端口\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n _transform($i: any, $o: any) {\n // 处理文本提示输入\n $i('prompt').receive(async (prompt: string) => {\n try {\n const completion = await this.generateCompletion(prompt);\n $o('completion').send(completion);\n } catch (error) {\n console.error('Deepseek API 调用错误:', error);\n $o('completion').send('API 调用错误');\n }\n });\n\n // 处理对话消息输入\n $i('messages').receive(async (messages: Message[]) => {\n try {\n const responseMessage = await this.chatCompletion(messages);\n $o('message').send(responseMessage);\n } catch (error) {\n console.error('Deepseek API 调用错误:', error);\n $o('message').send({\n role: 'assistant',\n content: 'API 调用错误',\n });\n }\n });\n }\n}\n\n// 默认导出组件\nexport default Deepseek;\n"],"mappings":"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","names":[]}