@caoguo/maplibre-ai 0.0.4 → 0.0.6
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/dist/chunk-AIQSXKZQ.js +311 -0
- package/dist/chunk-AIQSXKZQ.js.map +1 -0
- package/dist/{chunk-ARYB2X4B.js → chunk-WVEICADA.js} +43 -15
- package/dist/chunk-WVEICADA.js.map +1 -0
- package/dist/copilot/index.d.cts +1 -1
- package/dist/copilot/index.d.ts +1 -1
- package/dist/deepseek-rSUSDXri.d.cts +81 -0
- package/dist/deepseek-rSUSDXri.d.ts +81 -0
- package/dist/index.cjs +205 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -2
- package/dist/llm/index.cjs +164 -0
- package/dist/llm/index.cjs.map +1 -1
- package/dist/llm/index.d.cts +64 -59
- package/dist/llm/index.d.ts +64 -59
- package/dist/llm/index.js +1 -1
- package/dist/nlpg/index.cjs +41 -13
- package/dist/nlpg/index.cjs.map +1 -1
- package/dist/nlpg/index.d.cts +5 -3
- package/dist/nlpg/index.d.ts +5 -3
- package/dist/nlpg/index.js +1 -1
- package/package.json +11 -11
- package/dist/chunk-ARYB2X4B.js.map +0 -1
- package/dist/chunk-ZI6ZF26Q.js +0 -149
- package/dist/chunk-ZI6ZF26Q.js.map +0 -1
package/dist/index.d.cts
CHANGED
|
@@ -3,4 +3,5 @@ export { BrandStyleOptions, CARRIER_STYLES, ColorScheme, GeneratedMapStyle, INDU
|
|
|
3
3
|
export { COLOR_NAMES, CopilotIntent, CopilotParams, CopilotResult, LlmCopilotConfig, LlmMapCopilot, MapCopilot, PLACE_COORDINATES, classifyIntent, extractParams, generateCode, generateFromQuery } from './copilot/index.cjs';
|
|
4
4
|
export { BatchGeocodeInput, BatchGeocodeOutput, CHINA_BOUNDS, DetectedCRS, GeocodeResult, HeaderDetection, ImportOptions, ImportResult, ImportStats, ImportedFeature, LOCAL_GEO_DB, ParsedAddress, batchGeocode, detectCRS, detectHeaders, gcj02ToWgs84, geocode, hasLocalGeo, importToGeoJSON, isInChina, isValidAddress, parseAddress, wgs84ToGcj02 } from './geoai/index.cjs';
|
|
5
5
|
export { AttributeCondition, DEFAULT_ALLOWED_TABLES, GenerateOptions, GeneratedQuery, LlmNlpg, LlmNlpgConfig, NlpgIntent, NlpgResult, Operator, SpatialCondition, ValidationIssue, ValidationResult, detectField, detectSpatial, detectTable, detectValue, generatePostGISQuery, nlpgQuery, parameterize, validateSql } from './nlpg/index.cjs';
|
|
6
|
-
export { ChatMessage, ChatOptions, ChatResult, DeepSeekClient, DeepSeekConfig, JsonChatResult, createDeepSeekClient } from './
|
|
6
|
+
export { C as ChatMessage, a as ChatOptions, b as ChatResult, D as DeepSeekClient, c as DeepSeekConfig, J as JsonChatResult, d as createDeepSeekClient } from './deepseek-rSUSDXri.cjs';
|
|
7
|
+
export { LlmClient, OpenAICompatibleClient, OpenAICompatibleConfig, createOpenAICompatibleClient } from './llm/index.cjs';
|
package/dist/index.d.ts
CHANGED
|
@@ -3,4 +3,5 @@ export { BrandStyleOptions, CARRIER_STYLES, ColorScheme, GeneratedMapStyle, INDU
|
|
|
3
3
|
export { COLOR_NAMES, CopilotIntent, CopilotParams, CopilotResult, LlmCopilotConfig, LlmMapCopilot, MapCopilot, PLACE_COORDINATES, classifyIntent, extractParams, generateCode, generateFromQuery } from './copilot/index.js';
|
|
4
4
|
export { BatchGeocodeInput, BatchGeocodeOutput, CHINA_BOUNDS, DetectedCRS, GeocodeResult, HeaderDetection, ImportOptions, ImportResult, ImportStats, ImportedFeature, LOCAL_GEO_DB, ParsedAddress, batchGeocode, detectCRS, detectHeaders, gcj02ToWgs84, geocode, hasLocalGeo, importToGeoJSON, isInChina, isValidAddress, parseAddress, wgs84ToGcj02 } from './geoai/index.js';
|
|
5
5
|
export { AttributeCondition, DEFAULT_ALLOWED_TABLES, GenerateOptions, GeneratedQuery, LlmNlpg, LlmNlpgConfig, NlpgIntent, NlpgResult, Operator, SpatialCondition, ValidationIssue, ValidationResult, detectField, detectSpatial, detectTable, detectValue, generatePostGISQuery, nlpgQuery, parameterize, validateSql } from './nlpg/index.js';
|
|
6
|
-
export { ChatMessage, ChatOptions, ChatResult, DeepSeekClient, DeepSeekConfig, JsonChatResult, createDeepSeekClient } from './
|
|
6
|
+
export { C as ChatMessage, a as ChatOptions, b as ChatResult, D as DeepSeekClient, c as DeepSeekConfig, J as JsonChatResult, d as createDeepSeekClient } from './deepseek-rSUSDXri.js';
|
|
7
|
+
export { LlmClient, OpenAICompatibleClient, OpenAICompatibleConfig, createOpenAICompatibleClient } from './llm/index.js';
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@ export { DIAGNOSIS_RULES, analyzePerformance, analyzeTiles, detectMemoryLeak, di
|
|
|
2
2
|
export { CARRIER_STYLES, INDUSTRY_TEMPLATES, adjustBrightness, extractDominantColor, generateBrandStyle, generateCarrierStyle, generateIndustryStyle, toggleMode } from './chunk-KNL3QRD2.js';
|
|
3
3
|
export { COLOR_NAMES, LlmMapCopilot, MapCopilot, PLACE_COORDINATES, classifyIntent, extractParams, generateCode, generateFromQuery } from './chunk-55G7QUFA.js';
|
|
4
4
|
export { CHINA_BOUNDS, LOCAL_GEO_DB, batchGeocode, detectCRS, detectHeaders, gcj02ToWgs84, geocode, hasLocalGeo, importToGeoJSON, isInChina, isValidAddress, parseAddress, wgs84ToGcj02 } from './chunk-HF3HJPXD.js';
|
|
5
|
-
export { DEFAULT_ALLOWED_TABLES, LlmNlpg, detectField, detectSpatial, detectTable, detectValue, generatePostGISQuery, nlpgQuery, parameterize, validateSql } from './chunk-
|
|
6
|
-
export { DeepSeekClient, createDeepSeekClient } from './chunk-
|
|
5
|
+
export { DEFAULT_ALLOWED_TABLES, LlmNlpg, detectField, detectSpatial, detectTable, detectValue, generatePostGISQuery, nlpgQuery, parameterize, validateSql } from './chunk-WVEICADA.js';
|
|
6
|
+
export { DeepSeekClient, OpenAICompatibleClient, createDeepSeekClient, createOpenAICompatibleClient } from './chunk-AIQSXKZQ.js';
|
|
7
7
|
//# sourceMappingURL=index.js.map
|
|
8
8
|
//# sourceMappingURL=index.js.map
|
package/dist/llm/index.cjs
CHANGED
|
@@ -146,7 +146,171 @@ function createDeepSeekClient(config) {
|
|
|
146
146
|
return new DeepSeekClient(config);
|
|
147
147
|
}
|
|
148
148
|
|
|
149
|
+
// src/llm/openaiCompatible.ts
|
|
150
|
+
function normalizeError2(body, provider) {
|
|
151
|
+
const err = new Error(body || `${provider} API \u8BF7\u6C42\u5931\u8D25`);
|
|
152
|
+
err.name = `${provider}Error`;
|
|
153
|
+
return err;
|
|
154
|
+
}
|
|
155
|
+
var OpenAICompatibleClient = class {
|
|
156
|
+
apiKey;
|
|
157
|
+
baseUrl;
|
|
158
|
+
model;
|
|
159
|
+
temperature;
|
|
160
|
+
maxTokens;
|
|
161
|
+
timeoutMs;
|
|
162
|
+
retries;
|
|
163
|
+
fetchImpl;
|
|
164
|
+
authScheme;
|
|
165
|
+
extraHeaders;
|
|
166
|
+
providerLabel;
|
|
167
|
+
constructor(config) {
|
|
168
|
+
if (!config.apiKey) throw new Error("OpenAICompatibleClient: apiKey \u4E0D\u80FD\u4E3A\u7A7A");
|
|
169
|
+
if (!config.baseUrl) throw new Error("OpenAICompatibleClient: baseUrl \u4E0D\u80FD\u4E3A\u7A7A");
|
|
170
|
+
if (!config.model) throw new Error("OpenAICompatibleClient: model \u4E0D\u80FD\u4E3A\u7A7A");
|
|
171
|
+
this.apiKey = config.apiKey;
|
|
172
|
+
this.baseUrl = config.baseUrl.replace(/\/+$/, "");
|
|
173
|
+
this.model = config.model;
|
|
174
|
+
this.temperature = config.temperature ?? 0.3;
|
|
175
|
+
this.maxTokens = config.maxTokens ?? 2048;
|
|
176
|
+
this.timeoutMs = config.timeoutMs ?? 3e4;
|
|
177
|
+
this.retries = config.retries ?? 2;
|
|
178
|
+
this.fetchImpl = config.fetchImpl ?? (globalThis.fetch ?? fetch);
|
|
179
|
+
this.authScheme = config.authScheme ?? "Bearer";
|
|
180
|
+
this.extraHeaders = config.extraHeaders ?? {};
|
|
181
|
+
this.providerLabel = (() => {
|
|
182
|
+
try {
|
|
183
|
+
return new URL(this.baseUrl).hostname || "LLM";
|
|
184
|
+
} catch {
|
|
185
|
+
return "LLM";
|
|
186
|
+
}
|
|
187
|
+
})();
|
|
188
|
+
}
|
|
189
|
+
async chat(messages, opts = {}) {
|
|
190
|
+
return this.requestWithRetry(messages, opts);
|
|
191
|
+
}
|
|
192
|
+
async chatJson(messages) {
|
|
193
|
+
const result = await this.chat(messages, { json: true });
|
|
194
|
+
const raw = result.content.trim();
|
|
195
|
+
const cleaned = raw.replace(/^```(?:json)?\s*/i, "").replace(/\s*```$/, "");
|
|
196
|
+
let data;
|
|
197
|
+
try {
|
|
198
|
+
data = JSON.parse(cleaned);
|
|
199
|
+
} catch {
|
|
200
|
+
const match = cleaned.match(/\{[\s\S]*\}|\[[\s\S]*\]/);
|
|
201
|
+
if (match) {
|
|
202
|
+
data = JSON.parse(match[0]);
|
|
203
|
+
} else {
|
|
204
|
+
throw new Error(`${this.providerLabel} \u8FD4\u56DE\u4E86\u975E JSON \u5185\u5BB9: ${raw.slice(0, 200)}`);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
return { data, raw, model: result.model };
|
|
208
|
+
}
|
|
209
|
+
async requestWithRetry(messages, opts) {
|
|
210
|
+
let lastError = null;
|
|
211
|
+
for (let attempt = 0; attempt <= this.retries; attempt++) {
|
|
212
|
+
try {
|
|
213
|
+
return await this.requestOnce(messages, opts);
|
|
214
|
+
} catch (e) {
|
|
215
|
+
lastError = e;
|
|
216
|
+
if (attempt < this.retries) {
|
|
217
|
+
await this.sleep(Math.min(1e3 * 2 ** attempt, 8e3));
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
throw lastError ?? new Error(`${this.providerLabel} \u8BF7\u6C42\u5931\u8D25`);
|
|
222
|
+
}
|
|
223
|
+
async requestOnce(messages, opts) {
|
|
224
|
+
const controller = new AbortController();
|
|
225
|
+
const timer = setTimeout(() => controller.abort(), this.timeoutMs);
|
|
226
|
+
const body = {
|
|
227
|
+
model: this.model,
|
|
228
|
+
messages,
|
|
229
|
+
temperature: this.temperature,
|
|
230
|
+
max_tokens: this.maxTokens,
|
|
231
|
+
stream: Boolean(opts.onChunk)
|
|
232
|
+
};
|
|
233
|
+
if (opts.json) {
|
|
234
|
+
body.response_format = { type: "json_object" };
|
|
235
|
+
}
|
|
236
|
+
const headers = {
|
|
237
|
+
"Content-Type": "application/json",
|
|
238
|
+
...this.extraHeaders
|
|
239
|
+
};
|
|
240
|
+
if (this.authScheme === "Bearer") {
|
|
241
|
+
headers.Authorization = `Bearer ${this.apiKey}`;
|
|
242
|
+
} else {
|
|
243
|
+
headers["X-Api-Key"] = this.apiKey;
|
|
244
|
+
}
|
|
245
|
+
try {
|
|
246
|
+
const res = await this.fetchImpl(`${this.baseUrl}/chat/completions`, {
|
|
247
|
+
method: "POST",
|
|
248
|
+
headers,
|
|
249
|
+
body: JSON.stringify(body),
|
|
250
|
+
signal: controller.signal
|
|
251
|
+
});
|
|
252
|
+
if (!res.ok) {
|
|
253
|
+
const text = await res.text().catch(() => "");
|
|
254
|
+
throw normalizeError2(`${this.providerLabel} HTTP ${res.status}: ${text}`, this.providerLabel);
|
|
255
|
+
}
|
|
256
|
+
if (opts.onChunk && res.body) {
|
|
257
|
+
return this.parseStream(res.body, opts.onChunk);
|
|
258
|
+
}
|
|
259
|
+
const json = await res.json();
|
|
260
|
+
const content = json.choices?.[0]?.message?.content ?? "";
|
|
261
|
+
return {
|
|
262
|
+
content,
|
|
263
|
+
model: json.model ?? this.model,
|
|
264
|
+
usage: json.usage ? {
|
|
265
|
+
promptTokens: json.usage.prompt_tokens,
|
|
266
|
+
completionTokens: json.usage.completion_tokens,
|
|
267
|
+
totalTokens: json.usage.prompt_tokens + json.usage.completion_tokens
|
|
268
|
+
} : void 0
|
|
269
|
+
};
|
|
270
|
+
} finally {
|
|
271
|
+
clearTimeout(timer);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
async parseStream(body, onChunk) {
|
|
275
|
+
const reader = body.getReader();
|
|
276
|
+
const decoder = new TextDecoder();
|
|
277
|
+
let content = "";
|
|
278
|
+
let buffer = "";
|
|
279
|
+
while (true) {
|
|
280
|
+
const { done, value } = await reader.read();
|
|
281
|
+
if (done) break;
|
|
282
|
+
buffer += decoder.decode(value, { stream: true });
|
|
283
|
+
const lines = buffer.split("\n");
|
|
284
|
+
buffer = lines.pop() ?? "";
|
|
285
|
+
for (const line of lines) {
|
|
286
|
+
const trimmed = line.trim();
|
|
287
|
+
if (!trimmed.startsWith("data:")) continue;
|
|
288
|
+
const data = trimmed.slice(5).trim();
|
|
289
|
+
if (data === "[DONE]") continue;
|
|
290
|
+
try {
|
|
291
|
+
const json = JSON.parse(data);
|
|
292
|
+
const delta = json.choices?.[0]?.delta?.content ?? "";
|
|
293
|
+
if (delta) {
|
|
294
|
+
content += delta;
|
|
295
|
+
onChunk(delta);
|
|
296
|
+
}
|
|
297
|
+
} catch {
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
return { content, model: this.model };
|
|
302
|
+
}
|
|
303
|
+
sleep(ms) {
|
|
304
|
+
return new Promise((r) => setTimeout(r, ms));
|
|
305
|
+
}
|
|
306
|
+
};
|
|
307
|
+
function createOpenAICompatibleClient(config) {
|
|
308
|
+
return new OpenAICompatibleClient(config);
|
|
309
|
+
}
|
|
310
|
+
|
|
149
311
|
exports.DeepSeekClient = DeepSeekClient;
|
|
312
|
+
exports.OpenAICompatibleClient = OpenAICompatibleClient;
|
|
150
313
|
exports.createDeepSeekClient = createDeepSeekClient;
|
|
314
|
+
exports.createOpenAICompatibleClient = createOpenAICompatibleClient;
|
|
151
315
|
//# sourceMappingURL=index.cjs.map
|
|
152
316
|
//# sourceMappingURL=index.cjs.map
|
package/dist/llm/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/llm/deepseek.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * DeepSeek LLM 客户端(PRD phase-0 §5.5 / §5.7 的 v1 后端能力)\n *\n * DeepSeek API 与 OpenAI Chat Completions 协议兼容:\n * base_url: https://api.deepseek.com\n * 模型: deepseek-chat(通用对话)/ deepseek-reasoner(深度推理)\n * 鉴权: Authorization: Bearer <API_KEY>\n *\n * 设计:\n * - 依赖注入的 fetch(浏览器/Node 均可运行,Node 18+ 原生 fetch)\n * - 自动重试(指数退避)\n * - 失败降级(可传入 fallback,规则引擎兜底)\n * - 支持流式(onChunk 回调)与 JSON 输出\n */\n\nexport interface DeepSeekConfig {\n /** API Key */\n apiKey: string;\n /** 基础地址,默认 https://api.deepseek.com */\n baseUrl?: string;\n /** 模型,默认 deepseek-chat */\n model?: 'deepseek-chat' | 'deepseek-reasoner' | (string & {});\n /** 温度 0-2 */\n temperature?: number;\n /** 最大 token */\n maxTokens?: number;\n /** 超时(ms),默认 30s */\n timeoutMs?: number;\n /** 重试次数,默认 2 */\n retries?: number;\n /** 注入 fetch(测试/Node 环境),默认 globalThis.fetch */\n fetchImpl?: typeof fetch;\n}\n\nexport interface ChatMessage {\n role: 'system' | 'user' | 'assistant';\n content: string;\n}\n\nexport interface ChatOptions {\n /** 是否启用 JSON 模式(要求模型返回纯 JSON) */\n json?: boolean;\n /** 流式回调 */\n onChunk?: (delta: string) => void;\n}\n\nexport interface ChatResult {\n /** 完整回复文本 */\n content: string;\n /** 消耗 token */\n usage?: { promptTokens: number; completionTokens: number; totalTokens: number };\n /** 使用的模型 */\n model: string;\n}\n\n/** 已解析的 JSON 回复 */\nexport interface JsonChatResult<T> {\n /** 解析出的 JSON 对象 */\n data: T;\n /** 原始文本 */\n raw: string;\n model: string;\n}\n\nconst DEFAULT_BASE_URL = 'https://api.deepseek.com';\nconst DEFAULT_MODEL = 'deepseek-chat';\n\n/** 把中文异常文案简化为错误码 */\nfunction normalizeError(body: string): Error {\n const err = new Error(body || 'DeepSeek API 请求失败');\n err.name = 'DeepSeekError';\n return err;\n}\n\nexport class DeepSeekClient {\n private config: Required<Omit<DeepSeekConfig, 'fetchImpl'>> & { fetchImpl: typeof fetch };\n private lastRequestId = 0;\n\n constructor(config: DeepSeekConfig) {\n if (!config.apiKey) throw new Error('DeepSeekClient: apiKey 不能为空');\n this.config = {\n apiKey: config.apiKey,\n baseUrl: (config.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, ''),\n model: config.model ?? DEFAULT_MODEL,\n temperature: config.temperature ?? 0.3,\n maxTokens: config.maxTokens ?? 2048,\n timeoutMs: config.timeoutMs ?? 30000,\n retries: config.retries ?? 2,\n fetchImpl: config.fetchImpl ?? ((globalThis as { fetch?: typeof fetch }).fetch ?? fetch),\n };\n }\n\n /** 发起一次聊天补全 */\n async chat(messages: ChatMessage[], opts: ChatOptions = {}): Promise<ChatResult> {\n return this.requestWithRetry(messages, opts);\n }\n\n /** 聊天 + JSON 解析 */\n async chatJson<T>(messages: ChatMessage[]): Promise<JsonChatResult<T>> {\n const result = await this.chat(messages, { json: true });\n const raw = result.content.trim();\n // 去除可能的 ```json 围栏\n const cleaned = raw.replace(/^```(?:json)?\\s*/i, '').replace(/\\s*```$/, '');\n let data: T;\n try {\n data = JSON.parse(cleaned) as T;\n } catch (e) {\n // 尝试从文本中提取首个 JSON 对象\n const match = cleaned.match(/\\{[\\s\\S]*\\}|\\[[\\s\\S]*\\]/);\n if (match) {\n data = JSON.parse(match[0]) as T;\n } else {\n throw new Error(`DeepSeek 返回了非 JSON 内容: ${raw.slice(0, 200)}`);\n }\n }\n return { data, raw, model: result.model };\n }\n\n private async requestWithRetry(messages: ChatMessage[], opts: ChatOptions): Promise<ChatResult> {\n let lastError: Error | null = null;\n for (let attempt = 0; attempt <= this.config.retries; attempt++) {\n try {\n return await this.requestOnce(messages, opts);\n } catch (e) {\n lastError = e as Error;\n // 仅对可重试错误(网络/429/5xx)重试\n const retryable = !(e instanceof Error) || !e.name.includes('DeepSeek') || this.isRetryable(e as Error);\n if (!retryable && !this.isRetryable(e as Error)) break;\n if (attempt < this.config.retries) {\n await this.sleep(Math.min(1000 * 2 ** attempt, 8000));\n }\n }\n }\n throw lastError ?? new Error('DeepSeek 请求失败');\n }\n\n private isRetryable(err: Error): boolean {\n const msg = err.message ?? '';\n return /429|500|502|503|504|timeout|network|ECONN|abort|fetch failed/i.test(msg);\n }\n\n private async requestOnce(messages: ChatMessage[], opts: ChatOptions): Promise<ChatResult> {\n const { fetchImpl } = this.config;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.config.timeoutMs);\n\n const body: Record<string, unknown> = {\n model: this.config.model,\n messages,\n temperature: this.config.temperature,\n max_tokens: this.config.maxTokens,\n stream: Boolean(opts.onChunk),\n };\n if (opts.json) {\n body.response_format = { type: 'json_object' };\n }\n\n try {\n const res = await fetchImpl(`${this.config.baseUrl}/chat/completions`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.config.apiKey}`,\n },\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n\n if (!res.ok) {\n const text = await res.text().catch(() => '');\n throw normalizeError(`DeepSeek HTTP ${res.status}: ${text}`);\n }\n\n // 流式\n if (opts.onChunk && res.body) {\n return this.parseStream(res.body, opts.onChunk);\n }\n\n // 非流式\n const json = (await res.json()) as {\n choices: Array<{ message: { content: string } }>;\n usage?: { prompt_tokens: number; completion_tokens: number; total_tokens: number };\n model?: string;\n };\n const content = json.choices?.[0]?.message?.content ?? '';\n return {\n content,\n model: json.model ?? this.config.model,\n usage: json.usage\n ? { promptTokens: json.usage.prompt_tokens, completionTokens: json.usage.completion_tokens, totalTokens: json.usage.total_tokens }\n : undefined,\n };\n } finally {\n clearTimeout(timer);\n }\n }\n\n /** 解析 SSE 流式响应 */\n private async parseStream(\n body: ReadableStream<Uint8Array>,\n onChunk: (delta: string) => void\n ): Promise<ChatResult> {\n const reader = body.getReader();\n const decoder = new TextDecoder();\n let content = '';\n let buffer = '';\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n buffer = lines.pop() ?? '';\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed.startsWith('data:')) continue;\n const data = trimmed.slice(5).trim();\n if (data === '[DONE]') continue;\n try {\n const json = JSON.parse(data) as { choices?: Array<{ delta?: { content?: string } }> };\n const delta = json.choices?.[0]?.delta?.content ?? '';\n if (delta) {\n content += delta;\n onChunk(delta);\n }\n } catch {\n // 忽略无法解析的行\n }\n }\n }\n return { content, model: this.config.model };\n }\n\n private sleep(ms: number): Promise<void> {\n return new Promise((r) => setTimeout(r, ms));\n }\n}\n\n/** 便捷工厂:创建默认配置的客户端 */\nexport function createDeepSeekClient(config: DeepSeekConfig): DeepSeekClient {\n return new DeepSeekClient(config);\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/llm/deepseek.ts","../../src/llm/openaiCompatible.ts"],"names":["normalizeError"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * DeepSeek LLM 客户端(PRD phase-0 §5.5 / §5.7 的 v1 后端能力)\n *\n * DeepSeek API 与 OpenAI Chat Completions 协议兼容:\n * base_url: https://api.deepseek.com\n * 模型: deepseek-chat(通用对话)/ deepseek-reasoner(深度推理)\n * 鉴权: Authorization: Bearer <API_KEY>\n *\n * 设计:\n * - 依赖注入的 fetch(浏览器/Node 均可运行,Node 18+ 原生 fetch)\n * - 自动重试(指数退避)\n * - 失败降级(可传入 fallback,规则引擎兜底)\n * - 支持流式(onChunk 回调)与 JSON 输出\n */\n\nexport interface DeepSeekConfig {\n /** API Key */\n apiKey: string;\n /** 基础地址,默认 https://api.deepseek.com */\n baseUrl?: string;\n /** 模型,默认 deepseek-chat */\n model?: 'deepseek-chat' | 'deepseek-reasoner' | (string & {});\n /** 温度 0-2 */\n temperature?: number;\n /** 最大 token */\n maxTokens?: number;\n /** 超时(ms),默认 30s */\n timeoutMs?: number;\n /** 重试次数,默认 2 */\n retries?: number;\n /** 注入 fetch(测试/Node 环境),默认 globalThis.fetch */\n fetchImpl?: typeof fetch;\n}\n\nexport interface ChatMessage {\n role: 'system' | 'user' | 'assistant';\n content: string;\n}\n\nexport interface ChatOptions {\n /** 是否启用 JSON 模式(要求模型返回纯 JSON) */\n json?: boolean;\n /** 流式回调 */\n onChunk?: (delta: string) => void;\n}\n\nexport interface ChatResult {\n /** 完整回复文本 */\n content: string;\n /** 消耗 token */\n usage?: { promptTokens: number; completionTokens: number; totalTokens: number };\n /** 使用的模型 */\n model: string;\n}\n\n/** 已解析的 JSON 回复 */\nexport interface JsonChatResult<T> {\n /** 解析出的 JSON 对象 */\n data: T;\n /** 原始文本 */\n raw: string;\n model: string;\n}\n\nconst DEFAULT_BASE_URL = 'https://api.deepseek.com';\nconst DEFAULT_MODEL = 'deepseek-chat';\n\n/** 把中文异常文案简化为错误码 */\nfunction normalizeError(body: string): Error {\n const err = new Error(body || 'DeepSeek API 请求失败');\n err.name = 'DeepSeekError';\n return err;\n}\n\nexport class DeepSeekClient {\n private config: Required<Omit<DeepSeekConfig, 'fetchImpl'>> & { fetchImpl: typeof fetch };\n private lastRequestId = 0;\n\n constructor(config: DeepSeekConfig) {\n if (!config.apiKey) throw new Error('DeepSeekClient: apiKey 不能为空');\n this.config = {\n apiKey: config.apiKey,\n baseUrl: (config.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, ''),\n model: config.model ?? DEFAULT_MODEL,\n temperature: config.temperature ?? 0.3,\n maxTokens: config.maxTokens ?? 2048,\n timeoutMs: config.timeoutMs ?? 30000,\n retries: config.retries ?? 2,\n fetchImpl: config.fetchImpl ?? ((globalThis as { fetch?: typeof fetch }).fetch ?? fetch),\n };\n }\n\n /** 发起一次聊天补全 */\n async chat(messages: ChatMessage[], opts: ChatOptions = {}): Promise<ChatResult> {\n return this.requestWithRetry(messages, opts);\n }\n\n /** 聊天 + JSON 解析 */\n async chatJson<T>(messages: ChatMessage[]): Promise<JsonChatResult<T>> {\n const result = await this.chat(messages, { json: true });\n const raw = result.content.trim();\n // 去除可能的 ```json 围栏\n const cleaned = raw.replace(/^```(?:json)?\\s*/i, '').replace(/\\s*```$/, '');\n let data: T;\n try {\n data = JSON.parse(cleaned) as T;\n } catch (e) {\n // 尝试从文本中提取首个 JSON 对象\n const match = cleaned.match(/\\{[\\s\\S]*\\}|\\[[\\s\\S]*\\]/);\n if (match) {\n data = JSON.parse(match[0]) as T;\n } else {\n throw new Error(`DeepSeek 返回了非 JSON 内容: ${raw.slice(0, 200)}`);\n }\n }\n return { data, raw, model: result.model };\n }\n\n private async requestWithRetry(messages: ChatMessage[], opts: ChatOptions): Promise<ChatResult> {\n let lastError: Error | null = null;\n for (let attempt = 0; attempt <= this.config.retries; attempt++) {\n try {\n return await this.requestOnce(messages, opts);\n } catch (e) {\n lastError = e as Error;\n // 仅对可重试错误(网络/429/5xx)重试\n const retryable = !(e instanceof Error) || !e.name.includes('DeepSeek') || this.isRetryable(e as Error);\n if (!retryable && !this.isRetryable(e as Error)) break;\n if (attempt < this.config.retries) {\n await this.sleep(Math.min(1000 * 2 ** attempt, 8000));\n }\n }\n }\n throw lastError ?? new Error('DeepSeek 请求失败');\n }\n\n private isRetryable(err: Error): boolean {\n const msg = err.message ?? '';\n return /429|500|502|503|504|timeout|network|ECONN|abort|fetch failed/i.test(msg);\n }\n\n private async requestOnce(messages: ChatMessage[], opts: ChatOptions): Promise<ChatResult> {\n const { fetchImpl } = this.config;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.config.timeoutMs);\n\n const body: Record<string, unknown> = {\n model: this.config.model,\n messages,\n temperature: this.config.temperature,\n max_tokens: this.config.maxTokens,\n stream: Boolean(opts.onChunk),\n };\n if (opts.json) {\n body.response_format = { type: 'json_object' };\n }\n\n try {\n const res = await fetchImpl(`${this.config.baseUrl}/chat/completions`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.config.apiKey}`,\n },\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n\n if (!res.ok) {\n const text = await res.text().catch(() => '');\n throw normalizeError(`DeepSeek HTTP ${res.status}: ${text}`);\n }\n\n // 流式\n if (opts.onChunk && res.body) {\n return this.parseStream(res.body, opts.onChunk);\n }\n\n // 非流式\n const json = (await res.json()) as {\n choices: Array<{ message: { content: string } }>;\n usage?: { prompt_tokens: number; completion_tokens: number; total_tokens: number };\n model?: string;\n };\n const content = json.choices?.[0]?.message?.content ?? '';\n return {\n content,\n model: json.model ?? this.config.model,\n usage: json.usage\n ? { promptTokens: json.usage.prompt_tokens, completionTokens: json.usage.completion_tokens, totalTokens: json.usage.total_tokens }\n : undefined,\n };\n } finally {\n clearTimeout(timer);\n }\n }\n\n /** 解析 SSE 流式响应 */\n private async parseStream(\n body: ReadableStream<Uint8Array>,\n onChunk: (delta: string) => void\n ): Promise<ChatResult> {\n const reader = body.getReader();\n const decoder = new TextDecoder();\n let content = '';\n let buffer = '';\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n buffer = lines.pop() ?? '';\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed.startsWith('data:')) continue;\n const data = trimmed.slice(5).trim();\n if (data === '[DONE]') continue;\n try {\n const json = JSON.parse(data) as { choices?: Array<{ delta?: { content?: string } }> };\n const delta = json.choices?.[0]?.delta?.content ?? '';\n if (delta) {\n content += delta;\n onChunk(delta);\n }\n } catch {\n // 忽略无法解析的行\n }\n }\n }\n return { content, model: this.config.model };\n }\n\n private sleep(ms: number): Promise<void> {\n return new Promise((r) => setTimeout(r, ms));\n }\n}\n\n/** 便捷工厂:创建默认配置的客户端 */\nexport function createDeepSeekClient(config: DeepSeekConfig): DeepSeekClient {\n return new DeepSeekClient(config);\n}\n","/**\n * 通用 OpenAI Chat Completions 兼容客户端(PRD phase-0 §5.5/§5.7 扩展)\n *\n * 任何遵循 OpenAI Chat Completions 协议的服务都可直接对接:\n * - OpenAI 官方(https://api.openai.com)\n * - Azure OpenAI\n * - SiliconFlow、DeepSeek、Moonshot、Together、Groq、OpenRouter 等\n *\n * 与 DeepSeekClient 区别:base_url 与鉴权 header 可自定义;接口形态完全一致,\n * 均为 LlmClient 实现,可互换使用。\n *\n * 重试 / 超时 / JSON 解析策略与 DeepSeekClient 完全一致,确保 provider 切换零行为漂移。\n */\n\nimport type { LlmClient } from './types';\nimport type {\n ChatMessage,\n ChatOptions,\n ChatResult,\n JsonChatResult,\n} from './deepseek';\n\nexport interface OpenAICompatibleConfig {\n /** API Key */\n apiKey: string;\n /** 基础地址(如 https://api.openai.com) */\n baseUrl: string;\n /** 模型名(必填,无默认以免误用 OpenAI gpt-4) */\n model: string;\n /** 温度 0-2,默认 0.3 */\n temperature?: number;\n /** 最大 token,默认 2048 */\n maxTokens?: number;\n /** 超时(ms),默认 30s */\n timeoutMs?: number;\n /** 重试次数,默认 2 */\n retries?: number;\n /** 注入 fetch(测试/Node 环境),默认 globalThis.fetch */\n fetchImpl?: typeof fetch;\n /** 鉴权 header 前缀,默认 'Bearer' */\n authScheme?: 'Bearer' | 'X-Api-Key';\n /** 自定义额外 headers(用于 Azure api-version 等) */\n extraHeaders?: Record<string, string>;\n}\n\nfunction normalizeError(body: string, provider: string): Error {\n const err = new Error(body || `${provider} API 请求失败`);\n err.name = `${provider}Error`;\n return err;\n}\n\nexport class OpenAICompatibleClient implements LlmClient {\n private readonly apiKey: string;\n private readonly baseUrl: string;\n private readonly model: string;\n private readonly temperature: number;\n private readonly maxTokens: number;\n private readonly timeoutMs: number;\n private readonly retries: number;\n private readonly fetchImpl: typeof fetch;\n private readonly authScheme: 'Bearer' | 'X-Api-Key';\n private readonly extraHeaders: Record<string, string>;\n private readonly providerLabel: string;\n\n constructor(config: OpenAICompatibleConfig) {\n if (!config.apiKey) throw new Error('OpenAICompatibleClient: apiKey 不能为空');\n if (!config.baseUrl) throw new Error('OpenAICompatibleClient: baseUrl 不能为空');\n if (!config.model) throw new Error('OpenAICompatibleClient: model 不能为空');\n this.apiKey = config.apiKey;\n this.baseUrl = config.baseUrl.replace(/\\/+$/, '');\n this.model = config.model;\n this.temperature = config.temperature ?? 0.3;\n this.maxTokens = config.maxTokens ?? 2048;\n this.timeoutMs = config.timeoutMs ?? 30000;\n this.retries = config.retries ?? 2;\n this.fetchImpl =\n config.fetchImpl ?? ((globalThis as { fetch?: typeof fetch }).fetch ?? fetch);\n this.authScheme = config.authScheme ?? 'Bearer';\n this.extraHeaders = config.extraHeaders ?? {};\n this.providerLabel = (() => {\n try {\n return new URL(this.baseUrl).hostname || 'LLM';\n } catch {\n return 'LLM';\n }\n })();\n }\n\n async chat(messages: ChatMessage[], opts: ChatOptions = {}): Promise<ChatResult> {\n return this.requestWithRetry(messages, opts);\n }\n\n async chatJson<T = unknown>(messages: ChatMessage[]): Promise<JsonChatResult<T>> {\n const result = await this.chat(messages, { json: true });\n const raw = result.content.trim();\n const cleaned = raw.replace(/^```(?:json)?\\s*/i, '').replace(/\\s*```$/, '');\n let data: T;\n try {\n data = JSON.parse(cleaned) as T;\n } catch {\n const match = cleaned.match(/\\{[\\s\\S]*\\}|\\[[\\s\\S]*\\]/);\n if (match) {\n data = JSON.parse(match[0]) as T;\n } else {\n throw new Error(`${this.providerLabel} 返回了非 JSON 内容: ${raw.slice(0, 200)}`);\n }\n }\n return { data, raw, model: result.model };\n }\n\n private async requestWithRetry(messages: ChatMessage[], opts: ChatOptions): Promise<ChatResult> {\n let lastError: Error | null = null;\n for (let attempt = 0; attempt <= this.retries; attempt++) {\n try {\n return await this.requestOnce(messages, opts);\n } catch (e) {\n lastError = e as Error;\n if (attempt < this.retries) {\n await this.sleep(Math.min(1000 * 2 ** attempt, 8000));\n }\n }\n }\n throw lastError ?? new Error(`${this.providerLabel} 请求失败`);\n }\n\n private async requestOnce(messages: ChatMessage[], opts: ChatOptions): Promise<ChatResult> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeoutMs);\n\n const body: Record<string, unknown> = {\n model: this.model,\n messages,\n temperature: this.temperature,\n max_tokens: this.maxTokens,\n stream: Boolean(opts.onChunk),\n };\n if (opts.json) {\n body.response_format = { type: 'json_object' };\n }\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n ...this.extraHeaders,\n };\n if (this.authScheme === 'Bearer') {\n headers.Authorization = `Bearer ${this.apiKey}`;\n } else {\n headers['X-Api-Key'] = this.apiKey;\n }\n\n try {\n const res = await this.fetchImpl(`${this.baseUrl}/chat/completions`, {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n if (!res.ok) {\n const text = await res.text().catch(() => '');\n throw normalizeError(`${this.providerLabel} HTTP ${res.status}: ${text}`, this.providerLabel);\n }\n if (opts.onChunk && res.body) {\n return this.parseStream(res.body, opts.onChunk);\n }\n const json = (await res.json()) as {\n choices: Array<{ message: { content: string } }>;\n usage?: { prompt_tokens: number; completion_tokens: number; total_tokens: number };\n model?: string;\n };\n const content = json.choices?.[0]?.message?.content ?? '';\n return {\n content,\n model: json.model ?? this.model,\n usage: json.usage\n ? {\n promptTokens: json.usage.prompt_tokens,\n completionTokens: json.usage.completion_tokens,\n totalTokens: json.usage.prompt_tokens + json.usage.completion_tokens,\n }\n : undefined,\n };\n } finally {\n clearTimeout(timer);\n }\n }\n\n private async parseStream(\n body: ReadableStream<Uint8Array>,\n onChunk: (delta: string) => void,\n ): Promise<ChatResult> {\n const reader = body.getReader();\n const decoder = new TextDecoder();\n let content = '';\n let buffer = '';\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n buffer = lines.pop() ?? '';\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed.startsWith('data:')) continue;\n const data = trimmed.slice(5).trim();\n if (data === '[DONE]') continue;\n try {\n const json = JSON.parse(data) as { choices?: Array<{ delta?: { content?: string } }> };\n const delta = json.choices?.[0]?.delta?.content ?? '';\n if (delta) {\n content += delta;\n onChunk(delta);\n }\n } catch {\n // 忽略无法解析的行\n }\n }\n }\n return { content, model: this.model };\n }\n\n private sleep(ms: number): Promise<void> {\n return new Promise((r) => setTimeout(r, ms));\n }\n}\n\n/** 便捷工厂 */\nexport function createOpenAICompatibleClient(config: OpenAICompatibleConfig): OpenAICompatibleClient {\n return new OpenAICompatibleClient(config);\n}"]}
|
package/dist/llm/index.d.cts
CHANGED
|
@@ -1,27 +1,53 @@
|
|
|
1
|
+
import { C as ChatMessage, a as ChatOptions, b as ChatResult, J as JsonChatResult } from '../deepseek-rSUSDXri.cjs';
|
|
2
|
+
export { D as DeepSeekClient, c as DeepSeekConfig, d as createDeepSeekClient } from '../deepseek-rSUSDXri.cjs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* 统一 LLM 客户端接口(facade)
|
|
6
|
+
*
|
|
7
|
+
* 任何实现该接口的对象都可被注入到 ai 包的 Copilot / NLPG / 后续 LLM 增强模块。
|
|
8
|
+
* 当前 ai 包内部默认实现:
|
|
9
|
+
* - DeepSeekClient (DeepSeek 官方 API)
|
|
10
|
+
* - OpenAICompatibleClient (任意 OpenAI Chat Completions 兼容服务,含 OpenAI 官方、
|
|
11
|
+
* Azure OpenAI、SiliconFlow、Together、Groq 等)
|
|
12
|
+
*
|
|
13
|
+
* 设计要点:
|
|
14
|
+
* 1. 仅暴露与业务相关的最小表面(chat/chatJson),不暴露各家差异
|
|
15
|
+
* 2. 流式通过 onChunk 回调注入,与 provider 无关
|
|
16
|
+
* 3. JSON 解析容错(自动剥围栏、容错提取)作为接口约定,**所有实现都必须做**
|
|
17
|
+
* 4. fetch 可注入,便于 Node 测试/SSR/CI 环境
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
interface LlmClient {
|
|
21
|
+
/** 发起一次聊天补全 */
|
|
22
|
+
chat(messages: ChatMessage[], opts?: ChatOptions): Promise<ChatResult>;
|
|
23
|
+
/** 聊天 + 自动 JSON 解析(自动剥 ```json 围栏、容错提取) */
|
|
24
|
+
chatJson<T = unknown>(messages: ChatMessage[]): Promise<JsonChatResult<T>>;
|
|
25
|
+
}
|
|
26
|
+
|
|
1
27
|
/**
|
|
2
|
-
*
|
|
28
|
+
* 通用 OpenAI Chat Completions 兼容客户端(PRD phase-0 §5.5/§5.7 扩展)
|
|
3
29
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
30
|
+
* 任何遵循 OpenAI Chat Completions 协议的服务都可直接对接:
|
|
31
|
+
* - OpenAI 官方(https://api.openai.com)
|
|
32
|
+
* - Azure OpenAI
|
|
33
|
+
* - SiliconFlow、DeepSeek、Moonshot、Together、Groq、OpenRouter 等
|
|
8
34
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* - 支持流式(onChunk 回调)与 JSON 输出
|
|
35
|
+
* 与 DeepSeekClient 区别:base_url 与鉴权 header 可自定义;接口形态完全一致,
|
|
36
|
+
* 均为 LlmClient 实现,可互换使用。
|
|
37
|
+
*
|
|
38
|
+
* 重试 / 超时 / JSON 解析策略与 DeepSeekClient 完全一致,确保 provider 切换零行为漂移。
|
|
14
39
|
*/
|
|
15
|
-
|
|
40
|
+
|
|
41
|
+
interface OpenAICompatibleConfig {
|
|
16
42
|
/** API Key */
|
|
17
43
|
apiKey: string;
|
|
18
|
-
/**
|
|
19
|
-
baseUrl
|
|
20
|
-
/**
|
|
21
|
-
model
|
|
22
|
-
/** 温度 0-2 */
|
|
44
|
+
/** 基础地址(如 https://api.openai.com) */
|
|
45
|
+
baseUrl: string;
|
|
46
|
+
/** 模型名(必填,无默认以免误用 OpenAI gpt-4) */
|
|
47
|
+
model: string;
|
|
48
|
+
/** 温度 0-2,默认 0.3 */
|
|
23
49
|
temperature?: number;
|
|
24
|
-
/** 最大 token */
|
|
50
|
+
/** 最大 token,默认 2048 */
|
|
25
51
|
maxTokens?: number;
|
|
26
52
|
/** 超时(ms),默认 30s */
|
|
27
53
|
timeoutMs?: number;
|
|
@@ -29,53 +55,32 @@ interface DeepSeekConfig {
|
|
|
29
55
|
retries?: number;
|
|
30
56
|
/** 注入 fetch(测试/Node 环境),默认 globalThis.fetch */
|
|
31
57
|
fetchImpl?: typeof fetch;
|
|
58
|
+
/** 鉴权 header 前缀,默认 'Bearer' */
|
|
59
|
+
authScheme?: 'Bearer' | 'X-Api-Key';
|
|
60
|
+
/** 自定义额外 headers(用于 Azure api-version 等) */
|
|
61
|
+
extraHeaders?: Record<string, string>;
|
|
32
62
|
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
/** 消耗 token */
|
|
47
|
-
usage?: {
|
|
48
|
-
promptTokens: number;
|
|
49
|
-
completionTokens: number;
|
|
50
|
-
totalTokens: number;
|
|
51
|
-
};
|
|
52
|
-
/** 使用的模型 */
|
|
53
|
-
model: string;
|
|
54
|
-
}
|
|
55
|
-
/** 已解析的 JSON 回复 */
|
|
56
|
-
interface JsonChatResult<T> {
|
|
57
|
-
/** 解析出的 JSON 对象 */
|
|
58
|
-
data: T;
|
|
59
|
-
/** 原始文本 */
|
|
60
|
-
raw: string;
|
|
61
|
-
model: string;
|
|
62
|
-
}
|
|
63
|
-
declare class DeepSeekClient {
|
|
64
|
-
private config;
|
|
65
|
-
private lastRequestId;
|
|
66
|
-
constructor(config: DeepSeekConfig);
|
|
67
|
-
/** 发起一次聊天补全 */
|
|
63
|
+
declare class OpenAICompatibleClient implements LlmClient {
|
|
64
|
+
private readonly apiKey;
|
|
65
|
+
private readonly baseUrl;
|
|
66
|
+
private readonly model;
|
|
67
|
+
private readonly temperature;
|
|
68
|
+
private readonly maxTokens;
|
|
69
|
+
private readonly timeoutMs;
|
|
70
|
+
private readonly retries;
|
|
71
|
+
private readonly fetchImpl;
|
|
72
|
+
private readonly authScheme;
|
|
73
|
+
private readonly extraHeaders;
|
|
74
|
+
private readonly providerLabel;
|
|
75
|
+
constructor(config: OpenAICompatibleConfig);
|
|
68
76
|
chat(messages: ChatMessage[], opts?: ChatOptions): Promise<ChatResult>;
|
|
69
|
-
|
|
70
|
-
chatJson<T>(messages: ChatMessage[]): Promise<JsonChatResult<T>>;
|
|
77
|
+
chatJson<T = unknown>(messages: ChatMessage[]): Promise<JsonChatResult<T>>;
|
|
71
78
|
private requestWithRetry;
|
|
72
|
-
private isRetryable;
|
|
73
79
|
private requestOnce;
|
|
74
|
-
/** 解析 SSE 流式响应 */
|
|
75
80
|
private parseStream;
|
|
76
81
|
private sleep;
|
|
77
82
|
}
|
|
78
|
-
/**
|
|
79
|
-
declare function
|
|
83
|
+
/** 便捷工厂 */
|
|
84
|
+
declare function createOpenAICompatibleClient(config: OpenAICompatibleConfig): OpenAICompatibleClient;
|
|
80
85
|
|
|
81
|
-
export {
|
|
86
|
+
export { ChatMessage, ChatOptions, ChatResult, JsonChatResult, type LlmClient, OpenAICompatibleClient, type OpenAICompatibleConfig, createOpenAICompatibleClient };
|
package/dist/llm/index.d.ts
CHANGED
|
@@ -1,27 +1,53 @@
|
|
|
1
|
+
import { C as ChatMessage, a as ChatOptions, b as ChatResult, J as JsonChatResult } from '../deepseek-rSUSDXri.js';
|
|
2
|
+
export { D as DeepSeekClient, c as DeepSeekConfig, d as createDeepSeekClient } from '../deepseek-rSUSDXri.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* 统一 LLM 客户端接口(facade)
|
|
6
|
+
*
|
|
7
|
+
* 任何实现该接口的对象都可被注入到 ai 包的 Copilot / NLPG / 后续 LLM 增强模块。
|
|
8
|
+
* 当前 ai 包内部默认实现:
|
|
9
|
+
* - DeepSeekClient (DeepSeek 官方 API)
|
|
10
|
+
* - OpenAICompatibleClient (任意 OpenAI Chat Completions 兼容服务,含 OpenAI 官方、
|
|
11
|
+
* Azure OpenAI、SiliconFlow、Together、Groq 等)
|
|
12
|
+
*
|
|
13
|
+
* 设计要点:
|
|
14
|
+
* 1. 仅暴露与业务相关的最小表面(chat/chatJson),不暴露各家差异
|
|
15
|
+
* 2. 流式通过 onChunk 回调注入,与 provider 无关
|
|
16
|
+
* 3. JSON 解析容错(自动剥围栏、容错提取)作为接口约定,**所有实现都必须做**
|
|
17
|
+
* 4. fetch 可注入,便于 Node 测试/SSR/CI 环境
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
interface LlmClient {
|
|
21
|
+
/** 发起一次聊天补全 */
|
|
22
|
+
chat(messages: ChatMessage[], opts?: ChatOptions): Promise<ChatResult>;
|
|
23
|
+
/** 聊天 + 自动 JSON 解析(自动剥 ```json 围栏、容错提取) */
|
|
24
|
+
chatJson<T = unknown>(messages: ChatMessage[]): Promise<JsonChatResult<T>>;
|
|
25
|
+
}
|
|
26
|
+
|
|
1
27
|
/**
|
|
2
|
-
*
|
|
28
|
+
* 通用 OpenAI Chat Completions 兼容客户端(PRD phase-0 §5.5/§5.7 扩展)
|
|
3
29
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
30
|
+
* 任何遵循 OpenAI Chat Completions 协议的服务都可直接对接:
|
|
31
|
+
* - OpenAI 官方(https://api.openai.com)
|
|
32
|
+
* - Azure OpenAI
|
|
33
|
+
* - SiliconFlow、DeepSeek、Moonshot、Together、Groq、OpenRouter 等
|
|
8
34
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* - 支持流式(onChunk 回调)与 JSON 输出
|
|
35
|
+
* 与 DeepSeekClient 区别:base_url 与鉴权 header 可自定义;接口形态完全一致,
|
|
36
|
+
* 均为 LlmClient 实现,可互换使用。
|
|
37
|
+
*
|
|
38
|
+
* 重试 / 超时 / JSON 解析策略与 DeepSeekClient 完全一致,确保 provider 切换零行为漂移。
|
|
14
39
|
*/
|
|
15
|
-
|
|
40
|
+
|
|
41
|
+
interface OpenAICompatibleConfig {
|
|
16
42
|
/** API Key */
|
|
17
43
|
apiKey: string;
|
|
18
|
-
/**
|
|
19
|
-
baseUrl
|
|
20
|
-
/**
|
|
21
|
-
model
|
|
22
|
-
/** 温度 0-2 */
|
|
44
|
+
/** 基础地址(如 https://api.openai.com) */
|
|
45
|
+
baseUrl: string;
|
|
46
|
+
/** 模型名(必填,无默认以免误用 OpenAI gpt-4) */
|
|
47
|
+
model: string;
|
|
48
|
+
/** 温度 0-2,默认 0.3 */
|
|
23
49
|
temperature?: number;
|
|
24
|
-
/** 最大 token */
|
|
50
|
+
/** 最大 token,默认 2048 */
|
|
25
51
|
maxTokens?: number;
|
|
26
52
|
/** 超时(ms),默认 30s */
|
|
27
53
|
timeoutMs?: number;
|
|
@@ -29,53 +55,32 @@ interface DeepSeekConfig {
|
|
|
29
55
|
retries?: number;
|
|
30
56
|
/** 注入 fetch(测试/Node 环境),默认 globalThis.fetch */
|
|
31
57
|
fetchImpl?: typeof fetch;
|
|
58
|
+
/** 鉴权 header 前缀,默认 'Bearer' */
|
|
59
|
+
authScheme?: 'Bearer' | 'X-Api-Key';
|
|
60
|
+
/** 自定义额外 headers(用于 Azure api-version 等) */
|
|
61
|
+
extraHeaders?: Record<string, string>;
|
|
32
62
|
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
/** 消耗 token */
|
|
47
|
-
usage?: {
|
|
48
|
-
promptTokens: number;
|
|
49
|
-
completionTokens: number;
|
|
50
|
-
totalTokens: number;
|
|
51
|
-
};
|
|
52
|
-
/** 使用的模型 */
|
|
53
|
-
model: string;
|
|
54
|
-
}
|
|
55
|
-
/** 已解析的 JSON 回复 */
|
|
56
|
-
interface JsonChatResult<T> {
|
|
57
|
-
/** 解析出的 JSON 对象 */
|
|
58
|
-
data: T;
|
|
59
|
-
/** 原始文本 */
|
|
60
|
-
raw: string;
|
|
61
|
-
model: string;
|
|
62
|
-
}
|
|
63
|
-
declare class DeepSeekClient {
|
|
64
|
-
private config;
|
|
65
|
-
private lastRequestId;
|
|
66
|
-
constructor(config: DeepSeekConfig);
|
|
67
|
-
/** 发起一次聊天补全 */
|
|
63
|
+
declare class OpenAICompatibleClient implements LlmClient {
|
|
64
|
+
private readonly apiKey;
|
|
65
|
+
private readonly baseUrl;
|
|
66
|
+
private readonly model;
|
|
67
|
+
private readonly temperature;
|
|
68
|
+
private readonly maxTokens;
|
|
69
|
+
private readonly timeoutMs;
|
|
70
|
+
private readonly retries;
|
|
71
|
+
private readonly fetchImpl;
|
|
72
|
+
private readonly authScheme;
|
|
73
|
+
private readonly extraHeaders;
|
|
74
|
+
private readonly providerLabel;
|
|
75
|
+
constructor(config: OpenAICompatibleConfig);
|
|
68
76
|
chat(messages: ChatMessage[], opts?: ChatOptions): Promise<ChatResult>;
|
|
69
|
-
|
|
70
|
-
chatJson<T>(messages: ChatMessage[]): Promise<JsonChatResult<T>>;
|
|
77
|
+
chatJson<T = unknown>(messages: ChatMessage[]): Promise<JsonChatResult<T>>;
|
|
71
78
|
private requestWithRetry;
|
|
72
|
-
private isRetryable;
|
|
73
79
|
private requestOnce;
|
|
74
|
-
/** 解析 SSE 流式响应 */
|
|
75
80
|
private parseStream;
|
|
76
81
|
private sleep;
|
|
77
82
|
}
|
|
78
|
-
/**
|
|
79
|
-
declare function
|
|
83
|
+
/** 便捷工厂 */
|
|
84
|
+
declare function createOpenAICompatibleClient(config: OpenAICompatibleConfig): OpenAICompatibleClient;
|
|
80
85
|
|
|
81
|
-
export {
|
|
86
|
+
export { ChatMessage, ChatOptions, ChatResult, JsonChatResult, type LlmClient, OpenAICompatibleClient, type OpenAICompatibleConfig, createOpenAICompatibleClient };
|
package/dist/llm/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { DeepSeekClient, createDeepSeekClient } from '../chunk-
|
|
1
|
+
export { DeepSeekClient, OpenAICompatibleClient, createDeepSeekClient, createOpenAICompatibleClient } from '../chunk-AIQSXKZQ.js';
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
|
3
3
|
//# sourceMappingURL=index.js.map
|