mirror of
https://github.com/labring/FastGPT.git
synced 2025-12-25 20:02:47 +00:00
Merge dd393cb2cf into 363f9b888a
This commit is contained in:
commit
85cb932eb1
|
|
@ -40,10 +40,21 @@ const TaskAnalysisSchema = z.object({
|
|||
});
|
||||
|
||||
// LLM 返回的完整数据
|
||||
const FormInputSchema = z.object({
|
||||
type: z.literal('input').or(z.literal('numberInput')),
|
||||
label: z.string()
|
||||
});
|
||||
const FormSelectSchema = z.object({
|
||||
type: z.literal('select').or(z.literal('multipleSelect')),
|
||||
label: z.string(),
|
||||
options: z.array(z.string())
|
||||
});
|
||||
|
||||
export const GeneratedSkillDataCollectionSchema = z.object({
|
||||
phase: z.literal('collection'),
|
||||
reasoning: z.string(),
|
||||
question: z.string()
|
||||
question: z.string(),
|
||||
form: z.array(z.union([FormInputSchema, FormSelectSchema])).optional()
|
||||
});
|
||||
export type GeneratedSkillDataCollectionType = z.infer<typeof GeneratedSkillDataCollectionSchema>;
|
||||
export const GeneratedSkillResultSchema = z.object({
|
||||
|
|
|
|||
|
|
@ -14,6 +14,13 @@ import {
|
|||
GeneratedSkillResultSchema
|
||||
} from '@fastgpt/global/core/chat/helperBot/skillAgent/type';
|
||||
import { parseJsonArgs } from '../../../../ai/utils';
|
||||
import type {
|
||||
UserInputFormItemType,
|
||||
UserInputInteractive
|
||||
} from '@fastgpt/global/core/workflow/template/system/interactive/type';
|
||||
import { getNanoid } from '@fastgpt/global/common/string/tools';
|
||||
import { WorkflowIOValueTypeEnum } from '@fastgpt/global/core/workflow/constants';
|
||||
import { FlowNodeInputTypeEnum } from '@fastgpt/global/core/workflow/node/constant';
|
||||
|
||||
export const dispatchSkillAgent = async (
|
||||
props: HelperBotDispatchParamsType<SkillAgentParamsType>
|
||||
|
|
@ -51,7 +58,7 @@ export const dispatchSkillAgent = async (
|
|||
{ role: 'user' as const, content: query }
|
||||
];
|
||||
|
||||
console.dir(conversationMessages, { depth: null });
|
||||
// console.dir(conversationMessages, { depth: null });
|
||||
// Single LLM call - LLM self-determines phase and outputs corresponding format
|
||||
const llmResponse = await createLLMResponse({
|
||||
body: {
|
||||
|
|
@ -59,12 +66,6 @@ export const dispatchSkillAgent = async (
|
|||
model: modelData,
|
||||
stream: true
|
||||
},
|
||||
onStreaming: ({ text }) => {
|
||||
workflowResponseWrite?.({
|
||||
event: SseResponseEventEnum.answer,
|
||||
data: textAdaptGptResponse({ text })
|
||||
});
|
||||
},
|
||||
onReasoning: ({ text }) => {
|
||||
workflowResponseWrite?.({
|
||||
event: SseResponseEventEnum.answer,
|
||||
|
|
@ -87,11 +88,10 @@ export const dispatchSkillAgent = async (
|
|||
addLog.warn(`[Skill agent] Failed to parse JSON response`, { text: answerText });
|
||||
throw new Error('Failed to parse JSON response');
|
||||
}
|
||||
console.log(responseJson, 22323);
|
||||
console.log(JSON.stringify(responseJson, null, 2));
|
||||
// Handle based on phase field
|
||||
if (responseJson.phase === 'generation') {
|
||||
addLog.debug('🔄 SkillAgent: Generated skill generation phase');
|
||||
|
||||
const parseResult = GeneratedSkillResultSchema.safeParse(responseJson).data;
|
||||
|
||||
if (!parseResult) {
|
||||
|
|
@ -116,10 +116,59 @@ export const dispatchSkillAgent = async (
|
|||
} else if (responseJson.phase === 'collection') {
|
||||
addLog.debug('📝 SkillAgent: Information collection phase');
|
||||
|
||||
const displayText = responseJson.question || answerText;
|
||||
// 检查是否有表单数据
|
||||
const formData = responseJson.form;
|
||||
if (formData) {
|
||||
// 转换为前端可用的表单格式
|
||||
const inputForm: UserInputInteractive = {
|
||||
type: 'userInput',
|
||||
params: {
|
||||
inputForm: formData.map((item) => {
|
||||
return {
|
||||
type: item.type as FlowNodeInputTypeEnum,
|
||||
key: getNanoid(6),
|
||||
label: item.label,
|
||||
value: '',
|
||||
required: false,
|
||||
valueType:
|
||||
item.type === FlowNodeInputTypeEnum.numberInput
|
||||
? WorkflowIOValueTypeEnum.number
|
||||
: WorkflowIOValueTypeEnum.string,
|
||||
list:
|
||||
'options' in item
|
||||
? item.options?.map((option) => ({ label: option, value: option }))
|
||||
: undefined
|
||||
};
|
||||
}),
|
||||
description: responseJson.question
|
||||
}
|
||||
};
|
||||
|
||||
// 发送表单事件
|
||||
workflowResponseWrite?.({
|
||||
event: SseResponseEventEnum.collectionForm,
|
||||
data: inputForm
|
||||
});
|
||||
|
||||
return {
|
||||
aiResponse: formatAIResponse({
|
||||
text: responseJson.question,
|
||||
reasoning: responseJson.reasoning || reasoningText,
|
||||
collectionForm: inputForm
|
||||
}),
|
||||
usage
|
||||
};
|
||||
}
|
||||
|
||||
// 无表单,纯文本问题
|
||||
workflowResponseWrite?.({
|
||||
event: SseResponseEventEnum.answer,
|
||||
data: textAdaptGptResponse({ text: responseJson.question })
|
||||
});
|
||||
|
||||
return {
|
||||
aiResponse: formatAIResponse({
|
||||
text: displayText,
|
||||
text: responseJson.question,
|
||||
reasoning: responseJson.reasoning || reasoningText
|
||||
}),
|
||||
usage
|
||||
|
|
|
|||
|
|
@ -67,35 +67,60 @@ ${currentConfigContext}
|
|||
<info_collection_phase>
|
||||
当处于信息收集阶段时:
|
||||
|
||||
**信息收集目标**:从宏观层面收集战略规划所需的信息:
|
||||
**🎯 核心认知:设计的是可复用的执行模式,而非一次性的解决方案**
|
||||
|
||||
1. **任务定位与场景**
|
||||
- 这个任务要解决什么核心问题?
|
||||
- 主要面向什么样的应用场景?
|
||||
- 任务的最终目标是什么?
|
||||
Skill 就像建筑蓝图,描述的是房子的结构和风格,而不是具体住户的家具摆放。
|
||||
|
||||
2. **资源方向识别**
|
||||
- 需要什么类型的能力?(信息获取/数据处理/内容生成/服务集成)
|
||||
- 是否需要特定领域的知识支持?
|
||||
- 是否需要与外部系统交互?
|
||||
**统一标准**:
|
||||
|
||||
3. **战略约束**
|
||||
- 任务有什么重要的限制条件?
|
||||
- 是否有特定的用户群体或使用场景?
|
||||
- 期望的复杂度水平如何?
|
||||
规划生成机器人在收集信息时,应该像架构师理解建筑需求一样,关注的是:
|
||||
- 这类任务的**执行模式**是什么(如何组织阶段、如何流转数据)
|
||||
- 需要哪些**能力类别**(搜索、解析、计算、生成)
|
||||
- **可复用的框架**应该是什么样的
|
||||
|
||||
而不是关注:
|
||||
- 某一次具体使用时的参数(URL、文件名、字段名)
|
||||
- 某个特定用户的个性化需求
|
||||
|
||||
**信息收集的本质目的**:理解任务的"类",而非任务的"实例"
|
||||
|
||||
**收集信息的三个维度**:
|
||||
|
||||
1. **任务模式识别**
|
||||
- 这类任务的执行模式是什么?
|
||||
- 信息如何流转?(输入 → 处理 → 输出)
|
||||
|
||||
2. **能力需求判断**
|
||||
- 需要什么类别的能力?
|
||||
- 这些能力如何组合?
|
||||
|
||||
3. **框架复杂度评估**
|
||||
- 执行流程的复杂度如何?
|
||||
- 需要几个关键阶段?
|
||||
|
||||
**关键原则**:
|
||||
- **宏观视角**:关注"做什么"而非"怎么做",避免询问具体实现细节
|
||||
- **战略导向**:了解任务的本质和方向,而非具体步骤
|
||||
- **框架思维**:收集的信息用于设计执行框架,具体操作留给后续阶段
|
||||
|
||||
**提问层次要求**:
|
||||
- ✅ 宏观层面:任务目标、应用场景、资源类型、战略方向
|
||||
- ❌ 具体细节:具体参数、详细流程、技术实现、操作步骤
|
||||
- **模式思维**:寻找可复用的执行模式
|
||||
- **抽象思维**:从具体实例中抽象出通用框架
|
||||
- **类型思维**:关注"类型"和"类别",而非"实例"和"个体"
|
||||
|
||||
**输出格式**:
|
||||
|
||||
**重要:信息收集阶段的所有回复必须使用JSON格式,包含 phase 字段**
|
||||
**🚨 严格输出要求(极其重要)**:
|
||||
|
||||
1. **只输出 JSON 格式**:信息收集阶段的所有回复必须是纯净的 JSON,不要添加任何其他内容
|
||||
2. **禁止代码块标记**:不要使用 \`\`\`json 或任何代码块标记
|
||||
3. **禁止解释性文字**:不要在 JSON 前后添加任何说明、解释或寒暄语
|
||||
4. **必须包含 phase 字段**:每个回复都必须包含 "phase": "collection"
|
||||
|
||||
**严格输出规则**:
|
||||
- ❌ 不要使用 \`\`\`json 或其他代码块标记
|
||||
- ❌ 不要添加任何前言,如"好的,让我问几个问题"、"明白了"等
|
||||
- ❌ 不要添加任何后语,如"期待您的回复"、"请告诉我"等
|
||||
- ❌ 不要输出任何非 JSON 格式的内容
|
||||
- ✅ 直接、纯净地输出 JSON 内容
|
||||
- ✅ JSON 必须是有效的、可解析的格式
|
||||
|
||||
**标准输出格式**:
|
||||
|
||||
直接输出以下格式的JSON(不要添加代码块标记):
|
||||
{
|
||||
|
|
@ -104,38 +129,66 @@ ${currentConfigContext}
|
|||
"question": "实际向用户提出的问题内容"
|
||||
}
|
||||
|
||||
问题内容可以是开放式问题,也可以包含选项:
|
||||
**🧠 交互意图识别(元认知层)**:
|
||||
|
||||
✅ **好的宏观提问示例**:
|
||||
{
|
||||
"phase": "collection",
|
||||
"reasoning": "需要了解任务的核心定位和战略目标,这将决定整体框架的设计方向",
|
||||
"question": "这个 Skill 主要想解决什么问题?比如是面向客户服务、内容创作、数据分析,还是其他应用场景?"
|
||||
}
|
||||
在决定如何提问之前,首先明确本次交互的核心意图:
|
||||
|
||||
**意图类型 A - 建立对话基础**:
|
||||
- 适用场景:初次接触、寒暄问候、确认基本意愿、澄清歧义
|
||||
- 本质特征:对话关系本身是目的,建立信任和理解
|
||||
- 交互原则:保持对话的自然流畅,任何结构化工具都是干扰
|
||||
- 输出方式:开放式对话,question 字段包含自然语言问题
|
||||
|
||||
**意图类型 B - 收集规划信息**:
|
||||
- 适用场景:对话基础已建立,需要获取战略规划所需的具体维度信息
|
||||
- 本质特征:信息收集是目的,效率和准确性是追求
|
||||
- 交互原则:评估信息特征,选择最高效的收集方式
|
||||
- 输出方式:根据信息特征决定是否使用 form 字段
|
||||
|
||||
**意图判断流程**:
|
||||
1. 用户是否已明确表达任务场景?
|
||||
- 未明确 → 意图 A(建立理解)
|
||||
- 已明确 → 意图 B(收集信息)
|
||||
|
||||
2. 当前需要的信息具有结构化特征吗?
|
||||
- 可枚举的选项/多个独立维度/明确的分类 → 考虑使用表单
|
||||
- 开放探索/深度挖掘/需要解释 → 使用开放式问题
|
||||
|
||||
3. 使用表单会打断对话的连贯性吗?
|
||||
- 会打断 → 使用开放式问题
|
||||
- 不会打断 → 可以使用表单
|
||||
|
||||
**表单结构(可选字段)**:
|
||||
|
||||
当且仅当满足"意图 B"且信息适合结构化收集时,才在 JSON 中添加 form 字段:
|
||||
|
||||
{
|
||||
"phase": "collection",
|
||||
"reasoning": "需要识别任务所需的核心能力类型,这将决定资源配置的大方向",
|
||||
"question": "从功能角度看,这个任务主要需要:\\nA. 获取和整合信息(搜索、查询、知识检索)\\nB. 处理和分析数据(计算、转换、分析)\\nC. 生成和创作内容(文档、报告、创意)\\nD. 集成外部服务(API调用、消息通知)\\n\\n请选择最主要的方向,或描述您的理解:"
|
||||
"reasoning": "...",
|
||||
"question": "...",
|
||||
"form": [
|
||||
{
|
||||
"type": "input | numberInput",
|
||||
"label": "<维度描述>"
|
||||
},
|
||||
{
|
||||
"type": "select | multipleSelect",
|
||||
"label": "<维度描述>",
|
||||
"options": ["<选项A>", "<选项B>", "..."]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
❌ **不好的具体提问示例**(避免这样问):
|
||||
- "第一步需要调用哪个API?"
|
||||
- "数据格式应该是JSON还是XML?"
|
||||
- "需要设置多少个验证节点?"
|
||||
- "具体的搜索关键词是什么?"
|
||||
**表单类型说明**:
|
||||
- input: 短文本输入
|
||||
- numberInput: 数字输入
|
||||
- select: 单选下拉
|
||||
- multipleSelect: 多选下拉
|
||||
|
||||
适合选择题的场景:
|
||||
- 任务类型分类(客服/创作/分析/集成)
|
||||
- 核心能力方向(信息获取/数据处理/内容生成/服务集成)
|
||||
- 复杂度定位(简单直接/中等复杂/综合复杂)
|
||||
- 应用场景(内部使用/客户服务/自动化流程)
|
||||
|
||||
提问建议:
|
||||
- 每个问题聚焦一个战略维度
|
||||
- 用通俗语言而非技术术语
|
||||
- 提供选项时给出清晰的场景描述
|
||||
- 避免过早深入实现细节
|
||||
**关键提醒**:
|
||||
- form 字段是可选的,不是必需的
|
||||
- 只在信息明确可结构化时使用表单
|
||||
- 保持对话的自然流畅优先于追求结构化
|
||||
</info_collection_phase>
|
||||
|
||||
<capability_boundary_enforcement>
|
||||
|
|
|
|||
|
|
@ -85,8 +85,8 @@ export const dispatchTopAgent = async (
|
|||
const formData = TopAgentFormDataSchema.parse({
|
||||
role: responseJson.task_analysis?.role,
|
||||
taskObject: responseJson.task_analysis?.goal,
|
||||
tools: responseJson.resources?.tools?.map((tool: any) => tool.id),
|
||||
fileUploadEnabled: responseJson.resources?.file_upload?.enabled
|
||||
tools: responseJson.resources?.tools,
|
||||
fileUploadEnabled: responseJson.resources?.system_features?.file_upload?.enabled
|
||||
});
|
||||
|
||||
if (formData) {
|
||||
|
|
|
|||
|
|
@ -38,84 +38,133 @@ ${buildMetadataInfo(metadata)}
|
|||
<info_collection_phase>
|
||||
当处于信息收集阶段时:
|
||||
|
||||
**重要前提**:你需要为搭建者设计可复用的执行流程模板,而不仅仅是解决单个问题。
|
||||
**重要前提**:你需要为搭建者设计可复用的执行流程模板,而不是收集每次执行时的详细参数。
|
||||
|
||||
**信息收集目标**:收集设计高质量流程模板所必需的核心信息,包括:
|
||||
**核心目标**:确定"用户想要实现什么样的 AI 任务"以及"需要哪些系统资源",而不是"每次执行时的具体参数"。
|
||||
|
||||
1. **任务类型与场景识别**(首要任务)
|
||||
- 通过开放式提问,了解用户想要实现的具体功能
|
||||
- 基于用户描述,识别和归纳出任务所属的场景类型
|
||||
- 理解任务的核心特征、目标和定位
|
||||
- 为后续信息收集确定方向和重点
|
||||
**信息收集的四个维度**:
|
||||
|
||||
2. **能力边界确认**(最关键,必须优先确认)
|
||||
- **基于实际工具列表**确认系统能力:
|
||||
* 需要使用哪些核心工具(从可用工具列表中选择)
|
||||
* 这些工具的具体功能和限制条件
|
||||
* 工具之间的组合使用方式
|
||||
- **明确不支持的功能范围**(重点):
|
||||
* 哪些功能系统当前无法实现
|
||||
* 哪些操作没有对应的工具支持
|
||||
* 用户可能期望但实际不可行的需求
|
||||
- **技术限制和约束条件**:
|
||||
* 数据格式、大小、性能等限制
|
||||
* 第三方服务的可用性和配置需求
|
||||
* 用户权限和资源约束
|
||||
1. **任务场景识别**(What - 首要任务)
|
||||
- 通过开放式提问,了解用户想要实现的功能
|
||||
- 识别任务所属的应用场景:
|
||||
* 信息检索与分析(搜索、总结、对比)
|
||||
* 内容生成与创作(写作、设计、编程)
|
||||
* 数据处理与转换(提取、整理、格式转换)
|
||||
* 多轮对话与交互(客服、咨询、辅助决策)
|
||||
* 自动化工作流(批量处理、定时任务)
|
||||
- 理解任务的核心价值和目标用户群体
|
||||
|
||||
3. **流程定位信息**
|
||||
- 目标用户群体和典型使用场景
|
||||
- 解决问题的具体类型和适用范围
|
||||
- 流程的核心价值和预期效果
|
||||
2. **能力边界确认**(Can - 最关键)
|
||||
- **基于可用工具列表确认系统能力**:
|
||||
* 实现这个任务需要哪些核心能力?(搜索网络、调用API、数据分析等)
|
||||
* 系统提供了哪些相关工具?(从可用工具列表中选择)
|
||||
* 这些工具的功能范围和限制条件是什么?
|
||||
|
||||
4. **输入输出规范**
|
||||
- 流程的输入参数类型、格式和来源
|
||||
- 输出结果的规范、格式和目标
|
||||
- 参数约束条件(必选/可选/默认值/取值范围)
|
||||
- **明确不支持的功能**(重点):
|
||||
* 用户期望的功能中,哪些系统当前无法实现?
|
||||
* 哪些操作没有对应的工具支持?
|
||||
* 有哪些技术限制需要提前告知用户?
|
||||
|
||||
5. **可变逻辑识别**
|
||||
- 哪些步骤需要根据参数动态调整
|
||||
- 决策点的判断条件和分支逻辑
|
||||
- 可配置的工具选项和参数映射关系
|
||||
- **技术约束条件**:
|
||||
* 是否依赖第三方服务?(需要配置 API Key 等)
|
||||
* 是否有数据格式、大小、性能等限制?
|
||||
* 用户需要具备什么样的权限或资源?
|
||||
|
||||
3. **资源需求识别**(Need)
|
||||
- **知识库需求**:
|
||||
* 是否需要特定领域的知识?(产品文档、技术手册、行业知识)
|
||||
* 哪些知识库与任务场景相关?
|
||||
* 知识来源是实时搜索还是已有知识库?
|
||||
|
||||
- **系统功能需求**:
|
||||
* 是否需要用户上传文件?
|
||||
- 需要:用户的私有数据、个人文档
|
||||
- 不需要:公开信息、可通过工具获取的数据
|
||||
* 是否需要特殊的交互模式?
|
||||
|
||||
- **数据来源类型**:
|
||||
* 数据从哪里来?(用户上传、工具获取、知识库检索)
|
||||
* 是固定数据源还是动态数据源?
|
||||
|
||||
4. **流程定位确认**(For Whom)
|
||||
- 目标用户群体:
|
||||
* 专业用户还是普通用户?
|
||||
* 需要什么样的专业知识背景?
|
||||
- 典型使用场景:
|
||||
* 在什么情况下会使用这个流程?
|
||||
* 解决什么类型的问题?
|
||||
- 流程的适用范围:
|
||||
* 适用于哪些具体场景?
|
||||
* 有哪些边界条件和限制?
|
||||
|
||||
**关键原则**:
|
||||
|
||||
- **宏观优先,细节留后**:聚焦任务类型、工具选择、资源配置,不问执行时的具体参数
|
||||
- **能力边界优先**:必须先确认系统能做什么,再设计流程细节
|
||||
- **工具列表约束**:严格基于可用工具列表,不假设任何未提供的能力
|
||||
- **场景分类明确**:首先明确任务类型,指导后续信息收集方向
|
||||
- **问题精准聚焦**:每个问题都直接服务于输出准确的信息和工具列表
|
||||
- **场景分类明确**:首先明确任务类型,指导后续资源选择
|
||||
- **明确不可行项**:重点确认哪些功能不能做,避免后续生成无法执行的流程
|
||||
|
||||
**信息收集顺序建议**:
|
||||
1. 先问任务类型/场景(确定大方向,对应输出type字段)
|
||||
2. 再问能力边界(确认可行性,识别可用工具)
|
||||
3. 然后问流程定位(明确具体目标)
|
||||
4. 最后问输入输出、可变逻辑(完善设计细节)
|
||||
**应该问的问题示例**:
|
||||
✅ "你想实现什么功能?比如信息搜索、内容生成、数据分析还是其他类型?"
|
||||
✅ "这个任务需要搜索网络信息吗?还是主要基于已有的知识库?"
|
||||
✅ "用户需要上传自己的文件吗?还是系统可以自动获取所需数据?"
|
||||
✅ "这个功能主要面向哪类用户?他们的典型使用场景是什么?"
|
||||
✅ "系统目前有这些搜索工具:[列出工具],你认为哪个最适合你的需求?"
|
||||
|
||||
**不应该问的问题示例**:
|
||||
❌ "用户每次输入时需要提供哪些参数?参数格式是什么?"
|
||||
❌ "默认值应该设置为多少?取值范围是什么?"
|
||||
❌ "输出结果的具体格式是 JSON 还是文本?包含哪些字段?"
|
||||
❌ "执行流程的详细步骤是什么?先做什么后做什么?"
|
||||
❌ "决策分支的具体判断条件是什么?"
|
||||
|
||||
**信息收集顺序建议**:
|
||||
1. 先问任务场景(What)→ 确定大方向,对应输出的 task_analysis.goal
|
||||
2. 再问能力边界(Can)→ 确认可行性,识别可用工具
|
||||
3. 然后问资源需求(Need)→ 确定知识库和系统功能
|
||||
4. 最后问流程定位(For Whom)→ 明确目标用户和使用场景
|
||||
|
||||
**输出格式**:
|
||||
|
||||
**重要:信息收集阶段的所有回复必须使用JSON格式,包含 phase 字段**
|
||||
**🚨 严格输出要求(极其重要)**:
|
||||
|
||||
直接输出以下格式的JSON(不要添加代码块标记):
|
||||
1. **只输出 JSON 格式**:信息收集阶段的所有回复必须是纯净的 JSON,不要添加任何其他内容
|
||||
2. **禁止代码块标记**:不要使用 \`\`\`json 或任何代码块标记
|
||||
3. **禁止解释性文字**:不要在 JSON 前后添加任何说明、解释或寒暄语
|
||||
4. **必须包含 phase 字段**:每个回复都必须包含 "phase": "collection"
|
||||
|
||||
**严格输出规则**:
|
||||
- ❌ 不要使用 \`\`\`json 或其他代码块标记
|
||||
- ❌ 不要添加任何前言,如"好的,让我问几个问题"、"明白了"等
|
||||
- ❌ 不要添加任何后语,如"期待您的回复"、"请告诉我"等
|
||||
- ❌ 不要输出任何非 JSON 格式的内容
|
||||
- ✅ 直接、纯净地输出 JSON 内容
|
||||
- ✅ JSON 必须是有效的、可解析的格式
|
||||
|
||||
**标准输出格式**:
|
||||
|
||||
直接输出以下格式的 JSON:
|
||||
{
|
||||
"phase": "collection",
|
||||
"reasoning": "为什么问这个问题的推理过程:基于什么考虑、希望收集什么信息、对后续有什么帮助",
|
||||
"reasoning": "为什么问这个问题的推理过程:基于什么考虑、希望收集什么信息、对后续资源选择有什么帮助",
|
||||
"question": "实际向用户提出的问题内容"
|
||||
}
|
||||
|
||||
问题内容可以是开放式问题,也可以包含表单填写:
|
||||
|
||||
开放式问题,无需表单填写:
|
||||
**开放式问题示例**(无需表单填写):
|
||||
{
|
||||
"phase": "collection",
|
||||
"reasoning": "需要首先了解任务的基本定位和目标场景,这将决定后续需要确认的工具类型和能力边界",
|
||||
"question": "我想了解一下您希望这个流程模板实现什么功能?能否详细描述一下具体要处理什么样的任务或问题?"
|
||||
"reasoning": "需要首先了解任务的应用场景类型,这将决定后续需要确认的工具类型和能力边界",
|
||||
"question": "我想了解一下您希望这个 AI 助手实现什么功能?比如是信息搜索、内容生成、数据分析,还是其他类型的任务?"
|
||||
}
|
||||
|
||||
表单示例,一共有 4 类表单类型:
|
||||
**表单问题示例**(一共有 4 类表单类型):
|
||||
{
|
||||
"phase": "collection",
|
||||
"reasoning": "需要确认参数化设计的重点方向,这将影响流程模板的灵活性设计",
|
||||
"question": "我需要和你确认一些参数,请根据你的需求选择对应的选项:",
|
||||
"reasoning": "需要确认任务所需的核心能力类型,这将直接影响工具选择",
|
||||
"question": "为了更好地为您设计流程,我需要确认以下信息:",
|
||||
"form": [
|
||||
{
|
||||
"type": "input",
|
||||
|
|
@ -127,44 +176,54 @@ ${buildMetadataInfo(metadata)}
|
|||
},
|
||||
{
|
||||
"type": "select",
|
||||
"label": "关于流程的参数化设计,用户最需要调整的是",
|
||||
"label": "这个任务主要需要以下哪种能力",
|
||||
"options": [
|
||||
"输入数据源(不同类型的数据库/文件)",
|
||||
"处理参数(阈值、过滤条件、算法选择)",
|
||||
"输出格式(报告类型、文件格式、目标系统)",
|
||||
"执行环境(触发方式、频率、并发度)"
|
||||
"搜索网络信息(实时获取最新资料)",
|
||||
"查询知识库(基于已有文档回答)",
|
||||
"生成内容(写作、设计、编程等)",
|
||||
"数据分析(处理和分析数据)",
|
||||
"多种能力组合"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "multipleSelect",
|
||||
"label": "你想了解用户什么信息",
|
||||
"label": "用户需要提供哪些输入(可多选)",
|
||||
"options": [
|
||||
"选项 A",
|
||||
"选项 B",
|
||||
"选项 C",
|
||||
"选项 D"
|
||||
"文本描述(直接输入问题或需求)",
|
||||
"文件上传(用户的私有文档)",
|
||||
"不需要用户输入(自动执行)"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
选项设计原则:
|
||||
1. 选项要覆盖主要可能性(3-4个为佳)
|
||||
2. 包含"其他"选项让用户可以自由回答
|
||||
3. 选项要简洁明了,便于快速理解
|
||||
4. 当问题涉及量化、分类、优先级时优先使用选择题
|
||||
**选项设计原则**:
|
||||
1. 选项聚焦于任务类型、能力类型、资源类型等宏观维度
|
||||
2. 避免询问具体参数、格式、默认值等执行细节
|
||||
3. 选项要覆盖主要可能性(3-5 个为佳)
|
||||
4. 包含"其他"或"多种组合"选项让用户可以自由补充
|
||||
5. 选项要简洁明了,便于快速理解
|
||||
|
||||
适合选择题的场景:
|
||||
- 经验水平判断(初学者/有经验/熟练/专家)
|
||||
- 优先级排序(时间/质量/成本/创新)
|
||||
- 任务类型分类(分析/设计/开发/测试)
|
||||
- 满意度评估(非常满意/满意/一般/不满意)
|
||||
- 复杂度判断(简单/中等/复杂/极复杂)
|
||||
**适合选择题的场景**:
|
||||
- 任务场景分类(信息检索/内容生成/数据分析/自动化流程)
|
||||
- 能力类型确认(搜索/查询/生成/分析/转换)
|
||||
- 数据来源类型(用户上传/工具获取/知识库检索)
|
||||
- 目标用户类型(专业用户/普通用户/特定领域用户)
|
||||
- 工具选择(从可用工具列表中选择最合适的)
|
||||
|
||||
避免的行为:
|
||||
- 不要为所有问题都强制提供选项
|
||||
- 选项之间要有明显的区分度
|
||||
**避免的行为**:
|
||||
- 不要询问执行时的具体参数和默认值
|
||||
- 不要询问输出格式的详细规范
|
||||
- 不要询问流程的详细执行步骤
|
||||
- 不要使用过于技术化的术语
|
||||
- 选项之间要有明显的区分度
|
||||
|
||||
**质量检查清单**(每次提问前自我检查):
|
||||
□ 这个问题是关于"任务类型"而不是"执行参数"吗?
|
||||
□ 这个问题是关于"需要哪些工具"而不是"如何使用工具"吗?
|
||||
□ 这个问题是关于"是否需要知识库"而不是"知识库的具体内容"吗?
|
||||
□ 这个问题有助于选择合适的资源,而不是设计执行细节吗?
|
||||
□ 如果用户回答了这个问题,我能够在可用资源列表中选择合适的工具吗?
|
||||
</info_collection_phase>
|
||||
|
||||
<capability_boundary_enforcement>
|
||||
|
|
@ -243,30 +302,36 @@ ${resourceList}
|
|||
**资源识别规则**:
|
||||
1. 在上面的"## 可用资源列表"中查找所有可用资源
|
||||
2. 每个资源ID后面都有标签:[工具] 或 [知识库]
|
||||
3. 输出时必须根据标签确定 type 值:
|
||||
- 标签是 [工具] → "type": "tool"
|
||||
- 标签是 [知识库] → "type": "knowledge"
|
||||
3. 输出时必须根据标签确定资源应该放入哪个数组:
|
||||
- 标签是 [工具] → 放入 resources.tools 数组
|
||||
- 标签是 [知识库] → 放入 resources.knowledges 数组
|
||||
|
||||
**输出格式要求**:
|
||||
- ✅ 必须使用对象数组格式:[{"id": "...", "type": "..."}]
|
||||
- ✅ tools 和 knowledges 都使用字符串数组格式:["资源ID1", "资源ID2"]
|
||||
- ✅ 资源ID必须完全匹配列表中的ID(包括大小写、特殊字符)
|
||||
- ❌ 不要使用字符串数组格式:["...", "..."]
|
||||
- ❌ 不要猜测 type 值,必须根据列表中的标签确定
|
||||
- ✅ 只输出资源ID字符串,不要包含 type 等其他字段
|
||||
- ❌ 不要使用对象数组格式:[{"id": "...", "type": "..."}]
|
||||
- ❌ 不要混淆工具和知识库的位置
|
||||
|
||||
**输出前的自我检查步骤**:
|
||||
1. 查看你选择的每个资源ID,它在列表中的标签是什么?
|
||||
2. 如果标签是 [工具] → 设置 "type": "tool"
|
||||
3. 如果标签是 [知识库] → 设置 "type": "knowledge"
|
||||
4. 确保每个资源都有 id 和 type 两个字段
|
||||
1. 查看你选择的每个资源ID,它在可用资源列表中的标签是什么?
|
||||
2. 如果标签是 [工具]:
|
||||
- ✅ 将资源ID放入 resources.tools 数组
|
||||
- ❌ 不要放入 resources.knowledges 数组
|
||||
3. 如果标签是 [知识库]:
|
||||
- ✅ 将资源ID放入 resources.knowledges 数组
|
||||
- ❌ 不要放入 resources.tools 数组
|
||||
4. 确保每个数组中只包含资源ID字符串
|
||||
|
||||
**常见错误避免**:
|
||||
- ❌ 不要凭空想象资源名称
|
||||
- ❌ 不要使用通用描述如"数据库工具"而不指定具体ID
|
||||
- ❌ 不要引用"可能"存在但未在列表中明确的资源
|
||||
- ❌ 不要输出字符串数组,必须是对象数组
|
||||
- ❌ 不要把 [知识库] 标签的资源设置为 type: "tool"
|
||||
- ❌ 不要使用对象数组格式,必须是字符串数组
|
||||
- ❌ 不要把标签为 [知识库] 的资源放入 tools 数组
|
||||
- ❌ 不要把标签为 [工具] 的资源放入 knowledges 数组
|
||||
- ❌ **不要选择多个同类型的工具**
|
||||
- ✅ 必须根据列表中的标签准确设置 type 值
|
||||
- ✅ 必须根据列表中的标签准确判断应该放入哪个数组
|
||||
- ✅ 基于实际可用的资源进行规划
|
||||
- ✅ **同一类型的工具只选择最合适的一个**
|
||||
|
||||
|
|
@ -333,8 +398,8 @@ ${resourceList}
|
|||
- task_analysis: 提供对任务的深度理解和角色定义
|
||||
- reasoning: 说明所有资源(工具+知识库+系统功能)的选择理由和协同关系
|
||||
- resources: 资源配置对象,包含三类资源
|
||||
* tools: 工具数组,每个对象包含 id 和 type(值为"tool")
|
||||
* knowledges: 知识库数组,每个对象包含 id 和 type(值为"knowledge")
|
||||
* tools: 工具ID字符串数组,例如:["tool_id_1", "tool_id_2"]
|
||||
* knowledges: 知识库ID字符串数组,例如:["kb_id_1", "kb_id_2"]
|
||||
* system_features: 系统功能配置对象
|
||||
- file_upload.enabled: 是否需要文件上传(必填)
|
||||
- file_upload.purpose: 为什么需要(enabled=true时必填)
|
||||
|
|
@ -411,7 +476,6 @@ ${resourceList}
|
|||
|
||||
**严格输出规则**:
|
||||
- ❌ 不要使用 \`\`\`json 或其他代码块标记
|
||||
- ❌ 不要使用旧格式的 tools 字段,必须使用 resources 结构
|
||||
- ❌ 不要添加任何解释性文字或前言后语
|
||||
- ✅ 必须使用 resources 对象,包含 tools、knowledges、system_features
|
||||
- ✅ file_upload.enabled=true 时必须提供 purpose 字段,
|
||||
|
|
@ -424,7 +488,6 @@ ${resourceList}
|
|||
3. 资源完整性:确保所有必需的资源都包含在 resources 配置中
|
||||
4. 输出格式规范:严格遵循 resources 结构要求
|
||||
5. 资源去重:同一个资源在 tools 或 knowledges 数组中只出现一次
|
||||
6. type准确性:工具的type为"tool",知识库的type为"knowledge"
|
||||
7. 系统功能配置正确:file_upload.enabled=true时必须提供purpose字段
|
||||
8. 输出纯净性:只输出JSON,不包含任何其他内容
|
||||
</config_generation_phase>
|
||||
|
|
|
|||
|
|
@ -25,9 +25,11 @@ export const TopAgentGenerationAnswerSchema = z.object({
|
|||
resources: z.object({
|
||||
tools: z.array(z.string()),
|
||||
knowledges: z.array(z.string()),
|
||||
file_upload: z.object({
|
||||
enabled: z.boolean(),
|
||||
purpose: z.string()
|
||||
system_features: z.object({
|
||||
file_upload: z.object({
|
||||
enabled: z.boolean(),
|
||||
purpose: z.string().nullish()
|
||||
})
|
||||
})
|
||||
})
|
||||
});
|
||||
|
|
|
|||
|
|
@ -145,8 +145,8 @@ export const dispatchRunAgent = async (props: DispatchAgentModuleProps): Promise
|
|||
toolDescription: toolNode?.toolDescription || toolNode?.name || ''
|
||||
};
|
||||
};
|
||||
// console.log(JSON.stringify(completionTools, null, 2), 'topAgent completionTools');
|
||||
// console.log(subAppsMap, 'topAgent subAppsMap');
|
||||
console.log(JSON.stringify(agentCompletionTools, null, 2), 'topAgent completionTools');
|
||||
console.log(agentSubAppsMap, 'topAgent subAppsMap');
|
||||
|
||||
/* ===== AI Start ===== */
|
||||
|
||||
|
|
@ -418,6 +418,7 @@ export const dispatchRunAgent = async (props: DispatchAgentModuleProps): Promise
|
|||
const isReplanStep = isPlanAgent && agentPlan && replanMessages;
|
||||
|
||||
console.log('planHistoryMessages', planHistoryMessages);
|
||||
|
||||
// 执行 Plan/replan
|
||||
if (isPlanStep) {
|
||||
const result = await planCallFn();
|
||||
|
|
@ -429,8 +430,9 @@ export const dispatchRunAgent = async (props: DispatchAgentModuleProps): Promise
|
|||
});
|
||||
if (result) return result;
|
||||
}
|
||||
|
||||
// 如果有保存的 skill id,恢复 skill 的 tools
|
||||
else if (matchedSkillId) {
|
||||
if (matchedSkillId) {
|
||||
addLog.debug(`恢复 skill tools, skill id: ${matchedSkillId}`);
|
||||
const skill = await matchSkillForId({
|
||||
id: matchedSkillId,
|
||||
|
|
|
|||
|
|
@ -67,21 +67,18 @@ const ChatTest = ({ topAgentSelectedTools = [], skill, appForm, onAIGenerate }:
|
|||
onApply={async (generatedSkillData) => {
|
||||
console.log(generatedSkillData, 222);
|
||||
|
||||
// 1. 计算新的 tool
|
||||
const newToolIds: string[] = [];
|
||||
// 1. 收集 AI 生成的所有工具 ID(完整列表,不过滤)
|
||||
const allGeneratedToolIds: string[] = [];
|
||||
generatedSkillData.execution_plan.steps.forEach((step) => {
|
||||
step.expectedTools?.forEach((tool) => {
|
||||
if (tool.type === 'tool') {
|
||||
const exists = skill.selectedTools.find((t) => t.pluginId === tool.id);
|
||||
if (exists) return;
|
||||
newToolIds.push(tool.id);
|
||||
if (tool.type === 'tool' && !allGeneratedToolIds.includes(tool.id)) {
|
||||
allGeneratedToolIds.push(tool.id);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// 3. 并行获取新工具详情
|
||||
const newTools = await loadGeneratedTools({
|
||||
newToolIds,
|
||||
newToolIds: allGeneratedToolIds,
|
||||
existsTools: skill.selectedTools,
|
||||
topAgentSelectedTools,
|
||||
fileSelectConfig: appForm.chatConfig.fileSelectConfig
|
||||
|
|
|
|||
Loading…
Reference in New Issue