@hopemyl619/deepseek 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +661 -0
- package/README.md +216 -0
- package/dist/index.d.ts +178 -0
- package/dist/index.js +573 -0
- package/dist/index.js.map +1 -0
- package/package.json +59 -0
- package/src/deepseek-chat-language-model.ts +98 -0
- package/src/deepseek-chat-settings.ts +13 -0
- package/src/deepseek-provider.ts +50 -0
- package/src/index.ts +31 -0
- package/src/types.ts +100 -0
- package/src/utils/chinese-params-preprocessor.ts +161 -0
- package/src/utils/request-transformer.ts +183 -0
- package/src/utils/response-transformer.ts +90 -0
- package/src/utils/stream-parser.ts +176 -0
package/README.md
ADDED
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
# @hopemyl619/deepseek
|
|
2
|
+
|
|
3
|
+
DeepSeek 模型服务提供商,专为 Vercel AI SDK 设计。
|
|
4
|
+
|
|
5
|
+
## 核心特性
|
|
6
|
+
|
|
7
|
+
- ✅ 完整支持 DeepSeek 系列聊天模型
|
|
8
|
+
- ✅ 自动修复工具调用的 `finish_reason` 字段
|
|
9
|
+
- ✅ 中文参数预处理(城市名称自动转换)
|
|
10
|
+
- ✅ 流式输出支持
|
|
11
|
+
- ✅ 工具调用支持
|
|
12
|
+
- ✅ 完整的 TypeScript 类型定义
|
|
13
|
+
|
|
14
|
+
## 快速开始
|
|
15
|
+
|
|
16
|
+
### 安装依赖
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install @hopemyl619/deepseek ai
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### 基本用法
|
|
23
|
+
|
|
24
|
+
```typescript
|
|
25
|
+
import { deepseek } from '@hopemyl619/deepseek';
|
|
26
|
+
import { generateText } from 'ai';
|
|
27
|
+
|
|
28
|
+
async function main() {
|
|
29
|
+
const { text } = await generateText({
|
|
30
|
+
model: deepseek('deepseek-chat'),
|
|
31
|
+
prompt: '你好,请介绍一下你自己',
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
console.log(text);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
main();
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## 使用示例
|
|
41
|
+
|
|
42
|
+
### 流式文本生成
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
import { deepseek } from '@hopemyl619/deepseek';
|
|
46
|
+
import { streamText } from 'ai';
|
|
47
|
+
|
|
48
|
+
async function main() {
|
|
49
|
+
const result = await streamText({
|
|
50
|
+
model: deepseek('deepseek-chat'),
|
|
51
|
+
prompt: '请写一首关于春天的诗',
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
for await (const chunk of result.textStream) {
|
|
55
|
+
process.stdout.write(chunk);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
main();
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### 工具调用
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
import { deepseek } from '@hopemyl619/deepseek';
|
|
66
|
+
import { generateText, tool } from 'ai';
|
|
67
|
+
import { z } from 'zod';
|
|
68
|
+
|
|
69
|
+
async function main() {
|
|
70
|
+
const { toolCalls } = await generateText({
|
|
71
|
+
model: deepseek('deepseek-chat'),
|
|
72
|
+
tools: {
|
|
73
|
+
getWeather: tool({
|
|
74
|
+
description: '获取指定城市的天气信息',
|
|
75
|
+
parameters: z.object({
|
|
76
|
+
location: z.string().describe('城市名称'),
|
|
77
|
+
}),
|
|
78
|
+
execute: async ({ location }) => {
|
|
79
|
+
// 调用天气 API
|
|
80
|
+
return { temperature: 22, condition: '晴天' };
|
|
81
|
+
},
|
|
82
|
+
}),
|
|
83
|
+
},
|
|
84
|
+
prompt: '北京今天的天气怎么样?',
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
console.log('工具调用结果:', toolCalls);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
main();
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### 自定义 API 地址
|
|
94
|
+
|
|
95
|
+
```typescript
|
|
96
|
+
import { createDeepSeek } from '@hopemyl619/deepseek';
|
|
97
|
+
|
|
98
|
+
const customDeepSeek = createDeepSeek({
|
|
99
|
+
baseURL: 'http://your-custom-endpoint/v1',
|
|
100
|
+
apiKey: 'your-api-key',
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
const { text } = await generateText({
|
|
104
|
+
model: customDeepSeek('deepseek-chat'),
|
|
105
|
+
prompt: '你好',
|
|
106
|
+
});
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## 高级功能
|
|
110
|
+
|
|
111
|
+
### 自动修复 finish_reason
|
|
112
|
+
|
|
113
|
+
DeepSeek API 在某些情况下会返回 `finish_reason: 'stop'` 而非预期的 `finish_reason: 'tool-calls'`。本提供商会自动检测并修复此问题,确保工具调用流程正常执行。
|
|
114
|
+
|
|
115
|
+
### 中文参数预处理
|
|
116
|
+
|
|
117
|
+
工具调用参数中的中文城市名称会自动转换为英文:
|
|
118
|
+
|
|
119
|
+
| 中文 | 英文 |
|
|
120
|
+
|------|------|
|
|
121
|
+
| 北京 | Beijing |
|
|
122
|
+
| 上海 | Shanghai |
|
|
123
|
+
| 广州 | Guangzhou |
|
|
124
|
+
| 深圳 | Shenzhen |
|
|
125
|
+
|
|
126
|
+
添加自定义映射:
|
|
127
|
+
|
|
128
|
+
```typescript
|
|
129
|
+
import { ChineseParamsPreprocessor } from '@hopemyl619/deepseek';
|
|
130
|
+
|
|
131
|
+
const preprocessor = new ChineseParamsPreprocessor();
|
|
132
|
+
preprocessor.addCityMapping('成都', 'Chengdu');
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## 在 iFlow CLI 中配置
|
|
136
|
+
|
|
137
|
+
在 `~/.iflow/settings.json` 中添加配置:
|
|
138
|
+
|
|
139
|
+
```json
|
|
140
|
+
{
|
|
141
|
+
"modelName": "DeepSeek-V3.2-671B",
|
|
142
|
+
"baseUrl": "https://api.deepseek.com/v1",
|
|
143
|
+
"apiKey": "${DEEPSEEK_API_KEY}"
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
设置环境变量:
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
export DEEPSEEK_API_KEY=your-api-key
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## 支持的模型
|
|
154
|
+
|
|
155
|
+
- `deepseek-chat` - 通用聊天模型
|
|
156
|
+
- `deepseek-coder` - 代码专用模型
|
|
157
|
+
- `DeepSeek-V3.2-671B` - 超大规模模型
|
|
158
|
+
|
|
159
|
+
## 测试
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
# 运行单元测试
|
|
163
|
+
npm test
|
|
164
|
+
|
|
165
|
+
# 类型检查
|
|
166
|
+
npm run typecheck
|
|
167
|
+
|
|
168
|
+
# 构建项目
|
|
169
|
+
npm run build
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## 项目结构
|
|
173
|
+
|
|
174
|
+
```
|
|
175
|
+
@hopemyl619/deepseek/
|
|
176
|
+
├── src/
|
|
177
|
+
│ ├── deepseek-provider.ts # 提供商主文件
|
|
178
|
+
│ ├── deepseek-chat-language-model.ts
|
|
179
|
+
│ ├── deepseek-chat-settings.ts
|
|
180
|
+
│ ├── types.ts # 类型定义
|
|
181
|
+
│ └── utils/
|
|
182
|
+
│ ├── request-transformer.ts # 请求转换
|
|
183
|
+
│ ├── response-transformer.ts # 响应转换
|
|
184
|
+
│ ├── stream-parser.ts # 流式解析
|
|
185
|
+
│ └── chinese-params-preprocessor.ts # 中文预处理
|
|
186
|
+
├── test/
|
|
187
|
+
│ ├── stream-parser.test.ts # 流式解析测试
|
|
188
|
+
│ └── integration.test.ts # 集成测试
|
|
189
|
+
└── examples/
|
|
190
|
+
└── basic-usage.ts # 使用示例
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
## 常见问题
|
|
194
|
+
|
|
195
|
+
### Q: 工具调用没有触发执行?
|
|
196
|
+
A: 检查 DeepSeek API 返回的 `finish_reason`,本提供商已自动修复 `stop` → `tool-calls` 的转换。
|
|
197
|
+
|
|
198
|
+
### Q: 中文参数没有转换?
|
|
199
|
+
A: 确保使用 `ChineseParamsPreprocessor` 类处理参数,或检查映射配置是否正确。
|
|
200
|
+
|
|
201
|
+
### Q: 流式输出不完整?
|
|
202
|
+
A: StreamParser 已支持 JSON in content 格式,确保使用最新版本。
|
|
203
|
+
|
|
204
|
+
## 版本历史
|
|
205
|
+
|
|
206
|
+
### v0.1.0
|
|
207
|
+
- 初始版本发布
|
|
208
|
+
- 支持基础聊天功能
|
|
209
|
+
- 支持流式输出
|
|
210
|
+
- 支持工具调用
|
|
211
|
+
- 自动 finish_reason 修复
|
|
212
|
+
- 中文参数预处理
|
|
213
|
+
|
|
214
|
+
## 许可证
|
|
215
|
+
|
|
216
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { LanguageModelV1FinishReason, LanguageModelV1FunctionToolCall, LanguageModelV1CallWarning, LanguageModelV1, LanguageModelV1CallOptions, LanguageModelV1StreamPart } from '@ai-sdk/provider';
|
|
2
|
+
|
|
3
|
+
interface DeepSeekProviderSettings {
|
|
4
|
+
apiKey?: string;
|
|
5
|
+
baseURL?: string;
|
|
6
|
+
headers?: Record<string, string | undefined>;
|
|
7
|
+
}
|
|
8
|
+
interface DeepSeekChatSettings {
|
|
9
|
+
temperature?: number;
|
|
10
|
+
topP?: number;
|
|
11
|
+
maxTokens?: number;
|
|
12
|
+
presencePenalty?: number;
|
|
13
|
+
frequencyPenalty?: number;
|
|
14
|
+
}
|
|
15
|
+
interface DeepSeekMessage {
|
|
16
|
+
role: 'system' | 'user' | 'assistant' | 'tool';
|
|
17
|
+
content: string | Array<{
|
|
18
|
+
type: 'text' | 'image_url';
|
|
19
|
+
text?: string;
|
|
20
|
+
image_url?: {
|
|
21
|
+
url: string;
|
|
22
|
+
};
|
|
23
|
+
}>;
|
|
24
|
+
tool_calls?: DeepSeekToolCall[];
|
|
25
|
+
tool_call_id?: string;
|
|
26
|
+
}
|
|
27
|
+
interface DeepSeekToolCall {
|
|
28
|
+
id: string;
|
|
29
|
+
type: 'function';
|
|
30
|
+
function: {
|
|
31
|
+
name: string;
|
|
32
|
+
arguments: string;
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
interface DeepSeekTool {
|
|
36
|
+
type: 'function';
|
|
37
|
+
function: {
|
|
38
|
+
name: string;
|
|
39
|
+
description?: string;
|
|
40
|
+
parameters?: Record<string, any>;
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
interface DeepSeekRequest {
|
|
44
|
+
model: string;
|
|
45
|
+
messages: DeepSeekMessage[];
|
|
46
|
+
temperature?: number;
|
|
47
|
+
top_p?: number;
|
|
48
|
+
max_tokens?: number;
|
|
49
|
+
presence_penalty?: number;
|
|
50
|
+
frequency_penalty?: number;
|
|
51
|
+
stream?: boolean;
|
|
52
|
+
tools?: DeepSeekTool[];
|
|
53
|
+
tool_choice?: 'auto' | 'none' | 'required' | string;
|
|
54
|
+
}
|
|
55
|
+
interface DeepSeekChoice {
|
|
56
|
+
index: number;
|
|
57
|
+
message: {
|
|
58
|
+
role: string;
|
|
59
|
+
content: string | null;
|
|
60
|
+
tool_calls?: DeepSeekToolCall[];
|
|
61
|
+
};
|
|
62
|
+
finish_reason: string;
|
|
63
|
+
}
|
|
64
|
+
interface DeepSeekUsage {
|
|
65
|
+
prompt_tokens: number;
|
|
66
|
+
completion_tokens: number;
|
|
67
|
+
total_tokens: number;
|
|
68
|
+
}
|
|
69
|
+
interface DeepSeekResponse {
|
|
70
|
+
id: string;
|
|
71
|
+
object: string;
|
|
72
|
+
created: number;
|
|
73
|
+
model: string;
|
|
74
|
+
choices: DeepSeekChoice[];
|
|
75
|
+
usage: DeepSeekUsage;
|
|
76
|
+
}
|
|
77
|
+
interface DeepSeekStreamChoice {
|
|
78
|
+
index: number;
|
|
79
|
+
delta: {
|
|
80
|
+
role?: string;
|
|
81
|
+
content?: string;
|
|
82
|
+
tool_calls?: DeepSeekToolCall[];
|
|
83
|
+
};
|
|
84
|
+
finish_reason?: string;
|
|
85
|
+
}
|
|
86
|
+
interface DeepSeekStreamResponse {
|
|
87
|
+
id: string;
|
|
88
|
+
object: string;
|
|
89
|
+
created: number;
|
|
90
|
+
model: string;
|
|
91
|
+
choices: DeepSeekStreamChoice[];
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
interface V1GenerateResult {
|
|
95
|
+
text?: string;
|
|
96
|
+
reasoning?: string;
|
|
97
|
+
usage: {
|
|
98
|
+
promptTokens: number;
|
|
99
|
+
completionTokens: number;
|
|
100
|
+
};
|
|
101
|
+
finishReason: LanguageModelV1FinishReason;
|
|
102
|
+
toolCalls?: LanguageModelV1FunctionToolCall[];
|
|
103
|
+
rawCall: {
|
|
104
|
+
rawPrompt: unknown;
|
|
105
|
+
rawSettings: Record<string, unknown>;
|
|
106
|
+
};
|
|
107
|
+
warnings?: LanguageModelV1CallWarning[];
|
|
108
|
+
}
|
|
109
|
+
declare class ResponseTransformer {
|
|
110
|
+
transform(apiResponse: DeepSeekResponse): V1GenerateResult;
|
|
111
|
+
private fixFinishReason;
|
|
112
|
+
private transformToolCalls;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
declare class DeepSeekChatLanguageModel implements LanguageModelV1 {
|
|
116
|
+
readonly specificationVersion: "v1";
|
|
117
|
+
readonly provider: "deepseek";
|
|
118
|
+
readonly modelId: string;
|
|
119
|
+
readonly settings: Required<DeepSeekChatSettings>;
|
|
120
|
+
readonly defaultObjectGenerationMode: 'json' | 'tool' | undefined;
|
|
121
|
+
private baseURL;
|
|
122
|
+
private headers;
|
|
123
|
+
private requestTransformer;
|
|
124
|
+
private responseTransformer;
|
|
125
|
+
private streamParser;
|
|
126
|
+
constructor(modelId: string, settings: DeepSeekChatSettings | undefined, config: {
|
|
127
|
+
baseURL: string;
|
|
128
|
+
headers: () => Record<string, string>;
|
|
129
|
+
});
|
|
130
|
+
doGenerate(options: LanguageModelV1CallOptions): Promise<V1GenerateResult>;
|
|
131
|
+
doStream(options: LanguageModelV1CallOptions): Promise<{
|
|
132
|
+
stream: any;
|
|
133
|
+
rawCall: {
|
|
134
|
+
rawPrompt: unknown;
|
|
135
|
+
rawSettings: {};
|
|
136
|
+
};
|
|
137
|
+
warnings: never[];
|
|
138
|
+
}>;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
declare function createDeepSeek(options?: DeepSeekProviderSettings): {
|
|
142
|
+
chat: (modelId: string, settings?: DeepSeekChatSettings) => DeepSeekChatLanguageModel;
|
|
143
|
+
};
|
|
144
|
+
declare const deepseek: {
|
|
145
|
+
chat: (modelId: string, settings?: DeepSeekChatSettings) => DeepSeekChatLanguageModel;
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
declare function validateChatSettings(settings?: DeepSeekChatSettings): Required<DeepSeekChatSettings>;
|
|
149
|
+
|
|
150
|
+
declare class ChineseParamsPreprocessor {
|
|
151
|
+
private cityMap;
|
|
152
|
+
process(request: DeepSeekRequest): DeepSeekRequest;
|
|
153
|
+
private processMessages;
|
|
154
|
+
private processTools;
|
|
155
|
+
private processProperties;
|
|
156
|
+
private replaceCityNames;
|
|
157
|
+
addCityMapping(chinese: string, english: string): void;
|
|
158
|
+
addCityMappings(mappings: Record<string, string>): void;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
declare class RequestTransformer {
|
|
162
|
+
private preprocessor;
|
|
163
|
+
constructor();
|
|
164
|
+
transform(modelId: string, options: LanguageModelV1CallOptions): DeepSeekRequest;
|
|
165
|
+
private transformMessages;
|
|
166
|
+
private transformTools;
|
|
167
|
+
private transformToolChoice;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
declare class StreamParser {
|
|
171
|
+
parse(body: ReadableStream<Uint8Array>): AsyncIterable<LanguageModelV1StreamPart>;
|
|
172
|
+
private processPartialJson;
|
|
173
|
+
private processChunk;
|
|
174
|
+
private mapFinishReason;
|
|
175
|
+
private tryParseToolCall;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
export { ChineseParamsPreprocessor, DeepSeekChatLanguageModel, type DeepSeekChatSettings, type DeepSeekChoice, type DeepSeekMessage, type DeepSeekProviderSettings, type DeepSeekRequest, type DeepSeekResponse, type DeepSeekStreamChoice, type DeepSeekStreamResponse, type DeepSeekTool, type DeepSeekToolCall, type DeepSeekUsage, RequestTransformer, ResponseTransformer, StreamParser, createDeepSeek, deepseek, validateChatSettings };
|