mirror of
https://github.com/labring/FastGPT.git
synced 2026-05-05 01:02:59 +08:00
76d6234de6
* Agent features (#6345) * Test agent (#6220) * squash: compress all commits into one * feat: plan response in ui * response ui * perf: agent config * merge * tool select ux * perf: chat ui * perf: agent editform * tmp code * feat: save chat * Complete agent parent (#6049) * add role and tools filling * add: file-upload --------- Co-authored-by: xxyyh <2289112474@qq> * perf: top agent code * top agent (#6062) Co-authored-by: xxyyh <2289112474@qq> * fix: ts * skill editor ui * ui * perf: rewrite type with zod * skill edit ui * skill agent (#6089) * cp skill chat * rebasefdf933dand add skill chat * 1. skill 的 CRUD 2. skill 的信息渲染到前端界面 * solve comment * remove chatid and chatItemId * skill match * perf: skill manage * fix: ts --------- Co-authored-by: xxyyh <2289112474@qq> Co-authored-by: archer <545436317@qq.com> * fix: ts * fix: loop import * skill tool config (#6114) Co-authored-by: xxyyh <2289112474@qq> * feat: load tool in agent * skill memory (#6126) Co-authored-by: xxyyh <2289112474@qq> * perf: agent skill editor * perf: helperbot ui * agent code * perf: context * fix: request context * agent usage * perf: agent context and pause * perf: plan response * Test agent sigle skill (#6184) * feat:top box fill * prompt fix --------- Co-authored-by: xxyyh <2289112474@qq> * perf: agent chat ui * Test agent new (#6219) * have-replan * agent --------- Co-authored-by: xxyyh <2289112474@qq> * fix: ts --------- Co-authored-by: YeYuheng <57035043+YYH211@users.noreply.github.com> Co-authored-by: xxyyh <2289112474@qq> * feat: consolidate agent and MCP improvements This commit consolidates 17 commits including: - MCP tools enhancements and fixes - Agent system improvements and optimizations - Auth limit and prompt updates - Tool response compression and error tracking - Simple app adaptation - Code quality improvements (TypeScript, ESLint, Zod) - Version type migration to schema - Remove deprecated useRequest2 - Add LLM error tracking - Toolset ID validation fixes --------- Co-authored-by: YeYuheng <57035043+YYH211@users.noreply.github.com> Co-authored-by: xxyyh <2289112474@qq> * fix: transform avatar copy;perf: filter invalid tool * update llm response storage time * fix: openapi schema * update skill desc * feat: cache hit data * i18n * lock * chat logs support error filter & user search (#6373) * chat log support searching by user name * support error filter * fix * fix overflow * optimize * fix init script * fix * perf: get log users * updat ecomment * fix: ts * fix: test --------- Co-authored-by: archer <545436317@qq.com> * Fix: agent (#6376) * Agent features (#6345) * Test agent (#6220) * squash: compress all commits into one * feat: plan response in ui * response ui * perf: agent config * merge * tool select ux * perf: chat ui * perf: agent editform * tmp code * feat: save chat * Complete agent parent (#6049) * add role and tools filling * add: file-upload --------- Co-authored-by: xxyyh <2289112474@qq> * perf: top agent code * top agent (#6062) Co-authored-by: xxyyh <2289112474@qq> * fix: ts * skill editor ui * ui * perf: rewrite type with zod * skill edit ui * skill agent (#6089) * cp skill chat * rebasefdf933dand add skill chat * 1. skill 的 CRUD 2. skill 的信息渲染到前端界面 * solve comment * remove chatid and chatItemId * skill match * perf: skill manage * fix: ts --------- Co-authored-by: xxyyh <2289112474@qq> Co-authored-by: archer <545436317@qq.com> * fix: ts * fix: loop import * skill tool config (#6114) Co-authored-by: xxyyh <2289112474@qq> * feat: load tool in agent * skill memory (#6126) Co-authored-by: xxyyh <2289112474@qq> * perf: agent skill editor * perf: helperbot ui * agent code * perf: context * fix: request context * agent usage * perf: agent context and pause * perf: plan response * Test agent sigle skill (#6184) * feat:top box fill * prompt fix --------- Co-authored-by: xxyyh <2289112474@qq> * perf: agent chat ui * Test agent new (#6219) * have-replan * agent --------- Co-authored-by: xxyyh <2289112474@qq> * fix: ts --------- Co-authored-by: YeYuheng <57035043+YYH211@users.noreply.github.com> Co-authored-by: xxyyh <2289112474@qq> * feat: consolidate agent and MCP improvements This commit consolidates 17 commits including: - MCP tools enhancements and fixes - Agent system improvements and optimizations - Auth limit and prompt updates - Tool response compression and error tracking - Simple app adaptation - Code quality improvements (TypeScript, ESLint, Zod) - Version type migration to schema - Remove deprecated useRequest2 - Add LLM error tracking - Toolset ID validation fixes --------- Co-authored-by: YeYuheng <57035043+YYH211@users.noreply.github.com> Co-authored-by: xxyyh <2289112474@qq> * 1. 把辅助生成前端上的 system prompt 加入到上下文中 2. mcp工具的前端渲染(图标) 3. 文件读取工具和文件上传进行关联 4. 添加了辅助生成返回格式出错的重试方案 5. ask 不出现在 plan 步骤中 6. 添加了辅助生成的头像和交互 UI * fix:read_file * helperbot ui * ts error * helper ui * delete Unused import * perf: helper bot * lock --------- Co-authored-by: Archer <545436317@qq.com> Co-authored-by: xxyyh <2289112474@qq> * fix date variable required & model auth (#6386) * fix date variable required & model auth * doc * feat: add chat id to finish callback * fix: iphone safari shareId (#6387) * fix: iphone safari shareId * fix: mcp file list can't setting * fix: reason output field * fix: skip JSON validation for HTTP tool body with variable (#6392) * fix: skip JSON validation for HTTP tool body with variable * doc * workflow fitview * perf: selecting memory * perf: cp api * ui * perf: toolcall auto adapt * fix: catch workflow error * fix: ts * perf: pagination type * remove * ignore * update doc * fix: simple app tool select * add default avatar to logs user * perf: loading user * select dataset ui * rename version * feat: add global/common test * perf: packages/global/common test * feat: package/global/ai,app test * add global/chat test * global/core test * global/core test * feat: packages/global all test * perf: test * add server api test * perf: init shell * perf: init4150 shell * remove invalid code * update doc * remove log * fix: chat effect * fix: plan fake tool (#6398) * 1. 提示词防注入功能 2. 无工具不进入 plan,防止虚拟工具生成 * Agent-dataset * dataset * dataset presetInfo * prefix * perf: prompt --------- Co-authored-by: xxyyh <2289112474@qq> Co-authored-by: archer <545436317@qq.com> * fix: review * adapt kimi2.5 think toolcall * feat: invoke fastgpt user info (#6403) feat: invoke fastgpt user info * fix: invoke fastgpt user info return orgs (#6404) * skill and version * retry helperbot (#6405) Co-authored-by: xxyyh <2289112474@qq> * update template * remove log * doc * update doc * doc * perf: internal ip check * adapt get paginationRecords * tool call adapt * fix: test * doc * fix: agent initial version * adapt completions v1 * feat: instrumentation check * rename skill * add workflow demo mode tracks (#6407) * chore: 统一 skills 目录命名为小写 将 .claude/Skills/ 重命名为 .claude/skills/ 以保持命名一致性。 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * add workflow demo mode tracks * code * optimize * fix: improve workflowDemoTrack based on PR review - Add comment to empty catch block for maintainability - Add @param docs to onDemoChange clarifying nodeCount usage - Replace silent .catch with console.debug for dev debugging - Handle appId changes by reporting old data before re-init Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: archer <545436317@qq.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> * remove repeat skill * fix(workflow): filter out orphan edges to prevent runtime errors (#6399) * fix(workflow): filter out orphan edges to prevent runtime errors Runtime edges that reference non-existent nodes (orphan edges) can cause unexpected behavior or crashes during workflow dispatch. This change adds a pre-check to filter out such edges before execution begins, ensuring system stability even with inconsistent graph data. * fix(workflow): enhance orphan edge filtering with logging and tests - Refactor: Extract logic to 'filterOrphanEdges' in utils.ts for better reusability - Feat: Add performance monitoring (warn if >100ms) and comprehensive logging - Feat: Support detailed edge inspection in debug mode - Docs: Add JSDoc explaining causes of orphan edges (migration, manual edits) - Test: Add unit tests covering edge cases and performance (1000 edges) Addresses PR review feedback regarding logging, variable naming, and testing." * move code * move code * add more unit test --------- Co-authored-by: archer <545436317@qq.com> * test * perf: test * add server/common/string test * fix: resolve $ref references in MCP tool input schemas (#6395) (#6409) * fix: resolve $ref references in MCP tool input schemas (#6395) * add test code --------- Co-authored-by: archer <545436317@qq.com> * chore(docs): add fastgpt, fastgpt-plugin version choice guide (#6411) * chore(doc): add fastgpt version description * doc * doc --------- Co-authored-by: archer <545436317@qq.com> * fix:dataset cite and description info (#6410) * 1. 添加知识库引用(plan 步骤和直接知识库调用) 2. 提示词框中的@知识库工具 3. plan 中 step 的 description dataset_search 改为中文 * fix: i18n * prompt * prompt --------- Co-authored-by: xxyyh <2289112474@qq> * fix: tool call * perf: workflow props * fix: merge ECharts toolbox options instead of overwriting (#6269) (#6412) * feat: integrate logtape and otel (#6400) * fix: deps * feat(logger): integrate logtape and otel * wip(log): add basic infras logs * wip(log): add request id and inject it into context * wip(log): add basic tx logs * wip(log): migrate * wip(log): category * wip(log): more sub category * fix: type * fix: sessionRun * fix: export getLogger from client.ts * chore: improve logs * docs: update signoz and changelog * change type * fix: ts * remove skill.md * fix: lockfile specifier * fix: test --------- Co-authored-by: archer <545436317@qq.com> * init log * doc * remove invalid log * fix: review * template * replace new log * fix: ts * remove log * chore: migrate all addLog to logtape * move skill * chore: migrate all addLog to logtape (#6417) * update skill * remove log * fix: tool check --------- Co-authored-by: YeYuheng <57035043+YYH211@users.noreply.github.com> Co-authored-by: xxyyh <2289112474@qq> Co-authored-by: heheer <heheer@sealos.io> Co-authored-by: Finley Ge <32237950+FinleyGe@users.noreply.github.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: xuyafei1996 <54217479+xuyafei1996@users.noreply.github.com> Co-authored-by: ToukoYui <2331631097@qq.com> Co-authored-by: roy <whoeverimf5@gmail.com>
287 lines
8.7 KiB
TypeScript
287 lines
8.7 KiB
TypeScript
import { replaceVariable } from '@fastgpt/global/common/string/tools';
|
||
import { type ChatItemType } from '@fastgpt/global/core/chat/type';
|
||
import { chats2GPTMessages } from '@fastgpt/global/core/chat/adapt';
|
||
import { getLLMModel } from '../model';
|
||
import { filterGPTMessageByMaxContext } from '../llm/utils';
|
||
import json5 from 'json5';
|
||
import { createLLMResponse } from '../llm/request';
|
||
import { useTextCosine } from '../hooks/useTextCosine';
|
||
import { getLogger, LogCategories } from '../../../common/logger';
|
||
|
||
const logger = getLogger(LogCategories.MODULE.AI.FUNCTIONS);
|
||
|
||
/*
|
||
Query Extension - Semantic Search Enhancement
|
||
This module can eliminate referential ambiguity and expand queries based on context to improve retrieval.
|
||
Submodular Optimization Mode: Generate multiple candidate queries, then use submodular algorithm to select the optimal query combination
|
||
*/
|
||
const title = global.feConfigs?.systemTitle || 'Nginx';
|
||
const defaultPrompt = `## 你的任务
|
||
你作为一个向量检索助手,你的任务是结合历史记录,为"原问题"生成{{count}}个不同版本的"检索词"。这些检索词应该从不同角度探索主题,以提高向量检索的语义丰富度和精度。
|
||
|
||
## 要求
|
||
1. 每个检索词必须与原问题相关
|
||
2. 检索词应该探索不同方面(例如:原因、影响、解决方案、示例、对比等)
|
||
3. 避免检索词之间的冗余
|
||
4. 保持检索词简洁且可搜索
|
||
5. 生成的问题要求指向对象清晰明确,并与"原问题语言相同"
|
||
|
||
## 参考示例
|
||
|
||
历史记录:
|
||
"""
|
||
null
|
||
"""
|
||
原问题: 介绍下剧情。
|
||
检索词: ["介绍下故事的背景。","故事的主题是什么?","介绍下故事的主要人物。","故事的转折点在哪里?","故事的结局如何?"]
|
||
----------------
|
||
历史记录:
|
||
"""
|
||
user: 对话背景。
|
||
assistant: 当前对话是关于 Nginx 的介绍和使用等。
|
||
"""
|
||
原问题: 怎么下载
|
||
检索词: ["Nginx 如何下载?","下载 Nginx 需要什么条件?","有哪些渠道可以下载 Nginx?","Nginx 各版本的下载方式有什么区别?","如何选择合适的 Nginx 版本下载?"]
|
||
----------------
|
||
历史记录:
|
||
"""
|
||
user: 对话背景。
|
||
assistant: 当前对话是关于 Nginx 的介绍和使用等。
|
||
user: 报错 "no connection"
|
||
assistant: 报错"no connection"可能是因为……
|
||
"""
|
||
原问题: 怎么解决
|
||
检索词: ["Nginx报错'no connection'如何解决?","造成'no connection'报错的原因。","Nginx提示'no connection',要怎么办?","'no connection'错误的常见解决步骤。","如何预防 Nginx 'no connection' 错误?"]
|
||
----------------
|
||
历史记录:
|
||
"""
|
||
user: How long is the maternity leave?
|
||
assistant: The number of days of maternity leave depends on the city in which the employee is located. Please provide your city so that I can answer your questions.
|
||
"""
|
||
原问题: ShenYang
|
||
检索词: ["How many days is maternity leave in Shenyang?","Shenyang's maternity leave policy.","The standard of maternity leave in Shenyang.","What benefits are included in Shenyang's maternity leave?","How to apply for maternity leave in Shenyang?"]
|
||
----------------
|
||
历史记录:
|
||
"""
|
||
user: 作者是谁?
|
||
assistant: ${title} 的作者是 labring。
|
||
"""
|
||
原问题: Tell me about him
|
||
检索词: ["Introduce labring, the author of ${title}." ,"Background information on author labring.","Why does labring do ${title}?","What other projects has labring worked on?","How did labring start ${title}?"]
|
||
----------------
|
||
历史记录:
|
||
"""
|
||
user: 对话背景。
|
||
assistant: 关于 ${title} 的介绍和使用等问题。
|
||
"""
|
||
原问题: 你好。
|
||
检索词: ["你好"]
|
||
----------------
|
||
历史记录:
|
||
"""
|
||
user: ${title} 如何收费?
|
||
assistant: ${title} 收费可以参考……
|
||
"""
|
||
原问题: 你知道 laf 么?
|
||
检索词: ["laf 的官网地址是多少?","laf 的使用教程。","laf 有什么特点和优势。","laf 的主要功能是什么?","laf 与其他类似产品的对比。"]
|
||
----------------
|
||
历史记录:
|
||
"""
|
||
user: ${title} 的优势
|
||
assistant: 1. 开源
|
||
2. 简便
|
||
3. 扩展性强
|
||
"""
|
||
原问题: 介绍下第2点。
|
||
检索词: ["介绍下 ${title} 简便的优势", "从哪些方面,可以体现出 ${title} 的简便"]。
|
||
----------------
|
||
历史记录:
|
||
"""
|
||
user: 什么是 ${title}?
|
||
assistant: ${title} 是一个 RAG 平台。
|
||
user: 什么是 Laf?
|
||
assistant: Laf 是一个云函数开发平台。
|
||
"""
|
||
原问题: 它们有什么关系?
|
||
检索词: ["${title}和Laf有什么关系?","介绍下${title}","介绍下Laf"]
|
||
|
||
## 输出要求
|
||
|
||
1. 输出格式为 JSON 数组,数组中每个元素为字符串。无需对输出进行任何解释。
|
||
2. 输出语言与原问题相同。原问题为中文则输出中文;原问题为英文则输出英文。
|
||
3. 确保生成恰好 {{count}} 个检索词。
|
||
|
||
## 开始任务
|
||
|
||
历史记录:
|
||
"""
|
||
{{histories}}
|
||
"""
|
||
原问题: {{query}}
|
||
检索词: `;
|
||
|
||
export const queryExtension = async ({
|
||
chatBg,
|
||
query,
|
||
histories = [],
|
||
llmModel,
|
||
embeddingModel,
|
||
generateCount = 10 // 生成优化问题集的数量,默认为10个
|
||
}: {
|
||
chatBg?: string;
|
||
query: string;
|
||
histories: ChatItemType[];
|
||
llmModel: string;
|
||
embeddingModel: string;
|
||
generateCount?: number;
|
||
}): Promise<{
|
||
rawQuery: string;
|
||
extensionQueries: string[];
|
||
llmModel: string;
|
||
embeddingModel: string;
|
||
inputTokens: number;
|
||
outputTokens: number;
|
||
embeddingTokens: number;
|
||
}> => {
|
||
const systemFewShot = chatBg
|
||
? `user: 对话背景。
|
||
assistant: ${chatBg}
|
||
`
|
||
: '';
|
||
|
||
// 1. Request model
|
||
const modelData = getLLMModel(llmModel);
|
||
const filterHistories = await filterGPTMessageByMaxContext({
|
||
messages: chats2GPTMessages({ messages: histories, reserveId: false }),
|
||
maxContext: modelData.maxContext - 1000
|
||
});
|
||
|
||
const historyFewShot = filterHistories
|
||
.map((item) => {
|
||
const role = item.role;
|
||
const content = item.content;
|
||
if ((role === 'user' || role === 'assistant') && content) {
|
||
if (typeof content === 'string') {
|
||
return `${role}: ${content}`;
|
||
} else {
|
||
return `${role}: ${content.map((item) => (item.type === 'text' ? item.text : '')).join('\n')}`;
|
||
}
|
||
}
|
||
})
|
||
.filter(Boolean)
|
||
.join('\n');
|
||
const concatFewShot = `${systemFewShot}${historyFewShot}`.trim();
|
||
|
||
const messages = [
|
||
{
|
||
role: 'user',
|
||
content: replaceVariable(defaultPrompt, {
|
||
query: `${query}`,
|
||
histories: concatFewShot || 'null',
|
||
count: generateCount.toString()
|
||
})
|
||
}
|
||
] as any;
|
||
|
||
const {
|
||
answerText: answer,
|
||
usage: { inputTokens, outputTokens }
|
||
} = await createLLMResponse({
|
||
body: {
|
||
stream: true,
|
||
model: modelData.model,
|
||
temperature: 0.1,
|
||
messages
|
||
}
|
||
});
|
||
|
||
if (!answer) {
|
||
return {
|
||
rawQuery: query,
|
||
extensionQueries: [],
|
||
llmModel: modelData.model,
|
||
embeddingModel,
|
||
inputTokens: inputTokens,
|
||
outputTokens: outputTokens,
|
||
embeddingTokens: 0
|
||
};
|
||
}
|
||
|
||
// 2. Parse answer
|
||
const start = answer.indexOf('[');
|
||
const end = answer.lastIndexOf(']');
|
||
if (start === -1 || end === -1) {
|
||
logger.warn('Query extension returned invalid JSON', {
|
||
answer
|
||
});
|
||
return {
|
||
rawQuery: query,
|
||
extensionQueries: [],
|
||
llmModel: modelData.model,
|
||
embeddingModel,
|
||
inputTokens: inputTokens,
|
||
outputTokens: outputTokens,
|
||
embeddingTokens: 0
|
||
};
|
||
}
|
||
|
||
// Intercept the content of [] and retain []
|
||
const jsonStr = answer
|
||
.substring(start, end + 1)
|
||
.replace(/(\\n|\\)/g, '')
|
||
.replace(/ /g, '');
|
||
|
||
try {
|
||
let queries = json5.parse(jsonStr) as string[];
|
||
|
||
if (!Array.isArray(queries) || queries.length === 0) {
|
||
return {
|
||
rawQuery: query,
|
||
extensionQueries: [],
|
||
llmModel: modelData.model,
|
||
embeddingModel,
|
||
inputTokens,
|
||
outputTokens,
|
||
embeddingTokens: 0
|
||
};
|
||
}
|
||
|
||
// 3. 通过计算获取到最优的检索词
|
||
const { lazyGreedyQuerySelection, embeddingModel: useEmbeddingModel } = useTextCosine({
|
||
embeddingModel
|
||
});
|
||
queries = queries.map((item) => String(item));
|
||
|
||
const { selectedData: selectedQueries, embeddingTokens } = await lazyGreedyQuerySelection({
|
||
originalText: query,
|
||
candidates: queries,
|
||
k: Math.min(3, queries.length), // 至多 3 个
|
||
alpha: 0.3
|
||
});
|
||
|
||
return {
|
||
rawQuery: query,
|
||
extensionQueries: selectedQueries,
|
||
llmModel: modelData.model,
|
||
embeddingModel: useEmbeddingModel,
|
||
inputTokens,
|
||
outputTokens,
|
||
embeddingTokens
|
||
};
|
||
} catch (error) {
|
||
logger.warn('Query extension failed', {
|
||
error,
|
||
answer
|
||
});
|
||
return {
|
||
rawQuery: query,
|
||
extensionQueries: [],
|
||
llmModel: modelData.model,
|
||
embeddingModel,
|
||
inputTokens,
|
||
outputTokens,
|
||
embeddingTokens: 0
|
||
};
|
||
}
|
||
};
|