Dify后台里那个“创建应用”按钮,看起来就是个普通入口,但真正点进去之后,你会发现摆在面前的不只是“填个名字点保存”那么简单。前两篇我们把环境跑起来、把平台基本概念理清楚了,到了这一篇,所有问题会集中爆发:聊天助手和Agent到底该选哪个?要不要先建知识库?为什么同样的提示词在别处好使,放进Dify里就开始胡编?如果你也卡在这一步,这篇文章就是把“构建应用”这件事从头到尾完整拆开,从创建应用、配模型、写提示词,到接知识库、开Agent工具、编排工作流,最后发布上线。我全程用模拟项目X做例子,一个企业内部的知识问答助手,方便你对照着一步步复现。
1. 先想清楚再做:应用类型没选对,后面全是坑
1.1 四种应用类型的适用边界
打开Dify后台,点击“创建应用”,界面上会让你选类型:聊天助手、Agent、工作流、文本生成。我见过太多人直接点“聊天助手”,理由是“能用就行”。但应用类型本质上是你在选择“业务逻辑的复杂度级别”,选错了后面改起来非常痛苦。
四种类型可以这样理解:
- 聊天助手:直接调LLM做多轮对话,模型想怎么回就怎么回,交互逻辑简单。适合纯问答、角色扮演、知识库问答这种“模型本身能搞定”的场景。
- Agent:在聊天助手基础上加了一个“推理循环”,模型可以自己决定要不要调工具、调哪个工具、工具返回结果怎么处理。适合需要查订单、查库存、访问第三方接口才能回答的场景。
- 工作流:不依赖模型随机决策,所有步骤都按你编排好的固定链路执行,每个节点做什么、顺序如何完全确定。适合客服分流、工单创建、定时任务这类必须可复现的业务流。
- 文本生成:单轮输入输出,不保留对话历史,适合写摘要、写邮件、批量生成标题。
我判断类型就一个经验法则:看这个应用需不需要“外部动作”。如果回答只依赖模型自身的理解能力和输入内容,聊天助手够了;如果答案是靠实时查数据得出来的,那就要么走Agent,要么走工作流。模拟项目X的需求是“售后人员输入问题描述,应用基于产品文档和故障库给建议,回答不了就转人工”,带着知识库和转人工判断,核心场景偏聊天助手,但转人工这个环节如果要接工单系统,就得考虑Agent或工作流。我在后面会分别演示两种走法。
1.2 先画链路图,再决定选型
我不建议直接在创建页里选完就开干。先在纸上把业务链路画出来,哪怕画得糙也比直接点按钮强。模拟项目X的需求拆开就是:用户提问 → 搜索内部资料 → 生成回答 → 判断是否需要转人工 → 输出。
这张图的价值在于,你能提前看到“知识检索”和“分支判断”这两个关键节点。有了链路图,再回头看应用类型,思路会清楚很多:知识检索需要接知识库,分支判断要么靠Agent自己决策,要么在工作流里做条件分支。
这里插一句经验:Dify的界面布局在不同版本里可能微调,但功能入口的位置大体一致,如果你看到的按钮和我写的有细微差异,以实际界面为准,对应的逻辑是一样的。
2. 创建应用与基础编排:模型、提示词和第一轮对话
2.1 创建应用与模型配置
链路图画好之后,回到创建应用页。模拟项目X我用“聊天助手”起步,原因很简单:先跑通最小可用版本,再逐步加能力。
创建完成后进入编排页,正事才开始。第一件事是配置“模型供应商”。这个入口在平台后台的“设置”里,找到模型供应商,接入你手里可用的LLM API。每家供应商的接入方式大同小异,核心就两件事:填API密钥、选模型。一个容易踩坑的点是,大模型接口在Dify里严格区分“对话模型”和“embedding模型”,同一个供应商的多个模型可能混在同一个列表里,你要先确认自己接的这个是对话模型还是嵌入模型。如果选错了类型,后面创建知识库或者对话调用时不会马上报错,但会在某个环节给你颜色看——我在第三章会详细讲。
模型配置好后,返回编排页。右上角会显示当前可用的默认模型,旁边有参数设置按钮。这一步很多人直接跳过,因为Dify给了默认值。我的建议是不要跳过,至少把temperature和max_tokens改一下。
2.2 模型参数的关键值:temperature和max_tokens
大模型的参数看起来多,实际需要调的没几个。对知识问答类应用,最要关注的是温度参数。给个参考:
- temperature:控制在0.2到0.4之间。模拟项目X是知识问答,回答必须尽量客观和贴近资料,温度太高模型会开始“自由发挥”,语气散、内容离谱。如果是创意写作、头脑风暴类的应用,再往0.8以上调。
- max_tokens:单次回答的最大输出长度。内部知识问答的回答一般不会特别长,但如果你设成500,遇到复杂问题时答案会被硬生生截断。稳妥一点设1024或更高,资源开销没有想象中那么大。
- top_p:核采样,保持默认即可。
- 频率惩罚和存在惩罚:这两个参数在知识问答场景没太大作用,不用专门调,除非发现模型在同一个回答里反复绕圈。
用开车来类比,temperature就是油门刹车踏板。知识问答你要的是“车稳稳走在车道里”,那油门就得小一点。别让模型开得太奔放,答错问题比答得无趣严重得多。
2.3 系统提示词:应用的“性格”和“规则”
编排页里的“系统提示词”是所有模型行为规则的源头。很多人把提示词当成“跟模型聊天的一句开场白”,这是误区。它是你对整个应用行为的约束,写得好不好直接决定回答质量。
模拟项目X的系统提示词,我按三段式来写:
第一段,定位角色:“你是某产品的售后服务知识助手,回答必须基于给定的知识库内容,不要强行生成答案。”
第二段,划定边界:“如果知识库中没有对应信息,直接回答‘该问题需要转人工处理’,不要编造维修步骤。”
第三段,明确输出要求:“回答采用总分结构,先给结论,再给操作步骤;涉及多个步骤时,用编号列出。”
这三段看起来普普通通,但每条都有它存在的理由。第一段防止模型脱离知识库乱答,第二段是兜底条款,第三段统一输出格式,方便售后人员快速获取信息。
这里有一个很容易被忽视的点:如果你不写“找不到就说不知道”,模型大概率会在上下文里硬找一点沾边的内容,然后脑补一份听起来很有道理的答案。知识问答类应用最怕的就是编造,而编造往往就是提示词里少了一句兜底导致的。
2.4 调试台第一轮对话的观察点
配置完成后,右侧调试台输入第一句:“我的设备开机后一直黑屏,怎么办?” 点击发送。
第一轮调试,重点不是看回答内容本身,而是看三个东西。第一,回答有没有基于“引用来源”——如果你已经接入了知识库,回答下面会显示引用了哪些文档片段;第二,回答有没有遵守规则,比如资料不足时有没有说出“转人工”而不是硬编;第三,多轮对话是否正常,也就是再追问一句“如果是刚换过主板呢”,模型能不能结合上一轮内容继续作答。
第一轮对话结束之后,平台里其实只完成了一半。一个纯聊天助手没有业务知识的支撑,回答再流畅也只是空话。下一章进入模拟项目X的核心步骤:接知识库。
3. 让应用“读懂业务文档”:知识库接入与检索调优
3.1 创建知识库并设置分段规则
模拟项目X要用的资料包括产品说明书、常见故障库、维修手册。打开“知识库”页面,创建新知识库,上传文档。
上传之后马上会遇到一个关键参数:分段设置。Dify会对文档做切片,把长文切成小块,后续检索时按块召回。分段规则有“自动分段”和“自定义分段”两种,我的建议是选自定义,因为自动分段在中文长文档上经常把语义完整的段落切开。
自定义分段主要看两个参数:
- 分段长度:单块字符数。我一般设300到500字符左右。太短,语义不完整,检索召回的片段可能会断在关键信息中间;太长,检索粒度太粗,一段内容里混了多个主题,回答时会引用到不相关的部分。
- 重叠长度:相邻片段之间保留的重叠字符数,我通常设50到100。作用是避免一个完整句子或概念被切到两块里,导致哪一块都不完整。
分段完成后,页面会展示分段预览。这个预览一定要看。我遇到过把“故障A的操作流程”和“故障B的操作流程”切进同一段的情况,这种时候不要犹豫,直接手动编辑分段,把不同主题切开。一个知识库里如果有明显交融的分段,后面检索就会出现“引用的内容一部分相关一部分不相关”的尴尬情况。
3.2 Embedding模型与索引模式的选择
创建知识库的流程里会要求选Embedding模型。这里强调一遍:Embedding模型和对话模型是两种类型,不能混用。你手里那个能聊天的模型不一定能用来做嵌入。选Embedding模型时优先考虑对中文支持好、维度适中的模型,Dify会列出你已经接入的可用嵌入模型列表,选一个用即可。
在“索引方式”下面,一般有“高质量”和“经济”两种模式。高质量模式会对文档做向量化和关键词索引,检索更准;经济模式在部署时更快、成本更低,但检索质量较弱。模拟项目X这种文档量不大的内部知识库,我强烈建议直接选高质量模式。如果知识库有几千段以上,可以先选经济模式跑通流程,再择机切高质量。但我更推荐做这事之前先确认知识库本身质量,因为索引模式只是“找得准”,文档本身写得乱的话,再好的索引也没有意义。
3.3 检索参数:top_k和得分阈值
知识库创建好之后,回到应用编排页,在“上下文”区域关联这个知识库。关联那一栏会有两个检索参数:召回数量和得分阈值。
- 召回数量:控制每次检索取回多少知识片段。模拟项目X设4到6比较合适。太小,信息可能不够用;太大,把无关内容也搅进来。
- 得分阈值:过滤低于相似度分数的片段。通常设0.4到0.6之间。阈值太高,检索结果可能为空;阈值太低,召回一堆不相关内容。
这两个参数的调优思路,我总结一句话:不要只调数值,要看“引用来源”。每一轮回答下面都会显示实际召回了哪几个片段,你逐条翻一遍,立刻就会发现问题是召回太少、召回太乱、还是文档本身分段不对。
模拟项目X前期调试时,我设了top_k=4、阈值0.5。测“我的设备开机黑屏”这个问题时,看到召回结果里有两条来自“常见故障库”、一条来自“产品说明”,但还有一条是“保修政策”的内容。这就是典型的召回噪音。解决办法不是把top_k调到2,而是去查为什么“保修政策”会被当作相关内容召回——大概率是分段不干净或者阈值设置偏松。
3.4 检索测试的实操方法
在Dify里,知识库页面会提供一个“检索测试”功能,你可以输入一句话,直接查看会召回哪些片段。这个功能对排查问题特别有用。
我的测试方法是:拿用户真正会问的问题去测,不用模拟问题,要拿售后群里真实出现过的话去测。比如“屏幕摔了还能修吗”和“设备进水了能不能开机”看起来差不多,但检索出来的片段可能完全不同。
如果检索测试时发现某类问题召回结果总是不理想,可能不是检索参数的问题,而是知识库里根本没有对应信息。这种时候要么补充文档,要么在文档里单独维护一个“高频问答”分区。很多团队在知识库里放的都是原文文档,召回效果差还以为是Dify的问题,其实是文档结构没有为“检索”设计。把“QA对”单独整理出来,检索效果提升特别明显,这个经验是真的好用。
4. 升级为Agent:让应用能调用外部工具
4.1 Agent模式到底是在解决什么问题
聊天助手加知识库,模拟项目X已经有了基本问答能力。但售后场景有个常见需求:客服要查这个设备的维保记录。维保记录是存在业务系统里的,模型本身不可能知道。这时候就需要Agent。
在Dify里创建应用时选“Agent”,或者从聊天助手变为Agent模式。Agent和普通聊天助手的区别在于:模型可以在对话过程中决定“调用哪个工具”、“什么时候调用”,工具返回结果后,再基于结果组织回答。这个过程看起来像模型自己在工作,但本质上是你提前把工具“说明书”写好,模型只是按说明书调用。
这里有个误区:不是所有应用都应该开Agent。如果你没有给Agent提供任何工具,它和聊天助手没有任何区别,甚至因为多了一层推理循环,响应还更慢。Agent的价值前提是:你有真实工具可调用。
4.2 自定义工具:OpenAPI Schema写法要点
模拟项目X的“维保记录查询”是一个内部HTTP接口。在Dify里接入这样的接口,走的是“自定义工具”功能,它支持通过OpenAPI Schema来描述接口。
这个Schema文件,形象点说就是给模型准备的一份“接口使用说明书”。模型通过读它来知道这个工具是干什么的、需要哪些参数、返回什么格式。
一个简化的维保查询接口Schema长这样:
{ "openapi": "3.1.0", "info": { "title": "维保记录查询", "description": "根据设备序列号查询该设备的维保记录", "version": "1.0.0" }, "paths": { "/repair-records": { "get": { "operationId": "getRepairRecords", "summary": "根据设备序列号查询维保记录", "parameters": [ { "name": "device_sn", "in": "query", "required": true, "description": "设备序列号,通常由用户提供", "schema": { "type": "string" } } ], "responses": { "200": { "description": "请求成功", "content": { "application/json": { "schema": { "type": "object", "properties": { "device_sn": { "type": "string" }, "record_list": { "type": "array", "items": { "type": "object", "properties": { "date": { "type": "string" }, "content": { "type": "string" } } } } } } } } } } } } } }保存后还要填“工具名称”和“工具描述”。这两个字段特别关键,尤其是描述。模型不是靠字段名理解工具的,它靠的是描述。如果你描述写得模糊,比如“查询维保”,模型在遇到问题时可能不知道用这个工具;但如果你写清楚“当用户需要查询设备维保记录、维修历史时调用此工具,查询参数为设备序列号”,模型就知道该怎么用了。
4.3 Agent工具调用失败的排查思路
开启Agent并接入工具后,调试时最容易遇到三个问题,我都踩过。
第一个:模型压根不调用工具。表现为用户问“帮我查一下这台设备的维修记录”,模型却回复“查询维修记录需要联系售后”。这种情况多半是工具描述不够明确,模型没意识到它手里有工具可调。把描述改得更贴近用户提问的口语表达,比如加上“用户通常会提供设备序列号”,就能有效改善。
第二个:模型调用工具但参数错误。它传了一个不存在的设备SN,接口报错。这种要去检查Schema里的参数说明是否清楚,比如“device_sn必须是设备外壳上的序列号标签,格式为字母加8位数字”。参数说明越具体,模型传参越准。
第三个:工具返回了数据,但模型回答时胡编。比如返回的record_list为空,模型却说“该设备有三次维修记录”。这是提示词里缺少约束。我通常在Agent模式的提示词里加一句“回答必须基于工具返回的数据内容,不要杜撰返回结果中不存在的字段”。加了这句话之后,胡编问题基本消失。
Agent适合灵活场景,但灵活性也意味着不确定性。如果你要做的是客服分流这种不能出错的流程,更推荐走上工作流。第四章末尾我可以直说:确定性优先走工作流,灵活性优先走Agent。
5. 工作流编排:把流程固化成稳定链路
5.1 为什么要从Agent切到工作流
Agent在模拟项目X里查维保记录很好用,但售后场景还有一个常见需求:自动分类工单。用户报一个问题,系统要判断是硬件还是软件故障,并决定走知识库回答还是转人工。这个流程如果交给Agent,模型每次都可能自己发挥,步骤顺序和行为不一定一致。在需要严格按流程执行的业务里,这种不确定性无法接受。
工作流就是来解决这个问题的。所有步骤都由你来编排,每个节点做什么完全固定,不依赖模型随机决策。Dify的工作流就是把可复现的确定性带回来。
5.2 常用节点逐个拆解
Dify工作流界面提供了多种节点,先认识最常用的几个:
- 开始节点:定义整个工作流的输入变量,比如“原始问题”。用户输入的内容从这里进入流程。
- LLM节点:可以独立配置模型和提示词,比应用全局提示词更精细。工作流里可以放多个LLM节点,各干各的活。
- 知识检索节点:绑定知识库,接收输入并输出检索到的相关段落。
- 问题分类节点:用LLM把用户输入归类,比如分为“硬件问题”、“软件问题”、“其他”。
- 条件分支节点:根据前一个节点的输出走不同分支。比如问题分类结果是“硬件问题”就走A分支,否则走B分支。
- 代码节点:支持写一段代码处理数据变换,适合格式转换类工作。
- 模板转换节点:把列表、对象等结构化数据转换成字符串文本,方便后续LLM节点使用。
- 结束节点:输出最终结果。工作流必须以结束节点收尾。
5.3 把模拟项目X改造成分流工作流
模拟项目X的完整工作流我这样编排:
开始节点接收用户输入的问题文本。第一个LLM节点做问题分类,提示词写“你是工单分类器,将用户问题分类为‘硬件’、‘软件’、‘其他’,只输出一个词”。输出结果传到条件分支节点。条件分支判断分类结果:如果“硬件”,走“转人工话术”分支;如果“软件”,先走知识检索节点,把问题作为检索关键词,再走第二个LLM节点,让它基于检索结果回答;最后汇聚到结束节点统一回复。
这个流程的好处很明显:软件类问题能自动回答,硬件类问题自动转人工,每一类都有固定路径,上线后不会出现“同一个问题上次回答、这次拒绝回答”的情况。
在Dify工作流编辑页面,可以实时运行一次流程看节点流转。我调试时习惯在每个节点之间看输入输出:进入LLM节点的文本是否正确、问题分类节点输出的是不是预期的分类结果、条件分支是否按预期走了对应分支。这个“逐节点追数据”的调试方式,比看最终回答高效得多,因为你能直接定位是哪个环节出了问题。
5.4 工作流调试的观察维度
工作流运行后,运行记录里会显示每个节点的耗时和输入输出。看的时候有几个重点:
先看分支是否正确。例如硬件问题有没有走转人工分支。再看变量传递是否成功。Dify里节点之间通过变量引用传递数据,变量名拼错是最高频的报错原因。最后看耗时,如果整个流程特别慢,通常是LLM节点多了,我一般会把不需要模型的分支尽量不用LLM,比如转人工分支直接拼固定文本,不需要调模型。
但我也想说句实在话:工作流不是节点越多越好。刚玩工作流的人容易把一个简单问答拆成七八个节点,最后维护成本比收益还高。模拟项目X的对话分流四个节点就够了,节点数量控制在“能清晰表达业务链路”的水平上就行。
6. 发布、接入和上线后的迭代思路
6.1 发布为WebApp与嵌入方式
调试到满意后,点击“发布”按钮。Dify会把当前应用发布为一个可访问的WebApp,得到一个链接,团队成员打开就能用。模拟项目X我直接把这个链接发给了售后团队的聊天群,大家第一反应是“这就在网页上能用了?”——对,就是这么简单。
发布前还可以设置WebApp的欢迎语、建议问题列表、以及是否开启用户反馈按钮。这几个都不要跳过,尤其是用户反馈按钮,它是后续迭代最重要的数据来源。用户在回答下面点“有帮助”或“没帮助”,比你自己猜哪类问题效果不好要直接得多。
6.2 通过API方式接入业务系统
WebApp适合人工使用,但如果要把能力集成到业务系统里,比如把回答能力嵌入到内部工单工具,就需要API方式。在“API访问”页面创建一个API密钥,然后通过标准HTTP接口调用。
一个最简单的调用样例:
curl --location --request POST 'https://your-domain/v1/chat-messages' \ --header 'Authorization: Bearer app-xxxxxxxxx' \ --header 'Content-Type: application/json' \ --data-raw '{ "inputs": {}, "query": "设备开机黑屏怎么办", "response_mode": "blocking", "user": "staff-001" }'这里解释一下response_mode两个选项:blocking是请求发出后一直等到完整回答返回,适合后端服务调用;streaming是流式输出,适合前端页面打字机效果。模拟项目X集成到内部系统时,用blocking就够了,接入成本更低。
有一个细节容易被忽略:user字段。API调用时传一个用户唯一标识,Dify用这个标识区隔不同用户的会话历史。不传的话所有会话串在一起,用户A问过的问题用户B也能看到上下文,这在企业内部是隐私事故。
6.3 上线后的迭代:数据驱动比经验驱动靠谱
应用上线不是终点,真正的迭代从有了真实用户反馈才刚开始。我建议每周看一次数据,重点看三个东西:
第一,用户反馈中被点“没帮助”的回答,把这些问题批量导出,逐个看是知识库缺内容,还是检索没召回,还是回答本身跑偏。
第二,转人工的比例。模拟项目X上线初期转人工比例很高,一查原因,很多是知识库还没覆盖新发布的产品,这是业务问题不是AI问题。解决方案是更新知识库文档。
第三,用户实际提问和预设场景的差距。你上线前以为用户会问“开机黑屏怎么办”,实际上用户问的是“能不能开机后直接进壁纸界面”。这些真实语料就是下一轮优化提示词和知识库分段的依据。
知识库的更新,Dify支持直接替换或增量添加文档。但要注意,修改知识库的embedding模型会导致原有索引失效,需要重新处理文档,这个操作会在后期检索时产生问题。我的建议是:确定好一个嵌入模型就长期别换,换了就要把文档重新全量处理一遍。
7. 常见问题与排查速查
7.1 高频问题列表
| 现象 | 可能原因 | 解决办法 |
|---|---|---|
| 回答内容开始自由发挥,与资料无关 | 温度参数设置偏高 | 将temperature降到0.2到0.4之间 |
| 回答太长被截断 | max_tokens设太小 | 调大max_tokens到1024以上 |
| 知识库检索召回的内容明显无关 | 分段不干净或top_k/阈值不合适 | 检查知识库分段,重传文档;调低top_k、调高阈值 |
| 检索结果为空 | 得分阈值设置过高 | 调低阈值到0.4到0.5之间 |
| Agent不调用工具 | 工具描述模糊 | 重写工具描述,加入用户提问典型的说法 |
| Agent调用工具但参数错误 | Schema参数说明不清晰 | 补充参数格式、取值枚举说明 |
| 工作流运行慢 | 节点过多或模型多次调用 | 精简节点;无需模型的分支不调用LLM |
| 变量传不到下游节点 | 变量名拼写错误或类型不匹配 | 在节点输出位置检查变量路径,逐节点确认 |
| 换了Embedding模型后检索异常 | 原有知识库索引失效 | 重传文档并重新处理所有分段 |
| 多用户会话串线 | 没有传user字段区分用户 | API调用时带上唯一用户标识 |
7.2 我踩过的几个坑,写出来给你避雷
第一个坑:创建知识库时图省事用了自动分段,结果一个长篇说明文档被按固定长度硬切,很多段落是半句话,检索召回时引用了“上半句”和另一段的“下半句”,答案看起来像拼贴。后来我重新做了自定义分段,同样的问题,回答质量明显不一样。自动分段可以用于草稿阶段,但正式上线前一定要人工检查分段。
第二个坑:把temperature调到0.9做了次测试,忘记改回来。之后几天所有回答都带着一种“创作感”,用词华丽但不着边际,差点被合作方以为模型出问题了。检查半天才发现参数没改回来,教训是:改参数之后要在回复里带上下文,或者直接重置到稳妥的默认值。
第三个坑:做工作流时漏了结束节点,运行后应用一直“处理中”,还以为是模型响应慢。其实工作流必须有明确的结束节点,否则流程没有输出。这类问题在设计链路图时就能避免,所以我在第一章强调先画图再动手,就是这个原因。
第四个坑:多个应用共用同一个API密钥,后来查日志发现没法区分是哪个应用在消耗调用量。给每个应用单独生成密钥处理,问题就解了。
最后再分享一个我实际使用后的体会:Dify构建应用这件事,真正的难点其实不在平台操作上,而在业务逻辑的拆解。平台只是把你脑子里的流程变成了可点击的编排。如果你面前摆着一个新需求,先用五分钟把“输入是什么、输出是什么、中间分几步、异常怎么处理”写清楚,再打开Dify,你会觉得每一步都顺理成章。我第一次做模拟项目X的时候就是直接点创建,结果删了三次重做,后来养成先写流程草稿的习惯,一次成型,这个习惯比任何教程都管用。