@nocobase/plugin-ai 2.2.0-beta.16 → 2.2.0-beta.18
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/ai/docs/nocobase/ai-dev/watermark-plugin.md +2 -0
- package/dist/ai/docs/nocobase/api/cli/api/resource/create.md +4 -3
- package/dist/ai/docs/nocobase/file-manager/file-preview/index.md +44 -3
- package/dist/ai/docs/nocobase/file-manager/storage/aliyun-oss.md +100 -3
- package/dist/ai/docs/nocobase/plugin-development/build.md +10 -4
- package/dist/ai/docs/nocobase/plugin-development/client/appendix/faq.md +1 -1
- package/dist/ai/docs/nocobase/plugin-development/client/examples/custom-action.md +2 -0
- package/dist/ai/docs/nocobase/plugin-development/client/examples/custom-block.md +2 -0
- package/dist/ai/docs/nocobase/plugin-development/client/examples/custom-field.md +2 -0
- package/dist/ai/docs/nocobase/plugin-development/client/examples/fullstack-plugin.md +2 -0
- package/dist/ai/docs/nocobase/plugin-development/client/examples/settings-page.md +2 -0
- package/dist/ai/docs/nocobase/plugin-development/common/i18n.md +3 -3
- package/dist/ai/docs/nocobase/plugin-development/server/cache.md +1 -1
- package/dist/ai/docs/nocobase/plugin-development/server/collections.md +0 -6
- package/dist/ai/docs/nocobase/plugin-development/server/command.md +2 -2
- package/dist/ai/docs/nocobase/plugin-development/server/context.md +2 -2
- package/dist/ai/docs/nocobase/plugin-development/server/i18n.md +4 -4
- package/dist/ai/docs/nocobase/plugin-development/write-your-first-plugin.md +91 -43
- package/dist/ai/docs/nocobase/users-permissions/sync/index.md +8 -1
- package/dist/ai/docs/nocobase/users-permissions/sync/sources/dingtalk.md +138 -0
- package/dist/ai/docs/nocobase/users-permissions/sync/sources/ldap.md +87 -0
- package/dist/ai/docs/nocobase/workflow/nodes/javascript.md +21 -1
- package/dist/client/244.1086967ad8fdedf4.js +10 -0
- package/dist/client/{705.19b642db34de438a.js → 705.a4fe26945d175e8a.js} +1 -1
- package/dist/client/index.js +3 -3
- package/dist/client-v2/244.678c34d698985c60.js +10 -0
- package/dist/client-v2/420.a5b929a5e7f330be.js +10 -0
- package/dist/client-v2/{705.8dc34d43f02f322c.js → 705.f2e1b26a3f000075.js} +1 -1
- package/dist/client-v2/ai-employees/chatbox/hooks/reasoning-stream.d.ts +10 -0
- package/dist/client-v2/ai-employees/chatbox/stores/chat-box.d.ts +0 -2
- package/dist/client-v2/index.js +3 -3
- package/dist/client-v2/llm-providers/forms.d.ts +2 -0
- package/dist/client-v2/llm-providers/index.d.ts +1 -0
- package/dist/client-v2/models/ai-employees/AIEmployeeShortcutModel.d.ts +3 -0
- package/dist/client-v2/pages/EmployeesPage.d.ts +3 -0
- package/dist/client-v2/pages/LLMServicesPage.d.ts +9 -4
- package/dist/client-v2/repositories/AIConfigRepository.d.ts +2 -0
- package/dist/externalVersion.js +18 -16
- package/dist/locale/de-DE.json +2 -1
- package/dist/locale/en-US.json +9 -5
- package/dist/locale/es-ES.json +2 -1
- package/dist/locale/fr-FR.json +2 -1
- package/dist/locale/hu-HU.json +2 -1
- package/dist/locale/id-ID.json +2 -1
- package/dist/locale/it-IT.json +2 -1
- package/dist/locale/ja-JP.json +2 -1
- package/dist/locale/ko-KR.json +2 -1
- package/dist/locale/nl-NL.json +2 -1
- package/dist/locale/pt-BR.json +2 -1
- package/dist/locale/ru-RU.json +2 -1
- package/dist/locale/tr-TR.json +2 -1
- package/dist/locale/uk-UA.json +2 -1
- package/dist/locale/vi-VN.json +2 -1
- package/dist/locale/zh-CN.json +9 -5
- package/dist/locale/zh-TW.json +2 -1
- package/dist/node_modules/@langchain/mistralai/package.json +1 -1
- package/dist/node_modules/@langchain/xai/package.json +1 -1
- package/dist/node_modules/fs-extra/package.json +1 -1
- package/dist/node_modules/jsonrepair/package.json +1 -1
- package/dist/node_modules/just-bash/package.json +1 -1
- package/dist/node_modules/nodejs-snowflake/package.json +1 -1
- package/dist/node_modules/openai/package.json +1 -1
- package/dist/node_modules/zod/package.json +1 -1
- package/dist/server/ai-employees/ai-employee.js +40 -24
- package/dist/server/ai-employees/reasoning-stream-state.d.ts +23 -0
- package/dist/server/ai-employees/reasoning-stream-state.js +63 -0
- package/dist/server/llm-providers/common/reasoning.js +18 -10
- package/dist/{client-v2/ai-employees/chatbox/components/DebugPanel.d.ts → server/llm-providers/deepseek/index.d.ts} +2 -2
- package/dist/server/llm-providers/deepseek/index.js +32 -0
- package/dist/server/llm-providers/deepseek/provider.d.ts +57 -0
- package/dist/server/llm-providers/deepseek/provider.js +320 -0
- package/dist/server/llm-providers/deepseek/reasoning.d.ts +83 -0
- package/dist/server/llm-providers/deepseek/reasoning.js +285 -0
- package/dist/server/llm-providers/mistral.d.ts +1 -1
- package/dist/server/llm-providers/provider.d.ts +1 -0
- package/dist/server/llm-providers/provider.js +3 -0
- package/dist/server/llm-providers/shengsuanyun.d.ts +29 -0
- package/dist/server/llm-providers/shengsuanyun.js +114 -0
- package/dist/server/manager/ai-manager.d.ts +3 -0
- package/dist/server/manager/ai-manager.js +7 -2
- package/dist/server/plugin.js +2 -0
- package/dist/server/types/ai-message.type.d.ts +4 -0
- package/dist/swagger/index.d.ts +14 -0
- package/dist/swagger/llm.d.ts +8 -0
- package/dist/swagger/llm.js +8 -0
- package/dist/swagger/schemas.d.ts +6 -0
- package/dist/swagger/schemas.js +6 -0
- package/package.json +2 -2
- package/dist/client/244.8631eb5cf3f05e21.js +0 -10
- package/dist/client-v2/244.c428e645ecb94414.js +0 -10
- package/dist/client-v2/420.b2aedb1ff71fca0e.js +0 -10
- package/dist/client-v2/debug-logger.d.ts +0 -52
- package/dist/server/llm-providers/deepseek.d.ts +0 -40
- package/dist/server/llm-providers/deepseek.js +0 -174
|
@@ -58,6 +58,7 @@ var import_tool_call_sanitizer = require("./tool-call-sanitizer");
|
|
|
58
58
|
var import_attachments = require("../attachments");
|
|
59
59
|
var import_frontend_tools = require("../../common/frontend-tools");
|
|
60
60
|
var import_frontend_tools2 = require("../frontend-tools");
|
|
61
|
+
var import_reasoning_stream_state = require("./reasoning-stream-state");
|
|
61
62
|
class AIEmployee {
|
|
62
63
|
sessionId;
|
|
63
64
|
from = "main-agent";
|
|
@@ -415,10 +416,21 @@ class AIEmployee {
|
|
|
415
416
|
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z;
|
|
416
417
|
const aiMessageIdMap = /* @__PURE__ */ new Map();
|
|
417
418
|
const { signal, providerName, llmService, model, provider, responseMetadata, allowEmpty = false } = options;
|
|
418
|
-
|
|
419
|
+
const reasoningState = new import_reasoning_stream_state.ReasoningStreamState();
|
|
420
|
+
const stopReasoning = async (conversation) => {
|
|
421
|
+
if (reasoningState.stop(conversation)) {
|
|
422
|
+
await this.protocol.with(conversation).stopReasoning();
|
|
423
|
+
}
|
|
424
|
+
};
|
|
425
|
+
const stopAllReasoning = async () => {
|
|
426
|
+
for (const conversation of reasoningState.drain()) {
|
|
427
|
+
await this.protocol.with(conversation).stopReasoning();
|
|
428
|
+
}
|
|
429
|
+
};
|
|
419
430
|
let gathered;
|
|
420
431
|
signal.addEventListener("abort", async () => {
|
|
421
432
|
try {
|
|
433
|
+
await stopAllReasoning();
|
|
422
434
|
if ((gathered == null ? void 0 : gathered.type) === "ai") {
|
|
423
435
|
const values = (0, import_utils2.convertAIMessage)({
|
|
424
436
|
aiEmployee: this,
|
|
@@ -460,27 +472,27 @@ class AIEmployee {
|
|
|
460
472
|
const { currentConversation } = metadata;
|
|
461
473
|
if (chunk.type === "ai") {
|
|
462
474
|
gathered = gathered !== void 0 ? (0, import_stream.concat)(gathered, chunk) : chunk;
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
475
|
+
const reasoningContent = provider.parseReasoningContent(chunk);
|
|
476
|
+
if (reasoningContent) {
|
|
477
|
+
reasoningState.start(currentConversation);
|
|
478
|
+
await this.protocol.with(currentConversation).reasoning(reasoningContent);
|
|
479
|
+
}
|
|
480
|
+
const parsedContent = chunk.content ? provider.parseResponseChunk(chunk.content) : null;
|
|
481
|
+
if (parsedContent) {
|
|
482
|
+
await stopReasoning(currentConversation);
|
|
483
|
+
await this.protocol.with(currentConversation).content(parsedContent);
|
|
472
484
|
}
|
|
473
485
|
if ((_a = chunk.tool_call_chunks) == null ? void 0 : _a.length) {
|
|
486
|
+
await stopReasoning(currentConversation);
|
|
474
487
|
await this.protocol.with(currentConversation).toolCallChunks(chunk.tool_call_chunks);
|
|
475
488
|
}
|
|
476
489
|
const webSearch = provider.parseWebSearchAction(chunk);
|
|
477
490
|
if (webSearch == null ? void 0 : webSearch.length) {
|
|
491
|
+
await stopReasoning(currentConversation);
|
|
478
492
|
await this.protocol.with(currentConversation).webSearch(webSearch);
|
|
479
493
|
}
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
isReasoning = true;
|
|
483
|
-
await this.protocol.with(currentConversation).reasoning(reasoningContent);
|
|
494
|
+
if ((0, import_reasoning_stream_state.isReasoningFinishChunk)(chunk)) {
|
|
495
|
+
await stopReasoning(currentConversation);
|
|
484
496
|
}
|
|
485
497
|
}
|
|
486
498
|
} else if (mode === "updates") {
|
|
@@ -536,6 +548,7 @@ class AIEmployee {
|
|
|
536
548
|
}
|
|
537
549
|
}
|
|
538
550
|
} else if (chunks.action === "initToolCalls") {
|
|
551
|
+
await stopReasoning(currentConversation);
|
|
539
552
|
await this.protocol.with(currentConversation).toolCalls(chunks.body);
|
|
540
553
|
} else if (chunks.action === "beforeToolCall") {
|
|
541
554
|
const toolsMap = await this.getToolsMap();
|
|
@@ -597,12 +610,14 @@ class AIEmployee {
|
|
|
597
610
|
}
|
|
598
611
|
}
|
|
599
612
|
}
|
|
613
|
+
await stopAllReasoning();
|
|
600
614
|
if (this.protocol.statistics.sent === 0 && !signal.aborted && !allowEmpty) {
|
|
601
615
|
this.sendErrorResponse("Empty message");
|
|
602
616
|
return;
|
|
603
617
|
}
|
|
604
618
|
await this.protocol.with(aiEmployeeConversation).endStream();
|
|
605
619
|
} catch (err) {
|
|
620
|
+
await stopAllReasoning();
|
|
606
621
|
this.ctx.log.error(err);
|
|
607
622
|
if (err.name === "GraphRecursionError") {
|
|
608
623
|
this.sendSpecificError({ name: err.name, message: err.message });
|
|
@@ -1132,20 +1147,21 @@ If information is missing, clearly state it in the summary.</Important>`;
|
|
|
1132
1147
|
});
|
|
1133
1148
|
continue;
|
|
1134
1149
|
}
|
|
1150
|
+
const additionalKwargs = (0, import_tool_call_sanitizer.sanitizeAdditionalKwargsForToolCalls)((_b = msg.metadata) == null ? void 0 : _b.additional_kwargs, msg.toolCalls, {
|
|
1151
|
+
onDiscard: (info) => {
|
|
1152
|
+
var _a2;
|
|
1153
|
+
this.logger.warn("Discard malformed raw tool calls from AI message", {
|
|
1154
|
+
phase: "formatMessages",
|
|
1155
|
+
messageId: (_a2 = msg.metadata) == null ? void 0 : _a2.id,
|
|
1156
|
+
...info
|
|
1157
|
+
});
|
|
1158
|
+
}
|
|
1159
|
+
}).additionalKwargs;
|
|
1135
1160
|
formattedMessages.push({
|
|
1136
1161
|
role: "assistant",
|
|
1137
1162
|
content,
|
|
1138
1163
|
tool_calls: msg.toolCalls,
|
|
1139
|
-
additional_kwargs:
|
|
1140
|
-
onDiscard: (info) => {
|
|
1141
|
-
var _a2;
|
|
1142
|
-
this.logger.warn("Discard malformed raw tool calls from AI message", {
|
|
1143
|
-
phase: "formatMessages",
|
|
1144
|
-
messageId: (_a2 = msg.metadata) == null ? void 0 : _a2.id,
|
|
1145
|
-
...info
|
|
1146
|
-
});
|
|
1147
|
-
}
|
|
1148
|
-
}).additionalKwargs
|
|
1164
|
+
additional_kwargs: provider.prepareStoredAssistantAdditionalKwargs(additionalKwargs)
|
|
1149
1165
|
});
|
|
1150
1166
|
}
|
|
1151
1167
|
return formattedMessages;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
export type StreamConversation = {
|
|
10
|
+
sessionId: string;
|
|
11
|
+
from: string;
|
|
12
|
+
username: string;
|
|
13
|
+
};
|
|
14
|
+
export declare class ReasoningStreamState {
|
|
15
|
+
private readonly active;
|
|
16
|
+
start(conversation: StreamConversation): void;
|
|
17
|
+
stop(conversation: StreamConversation): boolean;
|
|
18
|
+
drain(): StreamConversation[];
|
|
19
|
+
}
|
|
20
|
+
export declare const isReasoningFinishChunk: (chunk: {
|
|
21
|
+
response_metadata?: Record<string, unknown>;
|
|
22
|
+
usage_metadata?: Record<string, unknown>;
|
|
23
|
+
}) => boolean;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
var __defProp = Object.defineProperty;
|
|
11
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
12
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
13
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
14
|
+
var __export = (target, all) => {
|
|
15
|
+
for (var name in all)
|
|
16
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
17
|
+
};
|
|
18
|
+
var __copyProps = (to, from, except, desc) => {
|
|
19
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
20
|
+
for (let key of __getOwnPropNames(from))
|
|
21
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
22
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
23
|
+
}
|
|
24
|
+
return to;
|
|
25
|
+
};
|
|
26
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
27
|
+
var reasoning_stream_state_exports = {};
|
|
28
|
+
__export(reasoning_stream_state_exports, {
|
|
29
|
+
ReasoningStreamState: () => ReasoningStreamState,
|
|
30
|
+
isReasoningFinishChunk: () => isReasoningFinishChunk
|
|
31
|
+
});
|
|
32
|
+
module.exports = __toCommonJS(reasoning_stream_state_exports);
|
|
33
|
+
const getConversationKey = (conversation) => `${conversation.from}:${conversation.sessionId}:${conversation.username}`;
|
|
34
|
+
class ReasoningStreamState {
|
|
35
|
+
active = /* @__PURE__ */ new Map();
|
|
36
|
+
start(conversation) {
|
|
37
|
+
this.active.set(getConversationKey(conversation), conversation);
|
|
38
|
+
}
|
|
39
|
+
stop(conversation) {
|
|
40
|
+
return this.active.delete(getConversationKey(conversation));
|
|
41
|
+
}
|
|
42
|
+
drain() {
|
|
43
|
+
const conversations = Array.from(this.active.values());
|
|
44
|
+
this.active.clear();
|
|
45
|
+
return conversations;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
const isReasoningFinishChunk = (chunk) => {
|
|
49
|
+
const metadata = chunk.response_metadata;
|
|
50
|
+
if (!metadata) {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
const finishReason = metadata.finish_reason ?? metadata.finishReason;
|
|
54
|
+
if (typeof finishReason === "string" && finishReason.length > 0) {
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
return metadata.status === "completed" || metadata.status === "incomplete" || metadata.status === "failed";
|
|
58
|
+
};
|
|
59
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
60
|
+
0 && (module.exports = {
|
|
61
|
+
ReasoningStreamState,
|
|
62
|
+
isReasoningFinishChunk
|
|
63
|
+
});
|
|
@@ -55,19 +55,27 @@ const collectReasoningMap = (messages) => {
|
|
|
55
55
|
return reasoningMap;
|
|
56
56
|
};
|
|
57
57
|
const patchRequestMessagesReasoning = (request, reasoningMap) => {
|
|
58
|
+
var _a;
|
|
58
59
|
if (!(reasoningMap == null ? void 0 : reasoningMap.size) || !Array.isArray(request == null ? void 0 : request.messages)) {
|
|
59
60
|
return;
|
|
60
61
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
62
|
+
let lastUserMessageIndex = -1;
|
|
63
|
+
for (let i = request.messages.length - 1; i >= 0; i--) {
|
|
64
|
+
if (((_a = request.messages[i]) == null ? void 0 : _a.role) === "user") {
|
|
65
|
+
lastUserMessageIndex = i;
|
|
66
|
+
break;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
for (let i = lastUserMessageIndex + 1; i < request.messages.length; i++) {
|
|
70
|
+
const message = request.messages[i];
|
|
71
|
+
if ((message == null ? void 0 : message.role) !== "assistant" || !Array.isArray(message.tool_calls) || message.tool_calls.length === 0) {
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
if (typeof message.reasoning_content === "string" && message.reasoning_content.length > 0) {
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
const reasoningContent = reasoningMap.get(String(i));
|
|
78
|
+
if (typeof reasoningContent === "string" && reasoningContent.length > 0) {
|
|
71
79
|
message.reasoning_content = reasoningContent;
|
|
72
80
|
}
|
|
73
81
|
}
|
|
@@ -6,5 +6,5 @@
|
|
|
6
6
|
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
7
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
8
|
*/
|
|
9
|
-
|
|
10
|
-
export
|
|
9
|
+
export * from './provider';
|
|
10
|
+
export * from './reasoning';
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
var __defProp = Object.defineProperty;
|
|
11
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
12
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
13
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
14
|
+
var __copyProps = (to, from, except, desc) => {
|
|
15
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
16
|
+
for (let key of __getOwnPropNames(from))
|
|
17
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
18
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
19
|
+
}
|
|
20
|
+
return to;
|
|
21
|
+
};
|
|
22
|
+
var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
|
|
23
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
24
|
+
var deepseek_exports = {};
|
|
25
|
+
module.exports = __toCommonJS(deepseek_exports);
|
|
26
|
+
__reExport(deepseek_exports, require("./provider"), module.exports);
|
|
27
|
+
__reExport(deepseek_exports, require("./reasoning"), module.exports);
|
|
28
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
29
|
+
0 && (module.exports = {
|
|
30
|
+
...require("./provider"),
|
|
31
|
+
...require("./reasoning")
|
|
32
|
+
});
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
import { ChatDeepSeek, type ChatDeepSeekInput } from '@langchain/deepseek';
|
|
10
|
+
import { AIMessage, AIMessageChunk, BaseMessage } from '@langchain/core/messages';
|
|
11
|
+
import { ChatOpenAI } from '@langchain/openai';
|
|
12
|
+
import type { CallbackManagerForLLMRun } from '@langchain/core/callbacks/manager';
|
|
13
|
+
import type OpenAI from 'openai';
|
|
14
|
+
import { Model } from '@nocobase/database';
|
|
15
|
+
import { LLMProvider, ReasoningOptions, ResolvedReasoningOptions } from '../provider';
|
|
16
|
+
import { LLMProviderMeta } from '../../manager/ai-manager';
|
|
17
|
+
import { DeepSeekReasoningConfig } from './reasoning';
|
|
18
|
+
import type { AIMessageInput } from '../../types';
|
|
19
|
+
declare class ReasoningDeepSeek extends ChatDeepSeek {
|
|
20
|
+
private readonly reasoningConfig;
|
|
21
|
+
constructor(fields: ChatDeepSeekInput, reasoningConfig: DeepSeekReasoningConfig);
|
|
22
|
+
_generate(messages: BaseMessage[], options: this['ParsedCallOptions'], runManager?: CallbackManagerForLLMRun): Promise<import("@langchain/core/dist/outputs").ChatResult>;
|
|
23
|
+
_streamResponseChunks(messages: BaseMessage[], options: this['ParsedCallOptions'], runManager?: CallbackManagerForLLMRun): AsyncGenerator<import("@langchain/core/dist/outputs").ChatGenerationChunk, void, unknown>;
|
|
24
|
+
completionWithRetry(request: OpenAI.Chat.ChatCompletionCreateParamsStreaming, requestOptions?: OpenAI.RequestOptions): Promise<AsyncIterable<OpenAI.Chat.Completions.ChatCompletionChunk>>;
|
|
25
|
+
completionWithRetry(request: OpenAI.Chat.ChatCompletionCreateParamsNonStreaming, requestOptions?: OpenAI.RequestOptions): Promise<OpenAI.Chat.Completions.ChatCompletion>;
|
|
26
|
+
}
|
|
27
|
+
export declare class DeepSeekProvider extends LLMProvider {
|
|
28
|
+
chatModel: ChatDeepSeek | ChatOpenAI;
|
|
29
|
+
get baseURL(): string;
|
|
30
|
+
createModel(): ChatOpenAI<import("@langchain/openai/dist/chat_models/index.cjs").ChatOpenAICallOptions> | ReasoningDeepSeek;
|
|
31
|
+
parseResponseChunk(chunk: unknown): string;
|
|
32
|
+
parseResponseMessage(message: Model): {
|
|
33
|
+
key: any;
|
|
34
|
+
createdAt: any;
|
|
35
|
+
content: any;
|
|
36
|
+
role: any;
|
|
37
|
+
};
|
|
38
|
+
parseReasoningContent(chunk: AIMessageChunk): {
|
|
39
|
+
status: string;
|
|
40
|
+
content: string;
|
|
41
|
+
} | null;
|
|
42
|
+
reshapeAIMessage({ aiMessage, values }: {
|
|
43
|
+
aiMessage: AIMessage;
|
|
44
|
+
values: AIMessageInput;
|
|
45
|
+
}): void;
|
|
46
|
+
prepareStoredAssistantAdditionalKwargs(additionalKwargs?: Record<string, unknown>): Record<string, unknown> | undefined;
|
|
47
|
+
protected builtInTools(): Record<string, unknown>[];
|
|
48
|
+
parseWebSearchAction(chunk: AIMessageChunk): {
|
|
49
|
+
type: string;
|
|
50
|
+
query: string;
|
|
51
|
+
}[];
|
|
52
|
+
protected resolveReasoningOptions(reasoning?: ReasoningOptions): ResolvedReasoningOptions;
|
|
53
|
+
isToolConflict(): boolean;
|
|
54
|
+
protected isApiSupportedAttachment(): boolean;
|
|
55
|
+
}
|
|
56
|
+
export declare const deepseekProviderOptions: LLMProviderMeta;
|
|
57
|
+
export {};
|
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
var __defProp = Object.defineProperty;
|
|
11
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
12
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
13
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
14
|
+
var __export = (target, all) => {
|
|
15
|
+
for (var name in all)
|
|
16
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
17
|
+
};
|
|
18
|
+
var __copyProps = (to, from, except, desc) => {
|
|
19
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
20
|
+
for (let key of __getOwnPropNames(from))
|
|
21
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
22
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
23
|
+
}
|
|
24
|
+
return to;
|
|
25
|
+
};
|
|
26
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
27
|
+
var provider_exports = {};
|
|
28
|
+
__export(provider_exports, {
|
|
29
|
+
DeepSeekProvider: () => DeepSeekProvider,
|
|
30
|
+
deepseekProviderOptions: () => deepseekProviderOptions
|
|
31
|
+
});
|
|
32
|
+
module.exports = __toCommonJS(provider_exports);
|
|
33
|
+
var import_deepseek = require("@langchain/deepseek");
|
|
34
|
+
var import_openai = require("@langchain/openai");
|
|
35
|
+
var import_provider = require("../provider");
|
|
36
|
+
var import_ai_manager = require("../../manager/ai-manager");
|
|
37
|
+
var import_reasoning = require("../common/reasoning");
|
|
38
|
+
var import_reasoning2 = require("./reasoning");
|
|
39
|
+
var import_utils = require("../../utils");
|
|
40
|
+
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
41
|
+
const collectReferences = (content, responseMetadata) => {
|
|
42
|
+
const references = [];
|
|
43
|
+
const addAnnotations = (annotations) => {
|
|
44
|
+
if (!Array.isArray(annotations)) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
for (const annotation of annotations) {
|
|
48
|
+
if (!isRecord(annotation)) {
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
const value = isRecord(annotation.value) ? annotation.value : annotation;
|
|
52
|
+
const url = typeof annotation.url === "string" ? annotation.url : value.url;
|
|
53
|
+
const title = typeof annotation.title === "string" ? annotation.title : value.title;
|
|
54
|
+
if (typeof url === "string") {
|
|
55
|
+
references.push({ title: typeof title === "string" ? title : "", url });
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
if (Array.isArray(content)) {
|
|
60
|
+
for (const block of content) {
|
|
61
|
+
if (isRecord(block) && block.type === "text") {
|
|
62
|
+
addAnnotations(block.annotations);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
if (isRecord(responseMetadata) && Array.isArray(responseMetadata.output)) {
|
|
67
|
+
for (const item of responseMetadata.output) {
|
|
68
|
+
if (!isRecord(item) || item.type !== "message" || !Array.isArray(item.content)) {
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
for (const part of item.content) {
|
|
72
|
+
if (isRecord(part) && part.type === "output_text") {
|
|
73
|
+
addAnnotations(part.annotations);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return Array.from(new Map(references.map((reference) => [reference.url, reference])).values());
|
|
79
|
+
};
|
|
80
|
+
class ReasoningDeepSeek extends import_deepseek.ChatDeepSeek {
|
|
81
|
+
constructor(fields, reasoningConfig) {
|
|
82
|
+
super(fields);
|
|
83
|
+
this.reasoningConfig = reasoningConfig;
|
|
84
|
+
}
|
|
85
|
+
async _generate(messages, options, runManager) {
|
|
86
|
+
const reasoningMap = (0, import_reasoning.collectReasoningMap)(messages);
|
|
87
|
+
return super._generate(
|
|
88
|
+
messages,
|
|
89
|
+
{
|
|
90
|
+
...options || {},
|
|
91
|
+
[import_reasoning.REASONING_MAP_KEY]: reasoningMap
|
|
92
|
+
},
|
|
93
|
+
runManager
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
async *_streamResponseChunks(messages, options, runManager) {
|
|
97
|
+
const reasoningMap = (options == null ? void 0 : options[import_reasoning.REASONING_MAP_KEY]) instanceof Map ? options[import_reasoning.REASONING_MAP_KEY] : (0, import_reasoning.collectReasoningMap)(messages);
|
|
98
|
+
yield* super._streamResponseChunks(
|
|
99
|
+
messages,
|
|
100
|
+
{
|
|
101
|
+
...options || {},
|
|
102
|
+
[import_reasoning.REASONING_MAP_KEY]: reasoningMap
|
|
103
|
+
},
|
|
104
|
+
runManager
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
async completionWithRetry(request, requestOptions) {
|
|
108
|
+
const reasoningMap = requestOptions == null ? void 0 : requestOptions[import_reasoning.REASONING_MAP_KEY];
|
|
109
|
+
const modelKwargs = requestOptions == null ? void 0 : requestOptions[import_reasoning.MODEL_KWARGS_KEY];
|
|
110
|
+
(0, import_reasoning.patchRequestMessagesReasoning)(request, reasoningMap);
|
|
111
|
+
(0, import_reasoning.patchRequestModelKwargs)(request, modelKwargs);
|
|
112
|
+
(0, import_reasoning2.normalizeDeepSeekChatRequest)(request, this.reasoningConfig);
|
|
113
|
+
if (request.stream === true) {
|
|
114
|
+
return super.completionWithRetry(request, requestOptions);
|
|
115
|
+
}
|
|
116
|
+
return super.completionWithRetry(request, requestOptions);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
class DeepSeekChatOpenAIResponses extends import_openai.ChatOpenAIResponses {
|
|
120
|
+
constructor(fields, reasoningConfig) {
|
|
121
|
+
super(fields);
|
|
122
|
+
this.reasoningConfig = reasoningConfig;
|
|
123
|
+
}
|
|
124
|
+
async completionWithRetry(request, requestOptions) {
|
|
125
|
+
(0, import_reasoning2.normalizeDeepSeekResponsesRequest)(request, this.reasoningConfig);
|
|
126
|
+
if (request.stream === true) {
|
|
127
|
+
const stream = await super.completionWithRetry(
|
|
128
|
+
request,
|
|
129
|
+
requestOptions
|
|
130
|
+
);
|
|
131
|
+
return (0, import_reasoning2.adaptDeepSeekResponsesStream)(stream);
|
|
132
|
+
}
|
|
133
|
+
return super.completionWithRetry(request, requestOptions);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
class DeepSeekProvider extends import_provider.LLMProvider {
|
|
137
|
+
get baseURL() {
|
|
138
|
+
return "https://api.deepseek.com";
|
|
139
|
+
}
|
|
140
|
+
createModel() {
|
|
141
|
+
const { apiKey } = this.serviceOptions || {};
|
|
142
|
+
const { responseFormat, structuredOutput, ...modelOptions } = this.modelOptions || {};
|
|
143
|
+
const model = typeof modelOptions.model === "string" ? modelOptions.model : "";
|
|
144
|
+
const reasoningConfig = (0, import_reasoning2.resolveDeepSeekReasoningConfig)(model, this.modelReasoningOptions);
|
|
145
|
+
const reasoningParams = (0, import_reasoning2.getDeepSeekReasoningRequestParams)(reasoningConfig);
|
|
146
|
+
if (reasoningConfig.protocol === "responses") {
|
|
147
|
+
const { name, schema, strict } = structuredOutput || {};
|
|
148
|
+
let responseFormatOptions = {
|
|
149
|
+
type: responseFormat ?? "text"
|
|
150
|
+
};
|
|
151
|
+
if (responseFormat === "json_schema" && schema) {
|
|
152
|
+
responseFormatOptions = {
|
|
153
|
+
...responseFormatOptions,
|
|
154
|
+
schema,
|
|
155
|
+
name: name ?? "default",
|
|
156
|
+
strict: strict ?? false
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
const fields = {
|
|
160
|
+
apiKey,
|
|
161
|
+
...modelOptions,
|
|
162
|
+
modelKwargs: {
|
|
163
|
+
text: {
|
|
164
|
+
format: responseFormatOptions
|
|
165
|
+
},
|
|
166
|
+
...reasoningParams
|
|
167
|
+
},
|
|
168
|
+
configuration: {
|
|
169
|
+
baseURL: this.getResolvedBaseURL()
|
|
170
|
+
},
|
|
171
|
+
verbose: false
|
|
172
|
+
};
|
|
173
|
+
return new import_openai.ChatOpenAI({
|
|
174
|
+
...fields,
|
|
175
|
+
responses: new DeepSeekChatOpenAIResponses(fields, reasoningConfig),
|
|
176
|
+
useResponsesApi: true
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
const modelKwargs = {
|
|
180
|
+
...reasoningParams
|
|
181
|
+
};
|
|
182
|
+
if (responseFormat) {
|
|
183
|
+
modelKwargs.response_format = {
|
|
184
|
+
type: responseFormat
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
return new ReasoningDeepSeek(
|
|
188
|
+
{
|
|
189
|
+
apiKey,
|
|
190
|
+
...modelOptions,
|
|
191
|
+
modelKwargs,
|
|
192
|
+
configuration: {
|
|
193
|
+
baseURL: this.getResolvedBaseURL()
|
|
194
|
+
},
|
|
195
|
+
verbose: false
|
|
196
|
+
},
|
|
197
|
+
reasoningConfig
|
|
198
|
+
);
|
|
199
|
+
}
|
|
200
|
+
parseResponseChunk(chunk) {
|
|
201
|
+
if (Array.isArray(chunk)) {
|
|
202
|
+
const text = chunk.filter(isRecord).filter((block) => block.type === "text").map((block) => block.text).filter((value) => typeof value === "string").join("");
|
|
203
|
+
return text ? (0, import_utils.stripToolCallTags)(text) : null;
|
|
204
|
+
}
|
|
205
|
+
return typeof chunk === "string" ? (0, import_utils.stripToolCallTags)(chunk) : null;
|
|
206
|
+
}
|
|
207
|
+
parseResponseMessage(message) {
|
|
208
|
+
var _a, _b;
|
|
209
|
+
const result = super.parseResponseMessage(message);
|
|
210
|
+
if (["user", "tool"].includes(result == null ? void 0 : result.role)) {
|
|
211
|
+
return result;
|
|
212
|
+
}
|
|
213
|
+
const json = ((_a = message == null ? void 0 : message.toJSON) == null ? void 0 : _a.call(message)) ?? {};
|
|
214
|
+
const metadata = isRecord(json.metadata) ? json.metadata : {};
|
|
215
|
+
const additionalKwargs = isRecord(metadata.additional_kwargs) ? metadata.additional_kwargs : {};
|
|
216
|
+
const responseMetadata = isRecord(metadata.response_metadata) ? metadata.response_metadata : {};
|
|
217
|
+
const reasoningContent = (0, import_reasoning2.extractDeepSeekReasoningText)({
|
|
218
|
+
additional_kwargs: additionalKwargs,
|
|
219
|
+
response_metadata: responseMetadata
|
|
220
|
+
});
|
|
221
|
+
if (reasoningContent) {
|
|
222
|
+
result.content = {
|
|
223
|
+
...result.content ?? {},
|
|
224
|
+
reasoning: {
|
|
225
|
+
status: "stop",
|
|
226
|
+
content: reasoningContent
|
|
227
|
+
}
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
const references = collectReferences((_b = result == null ? void 0 : result.content) == null ? void 0 : _b.content, responseMetadata);
|
|
231
|
+
if (references.length) {
|
|
232
|
+
result.content.reference = references;
|
|
233
|
+
}
|
|
234
|
+
return result;
|
|
235
|
+
}
|
|
236
|
+
parseReasoningContent(chunk) {
|
|
237
|
+
const content = (0, import_reasoning2.extractDeepSeekReasoningText)({
|
|
238
|
+
content: chunk.content,
|
|
239
|
+
additional_kwargs: chunk.additional_kwargs
|
|
240
|
+
});
|
|
241
|
+
return content ? { status: "streaming", content } : null;
|
|
242
|
+
}
|
|
243
|
+
reshapeAIMessage({ aiMessage, values }) {
|
|
244
|
+
const reasoningItem = (0, import_reasoning2.getDeepSeekResponsesReasoningItem)(aiMessage);
|
|
245
|
+
const reasoningContent = (0, import_reasoning2.extractDeepSeekReasoningText)(aiMessage);
|
|
246
|
+
if (reasoningItem || reasoningContent) {
|
|
247
|
+
const additionalKwargs = {
|
|
248
|
+
...values.metadata.additional_kwargs ?? {},
|
|
249
|
+
...reasoningItem ? { reasoning: reasoningItem } : {},
|
|
250
|
+
...reasoningContent ? { reasoning_content: reasoningContent } : {}
|
|
251
|
+
};
|
|
252
|
+
values.metadata.additional_kwargs = additionalKwargs;
|
|
253
|
+
aiMessage.additional_kwargs = {
|
|
254
|
+
...aiMessage.additional_kwargs,
|
|
255
|
+
...reasoningItem ? { reasoning: reasoningItem } : {}
|
|
256
|
+
};
|
|
257
|
+
aiMessage.lc_kwargs.additional_kwargs = aiMessage.additional_kwargs;
|
|
258
|
+
}
|
|
259
|
+
const references = collectReferences(aiMessage.content, aiMessage.response_metadata);
|
|
260
|
+
if (references.length) {
|
|
261
|
+
values.content.reference = references;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
prepareStoredAssistantAdditionalKwargs(additionalKwargs) {
|
|
265
|
+
var _a, _b;
|
|
266
|
+
if (((_b = (0, import_reasoning2.getDeepSeekModelCapabilities)(String((_a = this.modelOptions) == null ? void 0 : _a.model))) == null ? void 0 : _b.protocol) !== "responses" || !additionalKwargs) {
|
|
267
|
+
return additionalKwargs;
|
|
268
|
+
}
|
|
269
|
+
const nextAdditionalKwargs = { ...additionalKwargs };
|
|
270
|
+
delete nextAdditionalKwargs.reasoning;
|
|
271
|
+
delete nextAdditionalKwargs.reasoning_content;
|
|
272
|
+
return Object.keys(nextAdditionalKwargs).length ? nextAdditionalKwargs : void 0;
|
|
273
|
+
}
|
|
274
|
+
builtInTools() {
|
|
275
|
+
var _a, _b, _c, _d;
|
|
276
|
+
if (((_b = (0, import_reasoning2.getDeepSeekModelCapabilities)(String((_a = this.modelOptions) == null ? void 0 : _a.model))) == null ? void 0 : _b.supportsWebSearch) === true && ((_d = (_c = this.modelOptions) == null ? void 0 : _c.builtIn) == null ? void 0 : _d.webSearch) === true) {
|
|
277
|
+
return [{ type: "web_search" }];
|
|
278
|
+
}
|
|
279
|
+
return [];
|
|
280
|
+
}
|
|
281
|
+
parseWebSearchAction(chunk) {
|
|
282
|
+
var _a;
|
|
283
|
+
const toolOutputs = (_a = chunk.additional_kwargs) == null ? void 0 : _a.tool_outputs;
|
|
284
|
+
if (!Array.isArray(toolOutputs)) {
|
|
285
|
+
return [];
|
|
286
|
+
}
|
|
287
|
+
return toolOutputs.filter(isRecord).filter((tool) => tool.type === "web_search_call" && isRecord(tool.action)).map((tool) => tool.action).filter((action) => typeof action.query === "string").map((action) => ({
|
|
288
|
+
type: typeof action.type === "string" ? action.type : "web_search",
|
|
289
|
+
query: action.query
|
|
290
|
+
}));
|
|
291
|
+
}
|
|
292
|
+
resolveReasoningOptions(reasoning) {
|
|
293
|
+
var _a;
|
|
294
|
+
const model = typeof ((_a = this.modelOptions) == null ? void 0 : _a.model) === "string" ? this.modelOptions.model : "";
|
|
295
|
+
const config = (0, import_reasoning2.resolveDeepSeekReasoningConfig)(model, reasoning);
|
|
296
|
+
const params = (0, import_reasoning2.getDeepSeekReasoningRequestParams)(config);
|
|
297
|
+
return Object.keys(params).length ? { modelKwargs: params } : {};
|
|
298
|
+
}
|
|
299
|
+
isToolConflict() {
|
|
300
|
+
return false;
|
|
301
|
+
}
|
|
302
|
+
isApiSupportedAttachment() {
|
|
303
|
+
return false;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
const deepseekProviderOptions = {
|
|
307
|
+
title: "DeepSeek",
|
|
308
|
+
supportedModel: [import_ai_manager.SupportedModel.LLM],
|
|
309
|
+
models: {
|
|
310
|
+
[import_ai_manager.SupportedModel.LLM]: ["deepseek-v4-pro", "deepseek-v4-flash", "deepseek-chat", "deepseek-reasoner"]
|
|
311
|
+
},
|
|
312
|
+
supportWebSearch: true,
|
|
313
|
+
webSearchModels: ["deepseek-v4-flash", "deepseek-v4-pro"],
|
|
314
|
+
provider: DeepSeekProvider
|
|
315
|
+
};
|
|
316
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
317
|
+
0 && (module.exports = {
|
|
318
|
+
DeepSeekProvider,
|
|
319
|
+
deepseekProviderOptions
|
|
320
|
+
});
|