{'Header 1': 'Table of contents', 'Header 2': '入门 '} * [欢迎使用 Dify](README.md) * [特性与技术规格](getting-started/readme/features-and-specifications.md) * [模型供应商列表](getting-started/readme/model-providers.md) * [云服务](getting-started/cloud.md) * [社区版](getting-started/install-self-hosted/README.md) * [Docker Compose 部署](getting-started/install-self-hosted/docker-compose.md) * [本地源码启动](getting-started/install-self-hosted/local-source-code.md) * [单独启动前端 Docker 容器](getting-started/install-self-hosted/start-the-frontend-docker-container.md) {'Header 1': 'Table of contents', 'Header 2': '入门 '} * [环境变量说明](getting-started/install-self-hosted/environments.md) * [常见问题](getting-started/install-self-hosted/faq.md) * [Dify Premium](getting-started/dify-premium.md) {'Header 1': 'Table of contents', 'Header 2': '手册 '} * [模型](guides/model-configuration/README.md) * [增加新供应商](guides/model-configuration/new-provider.md) * [预定义模型接入](guides/model-configuration/predefined-model.md) * [自定义模型接入](guides/model-configuration/customizable-model.md) * [接入 Hugging Face 上的开源模型](guides/model-configuration/hugging-face.md) * [接入 Replicate 上的开源模型](guides/model-configuration/replicate.md) * [接入 Xinference 部署的本地模型](guides/model-configuration/xinference.md) * [接入 OpenLLM 部署的本地模型](guides/model-configuration/openllm.md) {'Header 1': 'Table of contents', 'Header 2': '手册 '} * [接入 LocalAI 部署的本地模型](guides/model-configuration/localai.md) * [接入 Ollama 部署的本地模型](guides/model-configuration/ollama.md) * [负载均衡](guides/model-configuration/load\_balancing.md) * [构建](guides/application\_orchestrate/README.md) * [创建应用](guides/application\_orchestrate/creating-an-application.md) * [聊天助手](guides/application\_orchestrate/conversation-application.md) * [Agent](guides/application\_orchestrate/agent.md) * [应用工具箱](guides/application\_orchestrate/app\_toolkits/README.md) {'Header 1': 'Table of contents', 'Header 2': '手册 '} * [敏感内容审查](guides/application\_orchestrate/app\_toolkits/moderation-tool.md) * [工作流](guides/workflow/README.md) * [关键概念](guides/workflow/key\_concept.md) * [节点说明](guides/workflow/node/README.md) * [开始](guides/workflow/node/start.md) * [结束](guides/workflow/node/end.md) * [直接回复](guides/workflow/node/answer.md) * [LLM](guides/workflow/node/llm.md) * [知识检索](guides/workflow/node/knowledge\_retrieval.md) * [问题分类](guides/workflow/node/question\_classifier.md) * [条件分支](guides/workflow/node/ifelse.md) {'Header 1': 'Table of contents', 'Header 2': '手册 '} * [条件分支](guides/workflow/node/ifelse.md) * [代码执行](guides/workflow/node/code.md) * [模板转换](guides/workflow/node/template.md) * [变量聚合](guides/workflow/node/variable\_assigner.md) * [迭代](guides/workflow/node/iteration.md) * [参数提取](guides/workflow/node/parameter\_extractor.md) * [HTTP 请求](guides/workflow/node/http\_request.md) * [工具](guides/workflow/node/tools.md) * [预览与调试](guides/workflow/debug\_and\_preview/README.md) * [预览与运行](guides/workflow/debug\_and\_preview/yu-lan-yu-yun-hang.md) {'Header 1': 'Table of contents', 'Header 2': '手册 '} * [单步调试](guides/workflow/debug\_and\_preview/step\_run.md) * [对话/运行日志](guides/workflow/debug\_and\_preview/log.md) * [检查清单](guides/workflow/debug\_and\_preview/checklist.md) * [运行历史](guides/workflow/debug\_and\_preview/history.md) * [应用发布](guides/workflow/publish.md) * [知识库](guides/knowledge-base/README.md) * [创建知识库&上传文档](guides/knowledge-base/create\_knowledge\_and\_upload\_documents.md) * [知识库及文档维护](guides/knowledge-base/knowledge\_and\_documents\_maintenance.md) {'Header 1': 'Table of contents', 'Header 2': '手册 '} * [在应用内集成知识库](guides/knowledge-base/integrate\_knowledge\_within\_application.md) * [召回测试/引用归属](guides/knowledge-base/retrieval\_test\_and\_citation.md) * [从 Notion 导入数据](guides/knowledge-base/sync-from-notion.md) * [从网页导入数据](guides/knowledge-base/sync\_from\_website.md) * [通过 API 维护知识库](guides/knowledge-base/maintain-dataset-via-api.md) * [外部数据工具](guides/knowledge-base/external\_data\_tool.md) * [工具](guides/gong-ju.md) * [快速接入工具](guides/tools/quick-tool-integration.md) {'Header 1': 'Table of contents', 'Header 2': '手册 '} * [高级接入工具](guides/tools/advanced-tool-integration.md) * [工具配置](guides/tools/tool-configuration/README.md) * [StableDiffusion](guides/tools/tool-configuration/stable-diffusion.md) * [SearXNG](guides/tools/tool-configuration/searxng.md) * [发布](guides/application-publishing/README.md) * [发布为公开 Web 站点](guides/application-publishing/launch-your-webapp-quickly/README.md) * [Web 应用的设置](guides/application-publishing/launch-your-webapp-quickly/web-app-settings.md) {'Header 1': 'Table of contents', 'Header 2': '手册 '} * [文本生成型应用](guides/application-publishing/launch-your-webapp-quickly/text-generator.md) * [对话型应用](guides/application-publishing/launch-your-webapp-quickly/conversation-application.md) * [嵌入网站](guides/application-publishing/embedding-in-websites.md) * [基于 APIs 开发](guides/application-publishing/developing-with-apis.md) * [基于前端组件再开发](guides/application-publishing/based-on-frontend-templates.md) * [标注](guides/biao-zhu/README.md) * [日志与标注](guides/biao-zhu/logs.md) {'Header 1': 'Table of contents', 'Header 2': '手册 '} * [日志与标注](guides/biao-zhu/logs.md) * [标注回复](guides/biao-zhu/annotation-reply.md) * [监测](guides/monitoring/README.md) * [集成外部 Ops 工具](guides/monitoring/integrate\_external\_ops\_tools/README.md) * [集成 LangSmith](guides/monitoring/integrate\_external\_ops\_tools/integrate\_langsmith.md) * [集成 Langfuse](guides/monitoring/integrate\_external\_ops\_tools/integrate\_langfuse.md) * [数据分析](guides/monitoring/analysis.md) * [扩展](guides/extension/README.md) {'Header 1': 'Table of contents', 'Header 2': '手册 '} * [扩展](guides/extension/README.md) * [API 扩展](guides/extension/api\_based\_extension/README.md) * [外部数据工具](guides/extension/api\_based\_extension/external\_data\_tool.md) * [使用 Cloudflare Workers 部署 API Tools](guides/extension/api\_based\_extension/cloudflare\_workers.md) * [敏感内容审查](guides/extension/api\_based\_extension/moderation.md) * [代码扩展](guides/extension/code\_based\_extension/README.md) * [外部数据工具](guides/extension/code\_based\_extension/external\_data\_tool.md) {'Header 1': 'Table of contents', 'Header 2': '手册 '} * [敏感内容审查](guides/extension/code\_based\_extension/moderation.md) * [协同](guides/workspace/README.md) * [发现](guides/workspace/app/README.md) * [邀请与管理成员](guides/workspace/invite-and-manage-members.md) * [管理](guides/management/README.md) * [管理应用](guides/management/manage-app.md) {'Header 1': 'Table of contents', 'Header 2': '社区 '} * [寻求支持](community/support.md) * [成为贡献者](community/contribution.md) {'Header 1': 'Table of contents', 'Header 2': '研发 '} * [后端](development/backend/README.md) * [DifySandbox](development/backend/sandbox/README.md) * [贡献指南](development/backend/sandbox/contribution.md) {'Header 1': 'Table of contents', 'Header 2': '阅读更多 '} * [应用案例](learn-more/use-cases/README.md) * [如何训练出专属于“你”的问答机器人?](learn-more/use-cases/train-a-qa-chatbot-that-belongs-to-you.md) * [教你十几分钟不用代码创建 Midjourney 提示词机器人](learn-more/use-cases/create-a-midjoureny-prompt-word-robot-with-zero-code.md) * [构建一个 Notion AI 助手](learn-more/use-cases/build-an-notion-ai-assistant.md) * [如何在几分钟内创建一个带有业务数据的官网 AI 智能客服](learn-more/use-cases/create-an-ai-chatbot-with-business-data-in-minutes.md) {'Header 1': 'Table of contents', 'Header 2': '阅读更多 '} * [使用全套开源工具构建 LLM 应用实战:在 Dify 调用 Baichuan 开源模型能力](learn-more/use-cases/practical-implementation-of-building-llm-applications-using-a-full-set-of-open-source-tools.md) * [手摸手教你把 Dify 接入微信生态](learn-more/use-cases/dify-on-wechat.md) * [使用Dify 和Twilio构建WhatsApp机器人](learn-more/use-cases/dify-on-whatsapp.md) * [扩展阅读](learn-more/extended-reading/README.md) * [什么是 LLMOps?](learn-more/extended-reading/what-is-llmops.md) * [检索增强生成(RAG)](learn-more/extended-reading/retrieval-augment/README.md) {'Header 1': 'Table of contents', 'Header 2': '阅读更多 '} * [混合检索](learn-more/extended-reading/retrieval-augment/hybrid-search.md) * [重排序](learn-more/extended-reading/retrieval-augment/rerank.md) * [召回模式](learn-more/extended-reading/retrieval-augment/retrieval.md) * [提示词编排](learn-more/extended-reading/prompt-engineering/README.md) * [提示词专家模式(已下线)](learn-more/extended-reading/prompt-engineering/prompt-engineering-1/README.md) * [提示词初始模版参考](learn-more/extended-reading/prompt-engineering/prompt-engineering-1/prompt-engineering-template.md) {'Header 1': 'Table of contents', 'Header 2': '阅读更多 '} * [常见问题](learn-more/faq/README.md) * [本地部署相关](learn-more/faq/install-faq.md) * [LLM 配置与使用](learn-more/faq/llms-use-faq.md) {'Header 1': 'Table of contents', 'Header 2': '政策 '} * [开源许可证](policies/open-source.md) * [用户协议](policies/agreement/README.md) * [服务条款](https://dify.ai/terms) * [隐私政策](https://dify.ai/privacy) {'Header 1': '欢迎使用 Dify'} **Dify** 是一款开源的大语言模型(LLM) 应用开发平台。它融合了后端即服务(Backend as Service)和 [LLMOps](learn-more/extended-reading/what-is-llmops.md) 的理念,使开发者可以快速搭建生产级的生成式 AI 应用。即使你是非技术人员,也能参与到 AI 应用的定义和数据运营过程中。 由于 Dify 内置了构建 LLM 应用所需的关键技术栈,包括对数百个模型的支持、直观的 Prompt 编排界面、高质量的 RAG 引擎、稳健的 Agent 框架、灵活的流程编排,并同时提供了一套易用的界面和 API。这为开发者节省了许多重复造轮子的时间,使其可以专注在创新和业务需求上。 {'Header 1': '欢迎使用 Dify', 'Header 3': '为什么使用 Dify?'} 你或许可以把 LangChain 这类的开发库(Library)想象为有着锤子、钉子的工具箱。与之相比,Dify 提供了更接近生产需要的完整方案,Dify 好比是一套脚手架,并且经过了精良的工程设计和软件测试。 重要的是,Dify 是**开源**的,它由一个专业的全职团队和社区共同打造。你可以基于任何模型自部署类似 Assistants API 和 GPTs 的能力,在灵活和安全的基础上,同时保持对数据的完全控制。 > 我们的社区用户对 Dify 的产品评价可以归结为简单、克制、迭代迅速。\ > ——路宇,Dify.AI CEO 希望以上信息和这份指南可以帮助你了解这款产品,我们相信 Dify 是为你而做的(Do It For You)。 {'Header 1': '欢迎使用 Dify', 'Header 3': 'Dify 能做什么?'} {% hint style="info" %} Dify 一词源自 Define + Modify,意指定义并且持续的改进你的 AI 应用,它是为你而做的(Do it for you)。 {% endhint %} * **创业**,快速的将你的 AI 应用创意变成现实,无论成功和失败都需要加速。在真实世界,已经有几十个团队通过 Dify 构建 MVP(最小可用产品)获得投资,或通过 POC(概念验证)赢得了客户的订单。 * **将 LLM 集成至已有业务**,通过引入 LLM 增强现有应用的能力,接入 Dify 的 RESTful API 从而实现 Prompt 与业务代码的解耦,在 Dify 的管理界面是跟踪数据、成本和用量,持续改进应用效果。 * **作为企业级 LLM 基础设施**,一些银行和大型互联网公司正在将 Dify 部署为企业内的 LLM 网关,加速 GenAI 技术在企业内的推广,并实现中心化的监管。 {'Header 1': '欢迎使用 Dify', 'Header 3': 'Dify 能做什么?'} * **探索 LLM 的能力边界**,即使你是一个技术爱好者,通过 Dify 也可以轻松的实践 Prompt 工程和 Agent 技术,在 GPTs 推出以前就已经有超过 60,000 开发者在 Dify 上创建了自己的第一个应用。 {'Header 1': '欢迎使用 Dify', 'Header 3': '下一步行动'} * 阅读[**快速开始**](guides/application\_orchestrate/creating-an-application.md),速览 Dify 的应用构建流程 * 了解如何[**自部署 Dify 到服务器**](getting-started/install-self-hosted/)上,并[**接入开源模型**](guides/model-configuration/) * 了解 Dify 的[**特性规格**](getting-started/readme/features-and-specifications.md)和 **Roadmap** * 在 [**GitHub**](https://github.com/langgenius/dify) 上为我们点亮一颗星,并阅读我们的**贡献指南** {'Header 1': '贡献', 'Header 3': '代码结构'} 参考如下代码文件结构可以帮助你更好地理解代码的组织方式。 ``` [cmd/] ├── server // Enterpoint for starting the server. ├── lib // Enterpoint for Shared libraries. └── test // Common test scripts. [build/] // build scripts for different architectures and platforms. [internal/] // Internal packages. ├── controller // HTTP request handlers. ├── middleware // Middleware for request processing. {'Header 1': '贡献', 'Header 3': '代码结构'} ├── server // Server setup and configuration. ├── service // Provides service for controller. ├── static // Configuration files. │ ├── nodejs_syscall // Whitelist for nodejs syscall. │ └── python_syscall // Whitelist for python syscall. ├── types // Entities ├── core // Core logic for isolation and execution. │ ├── lib // Shared libraries. │ ├── runner // Code execution. {'Header 1': '贡献', 'Header 3': '代码结构'} │ ├── runner // Code execution. │ │ ├── nodejs // Nodejs runner. | | └── python // Python runner. └── tests // Tests for CI/CD. ``` {'Header 1': '贡献', 'Header 3': '原理'} 目前来说,核心逻辑的入口部分有两个,一个是`DifySandbox`的`HTTP`服务入口,另一个是`动态链接库`的入口,在Sandbox尝试运行代码时,它会首先生产一个临时代码文件,在这个文件的最开始,会调用`动态链接库`来初始化运行环境,也就是`Sandbox`,随后才是用户代码的执行,最终执行代码时并不会直接执行用户提交的代码,而是执行这个临时文件,从而确保不会被用户提交的代码破坏系统。 其中,动态链接库中就是使用了`Seccomp`来限制系统调用,其中运行的系统调用位于`static`目录下的`nodejs_syscall`和`python_syscall`文件中,并分别提供了`ARM64`和`AMD64`两种架构的系统调用白名单,一共四份文件,在没有特殊需求的情况下,请不要随意修改这些文件。 {'Header 1': '贡献', 'Header 3': '如何贡献'} 首先,对于`Typo`、`Bug`等问题,欢迎直接提交`PR`,如果是较大的改动或`Feature`级别的提交,请先提交`Issue`,以便我们更好地讨论。 #### 待办事项 这里是一些我们目前正在考虑的待办事项,如果你有兴趣,可以选择其中一个来贡献。 - [ ] 新编程语言的支持: - 我们目前支持`Python`和`Nodejs`,如果你有兴趣,可以尝试添加新的编程语言支持。 - 请注意,每新增一个语言,都要同时考虑`ARM64`和`AMD64`两种架构,并提供`CI`测试,以便我们能确保新增语言的安全性。 - [ ] Nodejs的依赖问题: - 目前我们仅完成了`Python`的依赖支持,可以在`Sandbox`初始化时自动安装`Python`依赖,但对于`Nodejs`,由于其`node_modules`的复杂性,我们目前还没有找到一个很好的解决方案,如果你有兴趣,可以尝试解决这个问题。 - [ ] 图片处理: - 在未来、多模态是一个必然的趋势,因此在`Sandbox`支持处理图片也是一个很有意义的事情。 {'Header 1': '贡献', 'Header 3': '如何贡献'} - 在未来、多模态是一个必然的趋势,因此在`Sandbox`支持处理图片也是一个很有意义的事情。 - 你可以尝试添加对图片处理的支持,比如`Pillow`等库的支持,并支持在`Dify`中传入图片到`Sandbox`中进行处理。 - [ ] 完善的`CI`测试: - 目前我们的`CI`测试还不够完善,只有一些简单的用例。 - [ ] 生成多模态数据: - 尝试使用`Sandbox`生成多模态数据,比如文本和图片的组合数据。# DifySandbox {'Header 1': '贡献', 'Header 3': '介绍'} `DifySandbox`是一个轻量、快速、安全的代码运行环境,支持多种编程语言,包括`Python`、`Nodejs`等,用户在`Dify Workflow`中使用到的如`Code`节点、`Template Transform`节点、`LLM`节点的Jinja2语法、`Tool`节点的`Code Interpreter`等都基于DifySandbox运行,它确保了`Dify`可以运行用户代码的前提下整个系统的安全性。 {'Header 1': '贡献', 'Header 3': '特性'} - **多语言支持**:`DifySandbox`基于`Seccomp`,这是一个系统层级的解决方案,从而确保了可以支持多种编程语言,目前支持了`Python`与`Nodejs`。 - **系统安全**:使用白名单策略,只允许运行特定的系统调用,从而确保不会出现意外的绕过。 - **文件系统隔离**:用户代码将运行在一个独立的隔离的文件系统中。 - **网络隔离**: - **DockerCompose**:独立网络Sandbox网络,并使用代理容器进行网络访问,确保内网系统的安全,同时提供了灵活的代理配置方案。 - **K8s**:直接使用`Exgress`配置网络隔离策略即可。 {'Header 1': '贡献', 'Header 3': '项目地址'} 你可以直接访问[DifySandbox](https://github.com/langgenius/dify-sandbox)获取项目源码,并遵循项目文档进行部署和使用。 {'Header 1': '贡献', 'Header 3': '贡献'} 你可以参考[贡献指南](contribution.md)来参与到`DifySandbox`的开发中。 {'Header 1': '发现', 'Header 2': '模板应用'} 在 **探索 > 发现** 中, 我们提供了一些常用的模板应用。这些应用涵盖翻译、写作、编程和助手。
如果你想使用模板应用,点击模板上的“添加到工作区”按钮。便可以在左侧的工作区中使用该应用。
如果你要修改模板以创建新应用程序,请单击模板上的“自定义”按钮。 {'Header 1': '发现', 'Header 2': '工作区'} 工作区是应用程序的导航。在工作区中点击一个应用,便可直接使用该应用。
工作区中的应用包括:你自己的应用和其他团队添加到工作区的应用。 {'Header 1': '概念同步'} Dify的概念支持从概念导入并设置 **同步** 以便在概念更新后自动同步数据以进行更新. {'Header 1': '概念同步', 'Header 3': '鉴权'} 1. 当创建知识库时, 选择数据源, 点击 **从概念同步--转到连接**, 并根据提示完成授权验证. 2. 你也可以: 点击 **设置--数据源--添加数据源**, 点击概念来源 **连接** 以完成鉴权.

概念链接

{'Header 1': '概念同步', 'Header 3': '导入数据'} 完成鉴权操作后, 前往构建知识库页面, 点击 **概念同步**, 选择要导入的所需授权页面. {'Header 1': '概念同步', 'Header 3': '分段清洗'} 接下来, 选择你的 **分段设置** 和 **索引方法**, **保存并处理**. 等待dify数据处理, 通常此步骤需要在LLM提供程序中使用令牌. 不仅支持导入普通页面类型,还可以汇总保存数据库类型下的页面属性. _**便笺:当前不支持导入图像和文件。表数据将转换为文本.**_ {'Header 1': '概念同步', 'Header 3': '同步概念数据'} 如果您的概念内容已被修改,您可以直接在dify知识文档列表页面上单击[同步]按钮,一键同步数据(请注意,每次单击都会同步当前内容)。此步骤需要使用令牌.

同步概念数据

{'Header 1': '概念同步', 'Header 3': '(社区版) 概念集成配置指南'} 集成分为两种方式: **内部集成** 和 **公共集成** . 它可以按需在dify中配置. 有关这两种集成方法的具体区别,请参阅 [概念正式说明](https://developers.notion.com/docs/authorization). #### 1. **使用内部集成** 创建您的集成页面 [集成设置](https://www.notion.so/my-integrations) . 默认状态下, 所有集成都从内部集成开始; 内部集成将与您选择的工作空间相关联, 因此,您需要是工作区所有者才能创建集成. **具体操作步骤:** 点击 " **New integration** " 按钮, 即默认为内部(不能修改), 选择关联的空间, 输入名称并上传logo, 点击"**提交**" 成功创建集成.
{'Header 1': '概念同步', 'Header 3': '(社区版) 概念集成配置指南'} 一旦创建了集成, 您可以根据需要更新其设置。 **性能** 此选项卡,然后再单击 "**显示**" 按钮后 **密钥** 复制您的密钥.
将其复制并返回到dify源代码 , 在 **.env** 文件与配置相关的环境变量中,环境变量如下: **NOTION\_INTEGRATION\_TYPE** = 内部 或 **NOTION\_INTEGRATION\_TYPE** = 公用 **NOTION\_INTERNAL\_SECRET**= 你的内部密钥 #### 2. **使用公共集成** **您需要将内部集成升级为公共集成** , 导航到集成分发页面,并切换开关以显示集成. 要将开关切换到公共设置,您需要 **在组织信息中填写其他信息**, 包括您的公司名称, 网址, 和重定向目标路径, 然后点击 "提交" 按钮. {'Header 1': '概念同步', 'Header 3': '(社区版) 概念集成配置指南'}
在您公共集成成功后, 在您的[集成设置页面](https://www.notion.so/my-integrations), 您将能够在[密钥]选项卡中访问集成的密钥.
返回到dify源代码,在 **.env** 与文件配置相关的环境变量中, 环境变量如下: **NOTION\_INTEGRATION\_TYPE**=公共 **NOTION\_CLIENT\_SECRET**=你的客户端密钥 **NOTION\_CLIENT\_ID**=你的客户端id 配置完成后,您将能够使用知识部分中的概念数据导入和同步功能. {'Header 1': '维护 Knowledge API'} > 身份验证、调用方法和应用服务API保持一致。区别在于知识API令牌可以对所有知识库进行操作. {'Header 1': '维护 Knowledge API', 'Header 3': '使用 Knowledge API 的好处'} * 同步您的数据系统以分散Knowledge以创建强大的工作流. * 提供知识列表和文档列表API以及详细查询接口, 目的是为了便于生成自己的数据管理页. * 为了简化您的同步进程,支持纯文本和 文件上传 / 更新文档 以及批量新增和修改. * 提高Dify软件和服务的可见性,缩短手动处理文档和同步的时间. {'Header 1': '维护 Knowledge API', 'Header 3': '如何使用'} 请转到知识页面,您可以在左侧导航中切换到API页面。在此页面上,您可以查看dify提供的API文档并管理用于访问Knowledge API的凭据.

Knowledge API Document

{'Header 1': '维护 Knowledge API', 'Header 2': '**创建空的 Knowledge**'} **`POST /datasets`** {% hint style="warning" %} 仅用于创建空数据集 {% endhint %} ``` curl --location --request POST 'https://api.dify.ai/v1/datasets' \ --header 'Authorization: Bearer {api_key}' \ --header 'Content-Type: application/json' \ --data-raw '{"name": "name"}' ``` #### **Knowledge 列表** ``` curl --location --request GET 'https://api.dify.ai/v1/datasets?page=1&limit=20' \ --header 'Authorization: Bearer {api_key}' {'Header 1': '维护 Knowledge API', 'Header 2': '**创建空的 Knowledge**'} ``` #### **文本创建文档** ``` curl --location --request POST '/document/create_by_text>' \\ --header 'Authorization: Bearer {api_key}' \\ --header 'Content-Type: application/json' \\ --data-raw '{ "name": "Dify", "text": "Dify means Do it for you...", "indexing_technique": "high_quality", "process_rule": { "rules": { "pre_processing_rules": [{ "id": "remove_extra_spaces", "enabled": true }, { "id": "remove_urls_emails", "enabled": true }], {'Header 1': '维护 Knowledge API', 'Header 2': '**创建空的 Knowledge**'} "id": "remove_urls_emails", "enabled": true }], "segmentation": { "separator": "###", "max_tokens": 500 } }, "mode": "custom" } }' {'Header 1': '维护 Knowledge API', 'Header 2': '**创建空的 Knowledge**'} ``` #### **文件创建文档** ``` curl --location POST 'https://api.dify.ai/v1/datasets/{dataset_id}/document/create_by_file' \ --header 'Authorization: Bearer {api_key}' \ --form 'data="{ "name": "Dify", "indexing_technique": "high_quality", "process_rule": { "rules": { "pre_processing_rules": [{ "id": "remove_extra_spaces", "enabled": true }, { "id": "remove_urls_emails", "enabled": true }], "segmentation": { "separator": "###", "max_tokens": 500 } }, "mode": "custom" } }"; type=text/plain' \ {'Header 1': '维护 Knowledge API', 'Header 2': '**创建空的 Knowledge**'} } }, "mode": "custom" } }"; type=text/plain' \ --form 'file=@"/path/to/file"' {'Header 1': '维护 Knowledge API', 'Header 2': '**创建空的 Knowledge**'} ``` #### **获取文档嵌入状态** ``` curl --location --request GET 'https://api.dify.ai/v1/datasets/{dataset_id}/documents/{batch}/indexing-status' \ --header 'Authorization: Bearer {api_key}' ``` #### **删除文档** ``` curl --location --request GET 'https://api.dify.ai/v1/datasets/{dataset_id}/documents' \ --header 'Authorization: Bearer {api_key}' {'Header 1': '维护 Knowledge API', 'Header 2': '**创建空的 Knowledge**'} ``` #### **添加新的片段** ``` curl 'https://api.dify.ai/v1/datasets/aac47674-31a8-4f12-aab2-9603964c4789/documents/2034e0c1-1b75-4532-849e-24e72666595b/segment' \ --header 'Authorization: Bearer {api_key}' \ --header 'Content-Type: application/json' \ --data-raw $'"segments":[ {"content":"Dify means Do it for you", "keywords":["Dify","Do"] } ]' --compressed ``` {'Header 1': '维护 Knowledge API', 'Header 2': '**创建空的 Knowledge**', 'Header 3': '报错信息'} - `document_indexing`,表示文档正处于索引过程中 - `provider_not_initialize`, 表示未配置嵌入模型 - `not_found`,文档不存在 - `dataset_name_duplicate` ,重复命名 - `provider_quota_exceeded`,配额已超出最大限制 - `dataset_not_initialized`,未进行初始化 - `unsupported_file_type`,不支持的文件类型 - 现支持的文件类型如下:txt, markdown, md, pdf, html, htm, xlsx, docx, csv - `too_many_files`,表示文件数量太大,暂时只支持单文件上传 - `file_too_large`,表示文件太大,仅支持15M以下的文件# 基于 WebApp 模板 如果开发人员从零开始开发新产品,或者处于产品原型设计阶段,你可以使用Dify快速启动人工智能网站。同时,Dify希望开发者能够完全自由地创造出不同形式的前端应用。为此,我们提供: {'Header 1': '维护 Knowledge API', 'Header 2': '**创建空的 Knowledge**', 'Header 3': '报错信息'} * **SDK** 用于快速访问各种语言的dify API * **WebApp Template** 用于为每种类型的应用程序搭建WebApp开发脚手架 根据麻省理工学院的许可,WebApp模板是开源的。您可以自由地修改和部署它们以实现dify的所有功能,或者作为实现您自己的应用程序的参考代码. 您可以在GitHub上找到这些模板: * [Conversational app](https://github.com/langgenius/webapp-conversation) * [Text generation app](https://github.com/langgenius/webapp-text-generator) 使用WebApp模板的最快捷方式是通过github点击 "**Use this template**" , 这相当于派生一个新的存储库. 然后您需要配置dify应用ID和API密钥, 比如: ```javascript export const APP_ID = '' export const API_KEY = '' ``` {'Header 1': '维护 Knowledge API', 'Header 2': '**创建空的 Knowledge**', 'Header 3': '报错信息'} export const API_KEY = '' ``` More config in `config/index.ts`: ``` export const APP_INFO: AppInfo = { "title": 'Chat APP', "description": '', "copyright": '', "privacy_policy": '', "default_language": 'zh-Hans' } {'Header 1': '维护 Knowledge API', 'Header 2': '**创建空的 Knowledge**', 'Header 3': '报错信息'} export const isShowPrompt = true export const promptTemplate = '' ``` 每个WebApp模板都提供了一个包含部署说明的自述文件。通常,WebApp模板包含一个轻量级的后端服务,以确保开发者的API密钥不会直接暴露给用户. 这些WebApp模板可以帮助你快速构建AI应用的原型,并使用dify的所有功能。如果您在此基础上开发自己的应用程序或新模板,请随时与我们分享. {'Header 1': 'LLM 配置与使用', 'Header 3': '1. 如何在国内环境中使用 OpenAI 代理服务器进行访问?'} Dify 支持 OpenAI 的自定义 API 域名能力,支持任何兼容 OpenAI 的大模型 API 服务器。社区版中,通过 **设置 --> 模型供应商 --> OpenAI --> 编辑 API** 入口处填写目标服务器地址即可。 {'Header 1': 'LLM 配置与使用', 'Header 3': '**2. 如何选择基础模型?**'} * gpt-3.5-turbo gpt-3.5-turbo 是 gpt-3 模型系列的升级版,它比 gpt-3 更强大,可以处理更复杂的任务。 它在理解长文本和跨文档推理方面有重大提高。 gpt-3.5 turbo 可以产生更连贯和更具说服力的文本。它在摘要、翻译和创意写作方面也有很大提高。 擅长:**长文本理解、跨文档推理、摘要、翻译、创意写作。** * gpt-4 gpt-4 是最新最强大的 Transformer 语言模型。它拥有预训练的参数量增至约 200 亿,这使其在所有语言任务上都达到了最高水平,特别是在需要深入理解和生成长、复杂响应的任务上。gpt-4 可以处理人类语言的所有方面,包括理解抽象概念和跨页面的推理。gpt-4 是第一个真正的通用语言理解系统,它可以胜任人工智能领域内的任何自然语言处理任务。擅长: **所有 NLP 任务,语言理解,长文本生成,跨文档推理,抽象概念理解**具体可参考[文档](https://platform.openai.com/docs/models/overview)。 {'Header 1': 'LLM 配置与使用', 'Header 3': '**3. 为什么建议 max\\_tokens 设置小一点?**'} 因为在自然语言处理中,较长的文本输出通常需要更长的计算时间和更多的计算资源。因此,限制输出文本的长度可以在一定程度上降低计算成本和计算时间。例如设置:max\_tokens=500 ,表示最多只考虑输出文本的前 500 个 token,而超过这个长度的部分将会被丢弃。这样做的目的是保证输出文本的长度不会超过 LLM 的接受范围,同时还可以充分利用计算资源,提高模型的运行效率。另一方面,更多的情况是,限制 max\_tokens 能够增加 prompt 的长度,如 gpt-3.5-turbo 的限制为 4097 tokens,如果设置 max\_tokens=4000,那么 prompt 就只剩下 97 tokens 可用,如果超过就会报错。 {'Header 1': 'LLM 配置与使用', 'Header 3': '**4. 数据集长文本如何切分比较合理?**'} 在一些自然语言处理应用中,通常会将文本按照段落或者句子进行切分,以便更好地处理和理解文本中的语义和结构信息。最小切分单位取决于具体的任务和技术实现。例如: * 对于文本分类任务,通常将文本按照句子或者段落进行切分 * 对于机器翻译任务,则需要将整个句子或者段落作为切分单位。 最后,还需要进行实验和评估来确定最合适的 embedding 技术和切分单位。可以在测试集上 / 命中测试比较不同技术和切分单位的性能表现,并选择最优的方案。 {'Header 1': 'LLM 配置与使用', 'Header 3': '5. 我们在获取数据集分段时用的什么距离函数?'} 我们使用[余弦相似度](https://en.wikipedia.org/wiki/Cosine\_similarity)。距离函数的选择通常无关紧要。OpenAI 嵌入被归一化为长度 1,这意味着: 仅使用点积可以稍微更快地计算余弦相似度 余弦相似度和欧几里德距离将导致相同的排名 * > 如果将归一化后的嵌入向量用于计算余弦相似度或欧几里德距离,并基于这些相似性度量对向量进行排序,得到的排序结果将是相同的。也就是说,无论是使用余弦相似度还是欧几里德距离来衡量向量之间的相似性,排序后的结果将是一致的。这是因为在归一化后,向量的长度不再影响它们之间的相对关系,只有方向信息被保留下来。因此,使用归一化的向量进行相似性度量时,不同的度量方法将得到相同的排序结果。在向量归一化后,将所有向量的长度缩放到 1,这意味着它们都处于单位长度上。单位向量只描述了方向而没有大小,因为它们的长度恒为 1。_具体原理可问 ChatGPT._ {'Header 1': 'LLM 配置与使用', 'Header 3': '5. 我们在获取数据集分段时用的什么距离函数?'} 当嵌入向量被归一化为长度 1 后,计算两个向量之间的余弦相似度可以简化为它们的点积。因为归一化后的向量长度都为 1,点积的结果就等同于余弦相似度的结果。由于点积运算相对于其他相似度度量(如欧几里德距离)的计算速度更快,因此使用归一化的向量进行点积计算可以稍微提高计算效率。 {'Header 1': 'LLM 配置与使用', 'Header 3': '6. 如何免费申领智谱·AI、讯飞星火、MiniMax 模型的体验额度?'} 我们联合大模型厂商向中国用户提供一定的 token 体验额度。通过 Dify \*\*设置 --> 模型供应商 --> 显示更多模型供应商。\*\*在智谱·AI、讯飞星火或 MiniMax 图标处点击【免费获取】,如果你在英文界面看不到领取入口,请将产品语言切换成为中文: * \*\*智谱·AI: 免费领取 1000 万 token,\*\*点击【免费领取】,只需输入手机号及验证码,即可到账额度,不限制是否注册过智谱·AI。 * **讯飞星火 (V1.5 模型、V2.0 模型):免费领取 600 万token,V1.5 模型、V2.0 模型各 300 万 token,额度不互通**,需要从 Dify 的入口进入,完成讯飞星火开放平台的注册(仅限未注册过讯飞星火的手机号),返回 Dify 静候 5 分钟,刷新页面即可在 Dify 页面体现可用额度。 * **MiniMax:免费领取 100 万 token**,只需点击【免费领取】即可到账额度,无需手动注册流程,不限制是否注册过 MiniMax 账号。 {'Header 1': 'LLM 配置与使用', 'Header 3': '6. 如何免费申领智谱·AI、讯飞星火、MiniMax 模型的体验额度?'} 体验额度到账后,在应用内 **提示词编排 --> 模型及参数 --> 语言模型** 处选择需使用的模型即可。 {'Header 1': 'LLM 配置与使用', 'Header 3': '7. 填写 OpenAI key,校验失败报错提示:“**校验失败: You exceeded your current quota, please check your plan and billing details。**”是什么原因?'} 说明你的 OpenAI key 的账号没费用了,请前往 OpenAI 充值。 {'Header 1': 'LLM 配置与使用', 'Header 3': '8. 使用 OpenAI 的 key 在应用里对话,有如下报错提示,是什么原因?'} 报错一: ```JSON The server encountered an internal error and was unable to complete your request。Either the server is overloaded or there is an error in the application ``` 报错二: ```JSON {'Header 1': 'LLM 配置与使用', 'Header 3': '8. 使用 OpenAI 的 key 在应用里对话,有如下报错提示,是什么原因?'} ``` 报错二: ```JSON Rate limit reached for default-gpt-3.5-turboin organization org-wDrZCxxxxxxxxxissoZb on requestsper min。 Limit: 3 / min. Please try again in 20s. Contact us through our help center at help.openai.com if you continue to haveissues. Please add a payment method toyour account to increase your rate limit.Visit https://platform.openai.com/account/billingto add a payment method. ``` {'Header 1': 'LLM 配置与使用', 'Header 3': '8. 使用 OpenAI 的 key 在应用里对话,有如下报错提示,是什么原因?'} ``` 请检查是否达到了官方接口调用速率限制。具体请参考 [OpenAI 官方文档说明](https://platform.openai.com/docs/guides/rate-limits)。 {'Header 1': 'LLM 配置与使用', 'Header 3': '9. 用户自部署后,智聊不可使用,报错如下:**Unrecognized request argument supplied:functions**,该怎么解决?'} 首先请检查前后端版本是否是最新版且前后端版本保持一致;其次,该错误有可能是因为您使用了 Azure OpenAI 的 key,但没有成功部署模型,请检查您使用的 Azure OpenAI 里是否部署了模型;其中 gpt-3.5-turbo 模型版本必须是 0613 以上版本。(因为 0613 之前的版本不支持 智聊 所使用的 function call 能力,所以无法使用) {'Header 1': 'LLM 配置与使用', 'Header 3': '10. 设置 OpenAI Key 时,报错如下,是什么原因?'} ```JSON Error communicating with OpenAl: HTTPSConnectionPool(host='api.openai.com', port=443): Max retriesexceeded with url: /v1/chat/completions (Caused byNewConnectionError( ; Failed toestablish a new connection: [Errno -3] Temporary failure in name resolution')) ``` 通常情况下是由于您的环境设置了代理,请检查是否设置代理。 {'Header 1': 'LLM 配置与使用', 'Header 3': '11. 应用里切换模型使用时遇到如下报错,该怎么解决?'} ```JSON Anthropic: Error code: 400 - f'error': f'type': "invalid request error, 'message': 'temperature: range: -1 or 0..1) ``` 由于每个模型的参数取值不同,需要按照当前模型的该参数值范围设置。 {'Header 1': 'LLM 配置与使用', 'Header 3': '12. 遇到如下报错提示,该如何解决?'} ```JSON Query or prefix prompt is too long, you can reduce the preix prompt, or shrink the max token, or switch to a llm with a larger token limit size ``` 在编排页参数设置里,调小“最大 token”的值即可。 {'Header 1': 'LLM 配置与使用', 'Header 3': '13. Dify 里面默认的模型是什么,可否使用开源的模型?'} 默认的模型可以在 **设置 - 模型供应商** 处配置,目前支持 OpenAI / Azure OpenAl / Anthropic 等模型厂商的文本生成型模型,同时支持 Hugging Face/ Replicate / xinference 上托管的开源模型的接入。 {'Header 1': 'LLM 配置与使用', 'Header 3': '14. 在社区版中,数据集开启 **Q\\&A 分段模式**一直显示排队中,是什么原因?'} 请检查您所使用的 Embedding 模型 api-key 是否达到了速率限制。 {'Header 1': 'LLM 配置与使用', 'Header 3': '15. 用户在使用应用时遇到报错“Invalid token”,该怎么解决?'} 如果遇到报错为 “Invalid token”,你可尝试如下两种解决办法: * 浏览器清除缓存(Cookies、Session Storage 和 Local Storage),如果是手机里使用则清除对应 APP 的缓存,重新访问; * 二是重新生成一个 App 网址,重新网址进入即可。 {'Header 1': 'LLM 配置与使用', 'Header 3': '16. 数据集文档上传的大小限制有哪些?'} 目前数据集文档上传单个文档最大是 15MB,总文档数量限制 100 个。如您本地部署版本需要调整修改该限制,请参考[文档](https://docs.dify.ai/v/zh-hans/getting-started/faq/install-faq#11.-ben-di-bu-shu-ban-ru-he-jie-jue-shu-ju-ji-wen-dang-shang-chuan-de-da-xiao-xian-zhi-he-shu-liang)。 {'Header 1': 'LLM 配置与使用', 'Header 3': '17. 为什么选择了 Claude 模型,还是会消耗 OpenAI 的费用?'} 因为 Claude 不支持 Embedding 模型,因此 Embedding 过程以及其他对话生成,下一个问题建议等默认都是用的 OpenAI 的 key,因此还是会消耗 OpenAI 的额度。也可以在**设置-模型供应商**里设置其他默认推理模型和 Embedding 模型。 {'Header 1': 'LLM 配置与使用', 'Header 3': '18. 有什么方式能控制更多地使用上下文数据而不是模型自身生成能力吗?'} 是否使用数据集,会和数据集的描述有关系,尽可能把数据集描述写清楚,具体可参考[此文档编写技巧](https://docs.dify.ai/v/zh-hans/advanced/datasets)。 {'Header 1': 'LLM 配置与使用', 'Header 3': '19. 上传数据集文档是 Excel,该如何更好地分段?'} 首行设置表头,后面每行显示内容,不要有其他多余的表头设置,不要设置复杂格式的表格内容。 如下方表格示例,仅需保留第二行的表头,首行(表格1)为多余表头,需删掉。
{'Header 1': 'LLM 配置与使用', 'Header 3': '20 买了 ChatGPT plus,为什么在 dify 里还不能使用 GPT4?'} OpenAI 的 GPT4 模型 API 和 ChatGPT Plus 是两个产品,分开收费的,模型的 API 有自己的定价,具体参考 [OpenAI 定价文档](https://openai.com/pricing) 。付费申请要先绑卡,绑了卡会有 GPT3.5 的权限,但没有 GPT4 的权限,GPT4 的权限得有一次支付的账单,具体参考 [OpenAI 官方文档](https://platform.openai.com/account/billing/overview)。 {'Header 1': 'LLM 配置与使用', 'Header 3': '21. 如何增加其他的 Embedding Model?'} Dify 支持以下作为 Embedding 模型使用,只需在配置框中选择 `Embeddings` 类型即可。 * Azure * LocalAI * MiniMax * OpenAI * Replicate * XInference {'Header 1': 'LLM 配置与使用', 'Header 3': '22. 如何把自己创建的应用设置成应用模板?'} 该功能为 Dify 官方提供的应用模板供云端版用户参考使用,暂未支持将自己创建的应用设置成应用模板。如您使用云端版,可 **添加到工作区** 或 **自定义** 修改后成为你自己的应用。如您使用社区版,需要为团队内创建更多的应用模板,您可咨询我们商业化团队获得付费的技术支持:`business@dify.ai` {'Header 1': '常见问题'} [本地部署相关常见问题](https://docs.dify.ai/v/zh-hans/getting-started/faq/install-faq) [LLM 配置与使用相关常见问题](https://docs.dify.ai/v/zh-hans/getting-started/faq/llms-use-faq) [API 使用常见问题](broken-reference) {'Header 1': '本地部署相关', 'Header 3': '1. 本地部署初始化后,密码错误如何重置?'} 若使用 docker compose 方式部署,可执行以下命令进行重置 ``` docker exec -it docker-api-1 flask reset-password ``` 输入账户 email 以及两次新密码即可。 {'Header 1': '本地部署相关', 'Header 3': '2. 本地部署日志中报 File not found 错误,如何解决?'} ``` ERROR:root:Unknown Error in completion Traceback (most recent call last): File "/www/wwwroot/dify/dify/api/libs/rsa.py", line 45, in decrypt private_key = storage.load(filepath) File "/www/wwwroot/dify/dify/api/extensions/ext_storage.py", line 65, in load raise FileNotFoundError("File not found") FileNotFoundError: File not found ``` 该错误可能是由于更换了部署方式,或者 `api/storage/privkeys` 删除导致,这个文件是用来加密大模型密钥的,因此丢失后不可逆。可以使用如下命令进行重置加密公私钥: * Docker compose 部署 ``` {'Header 1': '本地部署相关', 'Header 3': '2. 本地部署日志中报 File not found 错误,如何解决?'} * Docker compose 部署 ``` docker exec -it docker-api-1 flask reset-encrypt-key-pair ``` * 源代码启动 进入 api 目录 ``` flask reset-encrypt-key-pair ``` 按照提示进行重置。 {'Header 1': '本地部署相关', 'Header 3': '**3. 安装时后无法登录,登录成功,但后续接口均提示 401?**'} 这可能是由于切换了域名/网址,导致前端和服务端跨域。跨域和身份会涉及到下方的配置: 1. CORS 跨域配置 1. `CONSOLE_CORS_ALLOW_ORIGINS` 控制台 CORS 跨域策略,默认为 `*`,即所有域名均可访问。 2. `WEB_API_CORS_ALLOW_ORIGINS` WebAPP CORS 跨域策略,默认为 `*`,即所有域名均可访问。 {'Header 1': '本地部署相关', 'Header 3': '**4. 启动后页面一直在 loading,查看请求提示 CORS 错误?**'} 这可能是由于切换了域名/网址,导致前端和服务端跨域,请将 `docker-compose.yml` 中所有的以下配置项改为新的域名: `CONSOLE_API_URL:` 控制台 API 的后端 URL。 `CONSOLE_WEB_URL:` 控制台网页的前端 URL。 `SERVICE_API_URL:` 服务 API 的 URL。 `APP_API_URL:` WebApp API 的后端 URL。 `APP_WEB_URL:` WebApp 的 URL。 更多信息,请查看:[环境变量](../../getting-started/install-self-hosted/environments.md) {'Header 1': '本地部署相关', 'Header 3': '5. 部署后如何升级版本?'} 如果你是通过镜像启动,请重新拉取最新镜像完成升级。 如果你是通过源码启动,请拉取最新代码,然后启动,完成升级。 源码部署更新时,需要进入 api 目录下,执行以下命令将数据库结构迁移至最新版本: `flask db upgrade` {'Header 1': '本地部署相关', 'Header 3': '6. 使用 Notion 导入时如何配置环境变量?'} [**Notion 的集成配置地址**](https://www.notion.so/my-integrations)\*\*。\*\*进行私有化部署时,请设置以下配置: 1. **`NOTION_INTEGRATION_TYPE`** :该值应配置为(**public/internal**)。由于 Notion 的 Oauth 重定向地址仅支持 https,如果在本地部署,请使用 Notion 的内部集成。 2. **`NOTION_CLIENT_SECRET`** : Notion OAuth 客户端密钥(用于公共集成类型)。 3. **`NOTION_CLIENT_ID`** : OAuth 客户端ID(用于公共集成类型)。 4. **`NOTION_INTERNAL_SECRET`** : Notion 内部集成密钥,如果 `NOTION_INTEGRATION_TYPE` 的值为 **internal**,则需要配置此变量。 {'Header 1': '本地部署相关', 'Header 3': '7. 本地部署版,如何更改空间的名称?'} 在数据库 `tenants` 表里修改。 {'Header 1': '本地部署相关', 'Header 3': '8. 想修改访问应用的域名,在哪里修改?'} 在 `docker_compose.yaml` 里面找到 APP\_WEB\_URL 配置域名。 {'Header 1': '本地部署相关', 'Header 3': '9. 如果发生数据库迁移,需要备份哪些东西?'} 需要备份数据库、配置的存储以及向量数据库数据,若为 docker compose 方式部署,可直接备份 `dify/docker/volumes` 目录下所有数据内容。 {'Header 1': '本地部署相关', 'Header 3': '10. 为什么 Docker 部署 Dify,本地启动 OpenLLM 用 127.0.0.1 却无法访问本地的端口?'} 127.0.0.1 是容器内部地址, Dify 配置的服务器地址需要宿主机局域网 IP 地址。 {'Header 1': '本地部署相关', 'Header 3': '11. 本地部署版如何解决数据集文档上传的大小限制和数量限制。'} 可参考官网[环境变量说明文档](https://docs.dify.ai/v/zh-hans/getting-started/install-self-hosted/environments)去配置。 {'Header 1': '本地部署相关', 'Header 3': '12. 本地部署版如何通过邮箱邀请成员?'} 本地部署版,邀请成员可通过邮箱邀请,输入邮箱邀请后,页面显示邀请链接,复制邀请链接转发给用户,用户打开链接通过邮箱登录设置密码即可登录到你的空间内。 {'Header 1': '本地部署相关', 'Header 3': "13. 本地部署版本遇到这个错误需要怎么办 Can't load tokenizer for 'gpt2'"} ``` Can't load tokenizer for 'gpt2'. If you were trying to load it from 'https://huggingface.co/models', make sure you don't have a local directory with the same name. Otherwise, make sure 'gpt2' is the correct path to a directory containing all relevant files for a GPT2TokenizerFast tokenizer. ``` 可参考官网[环境变量说明文档](https://docs.dify.ai/v/zh-hans/getting-started/install-self-hosted/environments)去配置。以及相关 [Issue](https://github.com/langgenius/dify/issues/1261)。 {'Header 1': '本地部署相关', 'Header 3': '14. 本地部署 80 端口被占用应该如何解决?'} 本地部署 80 端口被占用,可通过停止占用 80 端口的服务,或者修改 docker-compose.yaml 里面的端口映射,将 80 端口映射到其他端口。通常 Apache 和 Nginx 会占用这个端口,可通过停止这两个服务来解决。 {'Header 1': '本地部署相关', 'Header 3': '15. 文本转语音遇到这个错误怎么办?'} ``` [openai] Error: ffmpeg is not installed ``` 由于 OpenAI TTS 实现了音频流分段,源码部署时需要安装 ffmpeg 才可正常使用,详细步骤: **Windows:** 1. 访问 [FFmpeg 官方网站](https://ffmpeg.org/download.html),下载已经编译好的 Windows shared 库。 2. 下载并解压 FFmpeg 文件夹,它会生成一个类似于 "ffmpeg-20200715-51db0a4-win64-static" 的文件夹。 3. 将解压后的文件夹移动到你想要的位置,例如 C:\Program Files\。 4. 将 FFmpeg 的 bin 目录所在的绝对路径添加到系统环境变量中。 5. 打开命令提示符,输入"ffmpeg -version",如果能看到 FFmpeg 的版本信息,那么说明安装成功。 **Ubuntu:** 1. 打开终端。 {'Header 1': '本地部署相关', 'Header 3': '15. 文本转语音遇到这个错误怎么办?'} **Ubuntu:** 1. 打开终端。 2. 输入以下命令来安装 FFmpeg:`sudo apt-get update`,然后输入`sudo apt-get install ffmpeg`。 3. 输入"ffmpeg -version" 来检查是否安装成功。 **CentOS:** 1. 首先,你需要启用EPEL存储库。在终端中输入:`sudo yum install epel-release` 2. 然后,输入:`sudo rpm -Uvh http://li.nux.ro/download/nux/dextop/el7/x86_64/nux-dextop-release-0-5.el7.nux.noarch.rpm` 3. 更新 yum 包,输入:`sudo yum update` 4. 最后,安装 FFmpeg,输入:`sudo yum install ffmpeg ffmpeg-devel` 5. 输入"ffmpeg -version" 来检查是否安装成功。 **Mac OS X:** 1. 打开终端。 {'Header 1': '本地部署相关', 'Header 3': '15. 文本转语音遇到这个错误怎么办?'} **Mac OS X:** 1. 打开终端。 2. 如果你还没有安装 Homebrew,你可以通过在终端中输入以下命令来安装:`/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"` 3. 使用 Homebrew 安装 FFmpeg,输入:`brew install ffmpeg` 4. 输入 "ffmpeg -version" 来检查是否安装成功。 {'Header 1': '本地部署相关', 'Header 3': '16. 本地部署时,如果遇到 Nginx 配置文件挂载失败,如何解决?'} ``` {'Header 1': '本地部署相关', 'Header 3': '16. 本地部署时,如果遇到 Nginx 配置文件挂载失败,如何解决?'} Error response from daemon: failed to create task for container: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: error during container init: error mounting "/run/desktop/mnt/host/d/Documents/docker/nginx/nginx.conf" to rootfs at "/etc/nginx/nginx.conf": mount /run/desktop/mnt/host/d/Documents/docker/nginx/nginx.conf:/etc/nginx/nginx.conf (via /proc/self/fd/9), flags: 0x5000: not a directory: unknown: Are you trying to mount a {'Header 1': '本地部署相关', 'Header 3': '16. 本地部署时,如果遇到 Nginx 配置文件挂载失败,如何解决?'} a directory: unknown: Are you trying to mount a directory onto a file (or vice-versa)? Check if the specified host path exists and is the expected type {'Header 1': '本地部署相关', 'Header 3': '16. 本地部署时,如果遇到 Nginx 配置文件挂载失败,如何解决?'} ``` 请下载完整的项目,进入 docker 执行 `docker-compose up -d` 即可。 ``` git clone https://github.com/langgenius/dify.git cd dify/docker docker compose up -d ``` {'Header 1': '本地部署相关', 'Header 3': '17. Migrate Vector Database to Qdrant or Milvus'} 如果您想将向量数据库从 Weaviate 迁移到 Qdrant 或 Milvus,您需要迁移向量数据库中的数据。以下是迁移方法: 步骤: 1. 如果您从本地源代码开始,请将 `.env` 文件中的环境变量修改为您要迁移到的向量数据库。 例如:`VECTOR_STORE=qdrant` 2. 如果您从 docker-compose 开始,请将 `docker-compose.yaml` 文件中的环境变量修改为您要迁移到的向量数据库,api 和 worker 都需要修改。 例如: ``` # The type of vector store to use. Supported values are `weaviate`, `qdrant`, `milvus`. VECTOR_STORE: weaviate ``` 3. 执行以下命令 ``` flask vdb-migrate # or docker exec -it docker-api-1 flask vdb-migrate ``` {'Header 1': '本地部署相关', 'Header 3': '18. 为什么需要SSRF\\_PROXY?'} 在社区版的`docker-compose.yaml`中你可能注意到了一些服务配置有`SSRF_PROXY`和`HTTP_PROXY`等环境变量,并且他们都指向了一个`ssrf_proxy`容器,这是因为为了避免SSRF攻击,关于SSRF攻击,你可以查看[这篇](https://portswigger.net/web-security/ssrf)文章。 为了避免不必要的风险,我们给所有可能造成SSRF攻击的服务都配置了一个代理,并强制如Sandbox等服务只能通过代理访问外部网络,从而确保你的数据安全和服务安全,默认的,这个代理不会拦截任何本地的请求,但是你可以通过修改`squid`的配置文件来自定义代理的行为。 #### 如何自定义代理的行为? {'Header 1': '本地部署相关', 'Header 3': '18. 为什么需要SSRF\\_PROXY?'} #### 如何自定义代理的行为? 在`docker/volumes/ssrf_proxy/squid.conf`中,你可以找到`squid`的配置文件,你可以在这里自定义代理的行为,比如你可以添加一些ACL规则来限制代理的访问,或者添加一些`http_access`规则来限制代理的访问,例如,您的本地可以访问`192.168.101.0/24`这个网段,但是其中的`192.168.101.19`这个IP具有敏感数据,你不希望使用你本地部署的dify的用户访问到这个IP,但是想要其他的IP可以访问,你可以在`squid.conf`中添加如下规则: ``` acl restricted_ip dst 192.168.101.19 acl localnet src 192.168.101.0/24 {'Header 1': '本地部署相关', 'Header 3': '18. 为什么需要SSRF\\_PROXY?'} http_access deny restricted_ip http_access allow localnet http_access deny all ``` 当然,这只是一个简单的例子,你可以根据你的需求来自定义代理的行为,如果您的业务更加复杂,比如说需要给代理配置上游代理,或者需要配置缓存等,你可以查看[squid的配置文档](http://www.squid-cache.org/Doc/config/)来了解更多。 {'Header 1': '本地部署相关', 'Header 3': '19. 如何将自己创建的应用设置为模板?'} 目前还不支持将你自己创建的应用设置为模板。现有的模板是由Dify官方为云版本用户参考提供的。如果你正在使用云版本,你可以将应用添加到你的工作空间或者在修改后定制它们以创建你自己的应用。如果你正在使用社区版本并且需要为你的团队创建更多的应用模板,你可以咨询我们的商务团队以获得付费技术支持:[business@dify.ai](mailto:business@dify.ai) {'Header 1': '本地部署相关', 'Header 3': '20.502 Bad Gateway'} 这是因为Nginx将服务转发到了错误的位置导致的,首先确保容器正在运行,然后以Root权限运行以下命令: ``` docker ps -q | xargs -n 1 docker inspect --format '{{ .Name }}: {{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' ``` 在输出内容中找到这两行: ``` /docker-web-1: 172.19.0.5 /docker-api-1: 172.19.0.7 ``` 记住后面的IP地址。然后打开你存放dify源代码的地方,打开`dify/docker/nginx/conf.d`,将`http://api:5001`替换为`http://172.19.0.7:5001`,将`http://web:3000`替换为`http://172.19.0.5:3000`,随后重启Nginx容器或者重载配置。\ 这些IP地址是_**示例性**_ 的,你必须执行命令获取你自己的IP地址,不要直接填入。\ {'Header 1': '本地部署相关', 'Header 3': '20.502 Bad Gateway'} 这些IP地址是_**示例性**_ 的,你必须执行命令获取你自己的IP地址,不要直接填入。\ 你可能在重新启动相关容器时需要再次根据IP进行配置。 {'Header 1': '什么是 LLMOps?'} **LLMOps(Large Language Model Operations)是一个涵盖了大型语言模型(如GPT系列)开发、部署、维护和优化的一整套实践和流程。LLMOps 的目标是确保高效、可扩展和安全地使用这些强大的 AI 模型来构建和运行实际应用程序。它涉及到模型训练、部署、监控、更新、安全性和合规性等方面。** 下表说明了使用 Dify 前后开发 AI 应用的各环节差异: {'Header 1': '什么是 LLMOps?'}
步骤未使用 LLMOps 平台使用 Dify LLMOps 平台时间差异
开发应用前&后端集成和封装 LLM 能力,花费较多时间开发前端应用直接使用 Dify 的后端服务,可基于 WebApp 脚手架开发-80%
Prompt Engineering仅能通过调用 API 或 Playground {'Header 1': '什么是 LLMOps?'} Engineering仅能通过调用 API 或 Playground 进行结合用户输入数据所见即所得完成调试-25%
数据准备与嵌入编写代码实现长文本数据处理、嵌入在平台上传文本或绑定数据源即可-80%
应用日志与分析编写代码记录日志,访问数据库查看平台提供实时日志与分析-70%
数据分析与微调技术人员进行数据管理和创建微调队列非技术人员可协同,可视化模型调整-60%
AI 插件开发与集成编写代码创建、集成 AI 插件平台提供可视化工具创建、集成插件能力-50%
{'Header 1': '什么是 LLMOps?'} 在使用 LLMOps 平台如 Dify 之前,基于 LLM 开发应用的过程可能会非常繁琐和耗时。开发者需要自行处理各个阶段的任务,这可能导致效率低下、难以扩展和安全性问题。以下是使用 LLMOps 平台前的开发过程: 1. 数据准备:手动收集和预处理数据,可能涉及到复杂的数据清洗和标注工作,需要编写较多代码。 2. Prompt Engineering:开发者只能通过调用 API 或 Playground 进行 Prompt 编写和调试,缺乏实时反馈和可视化调试。 3. 嵌入和上下文管理:手动处理长上下文的嵌入和存储,难以优化和扩展,需要不少编程工作,熟悉模型嵌入和向量数据库等技术。 4. 应用监控与维护:手动收集和分析性能数据,可能无法实时发现和处理问题,甚至可能没有日志记录。 5. 模型微调:自行处理微调数据准备和训练过程,可能导致效率低下,需要编写更多代码。 6. 系统和运营:需要技术人员参与或花费成本开发管理后台,增加开发和维护成本,缺乏多人协同和对非技术人员的友好支持。 {'Header 1': '什么是 LLMOps?'} 引入 Dify 这样的 LLMOps 平台后,基于 LLM 开发应用的过程将变得更加高效、可扩展和安全。以下是使用像 Dify 这样的 LLMOps 进行 LLM 应用开发的优势: 1. 数据准备:平台提供数据收集和预处理工具,简化了数据清洗和标注的工作,最小化甚至消除了编码工作。 2. Prompt Engineering:所见即所得的 Prompt 编辑和调试,可根据用户输入的数据进行实时优化和调整。 3. 嵌入和上下文管理:自动处理长上下文的嵌入、存储和管理,提高效率和扩展性,无需编写大量代码。 4. 应用监控与维护:实时监控性能数据,快速发现和处理问题,确保应用程序的稳定运行,提供完整的日志记录。 5. 微调数据准备:提供人工标注数据集的批量导出,在应用运营过程中收集线上反馈数据持续改善模型效果。 6. 系统和运营:易用的界面,非技术人员也可参与,支持多人协同,降低开发和维护成本。与传统开发方式相比,Dify 提供了更加透明和易于监控的应用管理,让团队成员更好地了解应用的运行情况。 {'Header 1': '什么是 LLMOps?'} 另外,Dify 将提供 AI 插件开发和集成的功能,使得开发者可以轻松地为各种应用创建和部署基于 LLM 的插件,进一步提升了开发效率和应用的价值。 --- description: 掌握如何使用 Dify 编排应用和实践 Prompt Engineering,通过内置的两种应用类型,搭建出高价值的 AI 应用。 --- {'Header 1': '设计提示词&编排应用'} Dify 的核心理念是可声明式的定义 AI 应用,包括 Prompt、上下文和插件等等的一切都可以通过一个 YAML 文件描述(这也是为什么称之为 Dify )。最终呈现的是单一 API 或开箱即用的 WebApp。 与此同时,Dify 提供了一个易用的 Prompt 编排界面,开发者能以 Prompt 为基础所见即所得的编排出各种应用特性。听上去是不是很简单? 无论简单或是复杂的 AI 应用,好的 Prompt 可以有效提高模型输出的质量,降低错误率,并满足特定场景的需求。Dify 已提供对话型和文本生成型两种常见的应用形态,这个章节会带你以可视化的方式完成 AI 应用的编排, {'Header 1': '设计提示词&编排应用', 'Header 3': '应用编排的步骤'} 1. 确定应用场景和功能需求 2. 设计并测试 Prompts 与模型参数 3. 编排 Prompts 与用户输入 4. 发布应用 5. 观测并持续迭代 {'Header 1': '设计提示词&编排应用', 'Header 3': '了解应用类型的区别'} Dify 中的文本生成型应用与对话型应用在 Prompt 编排上略有差异,对话型应用需结合“对话生命周期”来满足更复杂的用户情景和上下文管理需求。 Prompt Engineering 已发展为一个潜力巨大,值得持续探索的学科。请继续往下阅读,学习两种类型应用的编排指南。 {'Header 1': '设计提示词&编排应用', 'Header 3': '扩展阅读'} 1. [Learn Prompting](https://learnprompting.org/zh-Hans/) 2. [ChatGPT Prompt Engineering for Developers](https://www.deeplearning.ai/short-courses/chatgpt-prompt-engineering-for-developers/) 3. [Awesome ChatGPT Prompts](https://github.com/f/awesome-chatgpt-prompts) {'Header 1': '提示词初始模版参考'} 为了实现对 LLM 更加定制化的要求来满足开发人员的需要,Dify 在**专家模式**下将内置的完整提示词完全开放,并在编排界面提供了初始模版。以下是四种初始模版参考: {'Header 1': '提示词初始模版参考', 'Header 3': '1. 使用聊天模型构建对话型应用模版'} * **SYSTEM** ``` Use the following context as your learned knowledge, inside XML tags. {{#context#}} {'Header 1': '提示词初始模版参考', 'Header 3': '1. 使用聊天模型构建对话型应用模版'} {{#context#}} When answer to user: - If you don't know, just say that you don't know. - If you don't know when you are not sure, ask for clarification. Avoid mentioning that you obtained the information from the context. And answer according to the language of the user's question. {{pre_prompt}} ``` * **USER** ``` {{Query}} //这里输入查询的变量 ``` * **ASSITANT** ```Python "" ``` #### **模板结构(Prompt Structure):** * 上下文(`Context`) * 预编排提示词(`Pre-prompt`) * 查询变量(`Query`) {'Header 1': '提示词初始模版参考', 'Header 3': '2. 使用聊天模型构建文本生成型应用模版'} * **SYSTEM** ``` Use the following context as your learned knowledge, inside XML tags. {{#context#}} {'Header 1': '提示词初始模版参考', 'Header 3': '2. 使用聊天模型构建文本生成型应用模版'} When answer to user: - If you don't know, just say that you don't know. - If you don't know when you are not sure, ask for clarification. Avoid mentioning that you obtained the information from the context. And answer according to the language of the user's question. {{pre_prompt}} ``` * **USER** ``` {{Query}} //这里输入查询的变量,常用的是输入段落形式的变量 ``` * **ASSITANT** ```Python "" ``` #### **模板结构(Prompt Structure):** * 上下文(`Context`) * 预编排提示词(`Pre-prompt`) * 查询变量(`Query`) {'Header 1': '提示词初始模版参考', 'Header 3': '3. 使用文本补全模型构建对话型应用模版'} ```Python Use the following context as your learned knowledge, inside XML tags. {{#context#}} When answer to user: - If you don't know, just say that you don't know. - If you don't know when you are not sure, ask for clarification. Avoid mentioning that you obtained the information from the context. And answer according to the language of the user's question. {{pre_prompt}} {'Header 1': '提示词初始模版参考', 'Header 3': '3. 使用文本补全模型构建对话型应用模版'} {{pre_prompt}} Here is the chat histories between human and assistant, inside XML tags. {{#histories#}} Human: {{#query#}} Assistant: ``` **模板结构(Prompt Structure):** * 上下文(`Context`) * 预编排提示词(`Pre-prompt`) * 会话历史(`History`) * 查询变量(`Query`) {'Header 1': '提示词初始模版参考', 'Header 3': '4. 使用文本补全模型构建文本生成型应用模版'} ```Python Use the following context as your learned knowledge, inside XML tags. {{#context#}} When answer to user: - If you don't know, just say that you don't know. - If you don't know when you are not sure, ask for clarification. Avoid mentioning that you obtained the information from the context. And answer according to the language of the user's question. {'Header 1': '提示词初始模版参考', 'Header 3': '4. 使用文本补全模型构建文本生成型应用模版'} {{pre_prompt}} {{query}} ``` **模板结构(Prompt Structure):** * 上下文(`Context`) * 预编排提示词(`Pre-prompt`) * 查询变量(`Query`) {% hint style="warning" %} Dify 与部分模型厂商针对系统提示词做了联合深度优化,部分模型下的初始模版可能与以上示例不同。 {% endhint %} {'Header 1': '提示词初始模版参考', 'Header 3': '参数释义'} * 上下文(`Context`):用于将数据集中的相关文本作为提示词上下文插入至完整的提示词中。 * 对话前提示词(`Pre-prompt`):在**简易模式**下编排的对话前提示词将插入至完整提示词中。 * 会话历史(`History`):使用文本生成模型构建聊天应用时,系统会将用户会话历史作为上下文插入至完整提示词中。由于部分模型对角色前缀的响应有所差异,你也可以在对话历史的设置中修改对话历史中的角色前缀名,例如:将 “`Assistant`” 改为 “`AI`”。 * 查询内容(`Query`):查询内容为变量值,用于插入用户在聊天中输入的问题。 {'Header 1': '提示词专家模式(已下线)'} 在 Dify 创建应用的编排默认为**简易模式**,这很适合想要快速创建应用的非技术人员,比如你想创建一个企业知识库 Chatbot 或者文章摘要生成器,利用**简易模式**编排对话前提示词,添加变量,添加上下文等简易步骤即可发布一个完整的应用(可参考👉[conversation-application.md](../../../../guides/application\_orchestrate/conversation-application.md "mention")[Broken link](broken-reference "mention"))。 {'Header 1': '提示词专家模式(已下线)'} 而如果你是一个熟练掌握使用 **OpenAI** 的 **Playground** 的技术人员,正想创建一个学习导师应用,需要在提示词中针对不同的教学模块位置嵌入不同的上下文和变量,就可以选择**专家模式。在此模式下你可以自由地编写完整的提示词,包括修改内置的提示词,调整上下文和聊天历史内容在提示词中的位置,设定必要参数等。如果你对 Chat 和 Complete 两种模型不陌生,现在专家模式**可以快速切换 Chat 和Complete 模型以满足你的需要,并且都适用于对话型应用和文本生成型应用。 在你开始尝试新模式前,你需要知道**专家模式**下的必要元素: * **文本补全模型** ![](../../../../.gitbook/assets/screenshot-20231017-092613.png) {'Header 1': '提示词专家模式(已下线)'} 在选择模型的时候,模型名字的右侧显示 COMPLETE 的即为文本补全模型,该类模型接受名为“提示词”的自由格式文本字符串,模型将生成一个文本补全,试图匹配您给它的任何上下文或模式。例如,如果您给的提示词:“正如笛卡尔所说,我思故”,它将高概率返回“我在”作为补全。 * **聊天模型** 在选择模型的时候,模型名字的右侧显示 CHAT 的即为聊天模型,该类模型将消息列表作为输入,并返回模型生成的消息作为输出。尽管聊天格式旨在简化多轮对话,但它对于没有任何对话的单轮任务同样有用。聊天模型使用的是聊天消息作为输入和输出,包含 SYSTEM / USER / ASSISTANT 三种消息类型: * `SYSTEM` {'Header 1': '提示词专家模式(已下线)'} * `SYSTEM` * 系统消息有助于设置 AI 助手的行为。例如,您可以修改 AI 助手的个性或提供有关它在整个对话过程中应如何表现的具体说明。系统消息是可选的,没有系统消息的模型行为可能类似于使用通用消息,例如“你是一个有帮助的助手”。 * `USER` * 用户消息提供请求或评论以供 AI 助手响应。 * `ASSISTANT` * 助手消息存储以前的助手响应,但也可以由您编写以提供所需行为的示例。 * **停止序列 Stop\_Sequences** 是指特定的单词、短语或字符,用于向 LLM 发出停止生成文本的信号。 * **专家模式提示词中的内容块** * 用户在配置了数据集的 App 中,输入查询内容,App 会将查询内容作为数据集的检索条件,检索的结果在组织之后会作为上下文内容替换 `上下文` 变量,使 LLM 能够参考上下文的内容进行回答。 {'Header 1': '提示词专家模式(已下线)'} * 查询内容仅在对话型应用的文本补全模型中可用,对话中用户输入的内容将替换该变量,以触发每轮新的对话。 * 会话历史仅在对话型应用的文本补全模型中可用。在对话型应用中多次对话时,Dify 会将历史的对话记录根据内置规则进行组装拼接,并替换 `会话历史` 变量。其中 Human 和 Assistant 前缀可点击 `会话历史` 后的`...` 进行修改。 * **初始模版** 在**专家模式**下,正式编排之前,提示词框会给到一个初始模版,我们可以直接修改初始模版来对 LLM有更加定制化的要求。注意:不同类型应用的不同类型模式下有所区别。 {'Header 1': '提示词专家模式(已下线)'} 具体请参考👉[prompt-engineering-template.md](prompt-engineering-template.md "mention") {'Header 1': '提示词专家模式(已下线)', 'Header 2': '两种模式对比'}
对比维度简易模式专家模式
内置提示词可见性封装不可见开放可见
有无自动编排可用不可用
文本补全模型和聊天模型选择有无区别文本补全模型和聊天模型选择后有编排区别
变量插入
内容块校验
SYSTEM / USER / ASSISTANT
三种消息类型编排
上下文参数设置可设置可设置
查看 PROMPT {'Header 1': '提示词专家模式(已下线)', 'Header 2': '两种模式对比'} PROMPT LOG可查看完整提示词日志可查看完整提示词日志
停止序列 Stop_Sequences 参数设置可设置
{'Header 1': '提示词专家模式(已下线)', 'Header 2': '操作说明', 'Header 3': '1. 如何进入专家模式'} 创建应用后,在提示词编排页可以切换至**专家模式**,在此模式下可以编辑完整的应用提示词。

专家模式入口

{% hint style="warning" %} 在**专家模式**下修改提示词并发布应用后,将无法返回至**简易模式**。 {% endhint %} {'Header 1': '提示词专家模式(已下线)', 'Header 2': '操作说明', 'Header 3': '2. 修改插入上下文参数'} 在**简易模式**和**专家模式**下,都可以对插入上下文的参数进行修改,参数包含了 **TopK** 和 **Score 阈值**。 {% hint style="warning" %} 需要注意的是,我们只有先上传了上下文,在**专家模式**下才会呈现包含 \{{#context#\}} 的内置提示词 {% endhint %}

上下文参数设置

**TopK:值范围为整数 1~10** 用于筛选与用户问题相似度最高的文本片段。系统同时会根据选用模型上下文窗口大小动态调整片段数量。系统默认值为 2 。这个值建议可以设置为 2~5 ,因为我们期待的是得到与嵌入的上下文匹配度更高的答案。 **Score 阈值:值范围为两位小数的浮点数 0~1** {'Header 1': '提示词专家模式(已下线)', 'Header 2': '操作说明', 'Header 3': '2. 修改插入上下文参数'} **Score 阈值:值范围为两位小数的浮点数 0~1** 用于设置文本片段筛选的相似度阈值,即:只召回超过设置分数的文本片段(在“命中测试”中我们可以查看到每个片段的命中分数)。系统默认关闭该设置,即不会对召回的文本片段相似值过滤。打开后默认值为 0.7 。这里我们推荐保持默认关闭设置,如果你有更精准的回复要求,也可以设置更高的值(最高值为1,不建议过高) {'Header 1': '提示词专家模式(已下线)', 'Header 2': '操作说明', 'Header 3': '3. 设置**停止序列 Stop\\_Sequences**'} 我们不期望 LLM 生成多余的内容,所以需要设置指特定的单词、短语或字符(默认设置为 `Human:`),告知 LLM 停止生成文本。 比如你在提示词中写了 _Few-Shot_: ``` Human1: 天是什么颜色 Assistant1: 天是蓝色的 Human1: 火是什么颜色 Assistant1: 火是红色的 Human1: 土是什么颜色 Assistant1: ``` 那么在模型参数里的 `停止序列 Stop_Sequences`,输入 `Human1:`,并按下 "Tab" 键。 这样 LLM 在回复的时候只会回复一句: ``` Assistant1: 土是黄色的 ``` 而不会生成多余的对话(即 LLM 生成内容到达下一个 “Human1:” 之前就停止了)。 {'Header 1': '提示词专家模式(已下线)', 'Header 2': '操作说明', 'Header 3': '4. 快捷插入变量和内容块'} 在**专家模式**下,你可以在文本编辑器中输入“`/`”,快捷调出内容块来插入提示词中。内容块分为:`上下文`、`变量`、`会话历史`、`查询内容`。你也可以通过输入“`{`”,快捷插入已创建过的变量列表。\\

快捷键 “/”

{% hint style="warning" %} 除“`变量`”以外的其他内容块不可重复插入。在不同应用和模型下,可插入的内容块会根据不同的提示词模板结构有所区别,`会话历史`、`查询内容` 仅在对话型应用的文本补全模型中可用。 {% endhint %} {'Header 1': '提示词专家模式(已下线)', 'Header 2': '操作说明', 'Header 3': '5. 输入对话前提示词'} 系统的提示词初始模版提供了必要的参数和 LLM 回复要求,详情见👉:[prompt-engineering-template.md](prompt-engineering-template.md "mention")。 而开发人员前期编排的核心是对话前提示词(`Pre-prompt`),需要编辑后插入内置提示词,建议的插入位置如下(以创建 “iPhone 咨询客服”为例): ``` When answer to user: - If you don't know, just say that you don't know. - If you don't know when you are not sure, ask for clarification. Avoid mentioning that you obtained the information from the context. And answer according to the language of the user's question. {'Header 1': '提示词专家模式(已下线)', 'Header 2': '操作说明', 'Header 3': '5. 输入对话前提示词'} 你是 Apple 公司的一位客服助手,你可以为用户提供 iPhone 的咨询服务。 当你回答时需要列出 iPhone 详细参数,你必须一定要把这些信息输出为竖向 MARKDOWN 表格,若列表过多则进行转置。 你被允许长时间思考从而生成更合理的输出。 注意:你目前掌握的只是一部分 iPhone 型号,而不是全部。 ``` 当然,你也可以定制化修改提示词初始模版,比如你希望 LLM 回复的语言都是英文,你可以将上述的内置提示词修改为: ``` When answer to user: - If you don't know, just say that you don't know. - If you don't know when you are not sure, ask for clarification. Avoid mentioning that you obtained the information from the context. And answer according to the language English. ``` {'Header 1': '提示词专家模式(已下线)', 'Header 2': '操作说明', 'Header 3': '6. 调试日志'} 编排调试时不仅可以查看用户的输入和 LLM 的回复。在**专家模式**下,点击发送消息左上角图标,可以看到完整的提示词,方便开发者确认输入变量内容、上下文、聊天记录和查询内容是否符合预期。日志列表的相关说明请查看日志文档 👉 : [logs.md](../../../../guides/biao-zhu/logs.md "mention") #### 6.1 **查看调试日志** 在调试预览界面,用户与 AI 产生对话之后,将鼠标指针移动到任意的用户会话,即可在左上角看到“日志”标志按钮,点击即可查看提示词日志。

调试日志入口

在日志中,我们可以清晰的查看到: * 完整的内置提示词 * 当前会话引用的相关文本片段 * 历史会话记录 {'Header 1': '提示词专家模式(已下线)', 'Header 2': '操作说明', 'Header 3': '6. 调试日志'} * 完整的内置提示词 * 当前会话引用的相关文本片段 * 历史会话记录

调试预览界面查看提示词日志

从日志中,我们可以查看经过系统拼装后最终发送至 LLM 的完整提示词,并根据调试结果持续改进提示词输入。 #### **6.2 追溯调试历史** 在初始的构建应用主界面,左侧导航栏可以看到“日志与标注”,点击进去即可查看完整的日志。 在日志与标注的主界面,点击任意一个会话日志条目,在弹出的右侧对话框中同样鼠标指针移动到会话上即可点开“日志”按钮查看提示词日志。

日志与标注界面查看提示词日志

{'Header 1': '召回模式'} 当用户构建知识库问答类的 AI 应用时,如果在应用内关联了多个数据集,Dify 在检索时支持两种召回模式:N选1召回模式和多路召回模式。

召回模式设置

{'Header 1': '召回模式', 'Header 3': 'N选1召回模式'} 根据用户意图和数据集描述,由 Agent 自主判断选择最匹配的单个数据集来查询相关文本,适合数据集区分度大且数据集数量偏少的应用。N选1召回模式依赖模型的推理能力,模型需要根据用户意图,选择最符合的一个数据集召回。在推理选择数据集时,数据集将作为 Agent 的工具类通过意图推理来进行选择,工具描述即数据集描述。 在用户上传数据集时,系统将自动为数据集创建一个摘要式的描述。为了在该模式下获得最佳的召回效果,你可以在“数据集->设置->数据集描述”中查看到系统默认创建的摘要描述,并检查该内容是否可以清晰的概括数据集的内容。 以下是 N 选 1 召回模式的技术流程图:

N 选 1 召回

因此,在查询数据集过多,或者数据集描述差异较小时,该模式的保证召回的效果会受到影响。该模式更适用于数据集数量较少的应用。 {'Header 1': '召回模式', 'Header 3': 'N选1召回模式'} 提示:OpenAI Function Call 已支持多个工具调用,Dify 将在后续版本中升级该模式为 “N选M召回” 。\\ {'Header 1': '召回模式', 'Header 3': '多路召回模式'} 根据用户意图同时匹配所有数据集,从多路数据集查询相关文本片段,经过重排序步骤,从多路查询结果中选择匹配用户问题的最佳结果,需配置 Rerank 模型 API。在多路召回模式下,检索器会在所有与应用关联的数据集中去检索与用户问题相关的文本内容,并将多路召回的相关文档结果合并,并通过 Rerank 模型对检索召回的文档进行语义重排序。 在多路召回模式下,你需要配置 Rerank 模型,如何配置 Rerank 模型:🔗 以下是多路召回模式的技术流程图:

多路召回

{'Header 1': '召回模式', 'Header 3': '多路召回模式'} 由于多路召回模式不依赖于模型的推理能力或数据集描述,该模式在多数据集检索时能够获得质量更高的召回效果,除此之外加入 Rerank 步骤也能有效改进文档召回效果。因此,当创建的知识库问答应用关联了多个数据集时,我们更推荐将召回模式配置为多路召回。\ \ \ \ \ \\ {'Header 1': '检索增强生成(RAG)', 'Header 3': 'RAG 的概念解释'} 向量检索为核心的 RAG 架构已成为解决大模型获取最新外部知识,同时解决其生成幻觉问题时的主流技术框架,并且已在相当多的应用场景中落地实践。 开发者可以利用该技术低成本地构建一个 AI 智能客服、企业智能知识库、AI 搜索引擎等,通过自然语言输入与各类知识组织形式进行对话。以一个有代表性的 RAG 应用为例: 在下图中,当用户提问时 “美国总统是谁?” 时,系统并不是将问题直接交给大模型来回答,而是先将用户问题在知识库中(如下图中的维基百科)进行向量搜索,通过语义相似度匹配的方式查询到相关的内容(拜登是美国现任第46届总统…),然后再将用户问题和搜索到的相关知识提供给大模型,使得大模型获得足够完备的知识来回答问题,以此获得更可靠的问答结果。

RAG 基本架构

**为什么需要这样做呢?** {'Header 1': '检索增强生成(RAG)', 'Header 3': 'RAG 的概念解释'} **为什么需要这样做呢?** 我们可以把大模型比做是一个超级专家,他熟悉人类各个领域的知识,但他也有自己的局限性,比如他不知道你个人的一些状况,因为这些信息是你私人的,不会在互联网上公开,所以他没有提前学习的机会。 当你想雇佣这个超级专家来充当你的家庭财务顾问时,需要允许他在接受你的提问时先翻看一下你的投资理财记录、家庭消费支出等数据。这样他才能根据你个人的实际情况提供专业的建议。 **这就是 RAG 系统所做的事情:帮助大模型临时性地获得他所不具备的外部知识,允许它在回答问题之前先找答案。** 根据上面这个例子,我们很容易发现 RAG 系统中最核心是外部知识的检索环节。专家能不能向你提供专业的家庭财务建议,取决于能不能精确找到他需要的信息,如果他找到的不是投资理财记录,而是家庭减肥计划,那再厉害的专家都会无能为力。 {'Header 1': '重排序', 'Header 3': '为什么需要重排序?'} 混合检索能够结合不同检索技术的优势获得更好的召回结果,但在不同检索模式下的查询结果需要进行合并和归一化(将数据转换为统一的标准范围或分布,以便更好地进行比较、分析和处理),然后再一起提供给大模型。这时候我们需要引入一个评分系统:重排序模型(Rerank Model)。 **重排序模型会计算候选文档列表与用户问题的语义匹配度,根据语义匹配度重新进行排序,从而改进语义排序的结果**。其原理是计算用户问题与给定的每个候选文档之间的相关性分数,并返回按相关性从高到低排序的文档列表。常见的 Rerank 模型如:Cohere rerank、bge-reranker 等。

混合检索+重排序

{'Header 1': '重排序', 'Header 3': '为什么需要重排序?'} 在大多数情况下,在重排序之前会有一次前置检索,这是由于计算查询与数百万个文档之间的相关性得分将会非常低效。所以,**重排序一般都放在搜索流程的最后阶段,非常适合用于合并和排序来自不同检索系统的结果**。 不过,重排序并不是只适用于不同检索系统的结果合并,即使是在单一检索模式下,引入重排序步骤也能有效帮助改进文档的召回效果,比如我们可以在关键词检索之后加入语义重排序。 在具体实践过程中,除了将多路查询结果进行归一化之外,在将相关的文本分段交给大模型之前,我们一般会限制传递给大模型的分段个数(即 TopK,可以在重排序模型参数中设置),这样做的原因是大模型的输入窗口存在大小限制(一般为 4K、8K、16K、128K 的 Token 数量),你需要根据选用的模型输入窗口的大小限制,选择合适的分段策略和 TopK 值。 需要注意的是,即使模型上下文窗口很足够大,过多的召回分段会可能会引入相关度较低的内容,导致回答的质量降低,所以重排序的 TopK 参数并不是越大越好。 {'Header 1': '重排序', 'Header 3': '为什么需要重排序?'} 重排序并不是搜索技术的替代品,而是一种用于增强现有检索系统的辅助工具。**它最大的优势是不仅提供了一种简单且低复杂度的方法来改善搜索结果,允许用户将语义相关性纳入现有的搜索系统中,而且无需进行重大的基础设施修改。** 以 Cohere Rerank 为例,你只需要注册账户和申请 API ,接入只需要两行代码。另外,他们也提供了多语言模型,也就是说你可以将不同语言的文本查询结果进行一次性排序。\\ {'Header 1': '重排序', 'Header 3': '如何配置 Rerank 模型?'} Dify 目前已支持 Cohere Rerank 模型,通过进入“模型供应商-> Cohere”页面填入 Rerank 模型的 API 秘钥:

在模型供应商内配置 Cohere Rerank 模型

{'Header 1': '重排序', 'Header 3': '如何获取 Cohere Rerank 模型?'} 登录:[https://cohere.com/rerank](https://cohere.com/rerank),在页内注册并申请 Rerank 模型的使用资格,获取 API 秘钥。 {'Header 1': '重排序', 'Header 3': '数据集检索模式中设置 Rerank 模型'} 通过进入“数据集->创建数据集->检索设置”页面并在添加 Rerank 设置。除了在创建数据集可以设置 Rerank ,你也可以在已创建的数据集设置内更改 Rerank 配置,在应用编排的数据集召回模式设置中更改 Rerank 配置。

数据集检索模式中设置 Rerank 模型

\*\*TopK:\*\*用于设置 Rerank 后返回相关文档的数量。 \*\*Score 阈值:\*\*用于设置 Rerank 后返回相关文档的最低分值。设置 Rerank 模型后,TopK 和 Score 阈值设置仅在 Rerank 步骤生效。\\ {'Header 1': '重排序', 'Header 3': '数据集多路召回模式中设置 Rerank 模型'} 通过进入“提示词编排->上下文->设置”页面中设置为多路召回模式时需开启 Rerank 模型。 关于多路召回模式的说明:🔗

数据集多路召回模式中设置 Rerank 模型

{'Header 1': '混合检索', 'Header 3': '为什么需要混合检索?'} RAG 检索环节中的主流方法是向量检索,即语义相关度匹配的方式。技术原理是通过将外部知识库的文档先拆分为语义完整的段落或句子,并将其转换(Embedding)为计算机能够理解的一串数字表达(多维向量),同时对用户问题进行同样的转换操作。 计算机能够发现用户问题与句子之间细微的语义相关性,比如 “猫追逐老鼠” 和 “小猫捕猎老鼠” 的语义相关度会高于 “猫追逐老鼠” 和 “我喜欢吃火腿” 之间的相关度。在将相关度最高的文本内容查找到后,RAG 系统会将其作为用户问题的上下文一起提供给大模型,帮助大模型回答问题。 除了能够实现复杂语义的文本查找,向量检索还有其他的优势: * 相近语义理解(如老鼠/捕鼠器/奶酪,谷歌/必应/搜索引擎) * 多语言理解(跨语言理解,如输入中文匹配英文) * 多模态理解(支持文本、图像、音视频等的相似匹配) * 容错性(处理拼写错误、模糊的描述) 虽然向量检索在以上情景中具有明显优势,但有某些情况效果不佳。比如: * 搜索一个人或物体的名字(例如,伊隆·马斯克,iPhone 15) * 搜索缩写词或短语(例如,RAG,RLHF) {'Header 1': '混合检索', 'Header 3': '为什么需要混合检索?'} * 搜索缩写词或短语(例如,RAG,RLHF) * 搜索 ID(例如, `gpt-3.5-turbo` , `titan-xlarge-v1.01` ) 而上面这些的缺点恰恰都是传统关键词搜索的优势所在,传统关键词搜索擅长: * 精确匹配(如产品名称、姓名、产品编号) * 少量字符的匹配(通过少量字符进行向量检索时效果非常不好,但很多用户恰恰习惯只输入几个关键词) * 倾向低频词汇的匹配(低频词汇往往承载了语言中的重要意义,比如“你想跟我去喝咖啡吗?”这句话中的分词,“喝”“咖啡”会比“你”“想”“吗”在句子中承载更重要的含义) 对于大多数文本搜索的情景,首要的是确保潜在最相关结果能够出现在候选结果中。向量检索和关键词检索在检索领域各有其优势。混合搜索正是结合了这两种搜索技术的优点,同时弥补了两方的缺点。 在混合检索中,你需要在数据库中提前建立向量索引和关键词索引,在用户问题输入时,分别通过两种检索器在文档中检索出最相关的文本。 {'Header 1': '混合检索', 'Header 3': '为什么需要混合检索?'}

混合检索

“混合检索”实际上并没有明确的定义,本文以向量检索和关键词检索的组合为示例。如果我们使用其他搜索算法的组合,也可以被称为“混合检索”。比如,我们可以将用于检索实体关系的知识图谱技术与向量检索技术结合。 不同的检索系统各自擅长寻找文本(段落、语句、词汇)之间不同的细微联系,这包括了精确关系、语义关系、主题关系、结构关系、实体关系、时间关系、事件关系等。可以说没有任何一种检索模式能够适用全部的情景。**混合检索通过多个检索系统的组合,实现了多个检索技术之间的互补。**\ {'Header 1': '混合检索', 'Header 3': '**向量检索**'} 定义:通过生成查询嵌入并查询与其向量表示最相似的文本分段。

向量检索设置

**TopK:**用于筛选与用户问题相似度最高的文本片段。系统同时会根据选用模型上下文窗口大小动态调整片段数量。系统默认值为 3 。 **Score 阈值:**用于设置文本片段筛选的相似度阈值,即:只召回超过设置分数的文本片段。系统默认关闭该设置,即不会对召回的文本片段相似值过滤。打开后默认值为 0.5 。 **Rerank 模型:**你可以在“模型供应商”页面配置 Rerank 模型的 API 秘钥之后,在检索设置中打开“Rerank 模型”,系统会在语义检索后对已召回的文档结果再一次进行语义重排序,优化排序结果。设置 Rerank 模型后,TopK 和 Score 阈值设置仅在 Rerank 步骤生效。\ {'Header 1': '混合检索', 'Header 3': '**全文检索**'} 定义:索引文档中的所有词汇,从而允许用户查询任意词汇,并返回包含这些词汇的文本片段。

全文检索设置

**TopK:**用于筛选与用户问题相似度最高的文本片段。系统同时会根据选用模型上下文窗口大小动态调整片段数量。系统默认值为 3 。 **Rerank 模型:**你可以在“模型供应商”页面配置 Rerank 模型的 API 秘钥之后,在检索设置中打开“Rerank 模型”,系统会在全文检索后对已召回的文档结果再一次进行语义重排序,优化排序结果。设置 Rerank 模型后,TopK 和 Score 阈值设置仅在 Rerank 步骤生效。\ {'Header 1': '混合检索', 'Header 3': '**混合检索**'} 同时执行全文检索和向量检索,并应用重排序步骤,从两类查询结果中选择匹配用户问题的最佳结果,需配置 Rerank 模型 API。

混合检索设置

**TopK:**用于筛选与用户问题相似度最高的文本片段。系统同时会根据选用模型上下文窗口大小动态调整片段数量。系统默认值为 3 。 **Rerank 模型:**你可以在“模型供应商”页面配置 Rerank 模型的 API 秘钥之后,在检索设置中打开“Rerank 模型”,系统会在混合检索后对已召回的文档结果再一次进行语义重排序,优化排序结果。设置 Rerank 模型后,TopK 和 Score 阈值设置仅在 Rerank 步骤生效。\ {'Header 1': '混合检索', 'Header 3': '创建数据集时设置检索模式'} 通过进入“数据集->创建数据集”页面并在检索设置中设置不同的检索模式:

创建数据集时设置检索模式

{'Header 1': '混合检索', 'Header 3': '数据集设置中修改检索模式'} 通过进入“数据集->选择数据集->设置”页面中可以对已创建的数据集修改不同的检索模式。

数据集设置中修改检索模式

{'Header 1': '混合检索', 'Header 3': '提示词编排中修改检索模式'} 通过进入“提示词编排->上下文->选择数据集->设置”页面中可以在创建应用时修改不同的检索模式。

提示词编排中修改检索模式

{'Header 1': '构建一个 Notion AI 助手'} _作者:阿乔. Dify 用户_ {'Header 1': '构建一个 Notion AI 助手', 'Header 3': '概述'} Notion 是一个强大的知识管理工具。它的灵活性和可扩展性使其成为一个出色的个人知识库和共享工作空间。许多人使用它来存储他们的知识,并与他人协作,促进思想交流和新知识的创造。 然而,这些知识仍然是静态的,因为用户必须搜索他们需要的信息并阅读其中的内容才能找到他们寻求的答案。这个过程既不特别高效,也不智能。 你是否曾经梦想过拥有一个基于你的 Notion 库的 AI 助手?这个助手不仅可以帮助你审查知识库,还可以像一位经验丰富的管家一样参与交流,甚至回答其他人的问题,就好像你是自己的个人 Notion 库的主人一样。 {'Header 1': '构建一个 Notion AI 助手', 'Header 3': '如何实现自己的 Notion AI 助手?'} 现在,你可以通过 Dify 来实现这个梦想。Dify 是一个开源的 LLMOps(大型语言模型运维)平台。 ChatGPT 和 Claude 等大型语言模型已经利用其强大的能力改变了世界。它们的强大学习能力主要归功于丰富的训练数据。幸运的是,它们已经发展到足够智能的程度,可以从你提供的内容中进行学习,从而使从个人 Notion 库中生成创意成为现实。 在没有 Dify 的情况下,你可能需要熟悉 langchain,这是一个简化组装这些要素过程的抽象概念。 {'Header 1': '构建一个 Notion AI 助手', 'Header 3': '如何使用Dify创建自己的AI助手?'} 训练Notion AI助手的过程非常简单。您只需要按照如下步骤操作: 1.登录 Dify。 2.创建一个数据集。 3.将 Notion 和数据集连接起来。 4.开始训练。 5.创建自己的AI应用程序。 #### 1. 登录 Dify[](https://wsyfin.com/notion-dify#1-login-to-dify) 点击这里登录到 Dify。你可以使用你的 GitHub 或 Google 账户方便地登录。 > 如果你使用 GitHub 账户登录,不妨给这个[项目](https://github.com/langgenius/dify)点个星星吧?这真的对我们有很大的支持! ![login-1](https://pan.wsyfin.com/f/ERGcp/login-1.png) {'Header 1': '构建一个 Notion AI 助手', 'Header 3': '如何使用Dify创建自己的AI助手?'} #### 2.创建新的数据集 点击顶部侧边栏的 "Knowledge" 按钮,然后点击 "Create Knowledge" 按钮。 ![login-2](https://pan.wsyfin.com/f/G6ziA/login-2.png) #### 3. 与 Notion 和您的数据集进行连接 选择 "Sync from Notion",然后点击 "Connect" 按钮。 ![connect-with-notion-1](https://pan.wsyfin.com/f/J6WsK/connect-with-notion-1.png) {'Header 1': '构建一个 Notion AI 助手', 'Header 3': '如何使用Dify创建自己的AI助手?'} 然后,您将被重定向到 Notion 登录页面。使用您的 Notion 帐户登录。使用您的 Notion 帐户登录。 ![connect-with-notion-2](https://pan.wsyfin.com/f/KrEi4/connect-with-notion-2.png) 检查 Dify 所需的权限,然后单击“选择页面”按钮。 ![connect-with-notion-3](https://pan.wsyfin.com/f/L91iQ/connect-with-notion-3.png) 选择你要和 Dify 同步的页面,然后点击“允许访问”按钮。 ![connect-with-notion-4](https://pan.wsyfin.com/f/M8Xtz/connect-with-notion-4.png) #### 4. 开始训练 {'Header 1': '构建一个 Notion AI 助手', 'Header 3': '如何使用Dify创建自己的AI助手?'} 指定需要让 AI 学习的页面,使其能够理解 Notion 中这个部分的内容。然后点击 "下一步" 按钮。 ![train-1](https://pan.wsyfin.com/f/Nkjuj/train-1.png) 我们建议选择 "自动" 和 "高质量" 的选项来训练你的 AI 助手。然后点击 "保存并处理" 按钮。 ![train-2](https://pan.wsyfin.com/f/OYoCv/train-2.png) 等待几秒钟,embedding 处理进程完成。 ![train-3](https://pan.wsyfin.com/f/PN9F3/train-3.png) #### 5. 创建你自己的 AI 应用程序[](https://wsyfin.com/notion-dify#5-create-your-own-ai-application) {'Header 1': '构建一个 Notion AI 助手', 'Header 3': '如何使用Dify创建自己的AI助手?'} 你需要创建一个AI应用,然后连接刚刚创建的数据集。返回到仪表板,然后点击“创建新应用”按钮。建议直接使用聊天应用。 ![create-app-1](https://pan.wsyfin.com/f/QWRHo/create-app-1.png) 选择“Prompt Eng.”并在“context”中添加你的 Notion 数据集。 ![create-app-2](https://pan.wsyfin.com/f/R6DT5/create-app-2.png) 我建议在你的 AI 应用程序中添加一个「预设提示」。就像咒语对于哈利·波特来说是必不可少的一样,某些工具或功能可以极大地增强 AI 应用程序的能力。 例如,如果你的 Notion 笔记主要关注软件开发中的问题解决,可以在其中一个提示中写道: > 我希望你能在我的 Notion 工作区中扮演一个 IT 专家的角色,利用你对计算机科学、网络基础设施、Notion 笔记和 IT 安全的知识来解决问题。 {'Header 1': '构建一个 Notion AI 助手', 'Header 3': '如何使用Dify创建自己的AI助手?'}
建议初始时启用 AI 主动提供用户一个起始句子,给出可以询问的线索。此外,激活「语音转文字」功能可以让用户通过语音与你的 AI 助手进行互动。
现在您可以在“概览”中单击公共 URL 聊天与您自己的 AI 助手!
{'Header 1': '构建一个 Notion AI 助手', 'Header 3': '通过API集成到您的项目中'} 通过 Dify 打造的每个 AI 应用程序都可以通过其 API 进行访问。这种方法允许开发人员直接利用前端应用程序中强大的大型语言模型(LLM)的特性,提供真正的“后端即服务”(BaaS)体验。 通过无缝的 API 集成,您可以方便地调用您的 Notion AI 应用程序,无需复杂的配置。 在概览页面上点击「API 参考」按钮。您可以将其作为您应用程序的 API 文档参考。 ![using-api-1](https://pan.wsyfin.com/f/wp0Cy/using-api-1.png) #### 1. 生成 API 密钥 为了安全起见,建议生成 API 密钥以访问您的 AI 应用。 ![using-api-2](https://pan.wsyfin.com/f/xk2Fx/using-api-2.png) {'Header 1': '构建一个 Notion AI 助手', 'Header 3': '通过API集成到您的项目中'} #### 2.检索会话ID 与 AI 应用程序聊天后,您可以从“Logs & Ann.”页面检索会话 ID。 ![using-api-3](https://pan.wsyfin.com/f/yPXHL/using-api-3.png) #### 3. 调用API 您可以在API文档上运行示例请求代码来调用终端中的AI应用程序。 记住替换代码中的SECRET KEY和conversation\_id。 您可以在第一次输入空的conversation\_id,在收到包含conversation\_id的响应后将其替换。 ``` curl --location --request POST 'https://api.dify.ai/v1/chat-messages' \ {'Header 1': '构建一个 Notion AI 助手', 'Header 3': '通过API集成到您的项目中'} --header 'Authorization: Bearer ENTER-YOUR-SECRET-KEY' \ --header 'Content-Type: application/json' \ --data-raw '{ "inputs": {}, "query": "eh", "response_mode": "streaming", "conversation_id": "", "user": "abc-123" }' ``` 在终端中发送请求,您将获得成功的响应。 ![using-api-4](https://pan.wsyfin.com/f/zpnI4/using-api-4.png) 如果您想继续此聊天,请将请求代码的`conversation_id`替换为您从响应中获得的`conversation_id`。 你可以在`"Logs & Ann "`页面查看所有的对话记录。 ![using-api-5](https://pan.wsyfin.com/f/ADQSE/using-api-5.png) {'Header 1': '构建一个 Notion AI 助手', 'Header 3': '周期性地与 Notion 同步'} 如果你的 Notion 页面更新了,你可以定期与 Dify 同步,让你的人工智能助手保持最新状态。你的人工智能助手将从新内容中学习并回答新问题。 ![create-app-5](https://pan.wsyfin.com/f/XDBfO/create-app-5.png) {'Header 1': '构建一个 Notion AI 助手', 'Header 3': '总结'} 在本教程中,我们不仅学会了如何将您的 Notion 数据导入到 Dify 中,还学会了如何使用 API 将其与您的项目集成。 Dify 是一个用户友好的 LLMOps 平台,旨在赋予更多人创建可持续的 AI 原生应用程序的能力。通过为各种应用类型设计的可视化编排,Dify 提供了可供使用的应用程序,可以帮助您利用数据打造独特的 AI 助手。如果您有任何疑问,请随时与我们联系。 {'Header 1': '使用全套开源工具构建 LLM 应用实战:在 Dify 调用 Baichuan 开源模型能力'} > 作者:Rico。Dify.AI 资深前端工程师,LLM 技术探索者。 {'Header 1': '使用全套开源工具构建 LLM 应用实战:在 Dify 调用 Baichuan 开源模型能力', 'Header 2': '背景'} 在当下开源大语言模型火热的背景下,有很大一部分开发者希望本地部署开源 LLM,用于研究 LLM 或者是基于开源 LLM 构建自己的 LLM 应用。笔者也正在尝试通过开源社区的一系列相关优秀项目,通过本地化部署服务来构建自己的 LLM 应用。那么本地部署一个开源 LLM 来构建一个聊天应用需要哪些准备呢? 1. **本地环境的准备:**因为我们需要在本地部署一个开源的大模型,所以你需要准备一个相当硬核的本地环境。硬件上需要一台拥有高性能、大显存的 NVDIA 显卡,大容量高速内存以及大容量固态硬盘,软件上则需要安装显卡驱动、CUDA、Python 环境。笔者这次选择跑 Baichuan-13B-Chat 模型为例,基本配置是 CPU i9-13900K、GTX3090 24GB 双卡、64GB 内存和 2TB 固态硬盘。 {'Header 1': '使用全套开源工具构建 LLM 应用实战:在 Dify 调用 Baichuan 开源模型能力', 'Header 2': '背景'} 2. **一个大型语言模型(LLM):**这是我们构建 LLM 应用的基础。不同的 LLM 根据预训练的数据和目标任务的不同,其模型结构和学到的知识也不相同。基于不同模型构建出来的 AI 应用表现也会不一样。你可以通过火热的 AI 社区 [Hugging Face](https://huggingface.co/) 上找自己感兴趣的开源 LLMs 来进行尝试和能力对比 。 3. **一个本地部署 LLM 的推理服务:**推理服务可以将预训练好的 LLM 模型加载到本地服务器,并提供模型预测接口,这样就可以本地化使用 LLM 模型进行各种 NLP 任务,而不需要依赖云服务。你可以使用一些优秀的 GitHub 开源项目,这些项目对热门的开源 LLM 都做了推理服务的一键部署。知名度比较高的有 [LocalAI](https://github.com/go-skynet/LocalAI)、[openLLM](https://github.com/bentoml/OpenLLM) 等。 {'Header 1': '使用全套开源工具构建 LLM 应用实战:在 Dify 调用 Baichuan 开源模型能力', 'Header 2': '背景'} 4. **一个简单易用的“ LLM 操作系统 ” Dify.AI:**如果要基于 LLM 的能力构建一个聊天应用,你可能需要学习研究全套的 LLM 技术栈,比如:不同模型的 API 调用、向量数据库选型、Embedding 技术研究等等。如果你使用开源项目 [Dify.AI](https://github.com/langgenius/dify),则可以省掉这些研究学习工作,**帮助你通过可视化的界面即可快速创建基于不同 LLM 能力的** **AI** **应用。** Dify 最近的版本新增了对开源 LLMs 的支持,对托管在 HuggingFace 和 Replicate 上所有的模型都能快速调用和切换使用,同时支持本地部署方式能够基于 [OpenLLM](https://github.com/bentoml/OpenLLM) 和 [Xorbits inference](https://github.com/xorbitsai/inference) 推理服务来实现 AI 应用的构建。 {'Header 1': '使用全套开源工具构建 LLM 应用实战:在 Dify 调用 Baichuan 开源模型能力', 'Header 2': '背景'} 笔者将尝试使用**开源的 LLMOps 平台 Dify.AI + 开源的推理服务** **Xinference** **+** **开源模型 Baichuan-13B-Chat** 为例,手把手实操教你在 windows 环境下,使用全套开源工具产品来构建一个 LLM 聊天应用。 {'Header 1': '使用全套开源工具构建 LLM 应用实战:在 Dify 调用 Baichuan 开源模型能力', 'Header 2': '环境准备'} Conda 和 Python 是基础要求,本文将从零开始介绍环境配置。 #### 配置 python 环境 一般情况下建议使用 Conda 进行 python 版本管理。先根据 Conda [官网文档](https://docs.conda.io/projects/conda/en/stable/user-guide/install/index.html)安装 Conda。然后用 Conda 初始化 Python 3.11 环境: ``` conda create --name python-3-11 python=3.11 conda activate python-3-11 ``` #### 安装 CUDA 推荐直接从[官网](https://developer.nvidia.com/cuda-downloads?target\_os=Windows\&target\_arch=x86\_64\&target\_version=11\&target\_type=exe\_local)安装。 Windows 11 选择下图版本。 {'Header 1': '使用全套开源工具构建 LLM 应用实战:在 Dify 调用 Baichuan 开源模型能力', 'Header 2': '环境准备'}
根据引导安装完,打开 `NVDIA 控制面板 -> 系统信息` 看到完成了安装。
**WSL2 准备** 由于 Dify 的 docker 部署推荐使用 WSL2 环境。所以现在先安装 WSL2 。参考[微软官方指引](https://learn.microsoft.com/en-us/windows/wsl/install)。 **第一步,管理员身份运行** **CMD** **:** 1. Win + R 2. Input CMD 3. Ctrl + Shift + Enter {'Header 1': '使用全套开源工具构建 LLM 应用实战:在 Dify 调用 Baichuan 开源模型能力', 'Header 2': '环境准备'} 1. Win + R 2. Input CMD 3. Ctrl + Shift + Enter
**第二步,在** **CMD** **中用指令安装** ```PowerShell wsl --install ``` 结果看到了支持的各种系统版本: ```PowerShell 适用于 Linux 的 Windows 子系统已安装。 {'Header 1': '使用全套开源工具构建 LLM 应用实战:在 Dify 调用 Baichuan 开源模型能力', 'Header 2': '环境准备'} 以下是可安装的有效分发的列表。 请使用“wsl --install -d <分发>”安装。 {'Header 1': '使用全套开源工具构建 LLM 应用实战:在 Dify 调用 Baichuan 开源模型能力', 'Header 2': '环境准备'} NAME FRIENDLY NAME Ubuntu Ubuntu Debian Debian GNU/Linux kali-linux Kali Linux Rolling Ubuntu-18.04 Ubuntu 18.04 LTS Ubuntu-20.04 Ubuntu 20.04 LTS Ubuntu-22.04 Ubuntu 22.04 LTS OracleLinux_7_9 Oracle Linux 7.9 OracleLinux_8_7 Oracle Linux 8.7 {'Header 1': '使用全套开源工具构建 LLM 应用实战:在 Dify 调用 Baichuan 开源模型能力', 'Header 2': '环境准备'} OracleLinux_9_1 Oracle Linux 9.1 openSUSE-Leap-15.5 openSUSE Leap 15.5 SUSE-Linux-Enterprise-Server-15-SP4 SUSE Linux Enterprise Server 15 SP4 SUSE-Linux-Enterprise-15-SP5 SUSE Linux Enterprise 15 SP5 openSUSE-Tumbleweed openSUSE Tumbleweed ``` 我使用选择安装了默认的 Ubuntu 版本: ```PowerShell wsl --install -d Ubuntu ``` 之后就可以在 CMD 中使用 `wsl`命令进入Ubuntu 了。 **第三步,安装 Docker Desktop** {'Header 1': '使用全套开源工具构建 LLM 应用实战:在 Dify 调用 Baichuan 开源模型能力', 'Header 2': '环境准备'} **第三步,安装 Docker Desktop** 去 Docker [官方文档](https://docs.docker.com/desktop/install/windows-install/#wsl-2-backend)下载 Docker Desktop。安装时注意勾上 `Use WSL 2 instead of Hyper-V` 选项。安装完成后重启电脑。通过 CMD 查看是否正常安装好。 ```PowerShell wsl -l --verbose {'Header 1': '使用全套开源工具构建 LLM 应用实战:在 Dify 调用 Baichuan 开源模型能力', 'Header 2': '环境准备'} NAME STATE VERSION * Ubuntu Running 2 docker-desktop Running 2 docker-desktop-data Running 2 ``` 可以看到 WSL 中 Ubuntu 和 Docker 都运行起来了,并且确认是 WSL2 版本。 **第四步,为 WSL 配置代理** 由于每次重启后 WSL 的 ip 地址都会变更,所以我们可以编写一个脚本来解决。第 4 行改为你自己的端口号。 ```Bash #!/bin/sh hostip=$(cat /etc/resolv.conf | grep nameserver | awk '{ print $2 }') wslip=$(hostname -I | awk '{print $1}') port=7890 PROXY_HTTP="http://${hostip}:${port}" {'Header 1': '使用全套开源工具构建 LLM 应用实战:在 Dify 调用 Baichuan 开源模型能力', 'Header 2': '环境准备'} PROXY_HTTP="http://${hostip}:${port}" set_proxy(){ export http_proxy="${PROXY_HTTP}" export HTTP_PROXY="${PROXY_HTTP}" export https_proxy="${PROXY_HTTP}" export HTTPS_proxy="${PROXY_HTTP}" export ALL_PROXY="${PROXY_SOCKS5}" export all_proxy=${PROXY_SOCKS5} git config --global http.https://github.com.proxy ${PROXY_HTTP} git config --global https.https://github.com.proxy ${PROXY_HTTP} echo "Proxy has been opened." } {'Header 1': '使用全套开源工具构建 LLM 应用实战:在 Dify 调用 Baichuan 开源模型能力', 'Header 2': '环境准备'} echo "Proxy has been opened." } unset_proxy(){ unset http_proxy unset HTTP_PROXY unset https_proxy unset HTTPS_PROXY unset ALL_PROXY unset all_proxy git config --global --unset http.https://github.com.proxy git config --global --unset https.https://github.com.proxy echo "Proxy has been closed." } {'Header 1': '使用全套开源工具构建 LLM 应用实战:在 Dify 调用 Baichuan 开源模型能力', 'Header 2': '环境准备'} echo "Proxy has been closed." } test_setting(){ echo "Host IP:" ${hostip} echo "WSL IP:" ${wslip} echo "Try to connect to Google..." resp=$(curl -I -s --connect-timeout 5 -m 5 -w "%{http_code}" -o /dev/null www.google.com) if [ ${resp} = 200 ]; then echo "Proxy setup succeeded!" else echo "Proxy setup failed!" fi } if [ "$1" = "set" ] then set_proxy elif [ "$1" = "unset" ] then unset_proxy {'Header 1': '使用全套开源工具构建 LLM 应用实战:在 Dify 调用 Baichuan 开源模型能力', 'Header 2': '环境准备'} elif [ "$1" = "test" ] then test_setting else echo "Unsupported arguments." fi ``` 可以修改`~/.bashrc` 方便使用命令: ```Bash alias proxy="source /path/to/proxy.sh" ``` 详细可以参考了该[博客](https://www.cnblogs.com/tuilk/p/16287472.html)。 **第五步,进入 Ubuntu 安装 conda 配置 python** 和前面的环境准备一样,参照官方文档安装 conda 配置 python,不过是安装 linux 版本。 **第六步,安装 WSL 的 CUDA** 进入官网,选择 WSL-Ubuntu 版本,按照指引使用命令行安装。
{'Header 1': '使用全套开源工具构建 LLM 应用实战:在 Dify 调用 Baichuan 开源模型能力', 'Header 2': '环境准备'} 修改`~/.bashrc`将 CUDA 添加至环境变量: ```Bash export LD_LIBRARY_PATH=/usr/local/cuda-12.2/lib64 export PATH=$PATH:/usr/local/cuda-12.2/lib64 ``` **第七步,安装 PyTorch** 进入 PyTorch [官网](https://pytorch.org/),按照环境安装 PyTorch。
这样环境准备就完成了。 {'Header 1': '使用全套开源工具构建 LLM 应用实战:在 Dify 调用 Baichuan 开源模型能力', 'Header 2': '部署推理服务 Xinference'} 根据 Dify 的[部署文档](https://docs.dify.ai/v/zh-hans/advanced/model-configuration/xinference),Xinference 支持的模型种类很多。本次以 Baichuan-13B-Chat 为例。 > [Xorbits inference](https://github.com/xorbitsai/inference) 是一个强大且通用的分布式推理框架,旨在为大型语言模型、语音识别模型和多模态模型提供服务,甚至可以在笔记本电脑上使用。它支持多种与 GGML 兼容的模型,如 ChatGLM,Baichuan,Whisper,Vicuna,Orca 等。 Dify 支持以本地部署的方式接入 Xinference 部署的大型语言模型推理和 Embedding 能力。 #### 安装 Xinfernece 在 WSL 中执行如下命令: ```Bash $ pip install "xinference" ``` {'Header 1': '使用全套开源工具构建 LLM 应用实战:在 Dify 调用 Baichuan 开源模型能力', 'Header 2': '部署推理服务 Xinference'} ```Bash $ pip install "xinference" ``` 上面的命令会安装 Xinference 用于推理的基础依赖。Xinference 还支持用 `ggml 推理` 和 `PyTorch 推理`,需要装如下的依赖: ```Bash $ pip install "xinference[ggml]" $ pip install "xinference[pytorch]" $ pip install "xinference[all]" ``` #### 启动 Xinference 并下载部署 Baichuan-13B-Chat 模型 在 WSL 中执行下面的命令: ```Bash $ xinference -H 0.0.0.0 ``` {'Header 1': '使用全套开源工具构建 LLM 应用实战:在 Dify 调用 Baichuan 开源模型能力', 'Header 2': '部署推理服务 Xinference'} ```Bash $ xinference -H 0.0.0.0 ``` Xinference 默认会在本地启动一个 worker,端点为:`http://127.0.0.1:9997`,端口默认为 `9997`。 默认只可本机访问,配置了 `-H 0.0.0.0`,非本地客户端可任意访问。 如需进一步修改 host 或 port,可查看 Xinference 的帮助信息:`xinference --help`。 ```Bash 2023-08-25 18:08:31,204 xinference 27505 INFO Xinference successfully started. Endpoint: http://0.0.0.0:9997 2023-08-25 18:08:31,204 xinference.core.supervisor 27505 INFO Worker 0.0.0.0:53860 has been added successfully {'Header 1': '使用全套开源工具构建 LLM 应用实战:在 Dify 调用 Baichuan 开源模型能力', 'Header 2': '部署推理服务 Xinference'} 2023-08-25 18:08:31,205 xinference.deploy.worker 27505 INFO Xinference worker successfully started. ``` 在浏览器中打开: [http://localhost:9997](http://localhost:9997),选择 baichuan-chat,pytorch,13B,4bit,点击 create 部署。
或者使用 CLI 部署: ```Bash xinference launch --model-name baichuan-chat --model-format pytorch --size-in-billions 13 --quantization 4 ``` {'Header 1': '使用全套开源工具构建 LLM 应用实战:在 Dify 调用 Baichuan 开源模型能力', 'Header 2': '部署推理服务 Xinference'} ``` 由于不同模型在不同硬件平台兼容性不同,请查看 [Xinference 内置模型](https://inference.readthedocs.io/en/latest/models/builtin/index.html) 确定创建的模型是否支持当前硬件平台。 #### 使用 Xinference 管理模型 要查看部署好的所有模型,在命令行中,执行下面的命令: ```Bash $ xinference list ``` 会显示类似下面的信息: ```Bash UID Type Name Format Size (in billions) Quantization ------------------------------------ ------ ------------- -------- -------------------- -------------- {'Header 1': '使用全套开源工具构建 LLM 应用实战:在 Dify 调用 Baichuan 开源模型能力', 'Header 2': '部署推理服务 Xinference'} 0fc70cd0-4b2a-11ee-a428-00155d0b318a LLM baichuan-chat pytorch 13 4-bit ``` `0fc70cd0-4b2a-11ee-a428-00155d0b318a` 就是刚才部署的模型的 uid 。 {'Header 1': '使用全套开源工具构建 LLM 应用实战:在 Dify 调用 Baichuan 开源模型能力', 'Header 2': '部署 Dify.AI'} 主要流程参考官网[部署文档](https://docs.dify.ai/v/zh-hans/getting-started/install-self-hosted/docker-compose)。 #### Clone Dify Clone Dify 源代码至本地。 ```Bash git clone https://github.com/langgenius/dify.git ``` #### Start Dify 进入 Dify 源代码的 docker 目录,执行一键启动命令: ```Bash cd dify/docker docker compose up -d ``` 部署结果: ```Bash [+] Running 7/7 ✔ Container docker-weaviate-1 Running 0.0s {'Header 1': '使用全套开源工具构建 LLM 应用实战:在 Dify 调用 Baichuan 开源模型能力', 'Header 2': '部署 Dify.AI'} ✔ Container docker-web-1 Running 0.0s ✔ Container docker-redis-1 Running 0.0s ✔ Container docker-db-1 Running 0.0s ✔ Container docker-worker-1 Running 0.0s ✔ Container docker-api-1 Running 0.0s {'Header 1': '使用全套开源工具构建 LLM 应用实战:在 Dify 调用 Baichuan 开源模型能力', 'Header 2': '部署 Dify.AI'} ✔ Container docker-nginx-1 Started 0.9s ``` 最后检查是否所有容器都正常运行: ```Bash docker compose ps ``` 运行状态: ```Bash NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS docker-api-1 langgenius/dify-api:0.3.16 "/bin/bash /entrypoi…" api 24 hours ago Up 3 hours 5001/tcp {'Header 1': '使用全套开源工具构建 LLM 应用实战:在 Dify 调用 Baichuan 开源模型能力', 'Header 2': '部署 Dify.AI'} docker-db-1 postgres:15-alpine "docker-entrypoint.s…" db 33 hours ago Up 3 hours 0.0.0.0:5432->5432/tcp docker-nginx-1 nginx:latest "/docker-entrypoint.…" nginx 24 hours ago Up 4 minutes 0.0.0.0:80->80/tcp docker-redis-1 redis:6-alpine "docker-entrypoint.s…" redis 33 hours ago Up 3 hours 6379/tcp {'Header 1': '使用全套开源工具构建 LLM 应用实战:在 Dify 调用 Baichuan 开源模型能力', 'Header 2': '部署 Dify.AI'} docker-weaviate-1 semitechnologies/weaviate:1.18.4 "/bin/weaviate --hos…" weaviate 33 hours ago Up 3 hours docker-web-1 langgenius/dify-web:0.3.16 "/bin/sh ./entrypoin…" web 33 hours ago Up 3 hours 3000/tcp docker-worker-1 langgenius/dify-api:0.3.16 "/bin/bash /entrypoi…" worker 33 hours ago Up 3 hours 5001/tcp ``` {'Header 1': '使用全套开源工具构建 LLM 应用实战:在 Dify 调用 Baichuan 开源模型能力', 'Header 2': '部署 Dify.AI'} ``` 包括 3 个业务服务 `api / worker / web`,以及 4 个基础组件 `weaviate / db / redis / nginx`。 Docker 启动成功后,在浏览器中访问:http://127.0.0.1/。设置过密码后登陆,会进入应用列表页。
至此,成功使用 Docker 部署了 Dify 社区版。 {'Header 1': '使用全套开源工具构建 LLM 应用实战:在 Dify 调用 Baichuan 开源模型能力', 'Header 2': '在 Dify 接入 Xinference'} #### 配置模型供应商 在 `设置 > 模型供应商 > Xinference` 中填入模型信息: * Model Name 是模型部署的名称。 * Server URL 是 Xinference 的 end point 地址。 * Model UID 则是通过 `xinference list`获取到的部署的模型的 UID。 需要注意的是 Sever Url 不能用 localhost。因为如果填 localhost,访问的是 docker 里的 localhost,会导致访问失败。解决方案是将 Sever Url 改成局域网 ip。 而 WSL 环境下则需要使用 WSL 的 IP 地址。在 WSL 中使用命令获取: ```Bash hostname -I 172.22.195.4 ```
#### 使用 Baichuan-13B-Chat {'Header 1': '使用全套开源工具构建 LLM 应用实战:在 Dify 调用 Baichuan 开源模型能力', 'Header 2': '在 Dify 接入 Xinference'} #### 使用 Baichuan-13B-Chat 创建应用,就可以在应用中使用上一步配置的 Baichuan-13B-Chat 模型了。在 Dify 的提示词编排界面,选择 baichuan-chat 模型,设计你的应用提示词(prompt),即可发布一个可访问的 AI 应用。
以上,就是本地部署 Dify 接入 Xinference 部署的 baichuan-chat 的全过程。 至此,我们基于 Baichuan-13B-Chat 的一个基本的聊天应用就基本完成了。 {'Header 1': '使用全套开源工具构建 LLM 应用实战:在 Dify 调用 Baichuan 开源模型能力', 'Header 2': '后记'} 当然,对于一个生产级别的 LLM 应用来说,只是完成大模型的接入和推理、聊天交互是远远不够。我们还需要针对性的对 LLM 进行 Prompt 的调优、添加私有数据作为上下文,亦或者是对 LLM 本身进行微调等工作,这需要长期的迭代和优化才能使得 LLM 应用表现越来越好。**Dify.AI 作为一个中间件工具平台,提供了一个完整 LLM App 技术栈的可视化的操作系统。完成了以上的基础服务部署后,后续的应用迭代和改进都可以基于 Dify 来完成,使得 LLM 应用的构建和管理变得更加简单和易用,在业务数据的处理上直接上传即可自动完成清洗处理,后续也将提供数据标注和改进的服务,甚至你的业务团队都可以参与协作。** 目前 LLM 的发展和应用落地还处于非常早期的阶段,相信在不久后,无论是 LLM 的能力释放,还是基于 LLM 之上的各个工具能力的不断完善,都会不断降低开发者探索 LLM 能力的门槛,让更多丰富场景的 AI 应用涌现。 {'Header 1': '手摸手教你把 Dify 接入微信生态'} > 作者:韩方圆,"Dify on WeChat"开源项目作者 {'Header 1': '手摸手教你把 Dify 接入微信生态', 'Header 2': '1. 概述'} 微信作为最热门的即时通信软件,拥有巨大的流量。 微信友好的聊天窗口是天然的AI应用LUI(Language User Interface)/CUI(Command User Interface)。 微信不仅有个人微信,同时提供了公众号、企业微信、企业微信应用、企业微信客服等对话渠道,拥有良好的微信生态。 把Dify应用接入微信生态,就能打造一个功能强大的智能客服,大大降低客服成本,同时也能够提升客户体验。本篇教程就是手摸手地教你如何利用[Dify on WeChat](https://github.com/hanfangyuan4396/dify-on-wechat)项目,把Dify应用接入微信生态。 {'Header 1': '手摸手教你把 Dify 接入微信生态', 'Header 2': '2. Dify接入个人微信', 'Header 3': '2.1. 准备工作'} #### 2.1.1. 创建聊天助手 **(1)Dify简介** Dify是一个优秀的LLMOps(大型语言模型运维)平台,Dify的详细介绍请移步官方文档[欢迎使用 Dify | 中文 | Dify](https://docs.dify.ai/v/zh-hans)。 **(2)登录Dify官方应用平台** 首先,登录[Dify官方应用平台](https://cloud.dify.ai/signin),你可以选择使用Github登录或者使用Google登录。此外,你也可以参考Dify官方教程[Docker Compose 部署 | 中文 | Dify](https://docs.dify.ai/v/zh-hans/getting-started/install-self-hosted/docker-compose) 私有部署,Dify是开源项目,支持私有部署。 {'Header 1': '手摸手教你把 Dify 接入微信生态', 'Header 2': '2. Dify接入个人微信', 'Header 3': '2.1. 准备工作'}
**(3)创建Dify基础编排聊天助手应用**
登录成功后,进入Dify页面,我们按照下方步骤创建一个基础编排聊天助手应用 1. 点击页面上方的工作室 2. 创建空白应用 3. 应用类型选择聊天助手 4. 聊天助手编排方式选择基础编排 5. 选择应用图标并为应用填写一个名称,比如基础编排聊天助手 6. 点击创建 {'Header 1': '手摸手教你把 Dify 接入微信生态', 'Header 2': '2. Dify接入个人微信', 'Header 3': '2.1. 准备工作'} 5. 选择应用图标并为应用填写一个名称,比如基础编排聊天助手 6. 点击创建
创建成功后我们会跳转到上图所示页面,我们继续配置应用 1. 选择模型,如gpt-3.5-turbo-0125 2. 设置模型参数 3. 填写应用提示词
在配置完成后,我们可以在右侧对话框进行测试,在测试完成后,进行如下操作 1. 发布 2. 更新 3. 访问API **(4)生成基础编排聊天助手API密钥** {'Header 1': '手摸手教你把 Dify 接入微信生态', 'Header 2': '2. Dify接入个人微信', 'Header 3': '2.1. 准备工作'} 1. 发布 2. 更新 3. 访问API **(4)生成基础编排聊天助手API密钥**
在点击"访问API"后,我们会跳转到上图的API管理页面,在这个页面我们按照如下步骤获取API密钥: 1. 点击右上角API密钥 2. 点击创建密钥 3. 复制保存密钥 在保存密钥后,还需要查看右上角的API服务器,如果是Dify官网的应用,API服务器地址为 "https://api.dify.ai/v1", 如果是私有部署的,请确认你自己的API服务器地址。 至此,创建聊天助手的准备工作结束,在此小节中我们只需要保存好两个东西:**API密钥**与**API服务器地址** #### 2.1.2. 下载Dify on WeChat项目 **(1)Dify on WeChat项目简介** {'Header 1': '手摸手教你把 Dify 接入微信生态', 'Header 2': '2. Dify接入个人微信', 'Header 3': '2.1. 准备工作'} **(1)Dify on WeChat项目简介** [Dify on WeChat](https://github.com/hanfangyuan4396/dify-on-wechat)是[ ChatGPT on WeChat](https://github.com/zhayujie/chatgpt-on-wechat)的下游分支,额外实现了对接[Dify](https://github.com/langgenius/dify) API,支持Dify聊天助手、支持Agent调用工具和知识库,支持Dify工作流,详情请查看GitHub仓库[Dify on WeChat](https://github.com/hanfangyuan4396/dify-on-wechat)。 **(2)下载代码并安装依赖** 1. 下载项目代码 ```bash git clone https://github.com/hanfangyuan4396/dify-on-wechat cd dify-on-wechat/ ``` 2. 安装python {'Header 1': '手摸手教你把 Dify 接入微信生态', 'Header 2': '2. Dify接入个人微信', 'Header 3': '2.1. 准备工作'} cd dify-on-wechat/ ``` 2. 安装python Dify on WeChat项目使用python语言编写,请在[python官网](https://www.python.org/downloads/)下载安装python,推荐安装python3.8以上版本,我在ubuntu测试过3.11.6版本,可以正常运行。 3. 安装核心依赖(必选): ```bash pip3 install -r requirements.txt # 国内可以在该命令末尾添加 "-i https://mirrors.aliyun.com/pypi/simple" 参数,使用阿里云镜像源安装依赖 ``` 4. 拓展依赖 (可选,建议安装): ```bash pip3 install -r requirements-optional.txt # 国内可以在该命令末尾添加 "-i https://mirrors.aliyun.com/pypi/simple" 参数,使用阿里云镜像源安装依赖 ``` **(3)填写配置文件** {'Header 1': '手摸手教你把 Dify 接入微信生态', 'Header 2': '2. Dify接入个人微信', 'Header 3': '2.1. 准备工作'} ``` **(3)填写配置文件** 我们在项目根目录创建名为config.json的文件,文件内容如下,我们在**2.1.1小节(4)** 最后保存了**API密钥**与**API服务器地址**,请把**dify_api_base**配置为**API服务器地址**;**dify_api_key**配置为**API密钥**其他配置保持不变。 (PS: 很多朋友可能并不是严格按照我教程给出的步骤创建**聊天助手类型**的Dify应用,在此特别说明一下**dify_app_type**配置方法,如果你创建了**聊天助手**应用请配置为**chatbot**;创建了**Agent**应用请配置为**agent**; 创建了**工作流**应用请配置为**workflow**。) ```bash { "dify_api_base": "https://api.dify.ai/v1", "dify_api_key": "app-xxx", "dify_app_type": "chatbot", "channel_type": "wx", "model": "dify", {'Header 1': '手摸手教你把 Dify 接入微信生态', 'Header 2': '2. Dify接入个人微信', 'Header 3': '2.1. 准备工作'} "channel_type": "wx", "model": "dify", "single_chat_prefix": [""], "single_chat_reply_prefix": "", "group_chat_prefix": ["@bot"], "group_name_white_list": ["ALL_GROUP"] } ``` {'Header 1': '手摸手教你把 Dify 接入微信生态', 'Header 2': '2. Dify接入个人微信', 'Header 3': '2.2. 把基础编排聊天助手接入微信'} #### 2.2.1. 快速启动测试 **(1)在Dify on Wechat项目根目录执行如下命令** ```bash cd dify-on-wechat python3 app.py # windows环境下该命令通常为 python app.py ``` **(2)扫码登录**
本项目使用itchat实现个人微信登录,有封号风险,建议使用**实名认证**过的**微信小号**进行测试,在执行上述命令后,我们可以在控制台看到打印如上图所示二维码,使用微信扫码登录,登录后当看到"itchat:Start auto replying."字符,表示登录成功,我们可以进行测试。 **(3)对话测试** {'Header 1': '手摸手教你把 Dify 接入微信生态', 'Header 2': '2. Dify接入个人微信', 'Header 3': '2.2. 把基础编排聊天助手接入微信'} **(3)对话测试**
我们看到,微信机器人的回复与在Dify测试页面上的回复一致。至此,恭喜你成功把Dify接入了个人微信🎉🎉🎉 (PS: 有些朋友到这里可能在日志中看到正常回复了消息,但是微信中没有收到消息,请**不要用自己的微信给自己发消息**) **(4)服务器部署** 1. 源码部署 ```bash cd dify-on-wechat nohup python3 app.py & tail -f nohup.out # 在后台运行程序并通过日志输出二维码 ``` 2. docker compose部署 容器的**环境变量**会**覆盖**config.json文件的配置,请修改docker/docker-compose.yml文件环境变量为你实际的配置,配置方法与**2.1.1小节(4)** {'Header 1': '手摸手教你把 Dify 接入微信生态', 'Header 2': '2. Dify接入个人微信', 'Header 3': '2.2. 把基础编排聊天助手接入微信'} 的config.json配置一致。 请确保正确配置**DIFY_API_BASE**, **DIFY_API_KEY**与**DIFY_APP_TYPE**环境变量。 ```yaml version: '2.0' services: dify-on-wechat: image: hanfangyuan/dify-on-wechat container_name: dify-on-wechat security_opt: - seccomp:unconfined environment: DIFY_API_BASE: 'https://api.dify.ai/v1' DIFY_API_KEY: 'app-xx' DIFY_APP_TYPE: 'chatbot' MODEL: 'dify' SINGLE_CHAT_PREFIX: '[""]' SINGLE_CHAT_REPLY_PREFIX: '""' GROUP_CHAT_PREFIX: '["@bot"]' GROUP_NAME_WHITE_LIST: '["ALL_GROUP"]' ``` 然后执行如下命令启动容器 {'Header 1': '手摸手教你把 Dify 接入微信生态', 'Header 2': '2. Dify接入个人微信', 'Header 3': '2.2. 把基础编排聊天助手接入微信'} ``` 然后执行如下命令启动容器 ```bash cd dify-on-wechat/docker # 进入docker目录 docker compose up -d # 启动docker容器 docker logs -f dify-on-wechat # 查看二维码并登录 ``` {'Header 1': '手摸手教你把 Dify 接入微信生态', 'Header 2': '2. Dify接入个人微信', 'Header 3': '2.3. 把工作流编排聊天助手接入微信'} 在把Dify基础的聊天助手应用接入微信后,我们接下来增加难度,尝试把工作流编排聊天助手应用接入微信,实现一个具有Dify平台知识的微信智能客服,为我们解答Dify工作流相关知识。 #### 2.3.1. 创建知识库 **(1)下载知识库文件**
我们到[dify文档仓库](../../guides/workflow/)下载Dify工作流介绍的文档。 **(2)Dify中导入知识库**
进入知识库页面,创建知识库 {'Header 1': '手摸手教你把 Dify 接入微信生态', 'Header 2': '2. Dify接入个人微信', 'Header 3': '2.3. 把工作流编排聊天助手接入微信'} 进入知识库页面,创建知识库
选择导入已有文本,上传刚才下载的introduce.md文件,点击下一步
选择如下配置 * 分段设置:自动分段与清洗 * 索引方式:高质量 * 检索设置:向量检索 最后点击保存并处理 {'Header 1': '手摸手教你把 Dify 接入微信生态', 'Header 2': '2. Dify接入个人微信', 'Header 3': '2.3. 把工作流编排聊天助手接入微信'} * 索引方式:高质量 * 检索设置:向量检索 最后点击保存并处理
我们看到知识库正在进行嵌入处理,稍等片刻,即可嵌入成功。 #### 2.3.2. 创建工作流编排聊天助手
我们进入Dify工作室,点击从应用模板创建 {'Header 1': '手摸手教你把 Dify 接入微信生态', 'Header 2': '2. Dify接入个人微信', 'Header 3': '2.3. 把工作流编排聊天助手接入微信'} 我们进入Dify工作室,点击从应用模板创建
我们使用知识库+聊天机器人类型的模板,设置应用图标与名称,点击创建
跳转到工作流编排页面后,先点击知识检索节点,点击最右侧"+"添加知识库。我们选择之前上传好的introduce.md知识库,该知识库是对Dify工作流的基本介绍。最后我们点击添加,知识库节点设置完成。 {'Header 1': '手摸手教你把 Dify 接入微信生态', 'Header 2': '2. Dify接入个人微信', 'Header 3': '2.3. 把工作流编排聊天助手接入微信'}
接下来选择LLM节点,点击设置上下文,我们选择result变量,该变量存有知识检索的结果。
设置完LLM节点后,我们点击预览进行测试,输入问题:请介绍一下dify工作流。可以看到最终输出了Dify工作流的正确介绍。测试正常后,我们返回编辑模式。 {'Header 1': '手摸手教你把 Dify 接入微信生态', 'Header 2': '2. Dify接入个人微信', 'Header 3': '2.3. 把工作流编排聊天助手接入微信'}
返回编辑模式后,依次点击发布、更新、访问API #### 2.3.3. 生成工作流编排聊天助手API密钥 在跳转到API管理页面后,我们参照**2.1.1小节(4)获取"知识库+聊天机器人"应用的API密钥**与**API服务器地址** #### 2.3.4. 接入微信 与**2.1.2小节(3)类似,我们在项目根目录创建名为config.json的文件,文件内容如下,同样把dify\_api\_base**配置为**知识库+聊天机器人**应用的API服务器地址, **dify\_api\_key**配置为**知识库+聊天机器人**应用的API密钥,其他配置保持不变 ```bash { "dify_api_base": "https://api.dify.ai/v1", {'Header 1': '手摸手教你把 Dify 接入微信生态', 'Header 2': '2. Dify接入个人微信', 'Header 3': '2.3. 把工作流编排聊天助手接入微信'} { "dify_api_base": "https://api.dify.ai/v1", "dify_api_key": "app-xxx", "dify_app_type": "chatbot", "channel_type": "wx", "model": "dify", "single_chat_prefix": [""], "single_chat_reply_prefix": "", "group_chat_prefix": ["@bot"], "group_name_white_list": ["ALL_GROUP"] } ``` 我们按照**2.2.1小节**启动程序并扫码登录,然后给微信机器人发送消息,进行测试
{'Header 1': '手摸手教你把 Dify 接入微信生态', 'Header 2': '2. Dify接入个人微信', 'Header 3': '2.3. 把工作流编排聊天助手接入微信'} 微信机器人的回复与在Dify测试页面上的回复一致。恭喜你更进一步,把工作流编排应用接入了个人微信,你可以向知识库中导入更多的Dify官方文档,让微信机器人为你解答更多的Dify相关问题。 {'Header 1': '手摸手教你把 Dify 接入微信生态', 'Header 2': '2. Dify接入个人微信', 'Header 3': '2.4. 把Agent接入微信'} #### 2.4.1. 创建Agent应用
进入工作室页面,点击创建空白应用,选择Agent,设置图标和应用名称,最后点击创建
创建成功后,我们会进入Agent应用配置页面,在这个页面我们选择好对话模型,然后添加工具。我们首先添加DALL-E绘画工具,首次使用该工具需要授权,一般我们设置好OpenAI API key和OpenAI base URL即可使用该DALL-E绘画工具。 {'Header 1': '手摸手教你把 Dify 接入微信生态', 'Header 2': '2. Dify接入个人微信', 'Header 3': '2.4. 把Agent接入微信'}
授权成功后,我们添加DALL-E 3绘画工具
接着,继续添加DuckDuckGo搜索引擎和数学工具,进行后续的工具测试
{'Header 1': '手摸手教你把 Dify 接入微信生态', 'Header 2': '2. Dify接入个人微信', 'Header 3': '2.4. 把Agent接入微信'} 我们输入问题"搜索开源项目Dify的star数量,这个数量乘以3.14是多少",确认应用能够正常调用工具,我们依次点击发布、更新、访问API #### 2.4.2. 生成Agent API密钥 我们继续参照**2.1.1小节(4)获取智能助手**应用的**API密钥**与**API服务器地址** #### 2.4.3. 接入微信 我们在项目根目录创建名为config.json的文件,文件内容如下,同样把**dify\_api\_base**配置为**智能助手**应用的API服务器地址;**dify\_api\_key**配置为**智能助手**应用的API密钥,注意该应用为**智能助手**类型应用,还需要把**dify\_app\_type**设置为**agent**,其他配置保持不变 ```bash { "dify_api_base": "https://api.dify.ai/v1", "dify_api_key": "app-xxx", "dify_app_type": "agent", "channel_type": "wx", {'Header 1': '手摸手教你把 Dify 接入微信生态', 'Header 2': '2. Dify接入个人微信', 'Header 3': '2.4. 把Agent接入微信'} "dify_app_type": "agent", "channel_type": "wx", "model": "dify", "single_chat_prefix": [""], "single_chat_reply_prefix": "", "group_chat_prefix": ["@bot"], "group_name_white_list": ["ALL_GROUP"] } {'Header 1': '手摸手教你把 Dify 接入微信生态', 'Header 2': '2. Dify接入个人微信', 'Header 3': '2.4. 把Agent接入微信'} ``` 继续参照**2.2.1小节**启动程序并扫码登录,然后给微信机器人发送消息,进行测试
可以看到微信机器人可以正常使用搜索和绘画工具。再一次恭喜你,把Dify Agent应用接入微信。也恭喜我,写到这里可以先睡觉了。 {'Header 1': '手摸手教你把 Dify 接入微信生态', 'Header 2': '2. Dify接入个人微信', 'Header 3': '2.5. 把工作流接入微信'} #### 2.5.1. 创建工作流应用
首先你需要提前下载好我预先创建的DSL文件,[点击此处下载](https://github.com/hanfangyuan4396/dify-on-wechat/blob/master/dsl/chat-workflow.yml)。下载完成后,进入工作室页面,点击导入DSL文件,上传提前下载好的文件,最后点击创建。
创建完成后,按照上图步骤进行测试。点击运行,输入你好,确保该工作流能正常输出结果。 {'Header 1': '手摸手教你把 Dify 接入微信生态', 'Header 2': '2. Dify接入个人微信', 'Header 3': '2.5. 把工作流接入微信'} 创建完成后,按照上图步骤进行测试。点击运行,输入你好,确保该工作流能正常输出结果。 你可以在此工作流的基础上进行修改,但是对于**工作流类型**的应用,它的输入变量名称十分灵活,,为了更方便地接入微信机器人,[Dify on WeChat](https://github.com/hanfangyuan4396/dify-on-wechat)项目约定**工作流类型**的应用**输入变量命名为`query`**,**输出变量命名为`text`**。
测试没有问题后,按照上图步骤发布应用,依次点击发布、更新、访问API。 #### 2.5.2. 生成工作流API密钥 我们同样参照**2.1.1小节(4)获取工作流**应用的**API密钥**与**API服务器地址**。 #### 2.5.3. 接入微信 {'Header 1': '手摸手教你把 Dify 接入微信生态', 'Header 2': '2. Dify接入个人微信', 'Header 3': '2.5. 把工作流接入微信'} #### 2.5.3. 接入微信 我们在项目根目录创建名为config.json的文件,文件内容如下,同样把**dify\_api\_base**配置为**工作流**应用的API服务器地址;**dify\_api\_key**配置为**工作流**应用的API密钥,注意该应用为**工作流**类型应用,还需要把**dify\_app\_type**设置为**workflow**,其他配置保持不变 ```bash { "dify_api_base": "https://api.dify.ai/v1", "dify_api_key": "app-xxx", "dify_app_type": "workflow", "channel_type": "wx", "model": "dify", "single_chat_prefix": [""], "single_chat_reply_prefix": "", "group_chat_prefix": ["@bot"], "group_name_white_list": ["ALL_GROUP"] } {'Header 1': '手摸手教你把 Dify 接入微信生态', 'Header 2': '2. Dify接入个人微信', 'Header 3': '2.5. 把工作流接入微信'} ``` 同样参照**2.2.1小节**启动程序并扫码登录,然后给微信机器人发送消息,进行测试。
可以看到机器人成功接通了工作流api并进行了回复,至此我们已经完全掌握了如何创建Dify所有类型的应用:基础聊天助手、工作流聊天助手、智能助手、工作流,我们也学会了如何把上述应用发布为API,并接入微信。 接下来我将会介绍如何把应用接入到微信的其他通道,如公众号、企业微信应用、企业微信客服等。 {'Header 1': '手摸手教你把 Dify 接入微信生态', 'Header 2': '3. Dify接入企业微信个人号(仅限windows环境)'} > 1. 有**封号风险**,请使用企业微信**小号**测试 > 2. 在登录旧版本的企业微信时可能会出现企业微信版本过低,无法登录情况,参考[issue1525](https://github.com/zhayujie/chatgpt-on-wechat/issues/1525),请尝试更换其他企业微信号重试 {'Header 1': '手摸手教你把 Dify 接入微信生态', 'Header 2': '3. Dify接入企业微信个人号(仅限windows环境)', 'Header 3': '3.1. 下载安装企业微信'} 确保你有一台windows系统的电脑,然后在此电脑下载安装特定版本的企业微信,[官方下载链接](https://dldir1.qq.com/wework/work\_weixin/WeCom\_4.0.8.6027.exe),[备用下载链接](https://www.alipan.com/s/UxQHrZ5WoxS)。 {'Header 1': '手摸手教你把 Dify 接入微信生态', 'Header 2': '3. Dify接入企业微信个人号(仅限windows环境)', 'Header 3': '3.2. 创建Dify应用'} 我们已经在前面的**2.1.1**、**2.3.2**、**2.4.1**与**2.5.1**小节分别介绍了创建基础聊天助手、工作流聊天助手、智能助手、工作流这4种不同的Dify应用,你可以根据上面的教程任意创建一种应用。 {'Header 1': '手摸手教你把 Dify 接入微信生态', 'Header 2': '3. Dify接入企业微信个人号(仅限windows环境)', 'Header 3': '3.3. 下载安装Dify on WeChat'} 根据 **2.1.2(2)** 步骤,下载代码并安装依赖,为了后续能按照ntwork依赖,**请确保你安装的python版本为3.8、3.9或3.10**。 {'Header 1': '手摸手教你把 Dify 接入微信生态', 'Header 2': '3. Dify接入企业微信个人号(仅限windows环境)', 'Header 3': '3.4. 安装ntwork依赖'} 由于ntwork的安装源不是很稳定,可以下载对应的whl文件,使用whl文件离线安装ntwork 首先需要查看你的python版本,在命令行中输入python查看版本信息,然后在[ntwork-whl](https://github.com/hanfangyuan4396/ntwork-bin-backup/tree/main/ntwork-whl)目录下找到对应的whl文件,运行`pip install xx.whl`安装ntwork依赖,注意"xx.whl"更换为whl文件的**实际路径**。 例如我的python版本信息为 "Python 3.8.5 (default, Sep 3 2020, 21:29:08) \[MSC v.1916 64 bit (AMD64)]" 可以看到python版本是**3.8.5**,并且是**AMD64**,所以对应的whl文件为**ntwork-0.1.3-cp38-cp38-win\_amd64.whl**,需要执行如下命令安装 ```sh {'Header 1': '手摸手教你把 Dify 接入微信生态', 'Header 2': '3. Dify接入企业微信个人号(仅限windows环境)', 'Header 3': '3.4. 安装ntwork依赖'} ```sh pip install your-path/ntwork-0.1.3-cp38-cp38-win_amd64.whl ``` {'Header 1': '手摸手教你把 Dify 接入微信生态', 'Header 2': '3. Dify接入企业微信个人号(仅限windows环境)', 'Header 3': '3.5. 填写配置文件'} 我们在Dify on WeChat项目根目录创建名为config.json的文件,下面是以Dify智能助手应用作为示例的配置文件,请正确填写你刚刚创建应用的dify\_api\_base、dify\_api\_key、dify\_app\_type信息,请注意channel\_type填写为 **wework** ```json { "dify_api_base": "https://api.dify.ai/v1", "dify_api_key": "app-xxx", "dify_app_type": "agent", "channel_type": "wework", "model": "dify", "single_chat_prefix": [""], "single_chat_reply_prefix": "", "group_chat_prefix": ["@bot"], "group_name_white_list": ["ALL_GROUP"] } ``` {'Header 1': '手摸手教你把 Dify 接入微信生态', 'Header 2': '3. Dify接入企业微信个人号(仅限windows环境)', 'Header 3': '3.6. 登录企业微信'} 务必提前在电脑扫码登录企业微信 {'Header 1': '手摸手教你把 Dify 接入微信生态', 'Header 2': '3. Dify接入企业微信个人号(仅限windows环境)', 'Header 3': '3.7. 启动微信个人号机器人'} 运行如下命令启动机器人 ```sh cd dify-on-wechat python app.py ``` 我们可以看到终端输出如下信息,**等待wework程序初始化完成**,最后启动成功\~ ``` [INFO][2024-04-30 21:16:04][wework_channel.py:185] - 等待登录······ [INFO][2024-04-30 21:16:05][wework_channel.py:190] - 登录信息:>>>user_id:xxx>>>>>>>>name: [INFO][2024-04-30 21:16:05][wework_channel.py:191] - 静默延迟60s,等待客户端刷新数据,请勿进行任何操作······ [INFO][2024-04-30 21:17:05][wework_channel.py:224] - wework程序初始化完成········ ``` {'Header 1': '手摸手教你把 Dify 接入微信生态', 'Header 2': '3. Dify接入企业微信个人号(仅限windows环境)', 'Header 3': '3.7. 启动微信个人号机器人'} ```
现在我们给机器人发送消息,可以看到接入成功! {'Header 1': '手摸手教你把 Dify 接入微信生态', 'Header 2': '4. Dify接入公众号'} 待更新\~ {'Header 1': '手摸手教你把 Dify 接入微信生态', 'Header 2': '5. Dify接入企业微信应用'} 待更新\~ {'Header 1': '手摸手教你把 Dify 接入微信生态', 'Header 2': '6. Dify接入企业微信客服'} 待更新\~ {'Header 1': '手摸手教你把 Dify 接入微信生态', 'Header 2': '7. 后记'} 我是社畜打工人,精力实在有限,只能晚上下班还有周末空闲时间维护[Dify on WeChat](https://github.com/hanfangyuan4396/dify-on-wechat)项目,单靠我个人开发项目进度十分缓慢,希望大家能一起参与进来这个项目,多多提PR,让Dify的生态变得更好\~ {'Header 1': '如何在几分钟内创建一个带有业务数据的官网 AI 智能客服'} 可能 AI 智能客服是每个业务网站的标配,在大型语言模型能力广泛被应用后,智能客服的实现变得更加轻易,可定制化的程度也更高。以下内容,将指导你如何在几分钟时间内,使用 Dify 创建你网站的 AI 智能客服。**Dify 产品支持将对话型应用嵌入到网页,你**只需要**花费几分钟**就可以将对话型应用**免费**嵌入到你的官网上,**定制你的 AI 智能客服。即使非技术人员也能搞定!** #### 首先,你需要理解 Dify.AI 是什么? {'Header 1': '如何在几分钟内创建一个带有业务数据的官网 AI 智能客服'} #### 首先,你需要理解 Dify.AI 是什么? Dify 是一个开源且非常简单易用的 LLMOps 平台,让你能够可视化快速创建并运营 AI 应用的工具平台。Dify 提供了可视化的 Prompt 编排、运营、数据集管理等功能。你甚至无需具备 AI 相关的技术研究和晦涩概念的理解。Dify 对接了各个出色的大型语言模型供应商,如 OpenAI、Azure OpenAI、Antropic 等,已提供 GPT 系列、Claude 系列模型,未来也将接入优秀的开源模型。这一切都是可以在设置中切换使用。这意味着,你在创建调试应用时,可以对比不同模型的效果,以确定使用最适合你的模型。**基于 Dify,你不仅可以很轻易地开发一个 AI 智能客服,还可以创造符合你使用习惯和需求的文本写作助手、虚拟招聘 HR 专家、会议总结助手、翻译助手等各种文本生成型应用,为你的工作提效。**
{'Header 1': '如何在几分钟内创建一个带有业务数据的官网 AI 智能客服'} **前提条件** **注册或部署 Dify.AI** Dify 是一个开源产品,你可以在 GitHub (https://github.com/langgenius/dify) 上找到它并部署在你本地或公司内网。同时它提供了云端 SaaS 版本,访问 https://dify.ai/zh 注册即可使用。 **申请 OpenAI 等模型厂商的 API key** 大模型的消息调用需要消耗 token,Dify 提供了 OpenAI GPT 系列(200 次) 和 Antropic Claude(1000 次) 模型的消息免费调用使用额度,在你消耗完毕前,需要通过模型厂商的官方渠道申请你自己的 API key。在 Dify 的【设置】--【模型提供商】处可填入 key。 #### 上传你的产品文档或知识库 {'Header 1': '如何在几分钟内创建一个带有业务数据的官网 AI 智能客服'} #### 上传你的产品文档或知识库 如果你希望能基于公司现有的知识库和产品文档构建人工智能客服,来与用户交流,那么你需要尽可能将你产品有关的文档上传到 Dify 的数据集中。Dify 帮助你完成数据的**分段处理和清洗**。Dify数据集支持高质量和经济两种索引模式,我们推荐使用高质量模式,会消耗 token 但能提供更高的准确性。操作步骤:在 【数据集】页面,新建一个数据集,上传你的业务数据(支持批量上传多个文本),选择清洗方式,【保存并处理】,只需几秒钟即可完成处理。
**创建一个 AI 应用,给 AI 指令** 在【构建应用】页面创建一个对话型应用。然后开始设置 AI 指令和它在前端和用户交互的体验: {'Header 1': '如何在几分钟内创建一个带有业务数据的官网 AI 智能客服'} 在【构建应用】页面创建一个对话型应用。然后开始设置 AI 指令和它在前端和用户交互的体验: 1. \*\*给 AI 指令:\*\*点击左侧【提示词编排】编辑你的 Prompt ,让它扮演客服的角色与用户交流,你可以指定它和用户交流的语气、风格、限定它回答问题的范围; 2. \*\*让 AI 拥有你的业务知识:\*\*在【上下文】中添加你刚才上传的目标数据集; 3. \*\*设置一个【对话开场白】:\*\*点击 【添加功能】打开功能开关。目的是为 AI 应用添加一个开场白,在用户打开客服窗口时,它会先和用户打招呼,增加亲和感。 4. \*\*设置【下一步问题建议】:\*\*在【添加功能】开启此功能。目的是为了让用户在提完一个问题后,给用户进行下一步提问的方向提示。 5. \*\*选择一个合适的模型并调整参数:\*\*页面右上角可以选择不同的模型。不同模型的表现和消耗的 token 价格都不一样。这个例子中,我们使用 GPT3.5 模型。 在这个 case 中,我们给 AI 指定了扮演的角色: {'Header 1': '如何在几分钟内创建一个带有业务数据的官网 AI 智能客服'} 在这个 case 中,我们给 AI 指定了扮演的角色: > 指令:你将扮演 Dify 的 AI 智能客服,你是 Dify 的第一个 AI 员工,名字叫 Bob。专门解答关于 Dify 产品、团队或 LLMOps 相关的用户问题。请注意,当用户提出的问题不在你的上下文内容范围内时,请回答不知道。请以友好的语气和用户交流,可以适当加入一些 emoji 表情增进与用户之间的互动。 > 开场白:你好,我是 Bob☀️, Dify的第一位AI成员。您可以与我讨论任何与Dify产品、团队甚至LLMOps相关的问题。
**调试 AI 智能客服的表现并发布** 完成以上的设置后,你可以在当前的页面右侧给它发送信息调试它的表现是否符合预期。然后点击【发布】。这时候你就已经拥有了一个 AI 智能客服。 {'Header 1': '如何在几分钟内创建一个带有业务数据的官网 AI 智能客服'}
**将 AI 客服应用嵌入到你的前端页面** 这一步,是将准备好的 AI 智能客服嵌入到你的官网页面。依次点击【概览】->【嵌入】,选择 \*\*script 标签方式,\*\*将 script 代码复制到你网站 `` 或 `` 标签中。如你是非技术人员,可让负责官网的开发帮忙粘贴并更新页面。
1. 将复制的代码粘贴到你官网的目标位置:
{'Header 1': '如何在几分钟内创建一个带有业务数据的官网 AI 智能客服'} 1. 更新你的官网,即可以得到一个拥有你业务数据的官网 AI智能客服。试一试效果:
以上通过 Dify 官网 AI 客服 Bob 的例子演示了如何将 Dify 应用嵌入到官网的具体操作步骤。当然,你还可以通过 Dify 提供的更多特性来增加 AI 客服的表现,例如增加一些变量设置,让用户在互动前填入必要的判断信息,如名字、使用的具体产品等等。 欢迎你一起来探索,定制企业的 AI 智能客服。
{'Header 1': '如何训练出专属于“你”的问答机器人?'} _作者:阿乔_ _火枪击穿了专属于骑士阶层身披的铠甲与荣耀,武力对等才会有真正的平权。_ 技术平权的速度从未来得如此之快。 作为兢兢业业的 CODING DevOps 项目的技术文档工程师,在为产品贡献数百篇文档后,依然止不住要在各种用户群 / 技术支持群里为客户解答问题。即使在每条答复中贴上文档链接,依然架不住新用户反复提问。(没办法,DevOps 产品中间又包含多项子产品) _注:CODING DevOps 是腾讯云旗下的一站式研发管理平台及云原生开发工具,旨在让软件研发如同工业生产般简单高效,助力提升企业研发管理效能。_ 虽然由 ChatGPT 掀起 AI 革命已来,但是它并不能够回答“我的”问题,也不能回答“你的”问题。但它却可以回答“大家”的问题。 {'Header 1': '如何训练出专属于“你”的问答机器人?'} 为什么?ChatGPT 本身便是由庞大的互联网语料库训练而成,并且这部分训练数据截止于 2021 年 9 月。如果你的产品在这个日期之前就有幸在互联网中占有一席之地,那恭喜你,GPT 可以大概率可以回答出你的产品是大概是干嘛用的。因为它会从你的官网收集已有的描述语料。具体到单独的产品或公司的细节时它便开始靠胡言乱语来敷衍你了。 例如这样 🔽
这里的“胡言乱语”指的是它会用其他不相关的概念进行回答,并且**你并不能够预期什么问题会有什么回答,这在商业场景下十分致命。在大多数情况下,ChatGPT 对于一些带有公理性质**的知识回答是没有问题的,作为一个可以日常侃大山闲聊的对象依然是合格的,可是你却看着它的强大的学习和理解能力望洋兴叹。 **“你这个孙悟空什么时候才能懂我,给我想要的回答?”** 这也是为什么说它能够回应大家的问题,但是却不能够回答出“我”想要的问题。 {'Header 1': '如何训练出专属于“你”的问答机器人?', 'Header 3': '**改变发生**'} 直到,Dify 横空出世。 你可以简单地将 Dify 理解为是一个能够帮助你进行数据清理和文档训练的地方。咱们也给狗屁通(GPT)补补课,手动给它补上缺失的语料。把它从通用型聊天机器人,变成你的专业问答机器人。是的,从侃大山到对答如流,这中间的鸿沟不是一点半点,需要强大的理解、归纳总结能力。不过这正是狗屁通(GPT)的强项。 {'Header 1': '如何训练出专属于“你”的问答机器人?', 'Header 3': '**注册并生成应用**'} 现在,我们打开 Dify 并注册一个聊天机器人,我们在这里选择“对话型应用”。
Duang,一个聊天机器人就做好了。
访问这个链接就可以看到一个聊天机器人了。但是,它现在也只是一个**通用型聊天机器人**,离商业可用的**专用型问答机器人**还差一个语料的距离。
{'Header 1': '如何训练出专属于“你”的问答机器人?', 'Header 3': '**准备语料**'} Dify 提供了一个名叫“数据集”的功能,这里就是我们上传语料的地方。
现在点击“创建数据集”选项,上传你的文本内容。
目前 Dify 仅支持上传单个文件,文件格式支持 TXT、HTML、MarkDown、PDF。 _是的没错,你也可以把电子书上传进来,用 AI 帮助你提炼书本内容。_ 在正式开始训练前,我们得先把教材准备好。好在 CODING 之前的所有文档皆以 Git 代码仓库 + Markdown 的形式进行协作,因此我只需要先把文档先拉到本地中。不过我现在碰到了第一个问题,那就是如何把仓库中的这一系列 .md 文档文件合并至同一个文件中? {'Header 1': '如何训练出专属于“你”的问答机器人?', 'Header 3': '**准备语料**'}
不怕,让 AI 给我们写一段 python 吧。
{'Header 1': '如何训练出专属于“你”的问答机器人?', 'Header 3': '**准备语料**'} 试着运行这个脚本,oh,输入路径后就成功生成了一篇总合文档!如果你想了解如何让 AI 给你写代码,不妨阅读[《如何用狗屁通(GPT )解决一个套娃问题》](http://mp.weixin.qq.com/s?\_\_biz=MzU2Njg1NDA3Mw==\&mid=2247484248\&idx=1\&sn=50809b40f520c767483e1a7b0eefb9c1\&chksm=fca76b8ecbd0e298e627140d63e7b3383d226ab293a2e8fefa04b5a1ee12f187520560ec1579\&scene=21#wechat\_redirect)。
{'Header 1': '如何训练出专属于“你”的问答机器人?', 'Header 3': '**开始训练**'} 现在要做的事,就是上传这个文件并静待训练成果了。
数据自动分段与清洗完成后,在刚创建的应用设置中的上下文,关联这一篇文档。为了保证响应速度和成本控制,这里直接用 3.5 模型。
{'Header 1': '如何训练出专属于“你”的问答机器人?', 'Header 3': '**训练成功**'} 现在再去和这个机器人互动,看看它会回答什么?
好了,你已经是个成熟的问答机器人了,可以回答更加复杂的产品问题了。
{'Header 1': '如何训练出专属于“你”的问答机器人?', 'Header 3': '**训练成功**'}
这个问答机器人花了多久做出来,成本如何? 整理语料+训练完成控制在半个小时以内,训练成本 0.27 美元。 现在,AI 可以深入到产品内部,变成妥妥的产品专家。只要有优秀的文档,所有公司都可以打造出专用型问答机器人。 武力对等才会有真正的平权。如果你对我的实践过程同样感兴趣,可以来体验一下我做好的机器人,地址:[https://udify.app/chat/F2Y4bKEWbuCb1FTC](https://udify.app/chat/F2Y4bKEWbuCb1FTC) 不妨也来 Dify 平台训练属于你自己的机器人。做一个考试问答机器人?出题机器人? {'Header 1': '使用Dify 和Twilio构建WhatsApp机器人'} > 作者:Warren, [Microsoft 最有價值專家 (MVP)](https://mvp.microsoft.com/en-US/mvp/profile/476f41d3-6bd1-ea11-a812-000d3a8dfe0d) {'Header 1': '使用Dify 和Twilio构建WhatsApp机器人', 'Header 2': '1. 概述'} 随着世界通过消息应用程序变得越来越紧密地连接在一起,聊天机器人已成为企业与客户进行更个人化交流的关键工具。 随着人工智能的崛起,聊天机器人变得更聪明,更个性化,更直观。在本文中,我们将向您展示如何使用使用Dify和Twilio将其与WhatsApp集成。 您将首先使用FastAPI 接入Dify设置后端,然后,您将集成Twilio的WhatsApp消息API,允许客户与您的WhatsApp聊天机器人开始对话。 使用Localtunnel,将FastAPI本地主机放在互联网上,使其可以供Twilio API通信。 {'Header 1': '使用Dify 和Twilio构建WhatsApp机器人', 'Header 2': '2. 準備工作'} - 安裝好Docker 和Docker Compose - Twilio帐户: 在[這裡](https://www.twilio.com/try-twilio) 創建一個免費Twilio帳戶 - 一部安装了WhatsApp的智能手机,用于测试您的AI聊天机器人 - 对FastAPI的基本理解,这是一个使用Python 3.6+构建API的框架 {'Header 1': '使用Dify 和Twilio构建WhatsApp机器人', 'Header 2': '3. 创建Dify基础编排聊天助手应用 (節錄自[手摸手教你把 Dify 接入微信生态](./dify-on-wechat.md))'} 首先,登录[Dify官方应用平台](https://cloud.dify.ai/signin),你可以选择使用Github登录或者使用Google登录。此外,你也可以参考Dify官方教程[Docker Compose 部署 | 中文 | Dify](https://docs.dify.ai/v/zh-hans/getting-started/install-self-hosted/docker-compose) 私有部署,Dify是开源项目,支持私有部署。
登录成功后,进入Dify页面,我们按照下方步骤创建一个基础编排聊天助手应用 1. 点击页面上方的工作室 2. 创建空白应用 3. 应用类型选择聊天助手 4. 聊天助手编排方式选择基础编排 5. 选择应用图标并为应用填写一个名称,比如基础编排聊天助手 6. 点击创建 {'Header 1': '使用Dify 和Twilio构建WhatsApp机器人', 'Header 2': '3. 创建Dify基础编排聊天助手应用 (節錄自[手摸手教你把 Dify 接入微信生态](./dify-on-wechat.md))'} 5. 选择应用图标并为应用填写一个名称,比如基础编排聊天助手 6. 点击创建
创建成功后我们会跳转到上图所示页面,我们继续配置应用 1. 选择模型,如gpt-3.5-turbo-0125 2. 设置模型参数 3. 填写应用提示词
在配置完成后,我们可以在右侧对话框进行测试,在测试完成后,进行如下操作 1. 发布 2. 更新 3. 访问API ##### (4)生成基础编排聊天助手API密钥 {'Header 1': '使用Dify 和Twilio构建WhatsApp机器人', 'Header 2': '3. 创建Dify基础编排聊天助手应用 (節錄自[手摸手教你把 Dify 接入微信生态](./dify-on-wechat.md))'} 1. 发布 2. 更新 3. 访问API ##### (4)生成基础编排聊天助手API密钥
在点击"访问API"后,我们会跳转到上图的API管理页面,在这个页面我们按照如下步骤获取API密钥: 1. 点击右上角API密钥 2. 点击创建密钥 3. 复制保存密钥 在保存密钥后,还需要查看右上角的API服务器,如果是Dify官网的应用,API服务器地址为 "https://api.dify.ai/v1", 如果是私有部署的,请确认你自己的API服务器地址。 至此,创建聊天助手的准备工作结束,在此小节中我们只需要保存好两个东西:**API密钥**与**API服务器地址** {'Header 1': '使用Dify 和Twilio构建WhatsApp机器人', 'Header 2': '4. 獲取Twilio密钥'} 转到[Twilio控制台] 畫面應該會直接獲取到Account SID 和Auth Token,保存好這两个东西。
{'Header 1': '使用Dify 和Twilio构建WhatsApp机器人', 'Header 2': '5. 创建您的聊天机器人'} 在这一部分,您将使用FastAPI和Twilio编写一个基本的聊天机器人的代码。 #### 5.1 下載代碼 ``` git clone https://github.com/somethingwentwell/dify-twilio-whatsapp ``` #### 5.2 配置.env 在项目根目录创建.env,內容如下: ``` TWILIO_NUMBER=+14155238886 TWILIO_ACCOUNT_SID=<在(4)獲取的Twilio Account SID> TWILIO_AUTH_TOKEN=<在(4)獲取的Twilio Auth Token> DIFY_URL=<在(3)獲取的Dify API服务器地址> DIFY_API_KEY=<在(3)獲取的Dify API密钥> ``` #### 5.3 運行代码 執行docker compose up ``` docker compose up ``` 如果运行成功,你应该会看到 ``` {'Header 1': '使用Dify 和Twilio构建WhatsApp机器人', 'Header 2': '5. 创建您的聊天机器人'} ``` docker compose up ``` 如果运行成功,你应该会看到 ``` dify-whatsapp-1 | INFO: Started server process [68] dify-whatsapp-1 | INFO: Waiting for application startup. dify-whatsapp-1 | INFO: Application startup complete. ``` 在浏览器中打开 http://localhost:9000。你应该看到的结果是一个JSON响应,内容为 {"msg": "working"}。 #### 5.4 使用Localtunnel 將本地项目放到公网访问 Twilio需要向您的后端发送消息,您需要在公共服务器上托管您的应用。一个简单的方法是使用localtunnel。 让FastAPI应用继续在9000端口运行,并在另一个终端窗口运行以下localtunnel命令: ``` npx localtunnel --port 9000 ``` {'Header 1': '使用Dify 和Twilio构建WhatsApp机器人', 'Header 2': '5. 创建您的聊天机器人'} ``` npx localtunnel --port 9000 ``` 上述命令在您的本地服务器(运行在9000端口)和localtunnel创建的公共域之间建立了一个连接。一旦您有了localtunnel转发URL,任何来自客户端对该URL的请求都会自动被定向到您的FastAPI后端。
#### 5.5 代码解释 ##### 5.5.1 检查该号码是否已在白名单中,不在白名单的用户直接返回“您未注册此服务。” ```python enrolled_numbers = ['+14155238886'] ``` 对应 ```python # Check if the number is enrolled if whatsapp_number not in enrolled_numbers: {'Header 1': '使用Dify 和Twilio构建WhatsApp机器人', 'Header 2': '5. 创建您的聊天机器人'} if whatsapp_number not in enrolled_numbers: message = client.messages.create( from_=f"whatsapp:{twilio_number}", body="You are not enrolled in this service.", to=f"whatsapp:{whatsapp_number}" ) return "" ``` ##### 5.5.2 将WhatsApp号码作为Dify会话ID,确保用户持续保持该会话 ```python conversation_ids = {} ``` 对应 ```python url = dify_url headers = { 'Content-Type': 'application/json', 'Authorization': f"Bearer {dify_api_key}", } data = { 'inputs': {}, 'query': Body, 'response_mode': 'streaming', {'Header 1': '使用Dify 和Twilio构建WhatsApp机器人', 'Header 2': '5. 创建您的聊天机器人'} 'query': Body, 'response_mode': 'streaming', 'conversation_id': conversation_ids.get(whatsapp_number, ''), 'user': whatsapp_number, } response = requests.post(url, headers=headers, data=json.dumps(data), stream=True) answer = [] for line in response.iter_lines(): if line: decoded_line = line.decode('utf-8') if decoded_line.startswith('data: '): decoded_line = decoded_line[6:] try: json_line = json.loads(decoded_line) if "conversation_id" in json_line: {'Header 1': '使用Dify 和Twilio构建WhatsApp机器人', 'Header 2': '5. 创建您的聊天机器人'} if "conversation_id" in json_line: conversation_ids[whatsapp_number] = json_line["conversation_id"] if json_line["event"] == "agent_thought": answer.append(json_line["thought"]) except json.JSONDecodeError: print(json_line) continue {'Header 1': '使用Dify 和Twilio构建WhatsApp机器人', 'Header 2': '5. 创建您的聊天机器人'} merged_answer = ''.join(answer) ``` {'Header 1': '使用Dify 和Twilio构建WhatsApp机器人', 'Header 2': '6. 配置您的Twilio沙箱以供WhatsApp使用'} #### 6.1 打开WhatsApp沙盒 要使用Twilio的消息API使聊天机器人能与WhatsApp用户通信,您需要配置Twilio沙箱以供WhatsApp使用。以下是操作方法: 转到[Twilio控制台](https://console.twilio.com/)并在左侧面板上选择消息选项卡。 在“试试看”下,点击“发送WhatsApp消息”。您将默认进入沙盒选项卡,您会看到一个电话号码“+14155238886”,旁边有一个加入的代码,右边有一个二维码。
要启用Twilio测试环境,将此代码的文本作为WhatsApp消息发送到显示的电话号码。如果您正在使用网络版本,可以点击超链接将您引导到WhatsApp聊天。 #### 6.2 配置WhatsApp沙盒 在“沙盒”选项卡旁边,选择“沙盒设置”选项卡。 {'Header 1': '使用Dify 和Twilio构建WhatsApp机器人', 'Header 2': '6. 配置您的Twilio沙箱以供WhatsApp使用'} #### 6.2 配置WhatsApp沙盒 在“沙盒”选项卡旁边,选择“沙盒设置”选项卡。 复制您的localtunnel URL并附加/message。将其粘贴到“当消息进入时”旁边的框中: Twilio沙盒webhook 完整的URL应如下所示:https://breezy-humans-help.loca.lt/message。 您将在FastAPI应用程序中配置的端点是/message,如上所述。聊天机器人的逻辑将在此端点上。 完成后,按“保存”按钮。
{'Header 1': '使用Dify 和Twilio构建WhatsApp机器人', 'Header 2': '7. WhatsApp測試'} 掃6.1 頁面的二維碼進入WhatsApp 沙盒環境,然後发送WhatsApp消息,并等待您的AI聊天机器人的回复。尝试向AI聊天机器人提问您可以向Dify 聊天助手提问的任何问题。
{'Header 1': '使用Dify 和Twilio构建WhatsApp机器人', 'Header 2': '8. 后记'} 现在,你的AI聊天机器人在WhatsApp上运行良好。也许你的下一步是使用你自己的WhatsApp商业账户,而不是Twilio沙盒,并使用服务器托管而不是在本地构建,使这个WhatsApp助手在生产中运行。希望你喜欢这个教程,我们下次再见。# 教你十几分钟不用代码创建 Midjourney 提示词机器人 _作者:歸藏的 AI 工具箱_ 试用了一下前几天我周刊里推荐的自然语言编程工具 Dify,它是 @goocarlos 开发的能够让一个不会代码的人只通过编写提示词生成一个 Web 应用,甚至连 API 也生成好了,你可以接入以后部署到你希望部署的平台上去。 下面这个应用就是我花 20 分钟写的,效果非常好,如果没有 Dify 我可能需要搞好久才能搞定。具体的功能就是根据输入的简短的主题生成 Midjourney 的提示词,也能帮助你快速填写常见的 Midjourney 命令。下面我会写一下这个应用的创建过程帮大家熟悉一下这个平台。 {'Header 1': '使用Dify 和Twilio构建WhatsApp机器人', 'Header 2': '8. 后记'} Dify 可以选择两种应用一种是对话型应用类似于 ChatGPT 那种,另一种是文本生成类应用没有多轮对话的机制点击按钮直接生成文本内容。我们要创建的 Midjoureny 提示词机器人,所以我们选择文本生成应用就行。 你可以在这里访问 Dify:https://dify.ai/
我们输入名称创建完成之后看到的页面就是我们的看板页面里面有一些数据监控和应用设置。我们先点击左侧的提示词编排,这里就是主要的工作页面了。
{'Header 1': '使用Dify 和Twilio构建WhatsApp机器人', 'Header 2': '8. 后记'} 这个页面左侧是提示词设置和一些其他功能,右侧可以实时预览和使用你创建的内容。前缀提示词就是用户每次输入内容后触发的提示词了,可以理解为每次 GPT 都会按照你的前缀提示词内容去处理用户输入的信息。
可以看一下我的前缀提示词结构,主要有两部分前面是中文写的让 GPT 按照下面英文的结构输出照片的描述。英文的结构就是生成提示词的模板了,主要意思是【主题彩色照片,错综复杂的图案,鲜明的对比,环境描述,相机型号,与输入内容相关的镜头焦距描述,与输入内容相关的构图描述,四位摄影师的名字】这个就是提示词的主要内容了。理论上你现在保存到右边预览区域输入你想生成的主题就能生成对应提示词了。
{'Header 1': '使用Dify 和Twilio构建WhatsApp机器人', 'Header 2': '8. 后记'} 那可能有人注意到了后面的 \{{proportion\}} 和 \{{version\}} 是什么呢,可以看到我右边需要用户选择图像比例和模型版本这两个变量就是用来传递用户选择的信息的。我们看一下如何设置。
我们的功能是把用户选择的信息填到提示词的最后方便用户直接复制不用重新填写和记忆这些命令,这里就要用到下面的变量功能。 变量的作用就是把用户表单填写或者选择的内容动态的带入到提示词里面。比如我这里创建了两个变量一个代表图像比例一个代表模型版本。点击添加按钮创建变量。
{'Header 1': '使用Dify 和Twilio构建WhatsApp机器人', 'Header 2': '8. 后记'} 创建之后首先需要填写前面的变量 Key 和字段名称,变量 Key 需要英文。后面的可选开启之后这个字段就会是选填的。之后我们需要点击操作栏的设置来设置变量内容。
变量包括两种内容一种是文本变量一种是下拉选项,文本的就是用户需要手动输入,下拉的话就是选择了。这里我们主要是不想用户手打命令,所以我们选择下拉选项。增加需要的选项就行。
之后就是使用变量了,我们需要把变量 Key 用两个 {} 包起来填写到前缀提示词里。这里由于我们不想让 GPT 改用户选择的内容,我加了一句提示词“如实输出变量内容”。 {'Header 1': '使用Dify 和Twilio构建WhatsApp机器人', 'Header 2': '8. 后记'}
加了上面那句话 GPT 还是有一定几率改掉我们的变量内容怎么办,我们可以在右侧模型选择这里把多样性调低,这样创造性输出就会降低,他就不容易改写我们的变量内容了。其他的几个参数的意思可看小叹号了解。
好了到这里我们的应用就创建完成了,测试输出没问题以后点击右上角的发布按钮,你的应用就发布了。你你和用户可以通过公开访问 URL 的地址访问你的应用。可以在设置里设置应用名称以及简介、图标之类的内容。
{'Header 1': '使用Dify 和Twilio构建WhatsApp机器人', 'Header 2': '8. 后记'} 这就是利用 Dify 创建一个简单 AI 应用的流程,你还可以通过生成的 API 把你的应用部署在其他平台或者更改它的 UI。同时 Dify 还支持上传你自己的数据,比如你可以建一个客服机器人帮助你回答自己产品的相关问题。教程到这里就结束了,感谢 @goocarlos 创建了这么好的产品。 {'Header 1': '开源许可证', 'Header 2': 'Dify 开源许可证'} Dify 项目在 Apache License 2.0 许可下开源,同时包含以下附加条件: 1. Dify 允许被用于商业化,例如作为其他应用的“后端即服务”使用,或者作为应用开发平台提供给企业。然而,当满足以下条件时,必须联系生产者获得商业许可: * 多租户 SaaS 服务:除非获得 Dify 的明确书面授权,否则不得使用 Dify.AI 的源码来运营与 Dify.AI 服务版类似的多租户 SaaS 服务。 * LOGO 及版权信息:在使用 Dify 的过程中,不得移除或修改 Dify 控制台内的 LOGO 或版权信息。 请通过电子邮件 [business@dify.ai](mailto:business@dify.ai) 联系我们咨询许可事宜。 2. 作为贡献者,你应同意你贡献的代码: * 生产者有权将开源协议调整为更严格或更宽松的形式。 * 可用于商业目的,例如 Dify 的云业务。 {'Header 1': '开源许可证', 'Header 2': 'Dify 开源许可证'} * 可用于商业目的,例如 Dify 的云业务。 除此之外,所有其他权利和限制均遵循 Apache License 2.0。如果你需要更多详细信息,可以参考 Apache License 2.0 的完整版本。本产品的交互设计受到外观专利保护。 © 2024 LangGenius, Inc. {'Header 1': '用户协议', 'Header 3': '关于数据安全'} 我们非常重视您的数据安全,并正在推进获得 SOC2 和 ISO27001 认证。 Dify.AI 的云服务位于美国区的 AWS 上,仅极少数获得授权的人员经审批后才可访问用户的数据。另外,我们的代码均在 GitHub 开源,如果您对云服务有安全担忧可以使用自部署版本。 在 Dify 的自部署版本中,仅有一处调用 Dify 服务器,即检查当前版本更新 API 的功能。且必须由管理员在后台触发。其它没有任何使用到远程服务器的技术,因此您可以安全使用。 如果您仍有疑虑,可以通过设置防火墙等方式对数据进行保护。 {'Header 1': '云服务'} {% hint style="info" %} **提示:** Dify 目前正在 Beta 测试阶段,如文档与产品存在不一致,请以产品实际体验为准。 {% endhint %} Dify 为所有人提供了[云服务](http://cloud.dify.ai),你无需自己部署即可使用 Dify 的完整功能。要使用 Dify 云服务,你需要有一个 GitHub 或 Google 账号。 1. 登录 [Dify 云服务](https://cloud.dify.ai),创建一个或加入已有的 Workspace 2. 配置你的模型供应商,或使用我们提供的托管模型供应商 3. 可以[创建应用](../guides/application\_orchestrate/creating-an-application.md)了! {'Header 1': '云服务', 'Header 3': '订阅计划'} 我们为云服务设计了多个订阅计划,您可以根据团队情况按需订阅: * Sandbox(免费版) * 专业版 * 团队版 * 企业版 各版本定价请参考:[https://dify.ai/pricing](https://dify.ai/pricing) {'Header 1': 'Dify Premium'} Dify Premium 是一款 [AWS AMI](https://docs.aws.amazon.com/zh\_cn/AWSEC2/latest/UserGuide/ec2-instances-and-amis.html) 产品,允许自定义品牌,并可作为 EC2 一键部署到你的 AWS VPC 上。前往 [AWS Marketplace](https://aws.amazon.com/marketplace/pp/prodview-t22mebxzwjhu6) 进行订阅并使用,它适合以下场景: * 在中小型企业内,需在服务器上创建一个或多应用程序,并且关心数据私有化。 * 你对 [Dify Cloud ](https://docs.dify.ai/v/zh-hans/getting-started/cloud)订阅计划感兴趣,但所需的用例资源超出了[计划](https://dify.ai/pricing)内所提供的资源。 * 你希望在组织内采用 Dify Enterprise 之前进行 POC 验证。 {'Header 1': 'Dify Premium', 'Header 3': '设置'} 如果这是您第一次访问 Dify,请输入管理员初始化密码(设置为你的 EC2 实例 ID)以开始设置过程。 部署 AMI 后,通过 EC2 控制台中找到的实例公有 IP 访问 Dify(默认使用 HTTP 端口 80)。 {'Header 1': 'Dify Premium', 'Header 3': '升级'} 在 EC2 实例中,运行以下命令: ```bash git clone https://github.com/langgenius/dify.git /tmp/dify mv -f /tmp/dify/docker/* /dify/ rm -rf /tmp/dify docker-compose down docker-compose pull docker-compose -f docker-compose.yaml -f docker-compose.override.yaml up -d ``` {'Header 1': 'Dify Premium', 'Header 3': '定制化'} 就像自托管部署一样,你可以根据需要修改 EC2 实例中 `.env` 下的环境变量。然后使用以下命令重新启动 Dify: ``` docker-compose down ocker-compose -f docker-compose.yaml -f docker-compose.override.yaml up -d ``` {'Header 1': '环境变量说明', 'Header 3': '公共变量'} #### CONSOLE\_API\_URL 控制台 API 后端 URL,用于拼接授权回调,传空则为同域。范例:`https://api.console.dify.ai`。 #### CONSOLE\_WEB\_URL 控制台 web **前端** URL,用于拼接部分前端地址,以及 CORS 配置使用,传空则为同域。范例:`https://console.dify.ai` #### SERVICE\_API\_URL Service API URL,用于**给前端**展示 Service API Base URL,传空则为同域。范例:`https://api.dify.ai` #### APP\_API\_URL WebApp API 后端 URL,用于声明**前端** API 后端地址,传空则为同域。范例:`https://app.dify.ai` #### APP\_WEB\_URL WebApp URL,用于**给前端**展示 WebAPP API Base URL,传空则为同域。范例:`https://api.app.dify.ai` {'Header 1': '环境变量说明', 'Header 3': '公共变量'} #### FILES\_URL 文件预览或下载 URL 前缀,用于将文件预览或下载 URL 给前端展示或作为多模态模型输入; 为了防止他人伪造,图片预览 URL 是带有签名的,并且有 5 分钟过期时间。 *** {'Header 1': '环境变量说明', 'Header 3': '服务端'} #### MODE 启动模式,仅使用 docker 启动时可用,源码启动无效。 * api 启动 API Server。 * worker 启动异步队列 worker。 #### DEBUG 调试模式,默认 false,建议本地开发打开该配置,可防止 monkey patch 导致的一些问题出现。 #### FLASK\_DEBUG Flask 调试模式,开启可在接口输出 trace 信息,方便调试。 #### SECRET\_KEY 一个用于安全地签名会话 cookie 并在数据库上加密敏感信息的密钥。初次启动需要设置改变量。可以使用`openssl rand -base64 42`生成一个强密钥。 #### DEPLOY\_ENV 部署环境。 * PRODUCTION(默认) 生产环境。 * TESTING 测试环境,前端页面会有明显颜色标识,该环境为测试环境。 #### LOG\_LEVEL 日志输出等级,默认为 INFO。生产建议设置为 ERROR。 {'Header 1': '环境变量说明', 'Header 3': '服务端'} 日志输出等级,默认为 INFO。生产建议设置为 ERROR。 #### MIGRATION\_ENABLED 当设置为 true 时,会在容器启动时自动执行数据库迁移,仅使用 docker 启动时可用,源码启动无效。源码启动需要在 api 目录手动执行 `flask db upgrade`。 #### CHECK\_UPDATE\_URL 是否开启检查版本策略,若设置为 false,则不调用 `https://updates.dify.ai` 进行版本检查。由于目前国内无法直接访问基于 CloudFlare Worker 的版本接口,设置该变量为空,可以屏蔽该接口调用。 #### 容器启动相关配置 仅在使用 docker 镜像或者 docker-compose 启动时有效。 * DIFY\_BIND\_ADDRESS API 服务绑定地址,默认:0.0.0.0,即所有地址均可访问。 * DIFY\_PORT API 服务绑定端口号,默认 5001。 * SERVER\_WORKER\_AMOUNT {'Header 1': '环境变量说明', 'Header 3': '服务端'} API 服务绑定端口号,默认 5001。 * SERVER\_WORKER\_AMOUNT API 服务 Server worker 数量,即 gevent worker 数量,公式:`cpu 核心数 x 2 + 1`可参考:https://docs.gunicorn.org/en/stable/design.html#how-many-workers * SERVER\_WORKER\_CLASS 默认为 gevent,若为 windows,可以切换为 sync 或 solo。 * GUNICORN\_TIMEOUT 请求处理超时时间,默认 200,建议 360,以支持更长的 sse 连接时间。 * CELERY\_WORKER\_CLASS 和 `SERVER_WORKER_CLASS` 类似,默认 gevent,若为 windows,可以切换为 sync 或 solo。 * CELERY\_WORKER\_AMOUNT Celery worker 数量,默认为 1,按需设置。 * HTTP\_PROXY {'Header 1': '环境变量说明', 'Header 3': '服务端'} Celery worker 数量,默认为 1,按需设置。 * HTTP\_PROXY HTTP 代理地址,用于解决国内无法访问 OpenAI、HuggingFace 的问题。注意,若代理部署在宿主机(例如`http://127.0.0.1:7890`),此处代理地址应当和接入本地模型时一样,使用docker容器内部的宿主机地址(例如`http://192.168.1.100:7890`或`http://172.17.0.1:7890`)。 * HTTPS\_PROXY HTTPS 代理地址,用于解决国内无法访问 OpenAI、HuggingFace 的问题。同上。 #### 数据库配置 数据库使用 PostgreSQL,请使用 public schema。 * DB\_USERNAME:用户名 * DB\_PASSWORD:密码 * DB\_HOST:数据库 host * DB\_PORT:数据库端口号,默认 5432 * DB\_DATABASE:数据库 database {'Header 1': '环境变量说明', 'Header 3': '服务端'} * DB\_DATABASE:数据库 database * SQLALCHEMY\_POOL\_SIZE:数据库连接池大小,默认 30 个连接数,可适当增加。 * SQLALCHEMY\_POOL\_RECYCLE:数据库连接池回收时间,默认 3600 秒。 * SQLALCHEMY\_ECHO:是否打印 SQL,默认 false。 #### Redis 配置 该 Redis 配置用于缓存以及对话时的 pub/sub。 * REDIS\_HOST:Redis host * REDIS\_PORT:Redis port,默认 6379 * REDIS\_DB:Redis Database,默认为 0,请和 Session Redis、Celery Broker 分开用不同 Database。 * REDIS\_USERNAME:Redis 用户名,默认为空 * REDIS\_PASSWORD:Redis 密码,默认为空,强烈建议设置密码。 * REDIS\_USE\_SSL:是否使用 SSL 协议进行连接,默认 false #### Celery 配置 {'Header 1': '环境变量说明', 'Header 3': '服务端'} #### Celery 配置 * CELERY\_BROKER\_URL 格式如下
redis://<redis_username>:<redis_password>@<redis_host>:<redis_port>/<redis_database>

范例:`redis://:difyai123456@redis:6379/1` * BROKER\_USE\_SSL 若设置为 true,则使用 SSL 协议进行连接,默认 false #### CORS 配置 用于设置前端跨域访问策略。 * CONSOLE\_CORS\_ALLOW\_ORIGINS 控制台 CORS 跨域策略,默认为 `*`,即所有域名均可访问。 * WEB\_API\_CORS\_ALLOW\_ORIGINS WebAPP CORS 跨域策略,默认为 `*`,即所有域名均可访问。 {'Header 1': '环境变量说明', 'Header 3': '服务端'} WebAPP CORS 跨域策略,默认为 `*`,即所有域名均可访问。 详细配置可参考:[跨域/身份相关指南](https://avytux375gg.feishu.cn/wiki/HyX3wdF1YiejX3k3U2CcTcmQnjg) #### 文件存储配置 用于存储数据集上传的文件、团队/租户的加密密钥等等文件。 * STORAGE\_TYPE 存储设施类型 * local(默认) 本地文件存储,若选择此项则需要设置下方 `STORAGE_LOCAL_PATH` 配置。 * s3 S3 对象存储,若选择此项则需要设置下方 S3\_ 开头的配置。 * azure-blob Azure Blob 存储,若选择此项则需要设置下方 AZURE\_BLOB\_ 开头的配置。 * STORAGE\_LOCAL\_PATH {'Header 1': '环境变量说明', 'Header 3': '服务端'} * STORAGE\_LOCAL\_PATH 默认为 storage,即存储在当前目录的 storage 目录下。若使用 docker 或 docker-compose 进行部署,请务必将两个容器中 `/app/api/storage` 目录挂载到同一个本机目录,否则可能会出现文件找不到的报错。 * S3\_ENDPOINT:S3 端点地址 * S3\_BUCKET\_NAME:S3 桶名称 * S3\_ACCESS\_KEY:S3 Access Key * S3\_SECRET\_KEY:S3 Secret Key * S3\_REGION:S3 地域信息,如:us-east-1 * AZURE\_BLOB\_ACCOUNT\_NAME: your-account-name 如 'difyai' * AZURE\_BLOB\_ACCOUNT\_KEY: your-account-key 如 'difyai' * AZURE\_BLOB\_CONTAINER\_NAME: your-container-name 如 'difyai-container' {'Header 1': '环境变量说明', 'Header 3': '服务端'} * AZURE\_BLOB\_ACCOUNT\_URL: 'https://\.blob.core.windows.net' #### 向量数据库配置 * VECTOR\_STORE **可使用的枚举类型包括:** * `weaviate` * `qdrant` * `milvus` * `zilliz` 与 `milvus` 一致 * `myscale` * `pinecone` (暂未开放) * `tidb_vector` * WEAVIATE\_ENDPOINT Weaviate 端点地址,如:`http://weaviate:8080`。 * WEAVIATE\_API\_KEY 连接 Weaviate 使用的 api-key 凭据。 * WEAVIATE\_BATCH\_SIZE {'Header 1': '环境变量说明', 'Header 3': '服务端'} * WEAVIATE\_BATCH\_SIZE Weaviate 批量创建索引 Object 的数量,默认 100。可参考此文档:https://weaviate.io/developers/weaviate/manage-data/import#how-to-set-batch-parameters * WEAVIATE\_GRPC\_ENABLED 是否使用 gRPC 方式与 Weaviate 进行交互,开启后性能会大大增加,本地可能无法使用,默认为 true。 * QDRANT\_URL Qdrant 端点地址,如:`https://your-qdrant-cluster-url.qdrant.tech/` * QDRANT\_API\_KEY 连接 Qdrant 使用的 api-key 凭据。 * PINECONE\_API\_KEY 连接 Pinecone 使用的 api-key 凭据。 * PINECONE\_ENVIRONMENT Pinecone 所在的额环境,如:`us-east4-gcp` {'Header 1': '环境变量说明', 'Header 3': '服务端'} Pinecone 所在的额环境,如:`us-east4-gcp` * MILVUS\_HOST Milvus host 配置。 * MILVUS\_PORT Milvus post 配置。 * MILVUS\_USER Milvus user 配置,默认为空。 * MILVUS\_PASSWORD Milvus 密码配置,默认为空。 * MILVUS\_SECURE Milvus 是否使用 SSL 连接,默认 false。 * MYSCALE\_HOST MyScale host 配置。 * MYSCALE\_PORT MyScale port 配置。 * MYSCALE\_USER MyScale 用户名配置,默认为 `default`。 * MYSCALE\_PASSWORD MyScale 密码配置,默认为空。 * MYSCALE\_DATABASE MyScale 数据库配置,默认为 `default`。 * MYSCALE\_FTS\_PARAMS {'Header 1': '环境变量说明', 'Header 3': '服务端'} * MYSCALE\_FTS\_PARAMS MyScale 全文搜索配置, 如需多语言支持,请参考 [MyScale 文档](https://myscale.com/docs/en/text-search/#understanding-fts-index-parameters),默认为空(仅支持英语)。 * TIDB\_VECTOR\_HOST TiDB Vector host 配置,如:`xxx.eu-central-1.xxx.tidbcloud.com` * TIDB\_VECTOR\_PORT TiDB Vector 端口号配置,如:`4000` * TIDB\_VECTOR\_USER TiDB Vector 用户配置,如:`xxxxxx.root` * TIDB\_VECTOR\_PASSWORD TiDB Vector 密码配置 * TIDB\_VECTOR\_DATABASE TiDB Vector 数据库配置,如:`dify` #### 知识库配置 * UPLOAD\_FILE\_SIZE\_LIMIT {'Header 1': '环境变量说明', 'Header 3': '服务端'} #### 知识库配置 * UPLOAD\_FILE\_SIZE\_LIMIT 上传文件大小限制,默认 15M。 * UPLOAD\_FILE\_BATCH\_LIMIT 每次上传文件数上限,默认 5 个。 * ETL\_TYPE **可使用的枚举类型包括:** * dify Dify 自研文件 Extract 方案 * Unstructured Unstructured.io 文件 Extract 方案 * UNSTRUCTURED\_API\_URL Unstructured API 路径,当 ETL\_TYPE 为 Unstructured 需要配置。 如:`http://unstructured:8000/general/v0/general` #### 多模态模型配置 * MULTIMODAL\_SEND\_IMAGE\_FORMAT {'Header 1': '环境变量说明', 'Header 3': '服务端'} * MULTIMODAL\_SEND\_IMAGE\_FORMAT 多模态模型输入时,发送图片的格式,默认为 `base64`,可选 `url`。 `url` 模式下,调用的延迟会比 `base64` 模式下低,一般建议使用兼容更好的 `base64` 模式。 若配置为 `url`,则需要将 `FILES_URL` 配置为外部可访问的地址,以便多模态模型可以访问到图片。 * UPLOAD\_IMAGE\_FILE\_SIZE\_LIMIT 上传图片文件大小限制,默认 10M。 #### Sentry 配置 用于应用监控和错误日志跟踪。 * SENTRY\_DSN Sentry DSN 地址,默认为空,为空时则所有监控信息均不上报 Sentry。 * SENTRY\_TRACES\_SAMPLE\_RATE Sentry events 的上报比例,若为 0.01,则为 1%。 * SENTRY\_PROFILES\_SAMPLE\_RATE Sentry profiles 的上报比例,若为 0.01,则为 1%。 {'Header 1': '环境变量说明', 'Header 3': '服务端'} Sentry profiles 的上报比例,若为 0.01,则为 1%。 #### Notion 集成配置 Notion 集成配置,变量可通过申请 Notion integration 获取:[https://www.notion.so/my-integrations](https://www.notion.so/my-integrations) * NOTION\_CLIENT\_ID * NOTION\_CLIENT\_SECRET #### 邮件相关配置 * MAIL\_TYPE * resend * MAIL\_DEFAULT\_SEND\_FROM\ 发件人的电子邮件名称,例如:no-reply [no-reply@dify.ai](mailto:no-reply@dify.ai),非必需。 * RESEND\_API\_KEY\ 用于 Resend 邮件提供程序的 API 密钥,可以从 API 密钥获取。 * smtp * SMTP\_SERVER\ SMTP 服务器地址 * SMTP\_PORT\ SMTP 服务器端口号 {'Header 1': '环境变量说明', 'Header 3': '服务端'} SMTP 服务器地址 * SMTP\_PORT\ SMTP 服务器端口号 * SMTP\_USERNAME\ SMTP 用户名 * SMTP\_PASSWORD\ SMTP 密码 * SMTP\_USE\_TLS\ 是否使用 TLS,默认为 false * MAIL\_DEFAULT\_SEND\_FROM\ 发件人的电子邮件名称,例如:no-reply [no-reply@dify.ai](mailto:no-reply@dify.ai),非必需。 #### 其他 * INVITE\_EXPIRY\_HOURS:成员邀请链接有效时间(小时),默认:72。 *** {'Header 1': '环境变量说明', 'Header 3': 'Web 前端'} #### SENTRY\_DSN Sentry DSN 地址,默认为空,为空时则所有监控信息均不上报 Sentry。 {'Header 1': '环境变量说明', 'Header 2': '已废弃'} #### CONSOLE\_URL > ⚠️ 修改于 0.3.8,于 0.4.9 废弃,替代为:`CONSOLE_API_URL` 和 `CONSOLE_WEB_URL`。 控制台 URL,用于拼接授权回调、控制台前端地址,以及 CORS 配置使用,传空则为同域。范例:`https://console.dify.ai`。 #### API\_URL > ⚠️ 修改于 0.3.8,于 0.4.9 废弃,替代为 `SERVICE_API_URL`。 API Url,用于**给前端**展示 Service API Base Url,传空则为同域。范例:`https://api.dify.ai` #### APP\_URL > ⚠️ 修改于 0.3.8,于 0.4.9 废弃,替代为 `APP_API_URL` 和 `APP_WEB_URL`。 WebApp Url,用于声明**前端** API 后端地址,传空则为同域。范例:`https://app.dify.ai` #### Session 配置 > ⚠️ 该配置从 0.3.24 版本起废弃。 {'Header 1': '环境变量说明', 'Header 2': '已废弃'} #### Session 配置 > ⚠️ 该配置从 0.3.24 版本起废弃。 仅 API 服务使用,用于验证接口身份。 * SESSION\_TYPE: Session 组件类型 * redis(默认) 选择此项,则需要设置下方 SESSION\_REDIS\_ 开头的环境变量。 * sqlalchemy 选择此项,则使用当前数据库连接,并使用 sessions 表进行读写 session 记录。 * SESSION\_REDIS\_HOST:Redis host * SESSION\_REDIS\_PORT:Redis port,默认 6379 * SESSION\_REDIS\_DB:Redis Database,默认为 0,请和 Redis、Celery Broker 分开用不同 Database。 * SESSION\_REDIS\_USERNAME:Redis 用户名,默认为空 * SESSION\_REDIS\_PASSWORD:Redis 密码,默认为空,强烈建议设置密码。 {'Header 1': '环境变量说明', 'Header 2': '已废弃'} * SESSION\_REDIS\_USE\_SSL:是否使用 SSL 协议进行连接,默认 false #### Cookie 策略配置 > ⚠️ 该配置从 0.3.24 版本起废弃。 用于设置身份校验的 Session Cookie 浏览器策略。 * COOKIE\_HTTPONLY Cookie HttpOnly 配置,默认为 true。 * COOKIE\_SAMESITE Cookie SameSite 配置,默认为 Lax。 * COOKIE\_SECURE Cookie Secure 配置,默认为 false。 {'Header 1': '本地源码启动', 'Header 3': '前置条件'} | 操作系统 | 软件 | 说明 | {'Header 1': '本地源码启动', 'Header 3': '前置条件'} | -------------------------- | -------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | {'Header 1': '本地源码启动', 'Header 3': '前置条件'} | macOS 10.14 or later | Docker Desktop | 将 Docker 虚拟机(VM)设置为使用至少 2 个虚拟 CPU(vCPU)和 8 GB 的初始内存。否则,安装可能会失败。有关更多信息,请参阅[在 Mac 上安装 Docker Desktop](https://docs.docker.com/desktop/mac/install/)。 | {'Header 1': '本地源码启动', 'Header 3': '前置条件'} | Linux platforms |

Docker 19.03 or later
Docker Compose 1.25.1 or later

| 请参阅[安装 Docker](https://docs.docker.com/engine/install/) 和[安装 Docker Compose](https://docs.docker.com/compose/install/) 以获取更多信息。 | {'Header 1': '本地源码启动', 'Header 3': '前置条件'} | Windows with WSL 2 enabled | Docker Desktop | 我们建议将源代码和其他数据绑定到 Linux 容器中时,将其存储在 Linux 文件系统中,而不是 Windows 文件系统中。有关更多信息,请参阅[使用 WSL 2 后端在 Windows 上安装 Docker Desktop](https://docs.docker.com/desktop/windows/install/#wsl-2-backend)。 | > 若需要使用 OpenAI TTS,需要在系统中安装 FFmpeg 才可正常使用,详情可参考:[Link](https://docs.dify.ai/v/zh-hans/learn-more/faq/install-faq#id-15.-wen-ben-zhuan-yu-yin-yu-dao-zhe-ge-cuo-wu-zen-me-ban)。 Clone Dify 代码: ```Bash {'Header 1': '本地源码启动', 'Header 3': '前置条件'} Clone Dify 代码: ```Bash git clone https://github.com/langgenius/dify.git ``` 在启用业务服务之前,我们需要先部署 PostgresSQL / Redis / Weaviate(如果本地没有的话),可以通过以下命令启动: ```Bash cd docker docker compose -f docker-compose.middleware.yaml up -d ``` *** {'Header 1': '本地源码启动', 'Header 3': '服务端部署'} * API 接口服务 * Worker 异步队列消费服务 #### 安装基础环境 服务器启动需要 Python 3.10.x。建议使用 [pyenv](https://github.com/pyenv/pyenv) 快速安装 Python 环境。 要安装其他 Python 版本,请使用 `pyenv install`。 ```Bash pyenv install 3.10 ``` 要切换到 "3.10" Python 环境,请使用以下命令: ```Bash pyenv global 3.10 ``` #### 启动步骤 1. 进入 api 目录 ``` cd api ``` 2. 复制环境变量配置文件 ``` cp .env.example .env ``` 3. 生成随机密钥,并替换 `.env` 中 `SECRET_KEY` 的值 ``` openssl rand -base64 42 sed -i 's/SECRET_KEY=.*/SECRET_KEY=/' .env ``` 4. 安装依赖包 {'Header 1': '本地源码启动', 'Header 3': '服务端部署'} ``` 4. 安装依赖包 Dify API 服务使用 [Poetry](https://python-poetry.org/docs/) 来管理依赖。您可以执行 `poetry shell` 来激活环境。 ``` poetry env use 3.10 poetry install ``` 5. 执行数据库迁移 将数据库结构迁移至最新版本。 ``` poetry shell flask db upgrade ``` 6. 启动 API 服务 ``` flask run --host 0.0.0.0 --port=5001 --debug ``` 正确输出: ``` * Debug mode: on INFO:werkzeug:WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. * Running on all addresses (0.0.0.0) {'Header 1': '本地源码启动', 'Header 3': '服务端部署'} * Running on all addresses (0.0.0.0) * Running on http://127.0.0.1:5001 INFO:werkzeug:Press CTRL+C to quit INFO:werkzeug: * Restarting with stat WARNING:werkzeug: * Debugger is active! INFO:werkzeug: * Debugger PIN: 695-801-919 ``` 7. 启动 Worker 服务 用于消费异步队列任务,如数据集文件导入、更新数据集文档等异步操作。 Linux / MacOS 启动: ``` celery -A app.celery worker -P gevent -c 1 -Q dataset,generation,mail,ops_trace --loglevel INFO ``` 如果使用 Windows 系统启动,请替换为该命令: ``` {'Header 1': '本地源码启动', 'Header 3': '服务端部署'} ``` 如果使用 Windows 系统启动,请替换为该命令: ``` celery -A app.celery worker -P solo --without-gossip --without-mingle -Q dataset,generation,mail,ops_trace --loglevel INFO ``` 正确输出: ``` -------------- celery@TAKATOST.lan v5.2.7 (dawn-chorus) --- ***** ----- -- ******* ---- macOS-10.16-x86_64-i386-64bit 2023-07-31 12:58:08 - *** --- * --- - ** ---------- [config] - ** ---------- .> app: app:0x7fb568572a10 - ** ---------- .> transport: redis://:**@localhost:6379/1 {'Header 1': '本地源码启动', 'Header 3': '服务端部署'} - ** ---------- .> results: postgresql://postgres:**@localhost:5432/dify - *** --- * --- .> concurrency: 1 (gevent) -- ******* ---- .> task events: OFF (enable -E to monitor tasks in this worker) --- ***** ----- -------------- [queues] .> dataset exchange=dataset(direct) key=dataset .> generation exchange=generation(direct) key=generation .> mail exchange=mail(direct) key=mail {'Header 1': '本地源码启动', 'Header 3': '服务端部署'} [tasks] . tasks.add_document_to_index_task.add_document_to_index_task . tasks.clean_dataset_task.clean_dataset_task . tasks.clean_document_task.clean_document_task . tasks.clean_notion_document_task.clean_notion_document_task . tasks.create_segment_to_index_task.create_segment_to_index_task . tasks.deal_dataset_vector_index_task.deal_dataset_vector_index_task . tasks.document_indexing_sync_task.document_indexing_sync_task . tasks.document_indexing_task.document_indexing_task {'Header 1': '本地源码启动', 'Header 3': '服务端部署'} . tasks.document_indexing_update_task.document_indexing_update_task . tasks.enable_segment_to_index_task.enable_segment_to_index_task . tasks.generate_conversation_summary_task.generate_conversation_summary_task . tasks.mail_invite_member_task.send_invite_member_mail_task . tasks.remove_document_from_index_task.remove_document_from_index_task . tasks.remove_segment_from_index_task.remove_segment_from_index_task . tasks.update_segment_index_task.update_segment_index_task {'Header 1': '本地源码启动', 'Header 3': '服务端部署'} . tasks.update_segment_keyword_index_task.update_segment_keyword_index_task {'Header 1': '本地源码启动', 'Header 3': '服务端部署'} [2023-07-31 12:58:08,831: INFO/MainProcess] Connected to redis://:**@localhost:6379/1 [2023-07-31 12:58:08,840: INFO/MainProcess] mingle: searching for neighbors [2023-07-31 12:58:09,873: INFO/MainProcess] mingle: all alone [2023-07-31 12:58:09,886: INFO/MainProcess] pidbox: Connected to redis://:**@localhost:6379/1. [2023-07-31 12:58:09,890: INFO/MainProcess] celery@TAKATOST.lan ready. ``` *** {'Header 1': '本地源码启动', 'Header 3': '前端页面部署'} Web 前端客户端页面服务 #### 安装基础环境 Web 前端服务启动需要用到 [Node.js v18.x (LTS)](http://nodejs.org) 、[NPM 版本 8.x.x ](https://www.npmjs.com/)或 [Yarn](https://yarnpkg.com/)。 * 安装 NodeJS + NPM 进入 https://nodejs.org/en/download,选择对应操作系统的 v18.x 以上的安装包下载并安装,建议 stable 版本,已自带 NPM。 #### 启动步骤 1. 进入 web 目录 ``` cd web ``` 2. 安装依赖包 ``` npm install ``` 3. 配置环境变量。在当前目录下创建文件 `.env.local`,并复制`.env.example`中的内容。根据需求修改这些环境变量的值: ``` # For production release, change this to PRODUCTION {'Header 1': '本地源码启动', 'Header 3': '前端页面部署'} NEXT_PUBLIC_DEPLOY_ENV=DEVELOPMENT # The deployment edition, SELF_HOSTED NEXT_PUBLIC_EDITION=SELF_HOSTED # The base URL of console application, refers to the Console base URL of WEB service if console domain is # different from api or web app domain. # example: http://cloud.dify.ai/console/api NEXT_PUBLIC_API_PREFIX=http://localhost:5001/console/api # The URL for Web APP, refers to the Web App base URL of WEB service if web app domain is different from # console or api domain. {'Header 1': '本地源码启动', 'Header 3': '前端页面部署'} # console or api domain. # example: http://udify.app/api NEXT_PUBLIC_PUBLIC_API_PREFIX=http://localhost:5001/api {'Header 1': '本地源码启动', 'Header 3': '前端页面部署'} # SENTRY NEXT_PUBLIC_SENTRY_DSN= NEXT_PUBLIC_SENTRY_ORG= NEXT_PUBLIC_SENTRY_PROJECT= ``` 4. 构建代码 ``` npm run build ``` 5. 启动 web 服务 ``` npm run start # or yarn start # or pnpm start ``` 正常启动后,终端会输出如下信息: ``` ready - started server on 0.0.0.0:3000, url: http://localhost:3000 warn - You have enabled experimental feature (appDir) in next.config.js. warn - Experimental features are not covered by semver, and may cause unexpected or broken application behavior. Use at your own risk. {'Header 1': '本地源码启动', 'Header 3': '前端页面部署'} info - Thank you for testing `appDir` please leave your feedback at https://nextjs.link/app-feedback ``` {'Header 1': '本地源码启动', 'Header 3': '访问 Dify'} 最后,访问 http://127.0.0.1:3000 即可使用本地部署的 Dify。 {'Header 1': '常见问题', 'Header 3': '1. 长时间未收到密码重置邮件应如何处理?'} 你需要在 `.env` 文件内配置 `Mail` 参数项,详细说明请参考 [《环境变量说明:邮件相关配置》](https://docs.dify.ai/v/zh-hans/getting-started/install-self-hosted/environments#you-jian-xiang-guan-pei-zhi)。 修改配置后,运行以下命令重启服务。 ```bash docker compose down docker compose up -d ``` 如果依然没能收到邮件,请检查邮件服务是否正常,以及邮件是否进入了垃圾邮件列表。 {'Header 1': '部署 Dify 到 Zeabur'} [Zeabur](https://zeabur.com) 是一个服务部署平台,可以通过一键部署的方式部署 Dify。本指南将指导您如何将 Dify 部署到 Zeabur。 {'Header 1': '部署 Dify 到 Zeabur', 'Header 2': '前置要求'} 在开始之前,您需要以下内容: - 一个 Zeabur 账户。如果您没有账户,可以在 [Zeabur](https://zeabur.com/) 注册一个免费账户。 - 升级您的 Zeabur 账户到开发者计划(每月 5 美元)。您可以从 [Zeabur 定价](https://zeabur.com/pricing) 了解更多信息。 {'Header 1': '部署 Dify 到 Zeabur', 'Header 2': '部署 Dify 到 Zeabur'} Zeabur 团队准备了一个一键部署模板,您只需点击下面的按钮即可开始: [![Deploy to Zeabur](https://zeabur.com/button.svg)](https://zeabur.com/1D4DOW) 点击按钮后,您将被导航到 Zeabur 上的模板页面,您可以在那里查看部署的详细信息和说明。
Zeabur Template Overview
点击部署按钮后,您需要输入一个生成的域名,以便将域名绑定到您的 Dify 实例并注入到其他服务中作为环境变量。 然后选择您喜欢的区域,点击部署按钮,您的 Dify 实例将在几分钟内部署完成。 {'Header 1': '部署 Dify 到 Zeabur', 'Header 2': '部署 Dify 到 Zeabur'} 然后选择您喜欢的区域,点击部署按钮,您的 Dify 实例将在几分钟内部署完成。
Select Region
部署完成后,您可以在 Zeabur 控制台中看到一个项目页面,如下图所示,您在部署过程中输入的域名将自动绑定到 NGINX 服务,您可以通过该域名访问您的 Dify 实例。
Zeabur Project Overview
{'Header 1': '部署 Dify 到 Zeabur', 'Header 2': '部署 Dify 到 Zeabur'} 你也可以在 NGINX 服务页面的 Networking 选项卡中更改域名。您可以参考 [Zeabur 文档](https://zeabur.com/docs/deploy/domain-binding) 了解更多信息。# 部署社区版 Dify 社区版即开源版本,你可以通过以下两种方式之一部署 Dify 社区版: * [Docker Compose 部署](https://docs.dify.ai/v/zh-hans/getting-started/install-self-hosted/docker-compose) * [本地源码启动](https://docs.dify.ai/v/zh-hans/getting-started/install-self-hosted/local-source-code) 在 GitHub 上查看 [Dify 社区版](https://github.com/langgenius/dify)。 {'Header 1': '部署 Dify 到 Zeabur', 'Header 2': '部署 Dify 到 Zeabur', 'Header 3': '贡献代码'} 为了确保正确审查,所有代码贡献 - 包括来自具有直接提交更改权限的贡献者 - 都必须提交 PR 请求并在合并分支之前得到核心开发人员的批准。 我们欢迎所有人提交 PR!如果您愿意提供帮助,可以在 [贡献指南](https://github.com/langgenius/dify/blob/main/CONTRIBUTING_CN.md) 中了解有关如何为项目做出贡献的更多信息。 {'Header 1': 'Docker Compose 部署', 'Header 3': '前提条件'} | 操作系统 | 软件 | 描述 | {'Header 1': 'Docker Compose 部署', 'Header 3': '前提条件'} | -------------------------- | -------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | {'Header 1': 'Docker Compose 部署', 'Header 3': '前提条件'} | macOS 10.14 or later | Docker Desktop | 为 Docker 虚拟机(VM)至少分配 2 个虚拟 CPU(vCPU) 和 8GB 初始内存,否则安装可能会失败。有关更多信息,请参考 [《在 Mac 内安装 Docker 桌面端》](https://docs.docker.com/desktop/install/mac-install/)。 | {'Header 1': 'Docker Compose 部署', 'Header 3': '前提条件'} | Linux platforms |

Docker 19.03 or later
Docker Compose 1.25.1 or later

| 请参阅[安装 Docker](https://docs.docker.com/engine/install/) 和[安装 Docker Compose](https://docs.docker.com/compose/install/) 以获取更多信息。 | {'Header 1': 'Docker Compose 部署', 'Header 3': '前提条件'} | Windows with WSL 2 enabled |

Docker Desktop

| 我们建议将源代码和其他数据绑定到 Linux 容器中时,将其存储在 Linux 文件系统中,而不是 Windows 文件系统中。有关更多信息,请参阅[使用 WSL 2 后端在 Windows 上安装 Docker Desktop](https://docs.docker.com/desktop/windows/install/#wsl-2-backend)。 | {'Header 1': 'Docker Compose 部署', 'Header 3': '克隆 Dify 代码仓库'} 克隆 Dify 源代码至本地。 ```bash git clone https://github.com/langgenius/dify.git ``` {'Header 1': 'Docker Compose 部署', 'Header 3': '启动 Dify'} 进入 Dify 源代码的 docker 目录,执行一键启动命令: ```Shell cd dify/docker cp .env.example .env docker compose up -d ``` > 如果您的系统安装了 Docker Compose V2 而不是 V1,请使用 `docker compose` 而不是 `docker-compose`。通过`$ docker compose version`检查这是否为情况。在[这里](https://docs.docker.com/compose/#compose-v2-and-the-new-docker-compose-command)阅读更多信息。 部署结果示例: ```Shell [+] Running 11/11 ✔ Network docker_ssrf_proxy_network Created 0.1s {'Header 1': 'Docker Compose 部署', 'Header 3': '启动 Dify'} ✔ Network docker_default Created 0.0s ✔ Container docker-redis-1 Started 2.4s ✔ Container docker-ssrf_proxy-1 Started 2.8s ✔ Container docker-sandbox-1 Started 2.7s {'Header 1': 'Docker Compose 部署', 'Header 3': '启动 Dify'} ✔ Container docker-web-1 Started 2.7s ✔ Container docker-weaviate-1 Started 2.4s ✔ Container docker-db-1 Started 2.7s ✔ Container docker-api-1 Started 6.5s {'Header 1': 'Docker Compose 部署', 'Header 3': '启动 Dify'} ✔ Container docker-worker-1 Started 6.4s ✔ Container docker-nginx-1 Started 7.1s ``` 最后检查是否所有容器都正常运行: ```bash docker compose ps ``` 包括 3 个业务服务 `api / worker / web`,以及 6 个基础组件 `weaviate / db / redis / nginx / ssrf_proxy / sandbox` 。 ```bash {'Header 1': 'Docker Compose 部署', 'Header 3': '启动 Dify'} ```bash NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS docker-api-1 langgenius/dify-api:0.6.13 "/bin/bash /entrypoi…" api About a minute ago Up About a minute 5001/tcp docker-db-1 postgres:15-alpine "docker-entrypoint.s…" db About a minute ago Up About a minute (healthy) 5432/tcp {'Header 1': 'Docker Compose 部署', 'Header 3': '启动 Dify'} docker-nginx-1 nginx:latest "sh -c 'cp /docker-e…" nginx About a minute ago Up About a minute 0.0.0.0:80->80/tcp, :::80->80/tcp, 0.0.0.0:443->443/tcp, :::443->443/tcp docker-redis-1 redis:6-alpine "docker-entrypoint.s…" redis About a minute ago Up About a minute (healthy) 6379/tcp {'Header 1': 'Docker Compose 部署', 'Header 3': '启动 Dify'} docker-sandbox-1 langgenius/dify-sandbox:0.2.1 "/main" sandbox About a minute ago Up About a minute docker-ssrf_proxy-1 ubuntu/squid:latest "sh -c 'cp /docker-e…" ssrf_proxy About a minute ago Up About a minute 3128/tcp docker-weaviate-1 semitechnologies/weaviate:1.19.0 "/bin/weaviate --hos…" weaviate About a minute ago Up About a minute {'Header 1': 'Docker Compose 部署', 'Header 3': '启动 Dify'} docker-web-1 langgenius/dify-web:0.6.13 "/bin/sh ./entrypoin…" web About a minute ago Up About a minute 3000/tcp docker-worker-1 langgenius/dify-api:0.6.13 "/bin/bash /entrypoi…" worker About a minute ago Up About a minute 5001/tcp ``` {'Header 1': 'Docker Compose 部署', 'Header 3': '更新 Dify'} 进入 dify 源代码的 docker 目录,按顺序执行以下命令: ```bash cd dify/docker docker compose down git pull origin main docker compose pull docker compose up -d ``` #### 同步环境变量配置 (重要!) * 如果 `.env.example` 文件有更新,请务必同步修改您本地的 `.env` 文件。 * 检查 `.env` 文件中的所有配置项,确保它们与您的实际运行环境相匹配。您可能需要将 `.env.example` 中的新变量添加到 `.env` 文件中,并更新已更改的任何值。 {'Header 1': 'Docker Compose 部署', 'Header 3': '访问 Dify'} 在浏览器中输入 `http://localhost` 访问 Dify。 {'Header 1': 'Docker Compose 部署', 'Header 3': '自定义配置'} 编辑 `.env` 文件中的环境变量值。然后,重新启动 Dify: ```bash docker compose down docker compose up -d ``` 完整的环境变量集合可以在 `docker/.env.example` 中找到。 {'Header 1': '单独启动前端 Docker 容器'} 当单独开发后端时,可能只需要源码启动后端服务,而不需要本地构建前端代码并启动,因此可以直接通过拉取 docker 镜像并启动容器的方式来启动前端服务,以下为具体步骤: #### 直接使用 DockerHub 镜像 ```Bash docker run -it -p 3000:3000 -e CONSOLE_API_URL=http://127.0.0.1:5001 -e APP_API_URL=http://127.0.0.1:5001 langgenius/dify-web:latest ``` #### 源码构建 Docker 镜像 1. 构建前端镜像 ``` cd web && docker build . -t dify-web ``` 2. 启动前端镜像 ``` docker run -it -p 3000:3000 -e CONSOLE_API_URL=http://127.0.0.1:5001 -e APP_API_URL=http://127.0.0.1:5001 dify-web ``` {'Header 1': '单独启动前端 Docker 容器'} ``` 3. 当控制台域名和 Web APP 域名不一致时,可单独设置 `CONSOLE_URL` 和 `APP_URL` 4. 本地访问 [http://127.0.0.1:3000](http://127.0.0.1:3000) --- description: 对于已经熟悉 LLM 应用技术栈的技术人士来说,这份文档将是您了解 Dify 独特优势的捷径。让您能够明智地比较和选择,甚至向同事和朋友推荐。 --- {'Header 1': '特性与技术规格'} {% hint style="info" %} 在 Dify,我们采用透明化的产品特性和技术规格政策,确保您在全面了解我们产品的基础上做出决策。这种透明度不仅有利于您的技术选型,也促进了社区成员对产品的深入理解和积极贡献。 {% endhint %} {'Header 1': '特性与技术规格', 'Header 3': '项目基础信息'}
项目设立2023 年 3 月
开源协议基于 Apache License 2.0 有限商业许可
官方研发团队超过 20 名全职员工
社区贡献者超过 290 人 (截止 2024 {'Header 1': '特性与技术规格', 'Header 3': '项目基础信息'} 290 人 (截止 2024 Q2)
后端技术Python/Flask/PostgreSQL
前端技术Next.js
代码行数超过 13 万行
发版周期平均每周一次
{'Header 1': '特性与技术规格', 'Header 3': '技术特性'}
LLM 推理引擎Dify Runtime ( 自 v0.4 起移除了 LangChain)
商业模型支持

10+ 家,包括 OpenAI 与 Anthropic

新的主流模型通常在 48 小时内完成接入

MaaS 供应商支持7 家,Hugging Face,Replicate,AWS Bedrock,NVIDIA,GroqCloud,together.ai,OpenRouter
本地模型推理 Runtime 支持6 {'Header 1': '特性与技术规格', 'Header 3': '技术特性'} Runtime 支持6 ,Xoribits(推荐),OpenLLM,LocalAI,ChatGLM,Ollama,NVIDIA TIS
OpenAI 接口标准模型接入支持∞ 家
多模态技术

ASR 模型

GPT-4o 规格的富文本模型

预置应用类型

对话型应用

文本生成应用
Agent
工作流

Prompt 即服务编排

广受好评的可视化的 Prompt 编排界面,在同一个界面中修改 Prompt 并预览效果

编排模式

  • 简易模式编排
  • Assistant 模式编排
  • Flow {'Header 1': '特性与技术规格', 'Header 3': '技术特性'} 模式编排
  • Flow 模式编排

Prompt 变量类型

  • 字符串
  • 单选枚举
  • 外部 API
  • 文件(Q3 即将推出)
Agentic Workflow 特性

行业领先的可视化流程编排界面,所见即所得的节点调试,可插拔的 DSL,原生的代码运行时,构建更复杂、可靠、稳定的 LLM 应用。

支持节点

  • LLM
  • 知识库检索
  • 问题分类
  • 条件分支
  • 代码执行
  • 模板转换
  • HTTP 请求
  • 工具
RAG {'Header 1': '特性与技术规格', 'Header 3': '技术特性'} 请求
  • 工具
  • RAG 特性

    首创的可视化的知识库管理界面,支持分段预览和召回效果测试。

    索引方式

    • 关键词
    • 文本向量
    • 由 LLM 辅助的问题-分段模式

    检索方式

    • 关键词
    • 文本相似度匹配
    • 混合检索
    • N 选 1 模式(即将下线)
    • 多路召回

    召回优化技术

    • 使用 ReRank 模型
    ETL 技术

    支持对 TXT、Markdown、PDF、HTML、DOC、CSV 等格式文件进行自动清洗,内置的 Unstructured 服务开启后可获得最大化支持。

    支持同步来自 Notion {'Header 1': '特性与技术规格', 'Header 3': '技术特性'} Unstructured 服务开启后可获得最大化支持。

    支持同步来自 Notion 的文档为知识库。
    支持同步网页为知识库。

    向量数据库支持Qdrant(推荐),Weaviate,Zilliz/Milvus,Pgvector,Pgvector-rs,Chroma,OpenSearch,TiDB,Tencent Vector,Oracle,Relyt
    Agent 技术

    ReAct,Function Call

    工具支持

    • 可调用 OpenAI Plugin 标准的工具
    • 可直接加载 OpenAPI Specification 的 API 作为工具

    内置工具

    • 40+ 款(截止 2024 {'Header 1': '特性与技术规格', 'Header 3': '技术特性'} 款(截止 2024 Q2)
    日志支持,可基于日志进行标注
    标注回复基于经人类标注的 Q&A 对,可用于相似度对比回复
    可导出为供模型微调环节使用的数据格式
    内容审查机制OpenAI Moderation 或外部 API
    团队协同工作空间与多成员管理支持
    API 规格RESTful,已覆盖大部分功能
    部署方式Docker,Helm
    {'Header 1': '模型供应商列表'} Dify 为以下模型提供商提供原生支持: {'Header 1': '模型供应商列表'} {'Header 1': '模型供应商列表'} {'Header 1': '模型供应商列表'} {'Header 1': '模型供应商列表'} {'Header 1': '模型供应商列表'} {'Header 1': '模型供应商列表'} {'Header 1': '模型供应商列表'} {'Header 1': '模型供应商列表'} {'Header 1': '模型供应商列表'} {'Header 1': '模型供应商列表'} {'Header 1': '模型供应商列表'} {'Header 1': '模型供应商列表'} {'Header 1': '模型供应商列表'} {'Header 1': '模型供应商列表'} {'Header 1': '模型供应商列表'} {'Header 1': '模型供应商列表'}
    Provider LLM Text Embedding Rerank Speech to text TTS
    OpenAI ✔️(🛠️)(👓) ✔️ ✔️ ✔️
    ✔️
    Anthropic ✔️(🛠️)
    Azure OpenAI ✔️(🛠️)(👓) ✔️ ✔️
    Google Cloud ✔️(👓)
    Nvidia API Catalog ✔️ ✔️ ✔️
    Nvidia NIM ✔️
    Nvidia Triton Inference Server ✔️
    AWS Bedrock ✔️ ✔️
    OpenRouter ✔️
    Cohere ✔️ ✔️ ✔️
    together.ai ✔️
    Ollama ✔️ ✔️
    Mistral AI ✔️
    groqcloud ✔️
    Replicate ✔️ ✔️
    Hugging Face ✔️ ✔️
    Xorbits inference ✔️ ✔️ ✔️ ✔️
    智谱 ✔️(🛠️)(👓) ✔️
    百川 ✔️ ✔️✔️
    讯飞星火 ✔️
    Minimax ✔️(🛠️) ✔️
    通义千问
    通义千问 ✔️ ✔️ ✔️
    文心一言 ✔️
    月之暗面 ✔️(🛠️)
    Tencent Cloud ✔️ ✔️
    阶跃星辰 ✔️
    火山引擎 ✔️✔️ ✔️
    零一万物 ✔️
    deepseek ✔️(🛠️)
    腾讯混元 ✔️
    SILICONFLOW ✔️
    Jina ✔️ ✔️✔️
    ChatGLM ✔️
    Xinference ✔️(🛠️)(👓) ✔️ ✔️
    OpenLLM
    OpenLLM ✔️ ✔️
    LocalAI ✔️ ✔️ ✔️ ✔️
    OpenAI API-Compatible ✔️ ✔️
    PerfXCloud ✔️ ✔️
    Lepton AI ✔️
    novita.ai ✔️✔️
    Amazon Sagemaker ✔️ ✔️ ✔️
    其中 (🛠️) 代表支持 Function Calling,(👓) 代表视觉能力。 {'Header 1': '模型供应商列表'} 其中 (🛠️) 代表支持 Function Calling,(👓) 代表视觉能力。 这张表格我们会一直保持更新。同时,我们也留意着社区成员们所提出的关于模型供应商的各种[请求](https://github.com/langgenius/dify/discussions/categories/ideas)。如果你有需要的模型供应商却没在上面找到,不妨动手参与进来,通过提交一个PR(Pull Request)来做出你的贡献。欢迎查阅我们的 [contribution.md](../../community/contribution.md "mention")指南了解更多。 {'Header 1': '工具', 'Header 3': '工具定义'} 工具可以扩展 LLM 的能力,比如联网搜索、科学计算或绘制图片,赋予并增强了 LLM 连接外部世界的能力。Dify 提供了两种工具类型:**第一方工具**和**自定义工具**。 你可以直接使用 Dify 生态提供的第一方内置工具,或者轻松导入自定义的 API 工具(目前支持 OpenAPI / Swagger 和 OpenAI Plugin 规范)。 #### 工具的作用: 1. 工具使用户可以在 Dify 上创建更强大的 AI 应用,如你可以为智能助理型应用(Agent)编排合适的工具,它可以通过任务推理、步骤拆解、调用工具完成复杂任务。 2. 方便将你的应用与其他系统或服务连接,与外部环境交互,如代码执行、对专属信息源的访问等。 {'Header 1': '工具', 'Header 3': '如何配置第一方工具'}

    第一方工具列表

    Dify 目前已支持: {'Header 1': '工具', 'Header 3': '如何配置第一方工具'}
    工具工具描述
    谷歌搜索用于执行 Google SERP 搜索并提取片段和网页的工具。输入应该是一个搜索查询
    维基百科用于执行维基百科搜索并提取片段和网页的工具。
    DALL-E {'Header 1': '工具', 'Header 3': '如何配置第一方工具'} 绘画用于通过自然语言输入生成高质量图片
    网页抓取用于爬取网页数据的工具
    WolframAlpha一个强大的计算知识引擎,能根据问题直接给出标准化答案,同时具有强大的数学计算功能
    图表生成用于生成可视化图表的工具,你可以通过它来生成柱状图、折线图、饼图等各类图表
    当前时间用于查询当前时间的工具
    雅虎财经获取并整理出最新的新闻、股票报价等一切你想要的财经信息。
    Stable Diffusion一个可以在本地部署的图片生成的工具,您可以使用 stable-diffusion-webui 来部署它
    Vectorizer一个将 PNG 和 JPG 图像快速轻松地转换为 SVG {'Header 1': '工具', 'Header 3': '如何配置第一方工具'} PNG 和 JPG 图像快速轻松地转换为 SVG 矢量图的工具。
    YouTube一个用于获取油管频道视频统计数据的工具
    {'Header 1': '工具', 'Header 3': '如何配置第一方工具'} {% hint style="info" %} 欢迎您为 Dify 贡献自己开发的工具,关于如何贡献的具体方法请查看 [Dify 开发贡献文档](https://github.com/langgenius/dify/blob/main/CONTRIBUTING.md),您的任何支持对我们都是极为宝贵的。 {% endhint %} #### 第一方工具授权 若你需要直接使用 Dify 生态提供的第一方内置工具,你需要在使用前配置相应的凭据。

    配置第一方工具凭据

    凭据校验成功后工具会显示“已授权”状态。配置凭据后,工作区中的所有成员都可以在编排应用程序时使用此工具。 {'Header 1': '工具', 'Header 3': '如何配置第一方工具'}

    第一方工具已授权

    {'Header 1': '工具', 'Header 3': '如何创建自定义工具'} 你可以在“工具-自定义工具”内导入自定义的 API 工具,目前支持 OpenAPI / Swagger 和 ChatGPT Plugin 规范。你可以将 OpenAPI schema 内容直接粘贴或从 URL 内导入。关于 OpenAPI / Swagger 规范您可以查看[官方文档说明](https://swagger.io/specification/)。 工具目前支持两种鉴权方式:无鉴权 和 API Key。

    创建自定义工具

    在导入 Schema 内容后系统会主动解析文件内的参数,并可预览工具具体的参数、 方法、路径。您也可以在此对工具参数进行测试。 {'Header 1': '工具', 'Header 3': '如何创建自定义工具'}

    自定义工具参数测试

    完成自定义工具创建之后,工作区中的所有成员都可以在“工作室”内编排应用程序时使用此工具。

    已添加自定义工具

    #### Cloudflare Workers 您也可以使用 [dify-tools-worker](https://github.com/crazywoola/dify-tools-worker) 来快速部署自定义工具。该工具提供了: * 可以导入 Dify 的路由 `https://difytoolsworker.yourname.workers.dev/doc`, 提供了 OpenAPI 兼容的接口文档 {'Header 1': '工具', 'Header 3': '如何创建自定义工具'} * API 的实现代码,可以直接部署到 Cloudflare Workers {'Header 1': '工具', 'Header 3': '如何在应用内使用工具'} 目前,您可以在“工作室”中创建**智能助手型应用**时,将已配置好凭据的工具在其中使用。

    创建智能助手型应用时添加工具

    以下图为例,在财务分析应用内添加工具后,智能助手将在需要时自主调用工具,从工具中查询财务报告数据,并将数据分析后完成与用户之间的对话。

    智能助手在对话中完成工具调用回复问题

    {'Header 1': '高级接入工具'} 在开始高级接入之前,请确保你已经阅读过[快速接入](https://docs.dify.ai/v/zh-hans/guides/tools/quick-tool-integration),并对Dify的工具接入流程有了基本的了解。 {'Header 1': '高级接入工具', 'Header 3': '工具接口'} 我们在`Tool`类中定义了一系列快捷方法,用于帮助开发者快速构较为复杂的工具。 #### 消息返回 Dify支持`文本` `链接` `图片` `文件BLOB` 等多种消息类型,你可以通过以下几个接口返回不同类型的消息给 LLM 和用户。 注意,在下面的接口中的部分参数将在后面的章节中介绍。 **图片URL** 只需要传递图片的URL即可,Dify会自动下载图片并返回给用户。 ```python def create_image_message(self, image: str, save_as: str = '') -> ToolInvokeMessage: """ create an image message {'Header 1': '高级接入工具', 'Header 3': '工具接口'} :param image: the url of the image :return: the image message """ ``` **链接** 如果你需要返回一个链接,可以使用以下接口。 ```python def create_link_message(self, link: str, save_as: str = '') -> ToolInvokeMessage: """ create a link message :param link: the url of the link :return: the link message """ ``` **文本** 如果你需要返回一个文本消息,可以使用以下接口。 ```python def create_text_message(self, text: str, save_as: str = '') -> ToolInvokeMessage: """ create a text message {'Header 1': '高级接入工具', 'Header 3': '工具接口'} :param text: the text of the message :return: the text message """ ``` **文件 BLOB** 如果你需要返回文件的原始数据,如图片、音频、视频、PPT、Word、Excel 等,可以使用以下接口。 * `blob` 文件的原始数据,bytes 类型 * `meta` 文件的元数据,如果你知道该文件的类型,最好传递一个`mime_type`,否则Dify将使用`octet/stream`作为默认类型 ```python def create_blob_message(self, blob: bytes, meta: dict = None, save_as: str = '') -> ToolInvokeMessage: """ create a blob message {'Header 1': '高级接入工具', 'Header 3': '工具接口'} :param blob: the blob :return: the blob message """ ``` #### 快捷工具 在大模型应用中,我们有两种常见的需求: * 先将很长的文本进行提前总结,然后再将总结内容传递给 LLM,以防止原文本过长导致 LLM 无法处理 * 工具获取到的内容是一个链接,需要爬取网页信息后再返回给 LLM 为了帮助开发者快速实现这两种需求,我们提供了以下两个快捷工具。 **文本总结工具** 该工具需要传入 user\_id 和需要进行总结的文本,返回一个总结后的文本,Dify 会使用当前工作空间的默认模型对长文本进行总结。 ```python def summary(self, user_id: str, content: str) -> str: """ summary the content {'Header 1': '高级接入工具', 'Header 3': '工具接口'} :param user_id: the user id :param content: the content :return: the summary """ ``` **网页爬取工具** 该工具需要传入需要爬取的网页链接和一个 user\_agent(可为空),返回一个包含该网页信息的字符串,其中`user_agent`是可选参数,可以用来识别工具,如果不传递,Dify将使用默认的`user_agent`。 ```python def get_url(self, url: str, user_agent: str = None) -> str: """ get url """ the crawled result ``` #### 变量池 我们在`Tool`中引入了一个变量池,用于存储工具运行过程中产生的变量、文件等,这些变量可以在工具运行过程中被其他工具使用。 下面,我们以`DallE3`和`Vectorizer.AI`为例,介绍如何使用变量池。 {'Header 1': '高级接入工具', 'Header 3': '工具接口'} 下面,我们以`DallE3`和`Vectorizer.AI`为例,介绍如何使用变量池。 * `DallE3`是一个图片生成工具,它可以根据文本生成图片,在这里,我们将让`DallE3`生成一个咖啡厅的 Logo。 * `Vectorizer.AI`是一个矢量图转换工具,它可以将图片转换为矢量图,使得图片可以无限放大而不失真,在这里,我们将`DallE3`生成的PNG图标转换为矢量图,从而可以真正被设计师使用。 **DallE3** 首先我们使用 DallE3,在创建完图片以后,我们将图片保存到变量池中,代码如下 ```python from typing import Any, Dict, List, Union from core.tools.entities.tool_entities import ToolInvokeMessage from core.tools.tool.builtin_tool import BuiltinTool {'Header 1': '高级接入工具', 'Header 3': '工具接口'} from base64 import b64decode from openai import OpenAI class DallE3Tool(BuiltinTool): def _invoke(self, user_id: str, tool_paramters: Dict[str, Any], ) -> Union[ToolInvokeMessage, List[ToolInvokeMessage]]: """ invoke tools """ client = OpenAI( api_key=self.runtime.credentials['openai_api_key'], ) # prompt prompt = tool_paramters.get('prompt', '') if not prompt: return self.create_text_message('Please input prompt') {'Header 1': '高级接入工具', 'Header 3': '工具接口'} # call openapi dalle3 response = client.images.generate( prompt=prompt, model='dall-e-3', size='1024x1024', n=1, style='vivid', quality='standard', response_format='b64_json' ) result = [] for image in response.data: # 将所有图片通过 save_as 参数保存到变量池中,变量名为 self.VARIABLE_KEY.IMAGE.value,如果如果后续有新的图片生成,那么将会覆盖之前的图片 result.append(self.create_blob_message(blob=b64decode(image.b64_json), meta={ 'mime_type': 'image/png' }, save_as=self.VARIABLE_KEY.IMAGE.value)) {'Header 1': '高级接入工具', 'Header 3': '工具接口'} return result ``` 我们可以注意到这里我们使用了`self.VARIABLE_KEY.IMAGE.value`作为图片的变量名,为了便于开发者们的工具能够互相配合,我们定义了这个`KEY`,大家可以自由使用,也可以不使用这个`KEY`,传递一个自定义的KEY也是可以的。 **Vectorizer.AI** 接下来我们使用 Vectorizer.AI,将 DallE3 生成的PNG图标转换为矢量图,我们先来过一遍我们在这里定义的函数,代码如下 ```python from core.tools.tool.builtin_tool import BuiltinTool from core.tools.entities.tool_entities import ToolInvokeMessage, ToolParamter from core.tools.errors import ToolProviderCredentialValidationError {'Header 1': '高级接入工具', 'Header 3': '工具接口'} from typing import Any, Dict, List, Union from httpx import post from base64 import b64decode class VectorizerTool(BuiltinTool): def _invoke(self, user_id: str, tool_paramters: Dict[str, Any]) \ -> Union[ToolInvokeMessage, List[ToolInvokeMessage]]: """ 工具调用,图片变量名需要从这里传递进来,从而我们就可以从变量池中获取到图片 """ def get_runtime_parameters(self) -> List[ToolParamter]: """ 重写工具参数列表,我们可以根据当前变量池里的实际情况来动态生成参数列表,从而 LLM 可以根据参数列表来生成表单 """ {'Header 1': '高级接入工具', 'Header 3': '工具接口'} def is_tool_avaliable(self) -> bool: """ 当前工具是否可用,如果当前变量池中没有图片,那么我们就不需要展示这个工具,这里返回 False 即可 """ ``` 接下来我们来实现这三个函数 ```python from core.tools.tool.builtin_tool import BuiltinTool from core.tools.entities.tool_entities import ToolInvokeMessage, ToolParamter from core.tools.errors import ToolProviderCredentialValidationError from typing import Any, Dict, List, Union from httpx import post from base64 import b64decode {'Header 1': '高级接入工具', 'Header 3': '工具接口'} class VectorizerTool(BuiltinTool): def _invoke(self, user_id: str, tool_paramters: Dict[str, Any]) \ -> Union[ToolInvokeMessage, List[ToolInvokeMessage]]: """ invoke tools """ api_key_name = self.runtime.credentials.get('api_key_name', None) api_key_value = self.runtime.credentials.get('api_key_value', None) if not api_key_name or not api_key_value: raise ToolProviderCredentialValidationError('Please input api key name and value') {'Header 1': '高级接入工具', 'Header 3': '工具接口'} # 获取 image_id,image_id 的定义可以在 get_runtime_parameters 中找到 image_id = tool_paramters.get('image_id', '') if not image_id: return self.create_text_message('Please input image id') # 从变量池中获取到之前 DallE 生成的图片 image_binary = self.get_variable_file(self.VARIABLE_KEY.IMAGE) if not image_binary: return self.create_text_message('Image not found, please request user to generate image firstly.') {'Header 1': '高级接入工具', 'Header 3': '工具接口'} # 生成矢量图 response = post( 'https://vectorizer.ai/api/v1/vectorize', files={ 'image': image_binary }, data={ 'mode': 'test' }, auth=(api_key_name, api_key_value), timeout=30 ) if response.status_code != 200: raise Exception(response.text) return [ self.create_text_message('the vectorized svg is saved as an image.'), self.create_blob_message(blob=response.content, meta={'mime_type': 'image/svg+xml'}) ] {'Header 1': '高级接入工具', 'Header 3': '工具接口'} def get_runtime_parameters(self) -> List[ToolParamter]: """ override the runtime parameters """ # 这里,我们重写了工具参数列表,定义了 image_id,并设置了它的选项列表为当前变量池中的所有图片,这里的配置与 yaml 中的配置是一致的 return [ ToolParamter.get_simple_instance( name='image_id', llm_description=f'the image id that you want to vectorize, \ and the image id should be specified in \ {[i.name for i in self.list_default_image_variables()]}', type=ToolParamter.ToolParameterType.SELECT, required=True, {'Header 1': '高级接入工具', 'Header 3': '工具接口'} required=True, options=[i.name for i in self.list_default_image_variables()] ) ] {'Header 1': '高级接入工具', 'Header 3': '工具接口'} def is_tool_avaliable(self) -> bool: # 只有当变量池中有图片时,LLM 才需要使用这个工具 return len(self.list_default_image_variables()) > 0 ``` 可以注意到的是,我们这里其实并没有使用到`image_id`,我们已经假设了调用这个工具的时候一定有一张图片在默认的变量池中,所以直接使用了`image_binary = self.get_variable_file(self.VARIABLE_KEY.IMAGE)`来获取图片,在模型能力较弱的情况下,我们建议开发者们也这样做,可以有效提升容错率,避免模型传递错误的参数。 {'Header 1': '快速接入工具'} 这里我们以 GoogleSearch 为例,介绍如何快速接入一个工具。 {'Header 1': '快速接入工具', 'Header 3': '1. 准备工具供应商 yaml'} #### 介绍 这个 yaml 将包含工具供应商的信息,包括供应商名称、图标、作者等详细信息,以帮助前端灵活展示。 #### 示例 我们需要在 `core/tools/provider/builtin`下创建一个`google`模块(文件夹),并创建`google.yaml`,名称必须与模块名称一致。 后续,我们关于这个工具的所有操作都将在这个模块下进行。 ```yaml identity: # 工具供应商的基本信息 author: Dify # 作者 name: google # 名称,唯一,不允许和其他供应商重名 label: # 标签,用于前端展示 en_US: Google # 英文标签 zh_Hans: Google # 中文标签 description: # 描述,用于前端展示 en_US: Google # 英文描述 zh_Hans: Google # 中文描述 icon: icon.svg # 图标,需要放置在当前模块的_assets文件夹下 {'Header 1': '快速接入工具', 'Header 3': '1. 准备工具供应商 yaml'} ``` * `identity` 字段是必须的,它包含了工具供应商的基本信息,包括作者、名称、标签、描述、图标等 * 图标需要放置在当前模块的`_assets`文件夹下,可以参考这里:api/core/tools/provider/builtin/google/\_assets/icon.svg ```xml {'Header 1': '快速接入工具', 'Header 3': '1. 准备工具供应商 yaml'} {'Header 1': '快速接入工具', 'Header 3': '1. 准备工具供应商 yaml'} {'Header 1': '快速接入工具', 'Header 3': '1. 准备工具供应商 yaml'} {'Header 1': '快速接入工具', 'Header 3': '1. 准备工具供应商 yaml'} ``` {'Header 1': '快速接入工具', 'Header 3': '2. 准备供应商凭据'} Google 作为一个第三方工具,使用了 SerpApi 提供的 API,而 SerpApi 需要一个 API Key 才能使用,那么就意味着这个工具需要一个凭据才可以使用,而像`wikipedia`这样的工具,就不需要填写凭据字段,可以参考这里:api/core/tools/provider/builtin/wikipedia/wikipedia.yaml ```yaml identity: author: Dify name: wikipedia label: en_US: Wikipedia zh_Hans: 维基百科 pt_BR: Wikipedia description: en_US: Wikipedia is a free online encyclopedia, created and edited by volunteers around the world. zh_Hans: 维基百科是一个由全世界的志愿者创建和编辑的免费在线百科全书。 {'Header 1': '快速接入工具', 'Header 3': '2. 准备供应商凭据'} zh_Hans: 维基百科是一个由全世界的志愿者创建和编辑的免费在线百科全书。 pt_BR: Wikipedia is a free online encyclopedia, created and edited by volunteers around the world. icon: icon.svg credentials_for_provider: ``` 配置好凭据字段后效果如下: ```yaml identity: author: Dify name: google label: en_US: Google zh_Hans: Google description: en_US: Google zh_Hans: Google icon: icon.svg credentials_for_provider: # 凭据字段 serpapi_api_key: # 凭据字段名称 type: secret-input # 凭据字段类型 required: true # 是否必填 label: # 凭据字段标签 en_US: SerpApi API key # 英文标签 {'Header 1': '快速接入工具', 'Header 3': '2. 准备供应商凭据'} label: # 凭据字段标签 en_US: SerpApi API key # 英文标签 zh_Hans: SerpApi API key # 中文标签 placeholder: # 凭据字段占位符 en_US: Please input your SerpApi API key # 英文占位符 zh_Hans: 请输入你的 SerpApi API key # 中文占位符 help: # 凭据字段帮助文本 en_US: Get your SerpApi API key from SerpApi # 英文帮助文本 zh_Hans: 从 SerpApi 获取您的 SerpApi API key # 中文帮助文本 url: https://serpapi.com/manage-api-key # 凭据字段帮助链接 {'Header 1': '快速接入工具', 'Header 3': '2. 准备供应商凭据'} ``` * `type`:凭据字段类型,目前支持`secret-input`、`text-input`、`select` 三种类型,分别对应密码输入框、文本输入框、下拉框,如果为`secret-input`,则会在前端隐藏输入内容,并且后端会对输入内容进行加密。 {'Header 1': '快速接入工具', 'Header 3': '3. 准备工具 yaml'} 一个供应商底下可以有多个工具,每个工具都需要一个 yaml 文件来描述,这个文件包含了工具的基本信息、参数、输出等。 仍然以 GoogleSearch 为例,我们需要在`google`模块下创建一个`tools`模块,并创建`tools/google_search.yaml`,内容如下。 ```yaml identity: # 工具的基本信息 name: google_search # 工具名称,唯一,不允许和其他工具重名 author: Dify # 作者 label: # 标签,用于前端展示 en_US: GoogleSearch # 英文标签 zh_Hans: 谷歌搜索 # 中文标签 description: # 描述,用于前端展示 human: # 用于前端展示的介绍,支持多语言 en_US: A tool for performing a Google SERP search and extracting snippets and webpages.Input should be a search query. {'Header 1': '快速接入工具', 'Header 3': '3. 准备工具 yaml'} zh_Hans: 一个用于执行 Google SERP 搜索并提取片段和网页的工具。输入应该是一个搜索查询。 llm: A tool for performing a Google SERP search and extracting snippets and webpages.Input should be a search query. # 传递给 LLM 的介绍,为了使得LLM更好理解这个工具,我们建议在这里写上关于这个工具尽可能详细的信息,让 LLM 能够理解并使用这个工具 parameters: # 参数列表 - name: query # 参数名称 type: string # 参数类型 required: true # 是否必填 label: # 参数标签 en_US: Query string # 英文标签 zh_Hans: 查询语句 # 中文标签 human_description: # 用于前端展示的介绍,支持多语言 en_US: used for searching zh_Hans: 用于搜索网页内容 {'Header 1': '快速接入工具', 'Header 3': '3. 准备工具 yaml'} en_US: used for searching zh_Hans: 用于搜索网页内容 llm_description: key words for searching # 传递给LLM的介绍,同上,为了使得LLM更好理解这个参数,我们建议在这里写上关于这个参数尽可能详细的信息,让LLM能够理解这个参数 form: llm # 表单类型,llm表示这个参数需要由Agent自行推理出来,前端将不会展示这个参数 - name: result_type type: select # 参数类型 required: true options: # 下拉框选项 - value: text label: en_US: text zh_Hans: 文本 - value: link label: en_US: link zh_Hans: 链接 default: link label: en_US: Result type zh_Hans: 结果类型 human_description: en_US: used for selecting the result type, text or link {'Header 1': '快速接入工具', 'Header 3': '3. 准备工具 yaml'} zh_Hans: 用于选择结果类型,使用文本还是链接进行展示 form: form # 表单类型,form表示这个参数需要由用户在对话开始前在前端填写 {'Header 1': '快速接入工具', 'Header 3': '3. 准备工具 yaml'} ``` * `identity` 字段是必须的,它包含了工具的基本信息,包括名称、作者、标签、描述等 * `parameters` 参数列表 * `name` 参数名称,唯一,不允许和其他参数重名 * `type` 参数类型,目前支持`string`、`number`、`boolean`、`select` 四种类型,分别对应字符串、数字、布尔值、下拉框 * `required` 是否必填 * 在`llm`模式下,如果参数为必填,则会要求 Agent 必须要推理出这个参数 * 在`form`模式下,如果参数为必填,则会要求用户在对话开始前在前端填写这个参数 * `options` 参数选项 * 在`llm`模式下,Dify 会将所有选项传递给 LLM,LLM 可以根据这些选项进行推理 * 在`form`模式下,`type`为`select`时,前端会展示这些选项 * `default` 默认值 * `label` 参数标签,用于前端展示 * `human_description` 用于前端展示的介绍,支持多语言 {'Header 1': '快速接入工具', 'Header 3': '3. 准备工具 yaml'} * `human_description` 用于前端展示的介绍,支持多语言 * `llm_description` 传递给 LLM 的介绍,为了使得 LLM 更好理解这个参数,我们建议在这里写上关于这个参数尽可能详细的信息,让 LLM 能够理解这个参数 * `form` 表单类型,目前支持`llm`、`form`两种类型,分别对应 Agent 自行推理和前端填写 {'Header 1': '快速接入工具', 'Header 3': '4. 准备工具代码'} 当完成工具的配置以后,我们就可以开始编写工具代码了,主要用于实现工具的逻辑。 在`google/tools`模块下创建`google_search.py`,内容如下。 ```python from core.tools.tool.builtin_tool import BuiltinTool from core.tools.entities.tool_entities import ToolInvokeMessage from typing import Any, Dict, List, Union {'Header 1': '快速接入工具', 'Header 3': '4. 准备工具代码'} from typing import Any, Dict, List, Union class GoogleSearchTool(BuiltinTool): def _invoke(self, user_id: str, tool_paramters: Dict[str, Any], ) -> Union[ToolInvokeMessage, List[ToolInvokeMessage]]: """ invoke tools """ query = tool_paramters['query'] result_type = tool_paramters['result_type'] api_key = self.runtime.credentials['serpapi_api_key'] # TODO: search with serpapi result = SerpAPI(api_key).run(query, result_type=result_type) {'Header 1': '快速接入工具', 'Header 3': '4. 准备工具代码'} if result_type == 'text': return self.create_text_message(text=result) return self.create_link_message(link=result) ``` #### 参数 工具的整体逻辑都在`_invoke`方法中,这个方法接收两个参数:`user_id`和`tool_paramters`,分别表示用户 ID 和工具参数 #### 返回数据 在工具返回时,你可以选择返回一个消息或者多个消息,这里我们返回一个消息,使用`create_text_message`和`create_link_message`可以创建一个文本消息或者一个链接消息。 {'Header 1': '快速接入工具', 'Header 3': '5. 准备供应商代码'} 最后,我们需要在供应商模块下创建一个供应商类,用于实现供应商的凭据验证逻辑,如果凭据验证失败,将会抛出`ToolProviderCredentialValidationError`异常。 在`google`模块下创建`google.py`,内容如下。 ```python from core.tools.entities.tool_entities import ToolInvokeMessage, ToolProviderType from core.tools.tool.tool import Tool from core.tools.provider.builtin_tool_provider import BuiltinToolProviderController from core.tools.errors import ToolProviderCredentialValidationError from core.tools.provider.builtin.google.tools.google_search import GoogleSearchTool {'Header 1': '快速接入工具', 'Header 3': '5. 准备供应商代码'} from typing import Any, Dict {'Header 1': '快速接入工具', 'Header 3': '5. 准备供应商代码'} class GoogleProvider(BuiltinToolProviderController): def _validate_credentials(self, credentials: Dict[str, Any]) -> None: try: # 1. 此处需要使用 GoogleSearchTool()实例化一个 GoogleSearchTool,它会自动加载 GoogleSearchTool 的 yaml 配置,但是此时它内部没有凭据信息 # 2. 随后需要使用 fork_tool_runtime 方法,将当前的凭据信息传递给 GoogleSearchTool # 3. 最后 invoke 即可,参数需要根据 GoogleSearchTool 的 yaml 中配置的参数规则进行传递 GoogleSearchTool().fork_tool_runtime( meta={ "credentials": credentials, } ).invoke( user_id='', tool_paramters={ "query": "test", {'Header 1': '快速接入工具', 'Header 3': '5. 准备供应商代码'} user_id='', tool_paramters={ "query": "test", "result_type": "link" }, ) except Exception as e: raise ToolProviderCredentialValidationError(str(e)) ``` {'Header 1': '快速接入工具', 'Header 3': '完成'} 当上述步骤完成以后,我们就可以在前端看到这个工具了,并且可以在 Agent 中使用这个工具。 当然,因为 google\_search 需要一个凭据,在使用之前,还需要在前端配置它的凭据。
    --- description: Dify 支持各种工具来增强应用的功能。 --- {'Header 1': '工具配置'} Dify 支持各种工具来增强应用的功能。每个工具都有独特的功能和参数,因此选择适合应用需求的工具。**在 Dify 中使用之前,请从工具提供商的官方网站获取 API 密钥。** {'Header 1': '工具配置', 'Header 2': '工具集成指南'} - [StableDiffusion](./stable-diffusion.md):一种基于文本提示生成图像的工具。 - [SearXNG](./searxng.md):一个免费的互联网元搜索引擎,整合了各种搜索服务的结果。用户不会被跟踪,也不会被分析。# SearXNG SearXNG 是一个免费的互联网元搜索引擎,整合了各种搜索服务的结果。用户不会被跟踪,也不会被分析。Dify 已经实现了访问 SearXNG 的接口,因此您可以直接在 Dify 中使用它。以下是将 SearXNG 集成到 Dify 的步骤: {'Header 1': '工具配置', 'Header 2': '1. 使用 Docker 安装 SearXNG 容器'} ``` docker run --rm \ -d -p 8080:8080 \ -v "${PWD}/searxng:/etc/searxng" \ -e "BASE_URL=http://0.0.0.0:8080/" \ -e "INSTANCE_NAME=searxng" \ searxng/searxng ``` 如果你想通过其他方式安装 SearXNG,请参考[这里](https://docs.searxng.org/admin/installation.html). {'Header 1': '工具配置', 'Header 2': '2. 修改 settings.yml'} 当您安装 SearXNG 时,默认的输出格式是 HTML 格式。您需要激活 JSON 格式。请将以下行添加到 settings.yml 文件中。如前面的示例所示,settings.yml 文件位于 ${PWD}/searxng/settings.yml ``` # remove format to deny access, use lower case. # formats: [html, csv, json, rss] formats: - html - json # <-- 添加这一行 ``` {'Header 1': '工具配置', 'Header 2': '3. 在 Dify 中集成 SearXNG'} 在 `工具 > SearXNG > 去认证` 中填写访问地址,例如:http://x.x.x.x:8080, {'Header 1': '工具配置', 'Header 2': '4. Finish'} 开启使用吧! {'Header 1': 'Stable Diffusion'} StableDiffusion 是一种基于文本提示生成图像的工具,Dify 已经实现了访问 Stable Diffusion WebUI API 的接口,因此你可以直接在 Dify 中使用它。以下是在 Dify 中集成 Stable Diffusion 的步骤。 {'Header 1': 'Stable Diffusion', 'Header 2': '1. 确保你有一台带 GPU 的机器'} Stable Diffusion 最好使用一台有较强 GPU 的机器来生成图像。但这并不是必须的,你也可以只使用 CPU 来生成图像,但速度可能会很慢。 {'Header 1': 'Stable Diffusion', 'Header 2': '2. 启动 Stable Diffusion WebUI'} 在本地机器或服务器上启动 Stable Diffusion WebUI。 {'Header 1': 'Stable Diffusion', 'Header 2': '2. 启动 Stable Diffusion WebUI', 'Header 3': '2.1. 克隆 Stable Diffusion WebUI 仓库'} 从[官方仓库](https://github.com/AUTOMATIC1111/stable-diffusion-webui)克隆 Stable Diffusion WebUI 仓库 ```bash git clone https://github.com/AUTOMATIC1111/stable-diffusion-webui ``` {'Header 1': 'Stable Diffusion', 'Header 2': '2. 启动 Stable Diffusion WebUI', 'Header 3': '2.2. 本地启动'} 克隆仓库后,你应该切换到克隆的仓库目录,并运行以下命令来启动 Stable Diffusion WebUI。 #### Windows ```bash cd stable-diffusion-webui ./webui.bat --api --listen ``` #### Linux ```bash cd stable-diffusion-webui ./webui.sh --api --listen ``` {'Header 1': 'Stable Diffusion', 'Header 2': '2. 启动 Stable Diffusion WebUI', 'Header 3': '2.3. 准备模型'} 现在你可以根据终端中显示的地址在浏览器中访问 Stable Diffusion WebUI,但模型还不可用。你需要从 HuggingFace 或其他来源下载模型,并将其放在 Stable Diffusion WebUI 的 `models` 目录中。 例如,我们使用 [pastel-mix](https://huggingface.co/JamesFlare/pastel-mix) 作为模型,使用 `git lfs` 下载模型并将其放在 `stable-diffusion-webui` 的 `models` 目录中。 ```bash git clone https://huggingface.co/JamesFlare/pastel-mix ``` {'Header 1': 'Stable Diffusion', 'Header 2': '2. 启动 Stable Diffusion WebUI', 'Header 3': '2.4 获取模型名称'} 现在你可以在模型列表中看到 `pastel-mix`,但我们仍然需要获取模型名称,访问 `http://your_id:port/sdapi/v1/sd-models`,你将看到如下的模型名称。 ```json [ { "title": "pastel-mix/pastelmix-better-vae-fp32.ckpt [943a810f75]", "model_name": "pastel-mix_pastelmix-better-vae-fp32", "hash": "943a810f75", "sha256": "943a810f7538b32f9d81dc5adea3792c07219964c8a8734565931fcec90d762d", "filename": "/home/takatost/stable-diffusion-webui/models/Stable-diffusion/pastel-mix/pastelmix-better-vae-fp32.ckpt", "config": null }, ] ``` {'Header 1': 'Stable Diffusion', 'Header 2': '2. 启动 Stable Diffusion WebUI', 'Header 3': '2.4 获取模型名称'} "config": null }, ] ``` `model_name` 就是我们需要的,这个例子中是 `pastel-mix_pastelmix-better-vae-fp32`。 {'Header 1': 'Stable Diffusion', 'Header 2': '3. 在 Dify 中集成 Stable Diffusion'} 在 `工具 > StableDiffusion > 去认证` 中填写认证和模型配置,使用你从之前步骤中获取的信息。 {'Header 1': 'Stable Diffusion', 'Header 2': '4. 完成'} 尝试在Dify中使用它吧! {'Header 1': '扩展'} 在创造 AI 应用的过程中,开发者面临着不断变化的业务需求和复杂的技术挑战。有效地利用扩展能力不仅可以提高应用的灵活性和功能性,还可以确保企业数据的安全性和合规性。 Dify 提供了以下两种扩展方式: * API 扩展 * 代码扩展 {'Header 1': 'Code Based Extensions'} For developers deploying Dify locally, if you want to implement extension capabilities without rewriting an API service, you can use code extensions. This allows you to extend or enhance the functionality of the program in code form (i.e., plugin capability) without disrupting the original code logic of Dify. It follows certain interfaces or specifications to achieve compatibility and plug-and-play capability with the main program. Currently, Dify offers two types of code extensions: {'Header 1': 'Code Based Extensions'} * Adding a new type of external data tool [external_data_tool.md](external_data_tool.md "mention") * Extending sensitive content moderation strategies [moderation.md](moderation.md "mention") Based on the above functionalities, you can achieve horizontal expansion by following the code-level interface specifications. If you are willing to contribute your extensions to us, we warmly welcome you to submit a PR to Dify. {'Header 1': 'Code Based Extensions', 'Header 2': 'Frontend Component Specification Definition'} The frontend styles of code extensions are defined through `schema.json`: * label: Custom type name, supporting system language switching * form_schema: List of form contents * type: Component type * select: Dropdown options * text-input: Text * paragraph: Paragraph * label: Component name, supporting system language switching * variable: Variable name * required: Whether it is required * default: Default value * placeholder: Component hint content {'Header 1': 'Code Based Extensions', 'Header 2': 'Frontend Component Specification Definition'} * placeholder: Component hint content * options: Exclusive property for the "select" component, defining the dropdown contents * label: Dropdown name, supporting system language switching * value: Dropdown option value * max_length: Exclusive property for the "text-input" component, maximum length {'Header 1': 'Code Based Extensions', 'Header 2': 'Frontend Component Specification Definition', 'Header 3': 'Template Example'} ```json { "label": { "en-US": "Cloud Service", "zh-Hans": "云服务" }, "form_schema": [ { "type": "select", "label": { "en-US": "Cloud Provider", "zh-Hans": "云厂商" }, "variable": "cloud_provider", "required": true, "options": [ { "label": { "en-US": "AWS", "zh-Hans": "亚马逊" }, "value": "AWS" }, { "label": { "en-US": "Google Cloud", "zh-Hans": "谷歌云" }, "value": "GoogleCloud" }, { "label": { "en-US": "Azure Cloud", "zh-Hans": "微软云" }, "value": "Azure" } ], "default": "GoogleCloud", "placeholder": "" }, {'Header 1': 'Code Based Extensions', 'Header 2': 'Frontend Component Specification Definition', 'Header 3': 'Template Example'} ], "default": "GoogleCloud", "placeholder": "" }, { "type": "text-input", "label": { "en-US": "API Endpoint", "zh-Hans": "API Endpoint" }, "variable": "api_endpoint", "required": true, "max_length": 100, "default": "", "placeholder": "https://api.example.com" }, { "type": "paragraph", "label": { "en-US": "API Key", "zh-Hans": "API Key" }, "variable": "api_keys", "required": true, "default": "", "placeholder": "Paste your API key here" } ] } ```# 外部数据工具 {'Header 1': 'Code Based Extensions', 'Header 2': 'Frontend Component Specification Definition', 'Header 3': 'Template Example'} } ] } ```# 外部数据工具 外部数据工具用于在终端用户提交数据后,利用外部工具获取额外数据组装至提示词中作为 LLM 额外上下文信息。Dify 默认提供了外部 API 调用的工具,具体参见 [api\_based\_extension](../api\_based\_extension/ "mention")。 而对于本地部署 Dify 的开发者,为了满足更加定制化的需求,或者不希望额外开发一个 API Server,可以直接在 Dify 服务的基础上,以插件的形式插入定制的外部数据工具实现逻辑。扩展自定义工具后,将会在工具类型的下拉列表中增加您的自定义工具选项,团队成员即可使用自定义的工具来获取外部数据。 {'Header 1': 'Code Based Extensions', 'Header 2': '快速开始'} 这里以一个 `天气查询` 外部数据工具扩展为例,步骤如下: 1. 初始化目录 2. 添加前端表单规范 3. 添加实现类 4. 预览前端界面 5. 调试扩展 {'Header 1': 'Code Based Extensions', 'Header 2': '快速开始', 'Header 3': '1. **初始化目录**'} 新增自定义类型 `Weather Search` ,需要在 `api/core/external_data_tool` 目录下新建相关的目录和文件。 ```python . └── api └── core └── external_data_tool └── weather_search ├── __init__.py ├── weather_search.py └── schema.json ``` {'Header 1': 'Code Based Extensions', 'Header 2': '快速开始', 'Header 3': '2. **添加前端组件规范**'} * `schema.json`,这里定义了前端组件规范,详细见 [.](./ "mention") ```json { "label": { "en-US": "Weather Search", "zh-Hans": "天气查询" }, "form_schema": [ { "type": "select", "label": { "en-US": "Temperature Unit", "zh-Hans": "温度单位" }, "variable": "temperature_unit", "required": true, "options": [ { "label": { "en-US": "Fahrenheit", "zh-Hans": "华氏度" }, "value": "fahrenheit" }, { "label": { "en-US": "Centigrade", "zh-Hans": "摄氏度" }, "value": "centigrade" } ], "default": "centigrade", {'Header 1': 'Code Based Extensions', 'Header 2': '快速开始', 'Header 3': '2. **添加前端组件规范**'} } ], "default": "centigrade", "placeholder": "Please select temperature unit" } ] } ``` {'Header 1': 'Code Based Extensions', 'Header 2': '快速开始', 'Header 3': '3. 添加实现类'} `weather_search.py` 代码模版,你可以在这里实现具体的业务逻辑。 {% hint style="warning" %} 注意:类变量 name 为自定义类型名称,需要跟目录和文件名保持一致,而且唯一。 {% endhint %} ```python from typing import Optional from core.external_data_tool.base import ExternalDataTool class WeatherSearch(ExternalDataTool): """ The name of custom type must be unique, keep the same with directory and file name. """ name: str = "weather_search" {'Header 1': 'Code Based Extensions', 'Header 2': '快速开始', 'Header 3': '3. 添加实现类'} @classmethod def validate_config(cls, tenant_id: str, config: dict) -> None: """ schema.json validation. It will be called when user save the config. Example: .. code-block:: python config = { "temperature_unit": "centigrade" } :param tenant_id: the id of workspace :param config: the variables of form config :return: """ if not config.get('temperature_unit'): raise ValueError('temperature unit is required') {'Header 1': 'Code Based Extensions', 'Header 2': '快速开始', 'Header 3': '3. 添加实现类'} def query(self, inputs: dict, query: Optional[str] = None) -> str: """ Query the external data tool. :param inputs: user inputs :param query: the query of chat app :return: the tool query result """ city = inputs.get('city') temperature_unit = self.config.get('temperature_unit') if temperature_unit == 'fahrenheit': return f'Weather in {city} is 32°F' else: return f'Weather in {city} is 0°C' ``` {'Header 1': 'Code Based Extensions', 'Header 2': '快速开始', 'Header 3': '4. **预览前端界面**'} 按照上面步骤执行,运行服务即可见新增的自定义类型。

    Add Tool

    {'Header 1': 'Code Based Extensions', 'Header 2': '快速开始', 'Header 3': '5. **调试扩展**'} 至此,即可在 Dify 应用编排界面选择自定义的 `Weather Search` 外部数据工具扩展类型进行调试。 {'Header 1': 'Code Based Extensions', 'Header 2': '实现类模版'} ```python from typing import Optional from core.external_data_tool.base import ExternalDataTool class WeatherSearch(ExternalDataTool): """ The name of custom type must be unique, keep the same with directory and file name. """ name: str = "weather_search" @classmethod def validate_config(cls, tenant_id: str, config: dict) -> None: """ schema.json validation. It will be called when user save the config. {'Header 1': 'Code Based Extensions', 'Header 2': '实现类模版'} :param tenant_id: the id of workspace :param config: the variables of form config :return: """ # implement your own logic here def query(self, inputs: dict, query: Optional[str] = None) -> str: """ Query the external data tool. :param inputs: user inputs :param query: the query of chat app :return: the tool query result """ # implement your own logic here return "your own data." ``` {'Header 1': 'Code Based Extensions', 'Header 2': '实现类模版', 'Header 3': 'def validate\\_config'} `schema.json` 表单校验方法,当用户点击「发布」保存配置时调用 * `config` 表单参数 * `{{variable}}` 表单自定义变量 {'Header 1': 'Code Based Extensions', 'Header 2': '实现类模版', 'Header 3': 'def query'} 用户自定义数据查询实现,返回的结果将会被替换到指定的变量。 * `inputs` :终端用户传入变量值 * `query` :终端用户当前对话输入内容,对话型应用固定参数。 {'Header 1': '敏感内容审查'} 除了系统内置的内容审查类型,Dify 也支持用户扩展自定义的内容审查规则,该方法适用于私有部署的开发者定制开发。比如企业内部客服,规定用户在查询的时候以及客服回复的时候,除了不可以输入暴力,性和非法行为等相关词语,也不能出现企业自己规定的禁词或违反内部制定的审查逻辑,那么开发者可以在私有部署的 Dify 代码层扩展自定义内容审查规则。 {'Header 1': '敏感内容审查', 'Header 2': '快速开始'} 这里以一个 `Cloud Service` 内容审查扩展为例,步骤如下: 1. 初始化目录 2. 添加前端组件定义文件 3. 添加实现类 4. 预览前端界面 5. 调试扩展 {'Header 1': '敏感内容审查', 'Header 2': '快速开始', 'Header 3': '1. 初始化目录'} 新增自定义类型 `Cloud Service`,需要在 `api/core/moderation` 目录下新建相关的目录和文件。 ```Plain . └── api └── core └── moderation └── cloud_service ├── __init__.py ├── cloud_service.py └── schema.json ``` {'Header 1': '敏感内容审查', 'Header 2': '快速开始', 'Header 3': '2.添加前端组件规范'} * `schema.json`,这里定义了前端组件规范,详细见 [.](./ "mention") 。 ```json { "label": { "en-US": "Cloud Service", "zh-Hans": "云服务" }, "form_schema": [ { "type": "select", "label": { "en-US": "Cloud Provider", "zh-Hans": "云厂商" }, "variable": "cloud_provider", "required": true, "options": [ { "label": { "en-US": "AWS", "zh-Hans": "亚马逊" }, "value": "AWS" }, { "label": { "en-US": "Google Cloud", "zh-Hans": "谷歌云" }, "value": "GoogleCloud" }, { "label": { "en-US": "Azure Cloud", "zh-Hans": "微软云" }, {'Header 1': '敏感内容审查', 'Header 2': '快速开始', 'Header 3': '2.添加前端组件规范'} "en-US": "Azure Cloud", "zh-Hans": "微软云" }, "value": "Azure" } ], "default": "GoogleCloud", "placeholder": "" }, { "type": "text-input", "label": { "en-US": "API Endpoint", "zh-Hans": "API Endpoint" }, "variable": "api_endpoint", "required": true, "max_length": 100, "default": "", "placeholder": "https://api.example.com" }, { "type": "paragraph", "label": { "en-US": "API Key", "zh-Hans": "API Key" }, "variable": "api_keys", "required": true, "default": "", {'Header 1': '敏感内容审查', 'Header 2': '快速开始', 'Header 3': '2.添加前端组件规范'} "required": true, "default": "", "placeholder": "Paste your API key here" } ] } ``` {'Header 1': '敏感内容审查', 'Header 2': '快速开始', 'Header 3': '3. 添加实现类'} `cloud_service.py` 代码模版,你可以在这里实现具体的业务逻辑。 {% hint style="warning" %} 注意:类变量 name 为自定义类型名称,需要跟目录和文件名保持一致,而且唯一。 {% endhint %} ```python from core.moderation.base import Moderation, ModerationAction, ModerationInputsResult, ModerationOutputsResult class CloudServiceModeration(Moderation): """ The name of custom type must be unique, keep the same with directory and file name. """ name: str = "cloud_service" {'Header 1': '敏感内容审查', 'Header 2': '快速开始', 'Header 3': '3. 添加实现类'} @classmethod def validate_config(cls, tenant_id: str, config: dict) -> None: """ schema.json validation. It will be called when user save the config. {'Header 1': '敏感内容审查', 'Header 2': '快速开始', 'Header 3': '3. 添加实现类'} Example: .. code-block:: python config = { "cloud_provider": "GoogleCloud", "api_endpoint": "https://api.example.com", "api_keys": "123456", "inputs_config": { "enabled": True, "preset_response": "Your content violates our usage policy. Please revise and try again." }, "outputs_config": { "enabled": True, "preset_response": "Your content violates our usage policy. Please revise and try again." } } :param tenant_id: the id of workspace :param config: the variables of form config :return: """ {'Header 1': '敏感内容审查', 'Header 2': '快速开始', 'Header 3': '3. 添加实现类'} cls._validate_inputs_and_outputs_config(config, True) if not config.get("cloud_provider"): raise ValueError("cloud_provider is required") if not config.get("api_endpoint"): raise ValueError("api_endpoint is required") if not config.get("api_keys"): raise ValueError("api_keys is required") def moderation_for_inputs(self, inputs: dict, query: str = "") -> ModerationInputsResult: """ Moderation for inputs. {'Header 1': '敏感内容审查', 'Header 2': '快速开始', 'Header 3': '3. 添加实现类'} :param inputs: user inputs :param query: the query of chat app, there is empty if is completion app :return: the moderation result """ flagged = False preset_response = "" if self.config['inputs_config']['enabled']: preset_response = self.config['inputs_config']['preset_response'] if query: inputs['query__'] = query flagged = self._is_violated(inputs) {'Header 1': '敏感内容审查', 'Header 2': '快速开始', 'Header 3': '3. 添加实现类'} # return ModerationInputsResult(flagged=flagged, action=ModerationAction.OVERRIDED, inputs=inputs, query=query) return ModerationInputsResult(flagged=flagged, action=ModerationAction.DIRECT_OUTPUT, preset_response=preset_response) def moderation_for_outputs(self, text: str) -> ModerationOutputsResult: """ Moderation for outputs. :param text: the text of LLM response :return: the moderation result """ flagged = False preset_response = "" {'Header 1': '敏感内容审查', 'Header 2': '快速开始', 'Header 3': '3. 添加实现类'} if self.config['outputs_config']['enabled']: preset_response = self.config['outputs_config']['preset_response'] flagged = self._is_violated({'text': text}) # return ModerationOutputsResult(flagged=flagged, action=ModerationAction.OVERRIDED, text=text) return ModerationOutputsResult(flagged=flagged, action=ModerationAction.DIRECT_OUTPUT, preset_response=preset_response) def _is_violated(self, inputs: dict): """ The main logic of moderation. {'Header 1': '敏感内容审查', 'Header 2': '快速开始', 'Header 3': '3. 添加实现类'} :param inputs: :return: the moderation result """ return False ``` {'Header 1': '敏感内容审查', 'Header 2': '快速开始', 'Header 3': '4. 预览前端界面'} 按照上面步骤执行,运行服务即可见新增的自定义类型。

    Cloud Service

    {'Header 1': '敏感内容审查', 'Header 2': '快速开始', 'Header 3': '5. 调试扩展'} 至此,即可在 Dify 应用编排界面选择自定义的 `Cloud Service` 内容审查扩展类型进行调试。\ {'Header 1': '敏感内容审查', 'Header 2': '实现类模版'} ```python from core.moderation.base import Moderation, ModerationAction, ModerationInputsResult, ModerationOutputsResult class CloudServiceModeration(Moderation): """ The name of custom type must be unique, keep the same with directory and file name. """ name: str = "cloud_service" @classmethod def validate_config(cls, tenant_id: str, config: dict) -> None: """ schema.json validation. It will be called when user save the config. {'Header 1': '敏感内容审查', 'Header 2': '实现类模版'} :param tenant_id: the id of workspace :param config: the variables of form config :return: """ cls._validate_inputs_and_outputs_config(config, True) # implement your own logic here def moderation_for_inputs(self, inputs: dict, query: str = "") -> ModerationInputsResult: """ Moderation for inputs. :param inputs: user inputs :param query: the query of chat app, there is empty if is completion app :return: the moderation result """ flagged = False preset_response = "" {'Header 1': '敏感内容审查', 'Header 2': '实现类模版'} # implement your own logic here # return ModerationInputsResult(flagged=flagged, action=ModerationAction.OVERRIDED, inputs=inputs, query=query) return ModerationInputsResult(flagged=flagged, action=ModerationAction.DIRECT_OUTPUT, preset_response=preset_response) def moderation_for_outputs(self, text: str) -> ModerationOutputsResult: """ Moderation for outputs. :param text: the text of LLM response :return: the moderation result """ flagged = False preset_response = "" {'Header 1': '敏感内容审查', 'Header 2': '实现类模版'} # implement your own logic here # return ModerationOutputsResult(flagged=flagged, action=ModerationAction.OVERRIDED, text=text) return ModerationOutputsResult(flagged=flagged, action=ModerationAction.DIRECT_OUTPUT, preset_response=preset_response) ``` {'Header 1': '敏感内容审查', 'Header 2': '实现类开发详细介绍', 'Header 3': 'def validate\\_config'} `schema.json` 表单校验方法,当用户点击「发布」保存配置时调用 * `config` 表单参数 * `{{variable}}` 表单自定义变量 * `inputs_config` 输入审查预设回复 * `enabled` 是否开启 * `preset_response` 输入预设回复 * `outputs_config`输出审查预设回复 * `enabled` 是否开启 * `preset_respons` 输出预设回复 {'Header 1': '敏感内容审查', 'Header 2': '实现类开发详细介绍', 'Header 3': 'def moderation\\_for\\_inputs'} 输入校验函数 * `inputs` :终端用户传入变量值 * `query` :终端用户当前对话输入内容,对话型应用固定参数。 * `ModerationInputsResult` * `flagged` 是否违反校验规则 * `action` 执行动作 * `direct_output` 直接输出预设回复 * `overrided` 覆写传入变量值 * `preset_response` 预设回复(仅当 action=direct\_output 返回) * `inputs` 终端用户传入变量值,key 为变量名,value 为变量值(仅当 action=overrided 返回) * `query` 覆写的终端用户当前对话输入内容,对话型应用固定参数。(仅当 action=overrided 返回) {'Header 1': '敏感内容审查', 'Header 2': '实现类开发详细介绍', 'Header 3': 'def moderation\\_for\\_outputs'} 输出校验函数 * `text` :模型输出内容 * `moderation_for_outputs` :输出校验函数 * `text` :LLM 回答内容。当 LLM 输出为流式时,此处为 100 字为一个分段的内容。 * `ModerationOutputsResult` * `flagged` 是否违反校验规则 * `action` 执行动作 * `direct_output`直接输出预设回复 * `overrided`覆写传入变量值 * `preset_response` 预设回复(仅当 action=direct\_output 返回) * `text` 覆写的 LLM 回答内容(仅当 action=overrided 返回)。 \ {'Header 1': 'API 扩展'} 开发者可通过 API 扩展模块能力,当前支持以下模块扩展: * `moderation` 敏感内容审计 * `external_data_tool` 外部数据工具 在扩展模块能力之前,您需要准备一个 API 和用于鉴权的 API Key(也可由 Dify 自动生成,可选)。 除了需要开发对应的模块能力,还需要遵照以下规范,以便 Dify 正确调用 API。

    基于 API 扩展

    {'Header 1': 'API 扩展', 'Header 3': 'API 规范 '} Dify 将会以以下规范调用您的接口: ``` POST {Your-API-Endpoint} ``` #### Header | Header | Value | Desc | | --------------- | ----------------- | --------------------------------------------------------------------- | | `Content-Type` | application/json | 请求内容为 JSON 格式。 | {'Header 1': 'API 扩展', 'Header 3': 'API 规范 '} | `Authorization` | Bearer {api\_key} | API Key 以 Token 令牌的方式传输,您需要解析该 `api_key` 并确认是否和提供的 API Key 一致,保证接口安全。 | #### Request Body ``` { "point": string, // 扩展点,不同模块可能包含多个扩展点 "params": { ... // 各模块扩展点传入参数 } } ``` #### API 返回 ``` { ... // API 返回的内容,不同扩展点返回见不同模块的规范设计 } ``` {'Header 1': 'API 扩展', 'Header 3': '校验 '} 在 Dify 配置 API-based Extension 时,Dify 将会发送一个请求至 API Endpoint,以检验 API 的可用性。 当 API Endpoint 接收到 `point=ping` 时,接口应返回 `result=pong`,具体如下: #### Header ``` Content-Type: application/json Authorization: Bearer {api_key} ``` #### Request Body ``` { "point": "ping" } ``` {'Header 1': 'API 扩展', 'Header 3': '校验 '} ``` { "point": "ping" } ``` #### API 期望返回 ``` { "result": "pong" } ``` {'Header 1': 'API 扩展', 'Header 3': '范例 '} 此处以外部数据工具为例,场景为根据地区获取外部天气信息作为上下文。 #### API 范例 ``` POST https://fake-domain.com/api/dify/receive ``` **Header** ``` Content-Type: application/json Authorization: Bearer 123456 ``` **Request Body** ``` { "point": "app.external_data_tool.query", "params": { "app_id": "61248ab4-1125-45be-ae32-0ce91334d021", "tool_variable": "weather_retrieve", "inputs": { "location": "London" }, "query": "How's the weather today?" } } ``` {'Header 1': 'API 扩展', 'Header 3': '范例 '} }, "query": "How's the weather today?" } } ``` **API 返回** ``` { "result": "City: London\nTemperature: 10°C\nRealFeel®: 8°C\nAir Quality: Poor\nWind Direction: ENE\nWind Speed: 8 km/h\nWind Gusts: 14 km/h\nPrecipitation: Light rain" } ``` #### 代码范例 代码基于 Python FastAPI 框架。 1. 安装依赖 ``` pip install fastapi[all] uvicorn ``` 2. 按照接口规范编写代码 ``` from fastapi import FastAPI, Body, HTTPException, Header {'Header 1': 'API 扩展', 'Header 3': '范例 '} from pydantic import BaseModel {'Header 1': 'API 扩展', 'Header 3': '范例 '} app = FastAPI() class InputData(BaseModel): point: str params: dict = {} @app.post("/api/dify/receive") async def dify_receive(data: InputData = Body(...), authorization: str = Header(None)): """ Receive API query data from Dify. """ expected_api_key = "123456" # TODO Your API key of this API auth_scheme, _, api_key = authorization.partition(' ') if auth_scheme.lower() != "bearer" or api_key != expected_api_key: raise HTTPException(status_code=401, detail="Unauthorized") {'Header 1': 'API 扩展', 'Header 3': '范例 '} point = data.point # for debug print(f"point: {point}") if point == "ping": return { "result": "pong" } if point == "app.external_data_tool.query": return handle_app_external_data_tool_query(params=data.params) # elif point == "{point name}": # TODO other point implementation here raise HTTPException(status_code=400, detail="Not implemented") {'Header 1': 'API 扩展', 'Header 3': '范例 '} def handle_app_external_data_tool_query(params: dict): app_id = params.get("app_id") tool_variable = params.get("tool_variable") inputs = params.get("inputs") query = params.get("query") # for debug print(f"app_id: {app_id}") print(f"tool_variable: {tool_variable}") print(f"inputs: {inputs}") print(f"query: {query}") {'Header 1': 'API 扩展', 'Header 3': '范例 '} # TODO your external data tool query implementation here, # return must be a dict with key "result", and the value is the query result if inputs.get("location") == "London": return { "result": "City: London\nTemperature: 10°C\nRealFeel®: 8°C\nAir Quality: Poor\nWind Direction: ENE\nWind " "Speed: 8 km/h\nWind Gusts: 14 km/h\nPrecipitation: Light rain" } else: return {"result": "Unknown city"} ``` {'Header 1': 'API 扩展', 'Header 3': '范例 '} } else: return {"result": "Unknown city"} ``` 3. 启动 API 服务,默认端口为 8000,API 完整地址为:`http://127.0.0.1:8000/api/dify/receive`,配置的 API Key 为 `123456`。
    uvicorn main:app --reload --host 0.0.0.0
    
    4. 在 Dify 配置该 API。

    配置 API

    5. 在 App 中选择该 API 扩展。 {'Header 1': 'API 扩展', 'Header 3': '范例 '} 5. 在 App 中选择该 API 扩展。

    选择扩展

    App 调试时,Dify 将请求配置的 API,并发送以下内容(范例): ``` { "point": "app.external_data_tool.query", "params": { "app_id": "61248ab4-1125-45be-ae32-0ce91334d021", "tool_variable": "weather_retrieve", "inputs": { "location": "London" }, "query": "How's the weather today?" } } ``` API 返回为: ``` { {'Header 1': 'API 扩展', 'Header 3': '范例 '} } } ``` API 返回为: ``` { "result": "City: London\nTemperature: 10°C\nRealFeel®: 8°C\nAir Quality: Poor\nWind Direction: ENE\nWind Speed: 8 km/h\nWind Gusts: 14 km/h\nPrecipitation: Light rain" } ``` {'Header 1': 'API 扩展', 'Header 3': '本地调试'} 由于 Dify 云端版无法访问内网 API 服务,为了方便本地调试 API 服务,可以使用 [Ngrok](https://ngrok.com) 将 API 服务的端点暴露到公网,实现云端调试本地代码。操作步骤: 1. 进入 [https://ngrok.com](https://ngrok.com) 官网,注册并下载 Ngrok 文件。

    Download

    2. 下载完成后,进入下载目录,根据下方说明解压压缩包,并执行说明中的初始化脚本。 * ```Shell $ unzip /path/to/ngrok.zip $ ./ngrok config add-authtoken 你的Token ``` 3. 查看本地 API 服务的端口: {'Header 1': 'API 扩展', 'Header 3': '本地调试'}

    查看端口

    并运行以下命令启动: {'Header 1': 'API 扩展', 'Header 3': '本地调试'} * ```Shell $ ./ngrok http 端口号 ``` 启动成功的样例如下:

    Ngrok 启动

    4. 我们找到 Forwarding 中,如上图:`https://177e-159-223-41-52.ngrok-free.app`(此为示例域名,请替换为自己的)即为公网域名。 * 按照上述的范例,我们把本地已经启动的服务端点暴露出去,将代码范例接口:`http://127.0.0.1:8000/api/dify/receive` 替换为 `https://177e-159-223-41-52.ngrok-free.app/api/dify/receive` {'Header 1': 'API 扩展', 'Header 3': '本地调试'} 此 API 端点即可公网访问。至此,我们即可在 Dify 配置该 API 端点进行本地调试代码,配置步骤请参考 [external\_data\_tool.md](../../knowledge-base/external\_data\_tool.md "mention")。 {'Header 1': 'API 扩展', 'Header 3': '使用 Cloudflare Workers 部署 API 扩展'} 我们推荐你使用 Cloudflare Workers 来部署你的 API 扩展,因为 Cloudflare Workers 可以方便的提供一个公网地址,而且可以免费使用。 [cloudflare\_workers.md](cloudflare\_workers.md "mention")。 {'Header 1': '外部数据工具'} 在创建 AI 应用时,开发者可以通过 API 扩展的方式实现使用外部工具获取额外数据组装至 Prompt 中作为 LLM 额外信息。具体的实操过程可以参考 [external\_data\_tool.md](../../knowledge-base/external\_data\_tool.md "mention")。 {'Header 1': '外部数据工具', 'Header 3': '前置条件'} 请先阅读 [.](./ "mention") 完成 API 服务基础能力的开发和接入。 {'Header 1': '外部数据工具', 'Header 3': '扩展点'} `app.external_data_tool.query` 应用外部数据工具查询扩展点。 该扩展点将终端用户传入的应用变量内容和对话输入内容(对话型应用固定参数)作为参数,传给 API。 开发者需要实现对应工具的查询逻辑,并返回字符串类型的查询结果。 #### Request Body ``` { "point": "app.external_data_tool.query", // 扩展点类型,此处固定为 app.external_data_tool.query "params": { "app_id": string, // 应用 ID "tool_variable": string, // 外部数据工具变量名称,表示对应变量工具调用来源 "inputs": { // 终端用户传入变量值,key 为变量名,value 为变量值 "var_1": "value_1", "var_2": "value_2", ... {'Header 1': '外部数据工具', 'Header 3': '扩展点'} "var_1": "value_1", "var_2": "value_2", ... }, "query": string | null // 终端用户当前对话输入内容,对话型应用固定参数。 } } ``` * Example * ``` { "point": "app.external_data_tool.query", "params": { "app_id": "61248ab4-1125-45be-ae32-0ce91334d021", "tool_variable": "weather_retrieve", "inputs": { "location": "London" }, "query": "How's the weather today?" } } ``` {'Header 1': '外部数据工具', 'Header 3': '扩展点'} #### API 返回 ``` { "result": string } ``` * Example * ``` { "result": "City: London\nTemperature: 10°C\nRealFeel®: 8°C\nAir Quality: Poor\nWind Direction: ENE\nWind Speed: 8 km/h\nWind Gusts: 14 km/h\nPrecipitation: Light rain" } ``` \\ {'Header 1': '使用 Cloudflare Workers 部署 API Tools', 'Header 2': '开始'} 因为 Dify API Extension 需要使用可以访问的公网地址作为 API Endpoint,所以我们需要将 API 扩展部署到一个公网地址上。这里我们使用 Cloudflare Workers 来部署我们的 API 扩展。 我们 Clone [Example GitHub Repository](https://github.com/crazywoola/dify-extension-workers),这个仓库包含了一个简单的 API 扩展,我们可以在这个基础上进行修改。 ```bash git clone https://github.com/crazywoola/dify-extension-workers.git cp wrangler.toml.example wrangler.toml ``` 打开 `wrangler.toml` 文件,修改 `name` 和 `compatibility_date` 为你的应用名称和兼容日期。 {'Header 1': '使用 Cloudflare Workers 部署 API Tools', 'Header 2': '开始'} 这里我们我们需要注意的配置就是 `vars` 里面的 `TOKEN`,在 Dify 添加 API 扩展的时候,我们需要填写这个 Token。出于安全考虑,我们建议你使用一个随机的字符串作为 Token,你不应该在源代码中直接写入 Token,而是使用环境变量的方式来传递 Token。所以请不要把 wrangler.toml 提交到你的代码仓库中。 ```toml name = "dify-extension-example" compatibility_date = "2023-01-01" {'Header 1': '使用 Cloudflare Workers 部署 API Tools', 'Header 2': '开始'} [vars] TOKEN = "bananaiscool" ``` 这个 API 扩展会返回一个随机的 Breaking Bad 名言。你可以在 `src/index.ts` 中修改这个 API 扩展的逻辑。这个例子展示了与第三方 API 进行交互的方式。 ```typescript // ⬇️ impliment your logic here ⬇️ // point === "app.external_data_tool.query" // https://api.breakingbadquotes.xyz/v1/quotes const count = params?.inputs?.count ?? 1; const url = `https://api.breakingbadquotes.xyz/v1/quotes/${count}`; const result = await fetch(url).then(res => res.text()) // ⬆️ impliment your logic here ⬆️ ``` {'Header 1': '使用 Cloudflare Workers 部署 API Tools', 'Header 2': '开始'} // ⬆️ impliment your logic here ⬆️ ``` 这个仓库简化了除了业务逻辑之外所有的配置,你可以直接使用 `npm` 命令来部署你的 API 扩展。 ```bash npm run deploy ``` 部署成功之后,你会得到一个公网地址,你可以在 Dify 中添加这个地址作为 API Endpoint。请注意不要遗漏 `endpoint` 这个路径。

    在 Dify 中添加 API Endpoint

    在 App 编辑页面中添加上 API Tool

    {'Header 1': '使用 Cloudflare Workers 部署 API Tools', 'Header 2': '其他逻辑 TL;DR', 'Header 3': '关于 Bearer Auth'} ```typescript import { bearerAuth } from "hono/bearer-auth"; (c, next) => { const auth = bearerAuth({ token: c.env.TOKEN }); return auth(c, next); }, ``` 我们的 Bearer 校验逻辑在如上代码中,我们使用了 `hono/bearer-auth` 这个包来实现 Bearer 校验。你可以在 `src/index.ts` 中使用 `c.env.TOKEN` 来获取 Token。 {'Header 1': '使用 Cloudflare Workers 部署 API Tools', 'Header 2': '其他逻辑 TL;DR', 'Header 3': '关于参数验证'} ```typescript import { z } from "zod"; import { zValidator } from "@hono/zod-validator"; const schema = z.object({ point: z.union([ z.literal("ping"), z.literal("app.external_data_tool.query"), ]), // Restricts 'point' to two specific values params: z .object({ app_id: z.string().optional(), tool_variable: z.string().optional(), inputs: z.record(z.any()).optional(), query: z.any().optional(), // string or null }) .optional(), }); {'Header 1': '使用 Cloudflare Workers 部署 API Tools', 'Header 2': '其他逻辑 TL;DR', 'Header 3': '关于参数验证'} ``` 我们这里使用了 `zod` 来定义参数的类型,你可以在 `src/index.ts` 中使用 `zValidator` 来校验参数。通过 `const { point, params } = c.req.valid("json");` 来获取校验后的参数。 我们这里的 point 只有两个值,所以我们使用了 `z.union` 来定义。 params 是一个可选的参数,所以我们使用了 `z.optional` 来定义。 其中会有一个 `inputs` 的参数,这个参数是一个 `Record` 类型,这个类型表示一个 key 为 string,value 为 any 的对象。这个类型可以表示任意的对象,你可以在 `src/index.ts` 中使用 `params?.inputs?.count` 来获取 `count` 参数。 {'Header 1': '使用 Cloudflare Workers 部署 API Tools', 'Header 2': '其他逻辑 TL;DR', 'Header 3': '获取 Cloudflare Workers 的日志'} ```bash wrangler tail ``` {'Header 1': '使用 Cloudflare Workers 部署 API Tools', 'Header 2': '参考内容'} * [Cloudflare Workers](https://workers.cloudflare.com/) * [Cloudflare Workers CLI](https://developers.cloudflare.com/workers/cli-wrangler/install-update) * [Example GitHub Repository](https://github.com/crazywoola/dify-extension-workers) {'Header 1': '敏感内容审查'} 该模块用于审查应用中终端用户输入的内容和 LLM 输出的内容,分为两个扩展点类型。 {'Header 1': '敏感内容审查', 'Header 3': '扩展点 '} * `app.moderation.input` 终端用户输入的内容审查扩展点 * 用于审查终端用户传入的变量内容以及对话型应用中对话的输入内容。 * `app.moderation.output`LLM 输出的内容审查扩展点 * 用于审查 LLM 输出的内容, * 当 LLM 输出为流式时,输出的内容将分 100 字为一个分段进行请求 API,尽可能避免输出内容较长时,审查不及时的问题。 {'Header 1': '敏感内容审查', 'Header 3': 'app.moderation.input 扩展点 '} #### Request Body ``` { "point": "app.moderation.input", // 扩展点类型,此处固定为 app.moderation.input "params": { "app_id": string, // 应用 ID "inputs": { // 终端用户传入变量值,key 为变量名,value 为变量值 "var_1": "value_1", "var_2": "value_2", ... }, "query": string | null // 终端用户当前对话输入内容,对话型应用固定参数。 } } ``` * Example * ``` { "point": "app.moderation.input", "params": { "app_id": "61248ab4-1125-45be-ae32-0ce91334d021", "inputs": { {'Header 1': '敏感内容审查', 'Header 3': 'app.moderation.input 扩展点 '} "inputs": { "var_1": "I will kill you.", "var_2": "I will fuck you." }, "query": "Happy everydays." } } ``` {'Header 1': '敏感内容审查', 'Header 3': 'app.moderation.input 扩展点 '} #### API 返回 ``` { "flagged": bool, // 是否违反校验规则 "action": string, // 动作,direct_output 直接输出预设回答; overrided 覆写传入变量值 "preset_response": string, // 预设回答(仅当 action=direct_output 返回) "inputs": { // 终端用户传入变量值,key 为变量名,value 为变量值(仅当 action=overrided 返回) "var_1": "value_1", "var_2": "value_2", ... }, "query": string | null // 覆写的终端用户当前对话输入内容,对话型应用固定参数。(仅当 action=overrided 返回) } ``` {'Header 1': '敏感内容审查', 'Header 3': 'app.moderation.input 扩展点 '} * Example * `action=``direct_output` * ``` { "flagged": true, "action": "direct_output", "preset_response": "Your content violates our usage policy." } ``` * `action=overrided` * ``` { "flagged": true, "action": "overrided", "inputs": { "var_1": "I will *** you.", "var_2": "I will *** you." }, "query": "Happy everydays." } ``` ### app.moderation.output 扩展点 {'Header 1': '敏感内容审查', 'Header 3': 'app.moderation.input 扩展点 '} #### Request Body ``` { "point": "app.moderation.output", // 扩展点类型,此处固定为 app.moderation.output "params": { "app_id": string, // 应用 ID "text": string // LLM 回答内容。当 LLM 输出为流式时,此处为 100 字为一个分段的内容。 } } ``` {'Header 1': '敏感内容审查', 'Header 3': 'app.moderation.input 扩展点 '} * Example * ``` { "point": "app.moderation.output", "params": { "app_id": "61248ab4-1125-45be-ae32-0ce91334d021", "text": "I will kill you." } } ``` #### API 返回 ``` { "flagged": bool, // 是否违反校验规则 "action": string, // 动作,direct_output 直接输出预设回答; overrided 覆写传入变量值 "preset_response": string, // 预设回答(仅当 action=direct_output 返回) "text": string // 覆写的 LLM 回答内容。(仅当 action=overrided 返回) } ``` * Example {'Header 1': '敏感内容审查', 'Header 3': 'app.moderation.input 扩展点 '} } ``` * Example * `action=direct_output` * ``` { "flagged": true, "action": "direct_output", "preset_response": "Your content violates our usage policy." } ``` * `action=overrided` * ``` { "flagged": true, "action": "overrided", "text": "I will *** you." } ``` {'Header 1': '协同'} Dify 是一个多用户平台,工作空间(Workspace)是团队的基本协作单元。工作空间的成员可创建和编辑应用、知识库,也可以直接在[发现](app/)区域直接使用团队其它成员创建的公共应用。 {'Header 1': '协同', 'Header 3': '登录方式'} 需要注意,目前 Dify 的云服务与社区版支持的登录方式有所区别,参见下表。 | | 云服务 | 社区版 | | -------------- | ---- | ---- | | Email 登录 | 不支持 | 支持 | | 使用 GitHub 账号登录 | 支持 | 不支持 | | 使用 Google 账号登录 | 支持 | 不支持 | | SSO 登录 | 计划支持 | 计划支持 | {'Header 1': '协同', 'Header 3': '创建账号'} 如果你使用的是云服务,当你首次登录后将为你自动创建一个工作空间,您将成为管理员。 在社区版中,安装时将提示你设置管理员 Email 与密码。社区版不支持开通多个工作空间。 {'Header 1': '邀请与管理成员'} 工作空间的成员可由负责人和管理员邀请和管理,登录后在 Dify 的用户头像下拉中找到设置,在该界面中的左侧打开成员管理界面。 {'Header 1': '邀请与管理成员', 'Header 3': '成员邀请'} 提供被邀请者的 Email,系统将即时批准对方访问工作空间,被邀请人同时将收到一份邮件。 系统将自动新成员创建 Dify 账号。 {'Header 1': '邀请与管理成员', 'Header 3': '成员删除'} 成员被移出团队后将不再能访问当前工作空间,但这不影响该用户访问其它已加入的工作空间。 {'Header 1': '发现', 'Header 2': '模版应用'} 在**发现**中,提供了一些常用的模版应用。这些应用涵盖了人力资源,助手,翻译,编程和写作。
    如果要使用某个模版应用,点击模版的“添加到工作区”按钮。在左侧的工作区中,可以使用该应用。
    如果要修改某个模版来创建一个新的应用,点击模版的“自定义”按钮。 {'Header 1': '发现', 'Header 2': '工作区'} 工作区是应用的导航。点击工作区里的应用,可以直接使用该应用。
    工作区中的应用包括:自己的应用和其他团队添加到工作区中的应用。 {'Header 1': '管理应用', 'Header 3': '编辑应用信息'} 创建应用后,如果你想要修改应用名称或描述,可以点击应用左上角的 「编辑信息」 ,重新修改应用的图标、名称或描述。
    zh-Hans-edit-app-info

    编辑应用信息

    {'Header 1': '管理应用', 'Header 3': '复制应用'} 应用均支持复制操作,点击应用左上角的 「复制」。 {'Header 1': '管理应用', 'Header 3': '迁移为工作流编排'} TODO 🚧 {'Header 1': '管理应用', 'Header 3': '导出应用'} 在 Dify 内创建的应用均支持以 DSL 格式进行导出,你可以自由地将配置文件导入至任意 Dify 的工作室。 {% hint style="info" %} Dify DSL 格式文件是 Dify.AI 定义的 AI 应用工程文件标准,文件格式为 YML。该标准涵盖应用的基本描述、模型参数、编排配置等信息。 {% endhint %} {'Header 1': '管理应用', 'Header 3': '删除应用'} 如果你想要清理应用,可以点击应用左上角的 「删除」 。 {% hint style="info" %} ⚠️ 应用的删除操作无法撤销,所有用户将无法访问你的应用,应用内的所有 Prompt、编排配置和日志均会被删除。 {% endhint %} {'Header 1': '接入 OpenLLM 部署的本地模型'} 使用 [OpenLLM](https://github.com/bentoml/OpenLLM), 您可以针对任何开源大型语言模型进行推理,部署到云端或本地,并构建强大的 AI 应用程序。 Dify 支持以本地部署的方式接入 OpenLLM 部署的大型语言模型的推理能力。 {'Header 1': '接入 OpenLLM 部署的本地模型', 'Header 2': '部署 OpenLLM 模型', 'Header 3': '开始部署'} 您可以通过以下方式部署: ```bash docker run --rm -it -p 3333:3000 ghcr.io/bentoml/openllm start facebook/opt-1.3b --backend pt ``` > 注意:此处使用 facebook/opt-1.3b 模型仅作为示例,效果可能不佳,请根据实际情况选择合适的模型,更多模型请参考:[支持的模型列表](https://github.com/bentoml/OpenLLM#-supported-models)。 模型部署完毕,在 Dify 中使用接入模型 在 `设置 > 模型供应商 > OpenLLM` 中填入: - 模型名称:`facebook/opt-1.3b` - 服务器 URL:`http://:3333` 替换成您的机器 IP 地址 "保存" 后即可在应用中使用该模型。 {'Header 1': '接入 OpenLLM 部署的本地模型', 'Header 2': '部署 OpenLLM 模型', 'Header 3': '开始部署'} "保存" 后即可在应用中使用该模型。 本说明仅作为快速接入的示例,如需使用 OpenLLM 更多特性和信息,请参考:[OpenLLM](https://github.com/bentoml/OpenLLM)# 接入 Xinference 部署的本地模型 [Xorbits inference](https://github.com/xorbitsai/inference) 是一个强大且通用的分布式推理框架,旨在为大型语言模型、语音识别模型和多模态模型提供服务,甚至可以在笔记本电脑上使用。它支持多种与GGML兼容的模型,如 chatglm, baichuan, whisper, vicuna, orca 等。 Dify 支持以本地部署的方式接入 Xinference 部署的大型语言模型推理和 embedding 能力。 {'Header 1': '接入 OpenLLM 部署的本地模型', 'Header 2': '部署 Xinference', 'Header 3': '开始部署'} 部署 Xinference 有两种方式,分别为[本地部署](https://github.com/xorbitsai/inference/blob/main/README\_zh\_CN.md#%E6%9C%AC%E5%9C%B0%E9%83%A8%E7%BD%B2)和[分布式部署](https://github.com/xorbitsai/inference/blob/main/README\_zh\_CN.md#%E5%88%86%E5%B8%83%E5%BC%8F%E9%83%A8%E7%BD%B2),以下以本地部署为例。 1. 首先通过 PyPI 安装 Xinference: ```bash $ pip install "xinference[all]" ``` 2. 本地部署方式启动 Xinference: ```bash $ xinference-local {'Header 1': '接入 OpenLLM 部署的本地模型', 'Header 2': '部署 Xinference', 'Header 3': '开始部署'} ```bash $ xinference-local 2023-08-20 19:21:05,265 xinference 10148 INFO Xinference successfully started. Endpoint: http://127.0.0.1:9997 2023-08-20 19:21:05,266 xinference.core.supervisor 10148 INFO Worker 127.0.0.1:37822 has been added successfully 2023-08-20 19:21:05,267 xinference.deploy.worker 10148 INFO Xinference worker successfully started. ``` {'Header 1': '接入 OpenLLM 部署的本地模型', 'Header 2': '部署 Xinference', 'Header 3': '开始部署'} ``` Xinference 默认会在本地启动一个 worker,端点为:`http://127.0.0.1:9997`,端口默认为 `9997`。 默认只可本机访问,可配置 `-H 0.0.0.0`,非本地客户端可任意访问。 如需进一步修改 host 或 port,可查看 xinference 的帮助信息:`xinference-local --help`。 > 使用 Dify Docker 部署方式的需要注意网络配置,确保 Dify 容器可以访问到 Xinference 的端点,Dify 容器内部无法访问到 localhost,需要使用宿主机 IP 地址。 3. 创建并部署模型 进入 `http://127.0.0.1:9997` 选择需要部署的模型和规格进行部署,如下图所示:
    {'Header 1': '接入 OpenLLM 部署的本地模型', 'Header 2': '部署 Xinference', 'Header 3': '开始部署'} 由于不同模型在不同硬件平台兼容性不同,请查看 [Xinference 内置模型](https://inference.readthedocs.io/en/latest/models/builtin/index.html) 确定创建的模型是否支持当前硬件平台。 4. 获取模型 UID 从上图所在页面获取对应模型的 ID,如:`2c886330-8849-11ee-9518-43b0b8f40bea` 5. 模型部署完毕,在 Dify 中使用接入模型 在 `设置 > 模型供应商 > Xinference` 中填入: * 模型名称:`vicuna-v1.3` * 服务器 URL:`http://:9997` **替换成您的机器 IP 地址** * 模型 UID:`2c886330-8849-11ee-9518-43b0b8f40bea` "保存" 后即可在应用中使用该模型。 {'Header 1': '接入 OpenLLM 部署的本地模型', 'Header 2': '部署 Xinference', 'Header 3': '开始部署'} "保存" 后即可在应用中使用该模型。 Dify 同时支持将 [Xinference embed 模型](https://github.com/xorbitsai/inference/blob/main/README\_zh\_CN.md#%E5%86%85%E7%BD%AE%E6%A8%A1%E5%9E%8B) 作为 Embedding 模型使用,只需在配置框中选择 `Embeddings` 类型即可。 如需获取 Xinference 更多信息,请参考:[Xorbits Inference](https://github.com/xorbitsai/inference/blob/main/README\_zh\_CN.md) {'Header 1': '预定义模型接入'} 供应商集成完成后,接下来为供应商下模型的接入。 我们首先需要确定接入模型的类型,并在对应供应商的目录下创建对应模型类型的 `module`。 当前支持模型类型如下: * `llm` 文本生成模型 * `text_embedding` 文本 Embedding 模型 * `rerank` Rerank 模型 * `speech2text` 语音转文字 * `tts` 文字转语音 * `moderation` 审查 依旧以 `Anthropic` 为例,`Anthropic` 仅支持 LLM,因此在 `model_providers.anthropic` 创建一个 `llm` 为名称的 `module`。 对于预定义的模型,我们首先需要在 `llm` `module` 下创建以模型名为文件名称的 YAML 文件,如:`claude-2.1.yaml`。 #### 准备模型 YAML ```yaml model: claude-2.1 # 模型标识 {'Header 1': '预定义模型接入'} ```yaml model: claude-2.1 # 模型标识 # 模型展示名称,可设置 en_US 英文、zh_Hans 中文两种语言,zh_Hans 不设置将默认使用 en_US。 # 也可不设置 label,则使用 model 标识内容。 label: en_US: claude-2.1 model_type: llm # 模型类型,claude-2.1 为 LLM features: # 支持功能,agent-thought 为支持 Agent 推理,vision 为支持图片理解 - agent-thought model_properties: # 模型属性 mode: chat # LLM 模式,complete 文本补全模型,chat 对话模型 context_size: 200000 # 支持最大上下文大小 parameter_rules: # 模型调用参数规则,仅 LLM 需要提供 - name: temperature # 调用参数变量名 {'Header 1': '预定义模型接入'} - name: temperature # 调用参数变量名 # 默认预置了 5 种变量内容配置模板,temperature/top_p/max_tokens/presence_penalty/frequency_penalty # 可在 use_template 中直接设置模板变量名,将会使用 entities.defaults.PARAMETER_RULE_TEMPLATE 中的默认配置 # 若设置了额外的配置参数,将覆盖默认配置 use_template: temperature - name: top_p use_template: top_p - name: top_k label: # 调用参数展示名称 zh_Hans: 取样数量 en_US: Top k type: int # 参数类型,支持 float/int/string/boolean help: # 帮助信息,描述参数作用 zh_Hans: 仅从每个后续标记的前 K 个选项中采样。 {'Header 1': '预定义模型接入'} zh_Hans: 仅从每个后续标记的前 K 个选项中采样。 en_US: Only sample from the top K options for each subsequent token. required: false # 是否必填,可不设置 - name: max_tokens_to_sample use_template: max_tokens default: 4096 # 参数默认值 min: 1 # 参数最小值,仅 float/int 可用 max: 4096 # 参数最大值,仅 float/int 可用 pricing: # 价格信息 input: '8.00' # 输入单价,即 Prompt 单价 output: '24.00' # 输出单价,即返回内容单价 unit: '0.000001' # 价格单位,即上述价格为每 100K 的单价 currency: USD # 价格货币 ``` 建议将所有模型配置都准备完毕后再开始模型代码的实现。 {'Header 1': '预定义模型接入'} ``` 建议将所有模型配置都准备完毕后再开始模型代码的实现。 同样,也可以参考 `model_providers` 目录下其他供应商对应模型类型目录下的 YAML 配置信息,完整的 YAML 规则见:Schema[^1]。 #### 实现模型调用代码 接下来需要在 `llm` `module` 下创建一个同名的 python 文件 `llm.py` 来编写代码实现。 在 `llm.py` 中创建一个 Anthropic LLM 类,我们取名为 `AnthropicLargeLanguageModel`(随意),继承 `__base.large_language_model.LargeLanguageModel` 基类,实现以下几个方法: * LLM 调用 实现 LLM 调用的核心方法,可同时支持流式和同步返回。 ```python def _invoke(self, model: str, credentials: dict, prompt_messages: list[PromptMessage], model_parameters: dict, {'Header 1': '预定义模型接入'} tools: Optional[list[PromptMessageTool]] = None, stop: Optional[List[str]] = None, stream: bool = True, user: Optional[str] = None) \ -> Union[LLMResult, Generator]: """ Invoke large language model {'Header 1': '预定义模型接入'} :param model: model name :param credentials: model credentials :param prompt_messages: prompt messages :param model_parameters: model parameters :param tools: tools for tool calling :param stop: stop words :param stream: is stream response :param user: unique user id :return: full response or stream response chunk generator result """ ``` {'Header 1': '预定义模型接入'} """ ``` 在实现时,需要注意使用两个函数来返回数据,分别用于处理同步返回和流式返回,因为Python会将函数中包含 `yield` 关键字的函数识别为生成器函数,返回的数据类型固定为 `Generator`,因此同步和流式返回需要分别实现,就像下面这样(注意下面例子使用了简化参数,实际实现时需要按照上面的参数列表进行实现): ```python def _invoke(self, stream: bool, **kwargs) \ -> Union[LLMResult, Generator]: if stream: return self._handle_stream_response(**kwargs) return self._handle_sync_response(**kwargs) {'Header 1': '预定义模型接入'} def _handle_stream_response(self, **kwargs) -> Generator: for chunk in response: yield chunk def _handle_sync_response(self, **kwargs) -> LLMResult: return LLMResult(**response) ``` * 预计算输入 tokens 若模型未提供预计算 tokens 接口,可直接返回 0。 ```python def get_num_tokens(self, model: str, credentials: dict, prompt_messages: list[PromptMessage], tools: Optional[list[PromptMessageTool]] = None) -> int: """ Get number of tokens for given prompt messages {'Header 1': '预定义模型接入'} :param model: model name :param credentials: model credentials :param prompt_messages: prompt messages :param tools: tools for tool calling :return: """ ``` * 模型凭据校验 与供应商凭据校验类似,这里针对单个模型进行校验。 ```python def validate_credentials(self, model: str, credentials: dict) -> None: """ Validate model credentials {'Header 1': '预定义模型接入'} :param model: model name :param credentials: model credentials :return: """ ``` * 调用异常错误映射表 当模型调用异常时需要映射到 Runtime 指定的 `InvokeError` 类型,方便 Dify 针对不同错误做不同后续处理。 Runtime Errors: * `InvokeConnectionError` 调用连接错误 * `InvokeServerUnavailableError` 调用服务方不可用 * `InvokeRateLimitError` 调用达到限额 * `InvokeAuthorizationError` 调用鉴权失败 * `InvokeBadRequestError` 调用传参有误 ```python @property def _invoke_error_mapping(self) -> dict[type[InvokeError], list[type[Exception]]]: """ {'Header 1': '预定义模型接入'} """ Map model invoke error to unified error The key is the error type thrown to the caller The value is the error type thrown by the model, which needs to be converted into a unified error type for the caller. {'Header 1': '预定义模型接入'} :return: Invoke error mapping """ ``` 接口方法说明见:[Interfaces](https://github.com/langgenius/dify/blob/main/api/core/model\_runtime/docs/zh\_Hans/interfaces.md),具体实现可参考:[llm.py](https://github.com/langgenius/dify-runtime/blob/main/lib/model\_providers/anthropic/llm/llm.py)。 [^1]: #### Provider * `provider` (string) 供应商标识,如:`openai` * `label` (object) 供应商展示名称,i18n,可设置 `en_US` 英文、`zh_Hans` 中文两种语言 * `zh_Hans` (string) \[optional] 中文标签名,`zh_Hans` 不设置将默认使用 `en_US`。 * `en_US` (string) 英文标签名 {'Header 1': '预定义模型接入'} * `en_US` (string) 英文标签名 * `description` (object) \[optional] 供应商描述,i18n * `zh_Hans` (string) \[optional] 中文描述 * `en_US` (string) 英文描述 * `icon_small` (string) \[optional] 供应商小 ICON,存储在对应供应商实现目录下的 `_assets` 目录,中英文策略同 `label` * `zh_Hans` (string) \[optional] 中文 ICON * `en_US` (string) 英文 ICON * `icon_large` (string) \[optional] 供应商大 ICON,存储在对应供应商实现目录下的 \_assets 目录,中英文策略同 label * `zh_Hans` (string) \[optional] 中文 ICON * `en_US` (string) 英文 ICON {'Header 1': '预定义模型接入'} * `en_US` (string) 英文 ICON * `background` (string) \[optional] 背景颜色色值,例:#FFFFFF,为空则展示前端默认色值。 * `help` (object) \[optional] 帮助信息 * `title` (object) 帮助标题,i18n * `zh_Hans` (string) \[optional] 中文标题 * `en_US` (string) 英文标题 * `url` (object) 帮助链接,i18n * `zh_Hans` (string) \[optional] 中文链接 * `en_US` (string) 英文链接 * `supported_model_types` (array\[ModelType]) 支持的模型类型 * `configurate_methods` (array\[ConfigurateMethod]) 配置方式 * `provider_credential_schema` (ProviderCredentialSchema) 供应商凭据规格 {'Header 1': '预定义模型接入'} * `model_credential_schema` (ModelCredentialSchema) 模型凭据规格 {'Header 1': '负载均衡'} 模型速率限制(Rate limits)是模型厂商对用户或客户在指定时间内访问 API 服务次数所添加的限制。它有助于防止 API 的滥用或误用,有助于确保每个用户都能公平地访问 API,控制基础设施的总体负载。 在企业级大规模调用模型 API 时,高并发请求会导致超过请求速率限制并影响用户访问。负载均衡可以通过在多个 API 端点之间分配 API 请求,确保所有用户都能获得最快的响应和最高的模型调用吞吐量,保障业务稳定运行。 你可以在 **模型供应商 -- 模型列表 -- 设置模型负载均衡** 打开该功能,并在同一个模型上添加多个凭据 (API key)。

    模型负载均衡

    {% hint style="info" %} {'Header 1': '负载均衡'} {% hint style="info" %} 模型负载均衡为付费特性,您可以通过[订阅 SaaS 付费服务](../../getting-started/cloud.md#ding-yue-ji-hua)或者购买企业版来开启该功能。 {% endhint %} 默认配置中的 API Key 为初次配置模型供应商时添加的凭据,您需要点击 **增加配置** 添加同一模型的不同 API Key 来正常使用负载均衡功能。

    配置负载均衡

    **需要额外添加至少 1 个模型凭据**即可保存并开启负载均衡。 你也可以将已配置的凭据**临时停用**或者**删除**。 {'Header 1': '负载均衡'} 你也可以将已配置的凭据**临时停用**或者**删除**。
    配置完成后再模型列表内会显示所有已开启负载均衡的模型。

    开启负载均衡

    {% hint style="info" %} 默认情况下,负载均衡使用 Round-robin 策略。如果触发速率限制,将应用 1 分钟的冷却时间。 {% endhint %} 你也可以从 **添加模型** 配置负载均衡,配置流程与上面一致。 {'Header 1': '负载均衡'} 你也可以从 **添加模型** 配置负载均衡,配置流程与上面一致。

    从添加模型配置负载均衡

    {'Header 1': '接入 Ollama 部署的本地模型'} ![ollama](../../.gitbook/assets/ollama.png) [Ollama](https://github.com/jmorganca/ollama) 是一个本地推理框架客户端,可一键部署如 Llama 2, Mistral, Llava 等大型语言模型。 Dify 支持接入 Ollama 部署的大型语言模型推理和 embedding 能力。 {'Header 1': '接入 Ollama 部署的本地模型', 'Header 2': '快速接入', 'Header 3': '下载并启动 Ollama'} 1. 下载 Ollama 访问 [https://ollama.ai/download](https://ollama.ai/download),下载对应系统 Ollama 客户端。 2. 运行 Ollama 并与 Llava 聊天 ```bash ollama run llava ``` 启动成功后,ollama 在本地 11434 端口启动了一个 API 服务,可通过 `http://localhost:11434` 访问。 其他模型可访问 [Ollama Models](https://ollama.ai/library) 了解详情。 3. 在 Dify 中接入 Ollama 在 `设置 > 模型供应商 > Ollama` 中填入: ![](../../.gitbook/assets/ollama-config-zh.png) - 模型名称:`llava` - 基础 URL:`http://:11434` 此处需填写可访问到的 Ollama 服务地址。 {'Header 1': '接入 Ollama 部署的本地模型', 'Header 2': '快速接入', 'Header 3': '下载并启动 Ollama'} 此处需填写可访问到的 Ollama 服务地址。 若 Dify 为 docker 部署,建议填写局域网 IP 地址,如:`http://192.168.1.100:11434` 或 docker 宿主机 IP 地址,如:`http://172.17.0.1:11434`。 若为本地源码部署,可填写 `http://localhost:11434`。 - 模型类型:`对话` - 模型上下文长度:`4096` 模型的最大上下文长度,若不清楚可填写默认值 4096。 - 最大 token 上限:`4096` 模型返回内容的最大 token 数量,若模型无特别说明,则可与模型上下文长度保持一致。 - 是否支持 Vision:`是` 当模型支持图片理解(多模态)勾选此项,如 `llava`。 点击 "保存" 校验无误后即可在应用中使用该模型。 Embedding 模型接入方式与 LLM 类似,只需将模型类型改为 Text Embedding 即可。 4. 使用 Ollama 模型 {'Header 1': '接入 Ollama 部署的本地模型', 'Header 2': '快速接入', 'Header 3': '下载并启动 Ollama'} 4. 使用 Ollama 模型 ![](../../.gitbook/assets/ollama-use-model.png) 进入需要配置的 App 提示词编排页面,选择 Ollama 供应商下的 `llava` 模型,配置模型参数后即可使用。 {'Header 1': '接入 Ollama 部署的本地模型', 'Header 2': 'FAQ', 'Header 3': '⚠️ 如果您使用Docker部署Dify和Ollama,您可能会遇到以下错误:'} ``` httpconnectionpool(host=127.0.0.1, port=11434): max retries exceeded with url:/cpi/chat (Caused by NewConnectionError(': fail to establish a new connection:[Errno 111] Connection refused')) {'Header 1': '接入 Ollama 部署的本地模型', 'Header 2': 'FAQ', 'Header 3': '⚠️ 如果您使用Docker部署Dify和Ollama,您可能会遇到以下错误:'} httpconnectionpool(host=localhost, port=11434): max retries exceeded with url:/cpi/chat (Caused by NewConnectionError(': fail to establish a new connection:[Errno 111] Connection refused')) ``` 这个错误是因为 Docker 容器无法访问 Ollama 服务。localhost 通常指的是容器本身,而不是主机或其他容器。要解决此问题,您需要将 Ollama 服务暴露给网络。 {'Header 1': '接入 Ollama 部署的本地模型', 'Header 2': 'FAQ', 'Header 3': '在Mac上设置环境变量'} 如果 `Ollama` 作为 `macOS` 应用程序运行,则应使用以下命令设置环境变量`launchctl`: 1. 通过调用`launchctl setenv`设置环境变量: ```bash launchctl setenv OLLAMA_HOST "0.0.0.0" ``` 2. 重启Ollama应用程序。 3. 如果以上步骤无效,可以使用以下方法: 问题是在docker内部,你应该连接到`host.docker.internal`,才能访问docker的主机,所以将`localhost`替换为`host.docker.internal`服务就可以生效了: ```bash http://host.docker.internal:11434 ``` {'Header 1': '接入 Ollama 部署的本地模型', 'Header 2': 'FAQ', 'Header 3': '在Linux上设置环境变量'} 如果Ollama作为systemd服务运行,应该使用`systemctl`设置环境变量: 1. 通过调用`systemctl edit ollama.service`编辑systemd服务。这将打开一个编辑器。 2. 对于每个环境变量,在`[Service]`部分下添加一行`Environment`: ```ini [Service] Environment="OLLAMA_HOST=0.0.0.0" ``` 3. 保存并退出。 4. 重载`systemd`并重启Ollama: ```bash systemctl daemon-reload systemctl restart ollama ``` {'Header 1': '接入 Ollama 部署的本地模型', 'Header 2': 'FAQ', 'Header 3': '在Windows上设置环境变量'} 在Windows上,Ollama继承了您的用户和系统环境变量。 1. 首先通过任务栏点击Ollama退出程序 2. 从控制面板编辑系统环境变量 3. 为您的用户账户编辑或新建变量,比如`OLLAMA_HOST`、`OLLAMA_MODELS`等。 4. 点击OK/应用保存 5. 在一个新的终端窗口运行`ollama` {'Header 1': '接入 Ollama 部署的本地模型', 'Header 2': 'FAQ', 'Header 3': '如何在我的网络上暴露Ollama?'} Ollama默认绑定127.0.0.1端口11434。通过`OLLAMA_HOST`环境变量更改绑定地址。 {'Header 1': '接入 Ollama 部署的本地模型', 'Header 2': '如需获取 Ollama 更多信息,请参考'} For more information on Ollama, please refer to: - [Ollama](https://github.com/jmorganca/ollama) - [Ollama FAQ](https://github.com/ollama/ollama/blob/main/docs/faq.md) {'Header 1': '自定义模型接入', 'Header 3': '介绍'} 供应商集成完成后,接下来为供应商下模型的接入,为了帮助理解整个接入过程,我们以`Xinference`为例,逐步完成一个完整的供应商接入。 需要注意的是,对于自定义模型,每一个模型的接入都需要填写一个完整的供应商凭据。 而不同于预定义模型,自定义供应商接入时永远会拥有如下两个参数,不需要在供应商 yaml 中定义。
    在前文中,我们已经知道了供应商无需实现`validate_provider_credential`,Runtime会自行根据用户在此选择的模型类型和模型名称调用对应的模型层的`validate_credentials`来进行验证。 #### 编写供应商 yaml 我们首先要确定,接入的这个供应商支持哪些类型的模型。 当前支持模型类型如下: * `llm` 文本生成模型 * `text_embedding` 文本 Embedding 模型 {'Header 1': '自定义模型接入', 'Header 3': '介绍'} * `llm` 文本生成模型 * `text_embedding` 文本 Embedding 模型 * `rerank` Rerank 模型 * `speech2text` 语音转文字 * `tts` 文字转语音 * `moderation` 审查 `Xinference`支持`LLM`、`Text Embedding`和`Rerank`,那么我们开始编写`xinference.yaml`。 ```yaml provider: xinference #确定供应商标识 label: # 供应商展示名称,可设置 en_US 英文、zh_Hans 中文两种语言,zh_Hans 不设置将默认使用 en_US。 en_US: Xorbits Inference icon_small: # 小图标,可以参考其他供应商的图标,存储在对应供应商实现目录下的 _assets 目录,中英文策略同 label en_US: icon_s_en.svg icon_large: # 大图标 en_US: icon_l_en.svg help: # 帮助 title: {'Header 1': '自定义模型接入', 'Header 3': '介绍'} en_US: icon_l_en.svg help: # 帮助 title: en_US: How to deploy Xinference zh_Hans: 如何部署 Xinference url: en_US: https://github.com/xorbitsai/inference supported_model_types: # 支持的模型类型,Xinference同时支持LLM/Text Embedding/Rerank - llm - text-embedding - rerank configurate_methods: # 因为Xinference为本地部署的供应商,并且没有预定义模型,需要用什么模型需要根据Xinference的文档自己部署,所以这里只支持自定义模型 - customizable-model provider_credential_schema: credential_form_schemas: ``` 随后,我们需要思考在 Xinference 中定义一个模型需要哪些凭据 {'Header 1': '自定义模型接入', 'Header 3': '介绍'} ``` 随后,我们需要思考在 Xinference 中定义一个模型需要哪些凭据 * 它支持三种不同的模型,因此,我们需要有`model_type`来指定这个模型的类型,它有三种类型,所以我们这么编写 ```yaml provider_credential_schema: credential_form_schemas: - variable: model_type type: select label: en_US: Model type zh_Hans: 模型类型 required: true options: - value: text-generation label: en_US: Language Model zh_Hans: 语言模型 - value: embeddings label: en_US: Text Embedding - value: reranking label: en_US: Rerank ``` * 每一个模型都有自己的名称`model_name`,因此需要在这里定义 ```yaml - variable: model_name {'Header 1': '自定义模型接入', 'Header 3': '介绍'} ```yaml - variable: model_name type: text-input label: en_US: Model name zh_Hans: 模型名称 required: true placeholder: zh_Hans: 填写模型名称 en_US: Input model name ``` * 填写 Xinference 本地部署的地址 ```yaml - variable: server_url label: zh_Hans: 服务器URL en_US: Server url type: text-input required: true placeholder: zh_Hans: 在此输入Xinference的服务器地址,如 https://example.com/xxx en_US: Enter the url of your Xinference, for example https://example.com/xxx ``` * 每个模型都有唯一的 model\_uid,因此需要在这里定义 ```yaml {'Header 1': '自定义模型接入', 'Header 3': '介绍'} ``` * 每个模型都有唯一的 model\_uid,因此需要在这里定义 ```yaml - variable: model_uid label: zh_Hans: 模型 UID en_US: Model uid type: text-input required: true placeholder: zh_Hans: 在此输入您的 Model UID en_US: Enter the model uid ``` 现在,我们就完成了供应商的基础定义。 #### 编写模型代码 然后我们以`llm`类型为例,编写`xinference.llm.llm.py` 在 `llm.py` 中创建一个 Xinference LLM 类,我们取名为 `XinferenceAILargeLanguageModel`(随意),继承 `__base.large_language_model.LargeLanguageModel` 基类,实现以下几个方法: * LLM 调用 实现 LLM 调用的核心方法,可同时支持流式和同步返回。 ```python {'Header 1': '自定义模型接入', 'Header 3': '介绍'} 实现 LLM 调用的核心方法,可同时支持流式和同步返回。 ```python def _invoke(self, model: str, credentials: dict, prompt_messages: list[PromptMessage], model_parameters: dict, tools: Optional[list[PromptMessageTool]] = None, stop: Optional[list[str]] = None, stream: bool = True, user: Optional[str] = None) \ -> Union[LLMResult, Generator]: """ Invoke large language model {'Header 1': '自定义模型接入', 'Header 3': '介绍'} :param model: model name :param credentials: model credentials :param prompt_messages: prompt messages :param model_parameters: model parameters :param tools: tools for tool calling :param stop: stop words :param stream: is stream response :param user: unique user id :return: full response or stream response chunk generator result """ ``` {'Header 1': '自定义模型接入', 'Header 3': '介绍'} """ ``` 在实现时,需要注意使用两个函数来返回数据,分别用于处理同步返回和流式返回,因为Python会将函数中包含 `yield` 关键字的函数识别为生成器函数,返回的数据类型固定为 `Generator`,因此同步和流式返回需要分别实现,就像下面这样(注意下面例子使用了简化参数,实际实现时需要按照上面的参数列表进行实现): ```python def _invoke(self, stream: bool, **kwargs) \ -> Union[LLMResult, Generator]: if stream: return self._handle_stream_response(**kwargs) return self._handle_sync_response(**kwargs) {'Header 1': '自定义模型接入', 'Header 3': '介绍'} def _handle_stream_response(self, **kwargs) -> Generator: for chunk in response: yield chunk def _handle_sync_response(self, **kwargs) -> LLMResult: return LLMResult(**response) ``` * 预计算输入 tokens 若模型未提供预计算 tokens 接口,可直接返回 0。 ```python def get_num_tokens(self, model: str, credentials: dict, prompt_messages: list[PromptMessage], tools: Optional[list[PromptMessageTool]] = None) -> int: """ Get number of tokens for given prompt messages {'Header 1': '自定义模型接入', 'Header 3': '介绍'} :param model: model name :param credentials: model credentials :param prompt_messages: prompt messages :param tools: tools for tool calling :return: """ ``` 有时候,也许你不需要直接返回0,所以你可以使用`self._get_num_tokens_by_gpt2(text: str)`来获取预计算的tokens,这个方法位于`AIModel`基类中,它会使用GPT2的Tokenizer进行计算,但是只能作为替代方法,并不完全准确。 * 模型凭据校验 与供应商凭据校验类似,这里针对单个模型进行校验。 ```python def validate_credentials(self, model: str, credentials: dict) -> None: """ Validate model credentials {'Header 1': '自定义模型接入', 'Header 3': '介绍'} :param model: model name :param credentials: model credentials :return: """ ``` * 模型参数 Schema 与自定义类型不同,由于没有在 yaml 文件中定义一个模型支持哪些参数,因此,我们需要动态时间模型参数的Schema。 如Xinference支持`max_tokens` `temperature` `top_p` 这三个模型参数。 但是有的供应商根据不同的模型支持不同的参数,如供应商`OpenLLM`支持`top_k`,但是并不是这个供应商提供的所有模型都支持`top_k`,我们这里举例 A 模型支持`top_k`,B模型不支持`top_k`,那么我们需要在这里动态生成模型参数的 Schema,如下所示: ```python def get_customizable_model_schema(self, model: str, credentials: dict) -> AIModelEntity | None: """ {'Header 1': '自定义模型接入', 'Header 3': '介绍'} """ used to define customizable model schema """ rules = [ ParameterRule( name='temperature', type=ParameterType.FLOAT, use_template='temperature', label=I18nObject( zh_Hans='温度', en_US='Temperature' ) ), ParameterRule( name='top_p', type=ParameterType.FLOAT, use_template='top_p', label=I18nObject( zh_Hans='Top P', en_US='Top P' ) ), ParameterRule( name='max_tokens', type=ParameterType.INT, use_template='max_tokens', min=1, default=512, label=I18nObject( zh_Hans='最大生成长度', en_US='Max Tokens' ) ) {'Header 1': '自定义模型接入', 'Header 3': '介绍'} zh_Hans='最大生成长度', en_US='Max Tokens' ) ) ] {'Header 1': '自定义模型接入', 'Header 3': '介绍'} # if model is A, add top_k to rules if model == 'A': rules.append( ParameterRule( name='top_k', type=ParameterType.INT, use_template='top_k', min=1, default=50, label=I18nObject( zh_Hans='Top K', en_US='Top K' ) ) ) """ some NOT IMPORTANT code here """ entity = AIModelEntity( model=model, label=I18nObject( en_US=model ), fetch_from=FetchFrom.CUSTOMIZABLE_MODEL, model_type=model_type, model_properties={ ModelPropertyKey.MODE: ModelType.LLM, }, parameter_rules=rules ) {'Header 1': '自定义模型接入', 'Header 3': '介绍'} return entity ``` * 调用异常错误映射表 当模型调用异常时需要映射到 Runtime 指定的 `InvokeError` 类型,方便 Dify 针对不同错误做不同后续处理。 Runtime Errors: * `InvokeConnectionError` 调用连接错误 * `InvokeServerUnavailableError` 调用服务方不可用 * `InvokeRateLimitError` 调用达到限额 * `InvokeAuthorizationError` 调用鉴权失败 * `InvokeBadRequestError` 调用传参有误 ```python @property def _invoke_error_mapping(self) -> dict[type[InvokeError], list[type[Exception]]]: """ Map model invoke error to unified error The key is the error type thrown to the caller {'Header 1': '自定义模型接入', 'Header 3': '介绍'} The key is the error type thrown to the caller The value is the error type thrown by the model, which needs to be converted into a unified error type for the caller. {'Header 1': '自定义模型接入', 'Header 3': '介绍'} :return: Invoke error mapping """ ``` 接口方法说明见:[Interfaces](https://github.com/langgenius/dify/blob/main/api/core/model\_runtime/docs/zh\_Hans/interfaces.md),具体实现可参考:[llm.py](https://github.com/langgenius/dify-runtime/blob/main/lib/model\_providers/anthropic/llm/llm.py)。 {'Header 1': '模型'} Dify 是基于大语言模型的 AI 应用开发平台,初次使用时你需要先在 Dify 的 **设置 -- 模型供应商** 页面内添加并配置所需要的模型。

    设置-模型供应商

    Dify 目前已支持主流的模型供应商,例如 OpenAI 的 GPT 系列、Anthropic 的 Claude 系列等。不同模型的能力表现、参数类型会不一样,你可以根据不同情景的应用需求选择你喜欢的模型供应商。**你在 Dify 应用以下模型能力前,应该前往不同的模型厂商官方网站获得他们的 API key 。** {'Header 1': '模型', 'Header 3': '模型类型'} 在 Dify 中,我们按模型的使用场景将模型分为以下 4 类: 1. **系统推理模型**。 在创建的应用中,用的是该类型的模型。智聊、对话名称生成、下一步问题建议用的也是推理模型。 {'Header 1': '模型', 'Header 3': '模型类型'} > 已支持的系统推理模型供应商:[OpenAI](https://platform.openai.com/account/api-keys)、[Azure OpenAI Service](https://azure.microsoft.com/en-us/products/ai-services/openai-service/)、[Anthropic](https://console.anthropic.com/account/keys)、Hugging Face {'Header 1': '模型', 'Header 3': '模型类型'} Face Hub、Replicate、Xinference、OpenLLM、[讯飞星火](https://www.xfyun.cn/solutions/xinghuoAPI)、[文心一言](https://console.bce.baidu.com/qianfan/ais/console/applicationConsole/application)、[通义千问](https://dashscope.console.aliyun.com/api-key\_management?spm=a2c4g.11186623.0.0.3bbc424dxZms9k)、[Minimax](https://api.minimax.chat/user-center/basic-information/interface-key)、ZHIPU(ChatGLM) {'Header 1': '模型', 'Header 3': '模型类型'} 2. **Embedding 模型**。在数据集中,将分段过的文档做 Embedding 用的是该类型的模型。在使用了数据集的应用中,将用户的提问做 Embedding 处理也是用的该类型的模型。 > 已支持的 Embedding 模型供应商:OpenAI、ZHIPU(ChatGLM)、JinaAI 3. [**Rerank 模型**](https://docs.dify.ai/v/zh-hans/advanced/retrieval-augment/rerank)。**Rerank 模型用于增强检索能力,改善 LLM 的搜索结果。** > 已支持的 Rerank 模型供应商:Cohere、JinaAI 4. **语音转文字模型**。将对话型应用中,将语音转文字用的是该类型的模型。 > 已支持的语音转文字模型供应商:OpenAI 根据技术变化和用户需求,我们将陆续支持更多 LLM 供应商。 {'Header 1': '模型', 'Header 3': '托管模型试用服务'} 我们为 Dify 云服务的用户提供了不同模型的试用额度,请在该额度耗尽前设置你自己的模型供应商,否则将会影响应用的正常使用。 * **OpenAI 托管模型试用:** 我们提供 200 次调用次数供你试用体验,可用于 GPT3.5-turbo、GPT3.5-turbo-16k、text-davinci-003 模型。 {'Header 1': '模型', 'Header 3': '设置默认模型'} Dify 在需要模型时,会根据使用场景来选择设置过的默认模型。在 `设置 > 模型供应商` 中设置默认模型。
    {'Header 1': '模型', 'Header 3': '接入模型设置'} 在 Dify 的 `设置 > 模型供应商` 中设置要接入的模型。
    模型供应商分为两种: 1. 自有模型。该类型的模型供应商提供的是自己开发的模型。如 OpenAI,Anthropic 等。 2. 托管模型。该类型的模型供应商提供的是第三方模型。如 Hugging Face,Replicate 等。 在 Dify 中接入不同类型的模型供应商的方式稍有不同。 **接入自有模型的模型供应商** 接入自有模型的供应商后,Dify 会自动接入该供应商下的所有模型。 在 Dify 中设置对应模型供应商的 API key,即可接入该模型供应商。 {% hint style="info" %} {'Header 1': '模型', 'Header 3': '接入模型设置'} {% hint style="info" %} Dify 使用了 [PKCS1\_OAEP](https://pycryptodome.readthedocs.io/en/latest/src/cipher/oaep.html) 来加密存储用户托管的 API 密钥,每个租户均使用了独立的密钥对进行加密,确保你的 API 密钥不被泄漏。 {% endhint %} **接入托管模型的模型供应商** 托管类型的供应商上面有很多第三方模型。接入模型需要一个个的添加。具体接入方式如下: * [Hugging Face](hugging-face.md) * [Replicate](replicate.md) * [Xinference](xinference.md) * [OpenLLM](openllm.md) {'Header 1': '模型', 'Header 3': '使用模型'} 配置完模型后,就可以在应用中使用这些模型了:
    {'Header 1': '增加新供应商', 'Header 3': '供应商配置方式'} 供应商支持三种模型配置方式: **预定义模型(predefined-model)** 表示用户只需要配置统一的供应商凭据即可使用供应商下的预定义模型。 **自定义模型(customizable-model)** 用户需要新增每个模型的凭据配置,如 Xinference,它同时支持 LLM 和 Text Embedding,但是每个模型都有唯一的 **model\_uid**,如果想要将两者同时接入,就需要为每个模型配置一个 **model\_uid**。 **从远程获取(fetch-from-remote)** 与 `predefined-model`配置方式一致,只需要配置统一的供应商凭据即可,模型通过凭据信息从供应商获取。 如OpenAI,我们可以基于 gpt-turbo-3.5 来 Fine Tune 多个模型,而他们都位于同一个 **api\_key** 下,当配置为`fetch-from-remote`时,开发者只需要配置统一的 **api\_key** 即可让 Dify Runtime 获取到开发者所有的微调模型并接入 Dify。 {'Header 1': '增加新供应商', 'Header 3': '供应商配置方式'} 这三种配置方式**支持共存**,即存在供应商支持`predefined-model` + `customizable-model` 或 `predefined-model` + `fetch-from-remote`等,也就是配置了供应商统一凭据可以使用预定义模型和从远程获取的模型,若新增了模型,则可以在此基础上额外使用自定义的模型。 {'Header 1': '增加新供应商', 'Header 3': '配置说明'} **名词解释** * `module`: 一个`module`即为一个 Python Package,或者通俗一点,称为一个文件夹,里面包含了一个`__init__.py`文件,以及其他的`.py`文件。 **步骤** 新增一个供应商主要分为几步,这里简单列出,帮助大家有一个大概的认识,具体的步骤会在下面详细介绍。 * 创建供应商 yaml 文件,根据 [Provider Schema](https://github.com/langgenius/dify/blob/main/api/core/model\_runtime/docs/zh\_Hans/schema.md) 编写。 * 创建供应商代码,实现一个`class`。 * 根据模型类型,在供应商`module`下创建对应的模型类型 `module`,如`llm`或`text_embedding`。 * 根据模型类型,在对应的模型`module`下创建同名的代码文件,如`llm.py`,并实现一个`class`。 {'Header 1': '增加新供应商', 'Header 3': '配置说明'} * 如果有预定义模型,根据模型名称创建同名的yaml文件在模型`module`下,如`claude-2.1.yaml`,根据 [AI Model Entity](https://github.com/langgenius/dify/blob/main/api/core/model\_runtime/docs/zh\_Hans/schema.md) 编写。 * 编写测试代码,确保功能可用。 #### 开始吧 增加一个新的供应商需要先确定供应商的英文标识,如 `anthropic`,使用该标识在 `model_providers` 创建以此为名称的 `module`。 在此 `module` 下,我们需要先准备供应商的 YAML 配置。 **准备供应商 YAML** 此处以 `Anthropic` 为例,预设了供应商基础信息、支持的模型类型、配置方式、凭据规则。 ```YAML provider: anthropic # 供应商标识 {'Header 1': '增加新供应商', 'Header 3': '配置说明'} ```YAML provider: anthropic # 供应商标识 label: # 供应商展示名称,可设置 en_US 英文、zh_Hans 中文两种语言,zh_Hans 不设置将默认使用 en_US。 en_US: Anthropic icon_small: # 供应商小图标,存储在对应供应商实现目录下的 _assets 目录,中英文策略同 label en_US: icon_s_en.png icon_large: # 供应商大图标,存储在对应供应商实现目录下的 _assets 目录,中英文策略同 label en_US: icon_l_en.png supported_model_types: # 支持的模型类型,Anthropic 仅支持 LLM - llm configurate_methods: # 支持的配置方式,Anthropic 仅支持预定义模型 - predefined-model provider_credential_schema: # 供应商凭据规则,由于 Anthropic 仅支持预定义模型,则需要定义统一供应商凭据规则 {'Header 1': '增加新供应商', 'Header 3': '配置说明'} credential_form_schemas: # 凭据表单项列表 - variable: anthropic_api_key # 凭据参数变量名 label: # 展示名称 en_US: API Key type: secret-input # 表单类型,此处 secret-input 代表加密信息输入框,编辑时只展示屏蔽后的信息。 required: true # 是否必填 placeholder: # PlaceHolder 信息 zh_Hans: 在此输入您的 API Key en_US: Enter your API Key - variable: anthropic_api_url label: en_US: API URL type: text-input # 表单类型,此处 text-input 代表文本输入框 required: false placeholder: zh_Hans: 在此输入您的 API URL en_US: Enter your API URL ``` {'Header 1': '增加新供应商', 'Header 3': '配置说明'} en_US: Enter your API URL ``` 如果接入的供应商提供自定义模型,比如`OpenAI`提供微调模型,那么我们就需要添加[`model_credential_schema`](https://github.com/langgenius/dify/blob/main/api/core/model\_runtime/docs/zh\_Hans/schema.md),以`OpenAI`为例: ```yaml model_credential_schema: model: # 微调模型名称 label: en_US: Model Name zh_Hans: 模型名称 placeholder: en_US: Enter your model name zh_Hans: 输入模型名称 credential_form_schemas: - variable: openai_api_key label: en_US: API Key type: secret-input required: true placeholder: {'Header 1': '增加新供应商', 'Header 3': '配置说明'} type: secret-input required: true placeholder: zh_Hans: 在此输入您的 API Key en_US: Enter your API Key - variable: openai_organization label: zh_Hans: 组织 ID en_US: Organization type: text-input required: false placeholder: zh_Hans: 在此输入您的组织 ID en_US: Enter your Organization ID - variable: openai_api_base label: zh_Hans: API Base en_US: API Base type: text-input required: false placeholder: zh_Hans: 在此输入您的 API Base en_US: Enter your API Base ``` {'Header 1': '增加新供应商', 'Header 3': '配置说明'} en_US: Enter your API Base ``` 也可以参考`model_providers`目录下其他供应商目录下的 [YAML 配置信息](https://github.com/langgenius/dify/blob/main/api/core/model\_runtime/docs/zh\_Hans/schema.md)。 **实现供应商代码** 我们需要在`model_providers`下创建一个同名的python文件,如`anthropic.py`,并实现一个`class`,继承`__base.provider.Provider`基类,如`AnthropicProvider`。 **自定义模型供应商** 当供应商为 Xinference 等自定义模型供应商时,可跳过该步骤,仅创建一个空的`XinferenceProvider`类即可,并实现一个空的`validate_provider_credentials`方法,该方法并不会被实际使用,仅用作避免抽象类无法实例化。 ```python {'Header 1': '增加新供应商', 'Header 3': '配置说明'} ```python class XinferenceProvider(Provider): def validate_provider_credentials(self, credentials: dict) -> None: pass ``` **预定义模型供应商** 供应商需要继承 `__base.model_provider.ModelProvider` 基类,实现 `validate_provider_credentials` 供应商统一凭据校验方法即可,可参考 [AnthropicProvider](https://github.com/langgenius/dify/blob/main/api/core/model\_runtime/model\_providers/anthropic/anthropic.py)。 ```python def validate_provider_credentials(self, credentials: dict) -> None: """ Validate provider credentials {'Header 1': '增加新供应商', 'Header 3': '配置说明'} """ Validate provider credentials You can choose any validate_credentials method of model type or implement validate method by yourself, such as: get model list api {'Header 1': '增加新供应商', 'Header 3': '配置说明'} if validate failed, raise exception {'Header 1': '增加新供应商', 'Header 3': '配置说明'} :param credentials: provider credentials, credentials form defined in `provider_credential_schema`. """ ``` 当然也可以先预留 `validate_provider_credentials` 实现,在模型凭据校验方法实现后直接复用。 **增加模型** [**增加预定义模型** ](https://docs.dify.ai/v/zh-hans/guides/model-configuration/predefined-model)**👈🏻** 对于预定义模型,我们可以通过简单定义一个 yaml,并通过实现调用代码来接入。 [**增加自定义模型**](https://docs.dify.ai/v/zh-hans/guides/model-configuration/customizable-model) **👈🏻** 对于自定义模型,我们只需要实现调用代码即可接入,但是它需要处理的参数可能会更加复杂。 *** #### 测试 {'Header 1': '增加新供应商', 'Header 3': '配置说明'} *** #### 测试 为了保证接入供应商/模型的可用性,编写后的每个方法均需要在 `tests` 目录中编写对应的集成测试代码。 依旧以 `Anthropic` 为例。 在编写测试代码前,需要先在 `.env.example` 新增测试供应商所需要的凭据环境变量,如:`ANTHROPIC_API_KEY`。 在执行前需要将 `.env.example` 复制为 `.env` 再执行。 **编写测试代码** 在 `tests` 目录下创建供应商同名的 `module`: `anthropic`,继续在此模块中创建 `test_provider.py` 以及对应模型类型的 test py 文件,如下所示: ```shell . ├── __init__.py ├── anthropic │ ├── __init__.py │ ├── test_llm.py # LLM 测试 │ └── test_provider.py # 供应商测试 ``` 针对上面实现的代码的各种情况进行测试代码编写,并测试通过后提交代码。 {'Header 1': '接入 Hugging Face 上的开源模型'} Dify 支持 Text-Generation 和 Embeddings,以下是与之对应的 Hugging Face 模型类型: * Text-Generation:[text-generation](https://huggingface.co/models?pipeline\_tag=text-generation\&sort=trending),[text2text-generation](https://huggingface.co/models?pipeline\_tag=text2text-generation\&sort=trending) * Embeddings:[feature-extraction](https://huggingface.co/models?pipeline\_tag=feature-extraction\&sort=trending) 具体步骤如下: 1. 你需要有 Hugging Face 账号([注册地址](https://huggingface.co/join))。 {'Header 1': '接入 Hugging Face 上的开源模型'} 2. 设置 Hugging Face 的 API key([获取地址](https://huggingface.co/settings/tokens))。 3. 进入 [Hugging Face 模型列表页](https://huggingface.co/models),选择对应的模型类型。
    Dify 支持用两种方式接入 Hugging Face 上的模型: 1. Hosted Inference API。这种方式是用的 Hugging Face 官方部署的模型。不需要付费。但缺点是,只有少量模型支持这种方式。 2. Inference Endpoint。这种方式是用 Hugging Face 接入的 AWS 等资源来部署模型,需要付费。 {'Header 1': '接入 Hugging Face 上的开源模型', 'Header 3': '接入 Hosted Inference API 的模型'} #### 1 选择模型 模型详情页右侧有包含 Hosted inference API 的 区域才支持 Hosted inference API 。如下图所:
    在模型详情页,可以获得模型的名称。
    #### 2 在 Dify 中使用接入模型 在 `设置 > 模型供应商 > Hugging Face > 模型类型` 的 Endpoint Type 选择 Hosted Inference API。如下图所示: {'Header 1': '接入 Hugging Face 上的开源模型', 'Header 3': '接入 Hosted Inference API 的模型'}
    API Token 为文章开头设置的 API Key。模型名字为上一步获得的模型名字。 {'Header 1': '接入 Hugging Face 上的开源模型', 'Header 3': '方式 2: Inference Endpoint'} #### 1 选择要部署模型 模型详情页右侧的 `Deploy` 按钮下有 Inference Endpoints 选项的模型才支持 Inference Endpoint。如下图所示:
    #### 2 部署模型 点击模型的部署按钮,选择 Inference Endpoint 选项。如果之前没绑过银行卡的,会需要绑卡。按流程走即可。绑过卡后,会出现下面的界面:按需求修改配置,点击左下角的 Create Endpoint 来创建 Inference Endpoint。
    模型部署好后,就可以看到 Endpoint URL。 {'Header 1': '接入 Hugging Face 上的开源模型', 'Header 3': '方式 2: Inference Endpoint'} 模型部署好后,就可以看到 Endpoint URL。
    #### 3 在 Dify 中使用接入模型 在 `设置 > 模型供应商 > Hugging Face > 模型类型` 的 Endpoint Type 选择 Inference Endpoints。如下图所示:
    API Token 为文章开头设置的 API Key。`Text-Generation 模型名字随便起,Embeddings 模型名字需要跟 Hugging Face 的保持一致。`Endpoint URL 为 上一步部署模型成功后获得的 Endpoint URL。 {'Header 1': '接入 Hugging Face 上的开源模型', 'Header 3': '方式 2: Inference Endpoint'}
    > 注意:Embeddings 的「用户名 / 组织名称」,需要根据你在 Hugging Face 的 [Inference Endpoints](https://huggingface.co/docs/inference-endpoints/guides/access) 部署方式,来填写「[用户名](https://huggingface.co/settings/account)」或者「[组织名称](https://ui.endpoints.huggingface.co/)」。 {'Header 1': '接入 Replicate 上的开源模型'} Dify 支持接入 Replicate 上的 [Language models](https://replicate.com/collections/language-models) 和 [Embedding models](https://replicate.com/collections/embedding-models)。Language models 对应 Dify 的推理模型,Embedding models 对应 Dify 的 Embedding 模型。 具体步骤如下: 1. 你需要有 Replicate 的账号([注册地址](https://replicate.com/signin?next=/docs))。 2. 获取 API Key([获取地址](https://replicate.com/account/api-tokens))。 {'Header 1': '接入 Replicate 上的开源模型'} 3. 挑选模型。在 [Language models](https://replicate.com/collections/language-models) 和 [Embedding models](https://replicate.com/collections/embedding-models) 下挑选模型。 4. 在 Dify 的 `设置 > 模型供应商 > Replicate` 中添加模型。
    API key 为第 2 步中设置的 API Key。Model Name 和 Model Version 可以在模型详情页中找到: {'Header 1': '接入 Replicate 上的开源模型'}
    {'Header 1': '接入 LocalAI 部署的本地模型'} [LocalAI](https://github.com/go-skynet/LocalAI) 是一个本地推理框架,提供了 RESTFul API,与 OpenAI API 规范兼容。它允许你在消费级硬件上本地或者在自有服务器上运行 LLM(和其他模型),支持与 ggml 格式兼容的多种模型家族。不需要 GPU。 Dify 支持以本地部署的方式接入 LocalAI 部署的大型语言模型推理和 embedding 能力。 {'Header 1': '接入 LocalAI 部署的本地模型', 'Header 2': '部署 LocalAI', 'Header 3': '使用前注意事项'} 如果确实需要直接使用容器的 IP 地址,以上步骤将帮助您获取到这一信息。 {'Header 1': '接入 LocalAI 部署的本地模型', 'Header 2': '部署 LocalAI', 'Header 3': '开始部署'} 可参考官方 [Getting Started](https://localai.io/basics/getting_started/) 进行部署,也可参考下方步骤进行快速接入: (以下步骤来自 [LocalAI Data query example](https://github.com/go-skynet/LocalAI/blob/master/examples/langchain-chroma/README.md)) 1. 首先拉取 LocalAI 代码仓库,并进入指定目录 ```bash $ git clone https://github.com/go-skynet/LocalAI $ cd LocalAI/examples/langchain-chroma ``` 2. 下载范例 LLM 和 Embedding 模型 ```bash $ wget https://huggingface.co/skeskinen/ggml/resolve/main/all-MiniLM-L6-v2/ggml-model-q4_0.bin -O models/bert {'Header 1': '接入 LocalAI 部署的本地模型', 'Header 2': '部署 LocalAI', 'Header 3': '开始部署'} $ wget https://gpt4all.io/models/ggml-gpt4all-j.bin -O models/ggml-gpt4all-j ``` 这里选用了较小且全平台兼容的两个模型,`ggml-gpt4all-j` 作为默认 LLM 模型,`all-MiniLM-L6-v2` 作为默认 Embedding 模型,方便在本地快速部署使用。 3. 配置 .env 文件 ```shell $ mv .env.example .env ``` NOTE:请确保 `.env` 中的 THREADS 变量值不超过您本机的 CPU 核心数。 4. 启动 LocalAI ```shell # start with docker-compose $ docker-compose up -d --build {'Header 1': '接入 LocalAI 部署的本地模型', 'Header 2': '部署 LocalAI', 'Header 3': '开始部署'} # tail the logs & wait until the build completes $ docker logs -f langchain-chroma-api-1 7:16AM INF Starting LocalAI using 4 threads, with models path: /models 7:16AM INF LocalAI version: v1.24.1 (9cc8d9086580bd2a96f5c96a6b873242879c70bc) {'Header 1': '接入 LocalAI 部署的本地模型', 'Header 2': '部署 LocalAI', 'Header 3': '开始部署'} ┌───────────────────────────────────────────────────┐ │ Fiber v2.48.0 │ │ http://127.0.0.1:8080 │ │ (bound on host 0.0.0.0 and port 8080) │ │ │ │ Handlers ............ 55 Processes ........... 1 │ │ Prefork ....... Disabled PID ................ 14 │ └───────────────────────────────────────────────────┘ ``` 开放了本机 `http://127.0.0.1:8080` 作为 LocalAI 请求 API 的端点。 {'Header 1': '接入 LocalAI 部署的本地模型', 'Header 2': '部署 LocalAI', 'Header 3': '开始部署'} 并提供了两个模型,分别为: - LLM 模型:`ggml-gpt4all-j` 对外访问名称:`gpt-3.5-turbo`(该名称可自定义,在 `models/gpt-3.5-turbo.yaml` 中配置。 - Embedding 模型:`all-MiniLM-L6-v2` 对外访问名称:`text-embedding-ada-002`(该名称可自定义,在 `models/embeddings.yaml` 中配置。 > 使用 Dify Docker 部署方式的需要注意网络配置,确保 Dify 容器可以访问到 Xinference 的端点,Dify 容器内部无法访问到 localhost,需要使用宿主机 IP 地址。 5. LocalAI API 服务部署完毕,在 Dify 中使用接入模型 在 `设置 > 模型供应商 > LocalAI` 中填入: 模型 1:`ggml-gpt4all-j` - 模型类型:文本生成 - 模型名称:`gpt-3.5-turbo` - 服务器 URL:http://127.0.0.1:8080 {'Header 1': '接入 LocalAI 部署的本地模型', 'Header 2': '部署 LocalAI', 'Header 3': '开始部署'} - 服务器 URL:http://127.0.0.1:8080 若 Dify 为 docker 部署,请填入 host 域名:`http://:8080`,可填写局域网 IP 地址,如:`http://192.168.1.100:8080` "保存" 后即可在应用中使用该模型。 模型 2:`all-MiniLM-L6-v2` - 模型类型:Embeddings - 模型名称:`text-embedding-ada-002` - 服务器 URL:http://127.0.0.1:8080 > 若 Dify 为 docker 部署,请填入 host 域名:`http://:8080`,可填写局域网 IP 地址,如:`http://192.168.1.100:8080` "保存" 后即可在应用中使用该模型。 如需获取 LocalAI 更多信息,请参考:https://github.com/go-skynet/LocalAI# Agent {'Header 1': '接入 LocalAI 部署的本地模型', 'Header 2': '部署 LocalAI', 'Header 3': '定义'} 智能助手(Agent Assistant),利用大语言模型的推理能力,能够自主对复杂的人类任务进行目标规划、任务拆解、工具调用、过程迭代,并在没有人类干预的情况下完成任务。 {'Header 1': '接入 LocalAI 部署的本地模型', 'Header 2': '部署 LocalAI', 'Header 3': '如何使用智能助手'} 为了方便快速上手使用,您可以在“探索”中找到智能助手的应用模板,添加到自己的工作区,或者在此基础上进行自定义。在全新的 Dify 工作室中,你也可以从零编排一个专属于你自己的智能助手,帮助你完成财务报表分析、撰写报告、Logo 设计、旅程规划等任务。

    探索-智能助手应用模板

    在“工作室-助手型应用”内选择智能助手即可开始编排。 {'Header 1': '接入 LocalAI 部署的本地模型', 'Header 2': '部署 LocalAI', 'Header 3': '如何使用智能助手'} 在“工作室-助手型应用”内选择智能助手即可开始编排。

    工作室-构建智能助手

    选择智能助手的推理模型,智能助手的任务完成能力取决于模型推理能力,我们建议在使用智能助手时选择推理能力更强的模型系列如 gpt-4 以获得更稳定的任务完成效果。

    选择智能助手的推理模型

    你可以在“提示词”中编写智能助手的指令,为了能够达到更优的预期效果,你可以在指令中明确它的任务目标、工作流程、资源和限制等。 {'Header 1': '接入 LocalAI 部署的本地模型', 'Header 2': '部署 LocalAI', 'Header 3': '如何使用智能助手'}

    编排智能助手的指令提示词

    {'Header 1': '接入 LocalAI 部署的本地模型', 'Header 2': '部署 LocalAI', 'Header 3': '添加助手需要的工具'} 在“上下文”中,你可以添加智能助手可以用于查询的知识库工具,这将帮助它获取外部背景知识。 在“工具”中,你可以添加需要使用的工具。工具可以扩展 LLM 的能力,比如联网搜索、科学计算或绘制图片,赋予并增强了 LLM 连接外部世界的能力。Dify 提供了两种工具类型:**第一方工具**和**自定义工具**。 你可以直接使用 Dify 生态提供的第一方内置工具,或者轻松导入自定义的 API 工具(目前支持 OpenAPI / Swagger 和 OpenAI Plugin 规范)。

    添加助手需要的工具

    {'Header 1': '接入 LocalAI 部署的本地模型', 'Header 2': '部署 LocalAI', 'Header 3': '添加助手需要的工具'} 工具使用户可以在 Dify 上创建更强大的 AI 应用,如你可以为智能助理型应用(Agent)编排合适的工具,它可以通过任务推理、步骤拆解、调用工具完成复杂任务。另外工具也可以方便将你的应用与其他系统或服务连接,与外部环境交互,如代码执行、对专属信息源的访问等。 {'Header 1': '接入 LocalAI 部署的本地模型', 'Header 2': '部署 LocalAI', 'Header 3': '配置 Agent'} 在 Dify 上为智能助手提供了 Function calling(函数调用)和 ReAct 两种推理模式。已支持 Function Call 的模型系列如 gpt-3.5/gpt-4 拥有效果更佳、更稳定的表现,尚未支持 Function calling 的模型系列,我们支持了 ReAct 推理框架实现类似的效果。 在 Agent 配置中,你可以修改助手的迭代次数限制。

    Function Calling 模式

    ReAct 模式

    {'Header 1': '接入 LocalAI 部署的本地模型', 'Header 2': '部署 LocalAI', 'Header 3': '配置对话开场白'} 您可以为智能助手配置一套会话开场白和开场问题,配置的对话开场白将在每次用户初次对话中展示助手可以完成什么样的任务,以及可以提出的问题示例。

    配置会话开场白和开场问题

    {'Header 1': '接入 LocalAI 部署的本地模型', 'Header 2': '部署 LocalAI', 'Header 3': '调试与预览'} 编排完智能助手之后,你可以在发布成应用之前进行调试与预览,查看助手的任务完成效果。

    调试与预览

    {'Header 1': '接入 LocalAI 部署的本地模型', 'Header 2': '部署 LocalAI', 'Header 3': '应用发布'}

    应用发布为 Webapp

    {'Header 1': '聊天助手'} 对话型应用采用一问一答模式与用户持续对话。 {'Header 1': '聊天助手', 'Header 3': '适用场景'} 对话型应用可以用在客户服务、在线教育、医疗保健、金融服务等领域。这些应用可以帮助组织提高工作效率、减少人工成本和提供更好的用户体验。 {'Header 1': '聊天助手', 'Header 3': '如何编排'} 对话型应用的编排支持:对话前提示词,变量,上下文,开场白和下一步问题建议。 下面边以做一个 **面试官** 的应用为例来介绍编排对话型应用。 #### 创建应用 在首页点击 “创建应用” 按钮创建应用。填上应用名称,应用类型选择**聊天助手**。

    创建聊天助手

    #### 编排应用 创建应用后会自动跳转到应用概览页。点击左侧菜单 **编排** 来编排应用。

    应用编排

    **填写提示词** {'Header 1': '聊天助手', 'Header 3': '如何编排'} **填写提示词** 提示词用于约束 AI 给出专业的回复,让回应更加精确。你可以借助内置的提示生成器,编写合适的提示词。提示词内支持插入表单变量,例如 `{{input}}`。提示词中的变量的值会替换成用户填写的值。 示例: 1. 输入提示指令,要求给出一段面试场景的提示词。 2. 右侧内容框将自动生成提示词。 3. 你可以在提示词内插入自定义变量。 ![](../../../img/zh-prompt-generator.png) 为了更好的用户体验,可以加上对话开场白:`你好,{{name}}。我是你的面试官,Bob。你准备好了吗?`。点击页面底部的 “添加功能” 按钮,打开 “对话开场白” 的功能:
    编辑开场白时,还可以添加数个开场问题: ![](../../../img/zh-opening-remarks.png) #### 添加上下文 {'Header 1': '聊天助手', 'Header 3': '如何编排'} #### 添加上下文 如果想要让 AI 的对话范围局限在[知识库](../knowledge-base/)内,例如企业内的客服话术规范,可以在“上下文”内引用知识库。 ![](<../../.gitbook/assets/image (108).png>) #### 调试 在右侧填写用户输入项,输入内容进行调试。 ![](../../../img/zh-conversation-debug.png) 如果回答结果不理想,可以调整提示词和底层模型。你也可以使用多个模型同步进行调试,搭配出合适的配置。 ![](../../../img/zh-modify-model.png) **多个模型进行调试:** 如果使用单一模型调试时感到效率低下,你也可以使用**“多个模型进行调试”**功能,批量检视模型的回答效果。 ![](../../../img/zh-multiple-models.png) 最多支持同时添加 4 个大模型。 ![](../../../img/zh-multiple-models-2.png) {'Header 1': '聊天助手', 'Header 3': '如何编排'} ![](../../../img/zh-multiple-models-2.png) > ⚠️ 使用多模型调试功能时,如果仅看到部分大模型,这是因为暂未添加其它大模型的 Key。你可以在[“增加新供应商”](https://docs.dify.ai/v/zh-hans/guides/model-configuration/new-provider)内手动添加多个模型的 Key。 #### 发布应用 调试好应用后,点击右上角的 **“发布”** 按钮生成独立的 AI 应用。除了通过公开 URL 体验该应用,你也进行基于 APIs 的二次开发、嵌入至网站内等操作。详情请参考[发布](https://docs.dify.ai/v/zh-hans/guides/application-publishing)。 如果想定制已发布的应用,可以 Fork 我们的开源的 [WebApp 的模版](https://github.com/langgenius/webapp-conversation)。基于模版改成符合你的情景与风格需求的应用。 {'Header 1': '创建应用'} 你可以通过 3 种方式在 Dify 的工作室内创建应用: * 基于应用模板创建(新手推荐) * 创建一个空白应用 * 通过 DSL 文件(本地/在线)创建应用 {'Header 1': '创建应用', 'Header 3': '从模板创建应用'} 初次使用 Dify 时,你可能对于应用创建比较陌生。为了帮助新手用户快速了解在 Dify 上能够构建哪些类型的应用,Dify 团队内的提示词工程师已经创建好了多场景、高质量的应用模板。 你可以从导航选择 「工作室 」,在应用列表内选择 「从模版创建」。

    从模板创建应用

    任意选择某个模板,并将其添加至工作区。

    Dify 应用模板

    {'Header 1': '创建应用', 'Header 3': '创建一个新应用'} 如果你需要在 Dify 上创建一个空白应用,你可以从导航选择 「工作室」 ,在应用列表内选择 「从空白创建 」。
    初次创建应用时,你可能需要先理解 Dify 上 4 种不同应用类型的[基本概念](./#application\_type),分别是聊天助手、文本生成应用、Agent 和工作流。 创建应用时,你需要给应用起一个名字、选择合适的图标、使用简介清晰的文字来描述此应用的用途,以方便后续应用在团队内的使用。

    创建一个空白应用

    {'Header 1': '创建应用', 'Header 3': '通过 DSL 文件创建应用'} {% hint style="info" %} Dify DSL 是由 Dify.AI 所定义的 AI 应用工程文件标准,文件格式为 YML。该标准涵盖应用在 Dify 内的基本描述、模型参数、编排配置等信息。 {% endhint %} #### 本地导入 如果你从社区或其它人那里获得了一个应用模版(DSL 文件),可以从工作室选择 「 导入DSL 文件 」。DSL 文件导入后将直接加载原应用的所有配置信息。

    导入 DSL 文件创建应用

    #### URL 导入 你也可以通过 URL 导入 DSL 文件,参考的链接格式: ```URL https://example.com/your_dsl.yml ``` {'Header 1': '创建应用', 'Header 3': '通过 DSL 文件创建应用'} ```URL https://example.com/your_dsl.yml ```

    通过 URL 导入 DSL 文件

    {'Header 1': '构建'} 在 Dify 中,一个“应用”是指基于 GPT 等大语言模型构建的实际场景应用。通过创建应用,您可以将智能 AI 技术应用于特定的需求。它既包含了开发 AI 应用的工程范式,也包含了具体的交付物。 简而言之,一个应用为开发者交付了: * 封装友好的 API,可由后端或前端应用直接调用,通过 Token 鉴权 * 开箱即用、美观且托管的 WebApp,你可以 WebApp 的模版进行二次开发 * 一套包含提示词工程、上下文管理、日志分析和标注的易用界面 你可以任选**其中之一**或**全部**,来支撑你的 AI 应用开发。 {'Header 1': '构建', 'Header 3': '应用类型 '} Dify 中提供了四种应用类型: * **聊天助手**:基于 LLM 构建对话式交互的助手 * **文本生成**:构建面向文本生成类任务的助手,例如撰写故事、文本分类、翻译等 * **Agent**:能够分解任务、推理思考、调用工具的对话式智能助手 * **工作流**:基于流程编排的方式定义更加灵活的 LLM 工作流 文本生成与聊天助手的区别见下表: {'Header 1': '构建', 'Header 3': '应用类型 '}
    文本生成聊天助手
    WebApp 界面表单+结果式聊天式
    WebAPI 端点completion-messageschat-messages
    交互方式一问一答多轮对话
    流式结果返回支持支持
    上下文保存当次持续
    用户输入表单支持支持
    数据集与插件支持支持
    AI {'Header 1': '构建', 'Header 3': '应用类型 '} 开场白不支持支持
    情景举例翻译、判断、索引聊天
    {'Header 1': '应用工具箱'} 在 **工作室 -- 应用编排** 内点击 **添加功能**,打开应用工具箱 应用工具箱为 Dify 的[应用](../#application\_type)提供了不同的附加功能:
    {'Header 1': '应用工具箱', 'Header 3': '对话开场白'} 在对话类应用中,AI 会主动说第一句话或者提出问题,你可以编辑开场白的内容包括开场问题。使用对话开场白可以引导用户提问,交代应用背景,降低对话提问的使用门槛。

    对话开场白

    {'Header 1': '应用工具箱', 'Header 3': '下一步问题建议'} 设置下一步问题建议可以在每次对话交互后,让 AI 根据之前的对话内容继续生成 3 个提问,引导下一轮对话。
    {'Header 1': '应用工具箱', 'Header 3': '文字转语音'} 开启后可以将 AI 回复的内容转换成自然的语音播放。
    {'Header 1': '应用工具箱', 'Header 3': '语音转文字'} 开启后可以在应用内录音并将语音自动转换成文本。
    {'Header 1': '应用工具箱', 'Header 3': '引用与归属'} 开启功能后,当大语言模型回复问题时引用来自知识库的内容时,可以在回复内容下面查看到具体的引用段落信息,包括原始分段文本、分段序号、匹配度等。 具体介绍请查看[引用与归属](../../knowledge-base/retrieval\_test\_and\_citation.md#id-2-yin-yong-yu-gui-shu)。 {'Header 1': '应用工具箱', 'Header 3': '内容审查'} 我们在与 AI 应用交互的过程中,往往在内容安全性,用户体验,法律法规等方面有较为苛刻的要求,此时我们需要“敏感内容审查”功能,来为终端用户创造一个更好的交互环境。 具体介绍请查看[敏感内容审查](moderation-tool.md)。 {'Header 1': '应用工具箱', 'Header 3': '标注回复'} 标注回复功能通过人工编辑标注为应用提供了可定制的高质量问答回复能力。 查看[标注回复](../../biao-zhu/annotation-reply.md) {'Header 1': '敏感内容审查'} 我们在与 AI 应用交互的过程中,往往在内容安全性,用户体验,法律法规等方面有较为苛刻的要求,此时我们需要“敏感词审查”功能,来为终端用户创造一个更好的交互环境。 在提示词编排页面,点击“添加功能”,找到底部的工具箱“内容审核”:

    Content moderation

    {'Header 1': '敏感内容审查', 'Header 3': '功能一:调用 OpenAI Moderation API'} OpenAI 和大多数 LLM 公司提供的模型,都带有内容审查功能,确保不会输出包含有争议的内容,比如暴力,性和非法行为,并且 OpenAI 还开放了这种内容审查能力,具体可以参考 [platform.openai.com](https://platform.openai.com/docs/guides/moderation/overview) 。现在你也可以直接在 Dify 上调用 OpenAI Moderation API,你可以审核输入内容或输出内容,只要输入对应的“预设回复”即可。

    OpenAI Moderation API

    {'Header 1': '敏感内容审查', 'Header 3': '功能二:自定义关键词'} 开发者可以自定义需要审查的敏感词,比如把“kill”作为关键词,在用户输入的时候作审核动作,要求预设回复内容为“The content is violating usage policies.”可以预见的结果是当用户在终端输入包含“kill”的语料片段,就会触发敏感词审查工具,返回预设回复内容。

    Keywords

    {'Header 1': '敏感内容审查', 'Header 3': '功能三: 敏感词审查 Moderation 扩展'} 不同的企业内部往往有着不同的敏感词审查机制,企业在开发自己的 AI 应用如企业内部知识库 ChatBot,需要对员工输入的查询内容作敏感词审查。为此,开发者可以根据自己企业内部的敏感词审查机制写一个 API 扩展,具体可参考 [moderation.md](../../extension/api\_based\_extension/moderation.md "mention"),从而在 Dify 上调用,实现敏感词审查的高度自定义和隐私保护。

    Moderation Settings

    比如我们在自己的本地服务中自定义敏感词审查规则:不能查询有关美国总统的名字的问题。当用户在`query`变量输入"Trump",则在对话时会返回 "Your content violates our usage policy." 测试效果如下: {'Header 1': '敏感内容审查', 'Header 3': '功能三: 敏感词审查 Moderation 扩展'}

    Moderation Test

    {'Header 1': '创建知识库&上传文档', 'Header 3': '1 创建知识库'} 在 Dify 主导航栏中点击知识库,在该页面你可以看到已有的知识库。你可以点击 **创建知识库** 进入创建向导:

    创建知识库

    * 如果你已经准备好了文件,可以从上传文件开始; * 如果你还没有准备好文档,可以先创建一个空数据集;

    创建知识库

    {% hint style="info" %} 如果你在创建数据集时选择了使用外部数据源,该知识库的类型不可更改。这是为了防止单一知识库存在多数据源而造成的管理困难。如果你需要使用多个数据源,建议创建多个知识库。 {% endhint %} *** {'Header 1': '创建知识库&上传文档', 'Header 3': '**2 上传文档**'} **知识库内上传文档的步骤:** 1. 从本地选择你需要上传的文档; 2. 分段与清洗,预览效果; 3. 选择及配置索引和检索策略; 4. 等待分段嵌入; 5. 完成上传,可以在应用中使用了🎉 **上传文档的限制:** * 单文档的上传大小限制为 15MB; * 单次批量上传文件个数上限为 20 个; * SaaS 版本的不同[订阅计划](https://dify.ai/pricing)限定了**批量上传个数、文档上传总数、向量存储**; {'Header 1': '创建知识库&上传文档', 'Header 3': '3 分段与清洗'} **分段**:大语言模型存在有限的上下文窗口,通常需要将整段文本进行分段处理后,将与用户问题关联度最高的几个段落召回,即分段 TopK 召回模式。此外,在用户问题与文本分段进行语义匹配时,合适的分段大小将有助于匹配关联性最高的文本内容,减少信息噪音。 **清洗:**为了保证文本召回的效果,通常需要在将数据传入模型之前对其进行清理。例如,如果输出中存在不需要的字符或者空行,可能会影响问题回复的质量。为了帮助用户解决这个问题, Dify 提供了多种清洗方法,可以帮助用户在将输出发送到下游应用程序之前对其进行清理。 分段与清洗支持两种配置策略 * 自动模式(即将下线) * 自定义模式
    在自定义模式下,用户可以根据不同的文档格式和场景要求来配置文本的分段和清洗策略。 **分段规则:** * 分段标识符,设置标识符如“\n”,系统将在文本中出现该标识符时分段; {'Header 1': '创建知识库&上传文档', 'Header 3': '3 分段与清洗'} **分段规则:** * 分段标识符,设置标识符如“\n”,系统将在文本中出现该标识符时分段; * 分段最大长度,根据分段的文本字符数最大上限来进行分段,超出该长度时将强制分段; * 分段重叠长度,设置分段间的重叠字符数,建议设置为分段长度的 10-25%,有助于保留分段之间的语义相关性,在多分段召回时提高召回效果。 **预处理规则:** * 替换连续的空格、换行符和制表符; * 删除所有 URL 和电子邮件地址; *** {'Header 1': '创建知识库&上传文档', 'Header 3': '4 ETL 可选配置'} 在 RAG 的生产级应用中,为了获得更好的数据召回效果,需要对多源数据进行预处理和清洗,即 ETL (_extract, transform, load_)。为了增强非结构化/半结构化数据的预处理能力,Dify 支持了可选的 ETL 方案:**Dify ETL** 和[ ](https://docs.unstructured.io/welcome)[**Unstructured ETL** ](https://unstructured.io/)。 > Unstructured 能够高效地提取并转换您的数据为干净的数据用于后续的步骤。 Dify 各版本的 ETL 方案选择: * SaaS 版不可选,默认使用 Unstructured ETL; * 社区版可选,默认使用 Dify ETL ,可通过[环境变量](../../getting-started/install-self-hosted/environments.md#zhi-shi-ku-pei-zhi)开启 Unstructured ETL; 文件解析支持格式的差异: {'Header 1': '创建知识库&上传文档', 'Header 3': '4 ETL 可选配置'} 文件解析支持格式的差异: | DIFY ETL | Unstructured ETL | | ---------------------------------------------- | ------------------------------------------------------------------------ | | txt、markdown、md、pdf、html、htm、xlsx、xls、docx、csv | txt、markdown、md、pdf、html、htm、xlsx、xls、docx、csv、eml、msg、pptx、ppt、xml、epub | {% hint style="info" %} {'Header 1': '创建知识库&上传文档', 'Header 3': '4 ETL 可选配置'} {% hint style="info" %} 不同的 ETL 方案在文件提取效果的方面也会存在差异,想了解更多关于 Unstructured ETL 的数据处理方式,请参考[官方文档](https://docs.unstructured.io/open-source/core-functionality/partitioning)。 {% endhint %} *** {'Header 1': '创建知识库&上传文档', 'Header 3': '5 索引方式'} 你需要选择文本的**索引方式**来指定数据的匹配方式,索引策略往往与检索方式相关,你需要根据场景需求来选择合适的索引方式。 **高质量模式:**将调用 OpenAI 的嵌入接口进行处理,以在用户查询时提供更高的准确度。 **经济模式**:会使用关键词索引方式,降低了准确度但无需花费 Token。 **Q\&A 模式(仅社区版支持):**Q\&A 分段模式功能,与上述普通的「Q to P」(问题匹配文本段落)匹配模式不同,它是采用「Q to Q」(问题匹配问题)匹配工作,在文档经过分段后,经过总结为每一个分段生成 Q\&A 匹配对,当用户提问时,系统会找出与之最相似的问题,然后返回对应的分段作为答案。这种方式更加精确,因为它直接针对用户问题进行匹配,可以更准确地获取用户真正需要的信息。 在知识库上传文档时,系统将对文本进行分段,使得用户的提问(输入)能匹配到相关的文本段落(Q to P),最后输出结果。 {'Header 1': '创建知识库&上传文档', 'Header 3': '5 索引方式'} > 问题文本是具有完整语法结构的自然语言,而不是文档检索任务中的一些关键字,所以 Q to Q (问题匹配问题)的模式会令语意和匹配更加清晰,并同时满足一些高频和高相似度问题的提问场景。

    Q&A 分段模式下被总结成多个 Q&A 对的文本

    Q to P 与 Q to Q 的索引模式区别

    *** {'Header 1': '创建知识库&上传文档', 'Header 3': '6 检索设置'} 在高质量索引模式下,Dify 提供了 3 种检索方案: * **向量检索**,通过生成查询嵌入并查询与其向量表示最相似的文本分段。 * **全文检索**,索引文档中的所有词汇,从而允许用户查询任意词汇,并返回包含这些词汇的文本片段。 * **混合检索**,同时执行全文检索和向量检索,并附加重排序步骤,从两类查询结果中选择匹配用户问题的最佳结果,需配置 Rerank 模型 API。 三种检索方式的具体配置如下: #### **向量检索** 定义:通过生成查询嵌入并查询与其向量表示最相似的文本分段。

    向量检索设置

    TopK:用于筛选与用户问题相似度最高的文本片段。系统同时会根据选用模型上下文窗口大小动态调整片段数量。系统默认值为 3 。 {'Header 1': '创建知识库&上传文档', 'Header 3': '6 检索设置'} Score 阈值:用于设置文本片段筛选的相似度阈值,即:只召回超过设置分数的文本片段。系统默认关闭该设置,即不会对召回的文本片段相似值过滤。打开后默认值为 0.5 。 Rerank 模型:你可以在“模型供应商”页面配置 Rerank 模型的 API 秘钥之后,在检索设置中打开“Rerank 模型”,系统会在语义检索后对已召回的文档结果再一次进行语义重排序,优化排序结果。设置 Rerank 模型后,TopK 和 Score 阈值设置仅在 Rerank 步骤生效。 #### **全文检索** 定义:索引文档中的所有词汇,从而允许用户查询任意词汇,并返回包含这些词汇的文本片段。

    全文检索设置

    TopK:用于筛选与用户问题相似度最高的文本片段。系统同时会根据选用模型上下文窗口大小动态调整片段数量。系统默认值为 3 。 {'Header 1': '创建知识库&上传文档', 'Header 3': '6 检索设置'} Rerank 模型:你可以在“模型供应商”页面配置 Rerank 模型的 API 秘钥之后,在检索设置中打开“Rerank 模型”,系统会在全文检索后对已召回的文档结果再一次进行语义重排序,优化排序结果。设置 Rerank 模型后,TopK 和 Score 阈值设置仅在 Rerank 步骤生效。 #### **混合检索** 同时执行全文检索和向量检索,并应用重排序步骤,从两类查询结果中选择匹配用户问题的最佳结果,需配置 Rerank 模型 API。

    混合检索设置

    TopK:用于筛选与用户问题相似度最高的文本片段。系统同时会根据选用模型上下文窗口大小动态调整片段数量。系统默认值为 3 。 {'Header 1': '创建知识库&上传文档', 'Header 3': '6 检索设置'} Rerank 模型:你可以在“模型供应商”页面配置 Rerank 模型的 API 秘钥之后,在检索设置中打开“Rerank 模型”,系统会在混合检索后对已召回的文档结果再一次进行语义重排序,优化排序结果。设置 Rerank 模型后,TopK 和 Score 阈值设置仅在 Rerank 步骤生效。 {'Header 1': '知识库'} 大语言模型的训练数据一般基于公开的数据,且每一次训练需要消耗大量算力,这意味着模型的知识一般不会包含私有领域的知识,同时在公开知识领域存在一定的滞后性。为了解决这一问题,目前通用的方案是采用 RAG(检索增强生成)技术,使用用户问题来匹配最相关的外部数据,将检索到的相关内容召回后作为模型提示词的上下文来重新组织回复。 {% hint style="info" %} 想要了解更多 ,请查看扩展阅读内的[检索增强生成(RAG)](../../learn-more/extended-reading/retrieval-augment/) {% endhint %} Dify 的知识库功能将 RAG 管线上的各环节可视化,提供了一套简单易用的用户界面来方便应用构建者管理个人或者团队的知识库,并能够快速集成至 AI 应用中。你只需准备文本内容,例如: * 长文本内容(TXT、Markdown、DOCX、HTML、JSONL 甚至是 PDF 文件) * 结构化数据(CSV、Excel 等) 另外,我们正在逐步支持从诸多数据源同步数据至数据集,包括: * 网页 * Notion {'Header 1': '知识库'} 另外,我们正在逐步支持从诸多数据源同步数据至数据集,包括: * 网页 * Notion * Github * 数据库 * …… {% hint style="info" %} **情景**:如果你的公司想基于现有知识库和产品文档建立一个 AI 客服助手,你可以在 Dify 中将文档上传至数据集,并建立一个对话型应用。这在过去可能需要花费你数周的时间,且难以持续维护。 {% endhint %} {'Header 1': '知识库', 'Header 3': '知识库与文档'} 在 Dify 中,知识库(Knowledge)是一些文档(Documents)的集合。一个知识库可以被整体集成至一个应用中作为检索上下文使用。文档可以由开发者或运营人员上传,或由其它数据源同步(通常对应数据源中的一个文件单位)。 {'Header 1': '外部数据工具', 'Header 2': '功能介绍'} 此前 [.](./ "mention") 功能允许开发者可以直接上传各类格式的长文本、结构化数据来构建数据集,使 AI 应用基于用户上传的最新上下文进行对话。 而本次更新的**外部数据工具**赋能开发者可以使用自有的搜索能力或内部知识库等外部数据作为 LLM 的上下文,通过 API 扩展的方式实现外部数据的获取并嵌入提示词。相比在云端上传数据集,使用**外部数据工具**可以在保障私有数据安全,自定义搜索,获取实时数据等方面有显著优势。 {'Header 1': '外部数据工具', 'Header 2': '具体实现'} 当终端用户向对话系统提出请求时,平台后端会触发外部数据工具(即调用自己的 API),它会查询用户问题相关的外部信息,如员工资料、实时记录等,通过 API 返回与当前请求相关的部分。平台后端会将返回的结果组装成文本作为上下文注入到提示词中,以输出更加个性化和符合用户需求的回复内容。 {'Header 1': '外部数据工具', 'Header 2': '操作说明'} 1. 在使用外部数据工具之前,你需要准备一个 API 和用于鉴权的 API Key,请阅读[external\_data\_tool.md](../extension/api\_based\_extension/external\_data\_tool.md "mention") 2. Dify 提供了集中式的 API 管理,在设置界面统一添加 API 扩展配置后,即可在 Dify 上的各类应用中直接使用。

    API-based Extension

    3. 我们以“查询天气”为例,在“新增基于 API 的扩展”对话框输入名字,API 端点,API Key。保存后我们就可以调用 API 了。 {'Header 1': '外部数据工具', 'Header 2': '操作说明'}

    Weather Inquiry

    4. 在提示词编排页面,点击“工具”右侧的“+添加”按钮,在打开的“添加 工具”对话框,填写名称和变量名称(变量名称会被引用到提示词中,请填写英文),以及选择第 2 步中已经添加的基于 API 的扩展。

    External_data_tool

    5. 这样,我们在提示词编排框就可以把查询到的外部数据拼装到提示词中。比如我们要查询今天的伦敦天气,可以添加`location` 变量,输入"London",结合外部数据工具的扩展变量名称`weather_data`,调试输出如下: {'Header 1': '外部数据工具', 'Header 2': '操作说明'}

    Weather_search_tool

    在对话日志中,我们也可以看到 API 返回的实时数据:

    Prompt Log

    {'Header 1': '在应用内集成知识库', 'Header 3': '1 创建知识库应用'} 知识库可以作为外部知识提供给大语言模型用于精确回复用户问题,你可以在 Dify 的[所有应用类型](../application\_orchestrate/#application\_type)内关联已创建的知识库。 以聊天助手为例,使用流程如下: 1. 进入 **工作室 -- 创建应用 --创建聊天助手** 2. 进入 **上下文设置** 点击 **添加** 选择已创建的知识库 3. 在 **上下文设置 -- 参数设置** 内配置**召回策略** 4. 在 **添加功能** 内打开 **引用和归属** 5. 在 **调试与预览** 内输入与知识库相关的用户问题进行调试 6. 调试完成之后**保存并发布**为一个 AI 知识库问答类应用

    在应用内关联知识库

    *** {'Header 1': '在应用内集成知识库', 'Header 3': '2 召回模式'} 进入 **上下文 -- 参数设置 -- 召回设置**,可以选择知识库的召回模式。 **N 选 1 召回**,根据用户意图和知识库描述,由 LLM 自主判断选择最匹配的单个知识库来查询相关文本。 **多路召回**,根据用户意图同时匹配所有知识库,从多路知识库查询相关文本片段,经过重排序步骤,从多路查询结果中选择匹配用户问题的最佳结果,需配置 Rerank 模型 API。
    **如何选择召回模式** N 选 1 召回由 Function Call/ReAct 进行驱动,每一个关联的知识库作为工具函数,LLM 会自主选择与用户问题最匹配的 1 个知识库来进行查询,**推理依据为用户问题与知识库描述的语义匹配性**。 因此 N 选 1 模式的召回效果主要受三个因素影响: {'Header 1': '在应用内集成知识库', 'Header 3': '2 召回模式'} 因此 N 选 1 模式的召回效果主要受三个因素影响: * **系统推理模型的能力,**部分模型对于 Function Call/ReAct 的指令遵循程度不稳定 * **知识库描述是否清晰**,描述内容会影响 LLM 对用户问题与相关知识库的推理 * **知识库的个数**,知识库过多会影响 LLM 的推理精确性,同时可能会超出推理模型的上下文窗口长度。 **N 选 1 模式的推荐配置方法:**选择效果更好的系统推理模型,关联尽量少的知识库,提供精确的知识库描述。 用户上传知识库时,系统推理模型将自动为知识库生成一个摘要描述。为了在该模式下获得最佳的召回效果,你可以在“知识库->设置->知识库描述”中查看到系统默认创建的摘要描述,并检查该内容是否可以清晰的概括知识库的内容。 以下是 N 选 1 召回模式的技术流程图:
    {% hint style="info" %} {'Header 1': '在应用内集成知识库', 'Header 3': '2 召回模式'} {% hint style="info" %} N 选 1 召回依赖模型的推理能力,使用限制较多,计划在 2024 Q3 调整该模式的召回策略。 {% endhint %} #### 多路召回模式(推荐) 在多路召回模式下,检索器会在所有与应用关联的知识库中去检索与用户问题相关的文本内容,并将多路召回的相关文档结果合并,并通过后置的重排序(Rerank)步骤对检索召回的文档进行语义重排。 以下是多路召回模式的技术流程图: {'Header 1': '在应用内集成知识库', 'Header 3': '2 召回模式'} 以下是多路召回模式的技术流程图:
    {% hint style="info" %} {'Header 1': '在应用内集成知识库', 'Header 3': '2 召回模式'} {% hint style="info" %} 多路召回模式下需要配置 Rerank 模型。 {% endhint %} 多路召回模式不依赖于模型的推理能力或知识库描述,该模式在多知识库检索时能够获得质量更高的召回效果,因此更**推荐将召回模式设置为多路召回**。 *** {'Header 1': '在应用内集成知识库', 'Header 3': '3 重排序(Rerank)'} 重排序模型通过将候选文档列表与用户问题语义匹配度进行重新排序,从而改进语义排序的结果。其原理是计算用户问题与给定的每个候选文档之间的相关性分数,并返回按相关性从高到低排序的文档列表。

    混合检索+重排序

    {% hint style="info" %} 想了解更多关于 Rerank 的相关知识,请查阅扩展阅读[重排序](integrate\_knowledge\_within\_application.md#zhong-pai-xu-rerank)。 {% endhint %} #### 如何配置 Rerank 模型? Dify 目前已支持 Cohere Rerank 模型,通过进入“模型供应商-> Cohere”页面填入 Rerank 模型的 API 秘钥: {'Header 1': '在应用内集成知识库', 'Header 3': '3 重排序(Rerank)'}

    在模型供应商内配置 Cohere Rerank 模型

    如何获取 Cohere Rerank 模型? 登录:[https://cohere.com/rerank](https://cohere.com/rerank),在页内注册并申请 Rerank 模型的使用资格,获取 API 秘钥。 {% hint style="info" %} 除了支持 Cohere Rerank API ,你也可以在使用本地推理框架如 Ollama、Xinference,并在推理框架内部署本地 Rerank 模型例如: bge-reranker。 {% endhint %} #### 设置 Rerank 模型 {'Header 1': '在应用内集成知识库', 'Header 3': '3 重排序(Rerank)'} {% endhint %} #### 设置 Rerank 模型 通过进入“数据集->创建数据集->检索设置”页面并在添加 Rerank 设置。除了在创建数据集可以设置 Rerank ,你也可以在已创建的数据集设置内更改 Rerank 配置,在应用编排的数据集召回模式设置中更改 Rerank 配置。

    数据集检索模式中设置 Rerank 模型

    **TopK**:用于设置 Rerank 后返回相关文档的数量。 {'Header 1': '在应用内集成知识库', 'Header 3': '3 重排序(Rerank)'} **TopK**:用于设置 Rerank 后返回相关文档的数量。 **Score 阈值**:用于设置 Rerank 后返回相关文档的最低分值。设置 Rerank 模型后,TopK 和 Score 阈值设置仅在 Rerank 步骤生效。 通过进入“提示词编排->上下文->设置”页面中设置为多路召回模式时需开启 Rerank 模型。

    数据集多路召回模式中设置 Rerank 模型

    {'Header 1': '知识库及文档维护', 'Header 3': '1 查看文本分段'} 知识库内已上传的每个文档都会以文本分段(Chunks)的形式进行存储,你可以在分段列表内查看每一个分段的具体文本内容。

    查看已上传的文档分段

    *** {'Header 1': '知识库及文档维护', 'Header 3': '2 检查分段质量'} 文档分段对于知识库应用的问答效果有明显影响,在将知识库与应用关联之前,建议人工检查分段质量。 通过字符长度、标识符或者 NLP 语义分段等机器自动化的分段方式虽然能够显著减少大规模文本分段的工作量,但分段质量与不同文档格式的文本结构、前后文的语义联系都有关系,通过人工检查和订正可以有效弥补机器分段在语义识别方面的缺点。 检查分段质量时,一般需要关注以下几种情况: * **过短的文本分段**,导致语义缺失;

    过短的文本分段

    * **过长的文本分段**,导致语义噪音影响匹配准确性;

    过长的文本分段

    {'Header 1': '知识库及文档维护', 'Header 3': '2 检查分段质量'} * **明显的语义截断**,在使用最大分段长度限制时会出现强制性的语义截断,导致召回时缺失内容;

    明显的语义截断

    *** {'Header 1': '知识库及文档维护', 'Header 3': '3 添加文本分段'} 在分段列表内点击 「 添加分段 」 ,可以在文档内自行添加一个或批量添加多个自定义分段。
    批量添加分段时,你需要先下载 CSV 格式的分段上传模板,并按照模板格式在 Excel 内编辑所有的分段内容,再将 CSV 文件保存后上传。

    批量添加自定义分段

    *** {'Header 1': '知识库及文档维护', 'Header 3': '4 编辑文本分段'} 在分段列表内,你可以对已添加的分段内容直接进行编辑修改。包括分段的文本内容和关键词。

    编辑文档分段

    *** {'Header 1': '知识库及文档维护', 'Header 3': '5 元数据管理'} 除了用于标记不同来源文档的元数据信息,例如网页数据的标题、网址、关键词、描述等。元数据将被用于知识库的分段召回过程中,作为结构化字段参与召回过滤或者显示引用来源。 {% hint style="info" %} 元数据过滤及引用来源功能当前版本尚未支持。 {% endhint %}

    元数据管理

    *** {'Header 1': '知识库及文档维护', 'Header 3': '6 添加文档'} 在「 知识库 > 文档列表 」 点击 「 添加文件 」,可以在已创建的知识库内上传新的文档或者 [Notion 页面](sync-from-notion.md)。 知识库(Knowledge)是一些文档(Documents)的集合。文档可以由开发者或运营人员上传,或由其它数据源同步(通常对应数据源中的一个文件单位)。

    知识库上传新文档

    *** {'Header 1': '知识库及文档维护', 'Header 3': '7 文档禁用和归档'} **禁用**:数据集支持将暂时不想被索引的文档或分段进行禁用,在数据集文档列表,点击禁用按钮,则文档被禁用;也可以在文档详情,点击禁用按钮,禁用整个文档或某个分段,禁用的文档将不会被索引。禁用的文档点击启用,可以取消禁用。 **归档**:一些不再使用的旧文档数据,如果不想删除可以将它进行归档,归档后的数据就只能查看或删除,不可以进行编辑。在数据集文档列表,点击归档按钮,则文档被归档,也可以在文档详情,归档文档。归档的文档将不会被索引。归档的文档也可以点击撤销归档。 *** {'Header 1': '知识库及文档维护', 'Header 3': '8 知识库设置'} 在知识库的左侧导航中点击**设置**,你可以改变知识库的以下设置项:

    知识库设置

    **知识库名称**,定义一个名称用于识别一个知识库。 **知识库描述**,用于描述知识库内文档代表的信息 {% hint style="info" %} 在知识库召回模式为 N 选 1 时,知识库作为工具提供给 LLM 进行推理调用,推理依据是知识库的描述,如果描述为空则会使用 Dify 的自动索引策略 {% endhint %} **可见权限**,可选择 「 只有我 」 或 「 所有团队成员 」,不具有权限的人将无法查阅和编辑数据集。 **索引模式**,[参考文档](create\_knowledge\_and\_upload\_documents.md#suo-yin-fang-shi) {'Header 1': '知识库及文档维护', 'Header 3': '8 知识库设置'} **Embedding 模型,**修改知识库的嵌入模型,修改 Embedding 模型将对知识库内的所有文档重新嵌入,原先的嵌入将会被删除。 **检索设置**,[参考文档](create\_knowledge\_and\_upload\_documents.md#jian-suo-she-zhi) *** {'Header 1': '知识库及文档维护', 'Header 3': '9 知识库 API 管理'} Dify 知识库提供整套标准 API ,开发者通过 API 调用对知识库内的文档、分段进行增删改查等日常管理维护操作,请参考[知识库 API 文档](maintain-dataset-via-api.md)。

    知识库 API 管理

    {'Header 1': '从网页导入数据'} Dify 知识库通过集成 Firecrawl ,支持网页抓取并解析为 Markdown 导入至知识库。 {% hint style="info" %} [Firecrawl ](https://www.firecrawl.dev/)是一个开源的网页解析工具,它能将网页将其转换为干净并且方便 LLM 识别的 Markdown 格式文本,它同时提供了易于使用的 API 服务。 {% endhint %} {'Header 1': '从网页导入数据', 'Header 3': '如何配置'} 首先需要在 DataSource 页面内配置 Firecrawl 的凭据。
    登录 [Firecrawl 官网](https://www.firecrawl.dev/) 完成注册,获取 API Key 后填入并保存。
    在知识库创建页选择 **Sync from website**,**填入需要抓取的网页 URL**。

    网页抓取配置

    {'Header 1': '从网页导入数据', 'Header 3': '如何配置'} 设置中的配置项包括:是否抓取子页面、抓取页面数量上限、页面抓取深度、排除页面、仅抓取页面、提取内容。完成配置后点击 **Run**,预览已解析的页面。

    执行抓取

    导入网页解析的文本后存储至知识库的文档中,查看导入结果。点击 **Add URL** 可以继续导入新的网页。

    导入网页解析文本至知识库内

    {'Header 1': '从 Notion 导入数据'} Dify 知识库支持从 Notion 导入,并设置 **同步** 使得数据在 Notion 更新后便自动同步到 Dify。 {'Header 1': '从 Notion 导入数据', 'Header 3': '授权验证'} 1. 在创建数据集,选择数据源时,点击 **同步自 Notion 内容-- 去绑定,根据提示完成授权验证。** 2. 你也可以:进入 **设置 -- 数据来源 -- 添加数据源** 中点击 Notion 来源 **绑定** ,完成授权验证。

    绑定 Notion

    {'Header 1': '从 Notion 导入数据', 'Header 3': '导入 Notion 数据'} 完成验证授权后,进入创建数据集页面,点击 \*\*同步自 Notion 内容 ,\*\*选择需要的授权页面进行导入。 {'Header 1': '从 Notion 导入数据', 'Header 3': '进行分段和清洗'} 接下来,选择你的**分段设置**和**索引方式**,**保存并处理**。等待 Dify 为你处理这些数据,通常该步骤在 LLM 供应商中需要消耗 Token。Dify 不仅支持普通类型页面导入,并且会将 database 类型下的页面属性进行汇总保存。 _**请注意:图片和文件暂不支持导入,表格类数据会被转换为文本展示。**_ {'Header 1': '从 Notion 导入数据', 'Header 3': '同步 Notion 数据'} 如果您的 Notion 内容有修改,您可以直接在 Dify 数据集 **文档列表页**中点击 **同步** 即可进行数据一键同步,该步骤是需要消耗 Token。

    同步 Notion 内容

    {'Header 1': '从 Notion 导入数据', 'Header 3': '社区版 Notion 的集成配置方法'} Notion集成分为**内部集成**(internal integration)和**外部集成**(public integration)两种方式。可按需在 Dify 里配置。两种集成方式的具体区别请参阅 [Notion 官方文档](https://developers.notion.com/docs/authorization)。 {'Header 1': '从 Notion 导入数据', 'Header 3': '1、**使用 internal 集成方式**'} 首先,在集成的设置页面中[创建集成](https://www.notion.so/my-integrations)。默认情况下,所有集成都以内部集成开始;内部集成将与您选择的工作区相关联,因此您需要是工作区所有者才能创建集成。 具体操作步骤: 点击“**New integration**”按钮,类型默认是 **Internal**(不可修改),选择关联的空间,输入集成名称并上传 logo 后,点击“Submit”,集成创建成功。
    创建集成后,您可以根据需要在 Capabilities 选项卡下更新其设置,并在 Secrets 下点击 “Show” 按钮然后复制 Secrets。 {'Header 1': '从 Notion 导入数据', 'Header 3': '1、**使用 internal 集成方式**'}
    复制后回到 Dify 源代码下,在 **.env** 文件里配置相关环境变量,环境变量如下: **NOTION\_INTEGRATION\_TYPE** = internal or **NOTION\_INTEGRATION\_TYPE** = public **NOTION\_INTERNAL\_SECRET**=you-internal-secret {'Header 1': '从 Notion 导入数据', 'Header 3': '2、**使用 Public 集成方式**'} **需要将 internal 集成升级为 public 集成**,导航到集成的 Distribution 页面,然后切换开关以公开集成。将开关切换到公共设置,您需要在下面的 Organization Information 表单中填写其他信息,包括您的公司名称、网站和重定向 URL 等信息,然后点击“Submit”按钮。
    在集成的设置页面中成功公开集成后,您将能够在密钥选项卡中访问集成的密钥:
    回到 Dify 源代码下,在 **.env** 文件里配置相关环境变量,环境变量如下: {'Header 1': '从 Notion 导入数据', 'Header 3': '2、**使用 Public 集成方式**'} 回到 Dify 源代码下,在 **.env** 文件里配置相关环境变量,环境变量如下: **NOTION\_INTEGRATION\_TYPE**=public **NOTION\_CLIENT\_SECRET**=you-client-secret **NOTION\_CLIENT\_ID**=you-client-id 配置完成后,即可在数据集中操作 Notion 的数据导入及同步功能。 {'Header 1': '通过 API 维护数据集'} > 鉴权、调用方式与应用 Service API 保持一致,不同的是一个数据集 API token 可操作所有数据集 {'Header 1': '通过 API 维护数据集', 'Header 3': '使用数据集API的优势'} * 将您的数据系统同步至 Dify 数据集,创建强大的工作流程。 * 提供数据集列表,文档列表及详情查询,方便构建您自己的数据管理页。 * 同时支持纯文本和文件两种上传和更新文档的接口,并支持分段级的批量新增和修改,便捷您的同步方式。 * 减少文档手动处理同步的时间,提高您对 Dify 的软件和服务的可见性。 {'Header 1': '通过 API 维护数据集', 'Header 3': '如何使用'} 进入数据集页面,你可以在左侧的导航中切换至 **API** 页面。在该页面中你可以查看 Dify 提供的数据集 API 文档,并可以在 **API 密钥** 中管理可访问数据集 API 的凭据。

    Knowledge API Document

    {'Header 1': '通过 API 维护数据集', 'Header 3': 'API 调用示例'} #### **创建空数据集** {% hint style="warning" %} 仅用来创建空数据集 {% endhint %} ``` curl --location --request POST 'https://api.dify.ai/v1/datasets' \ --header 'Authorization: Bearer {api_key}' \ --header 'Content-Type: application/json' \ --data-raw '{"name": "name"}' ``` #### **数据集列表** ``` curl --location --request GET 'https://api.dify.ai/v1/datasets?page=1&limit=20' \ --header 'Authorization: Bearer {api_key}' {'Header 1': '通过 API 维护数据集', 'Header 3': 'API 调用示例'} ``` #### **通过文本创建文档** ``` curl --location --request POST '/document/create_by_text>' \\ --header 'Authorization: Bearer {api_key}' \\ --header 'Content-Type: application/json' \\ --data-raw '{ "name": "Dify", "text": "Dify means Do it for you...", "indexing_technique": "high_quality", "process_rule": { "rules": { "pre_processing_rules": [{ "id": "remove_extra_spaces", "enabled": true }, { "id": "remove_urls_emails", "enabled": true }], {'Header 1': '通过 API 维护数据集', 'Header 3': 'API 调用示例'} "id": "remove_urls_emails", "enabled": true }], "segmentation": { "separator": "###", "max_tokens": 500 } }, "mode": "custom" } }' {'Header 1': '通过 API 维护数据集', 'Header 3': 'API 调用示例'} ``` #### **通过文件创建文档** ``` curl --location POST 'https://api.dify.ai/v1/datasets/{dataset_id}/document/create_by_file' \ --header 'Authorization: Bearer {api_key}' \ --form 'data="{ "name": "Dify", "indexing_technique": "high_quality", "process_rule": { "rules": { "pre_processing_rules": [{ "id": "remove_extra_spaces", "enabled": true }, { "id": "remove_urls_emails", "enabled": true }], "segmentation": { "separator": "###", "max_tokens": 500 } }, "mode": "custom" } }"; type=text/plain' \ {'Header 1': '通过 API 维护数据集', 'Header 3': 'API 调用示例'} } }, "mode": "custom" } }"; type=text/plain' \ --form 'file=@"/path/to/file"' {'Header 1': '通过 API 维护数据集', 'Header 3': 'API 调用示例'} ``` #### **获取文档嵌入状态(进度)** ``` curl --location --request GET 'https://api.dify.ai/v1/datasets/{dataset_id}/documents/{batch}/indexing-status' \ --header 'Authorization: Bearer {api_key}' ``` #### **删除文档** ``` curl --location --request DELETE 'https://api.dify.ai/v1/datasets/{dataset_id}/documents/{document_id}' \ --header 'Authorization: Bearer {api_key}' ``` #### **数据集文档列表** ``` curl --location --request GET 'https://api.dify.ai/v1/datasets/{dataset_id}/documents' \ {'Header 1': '通过 API 维护数据集', 'Header 3': 'API 调用示例'} --header 'Authorization: Bearer {api_key}' {'Header 1': '通过 API 维护数据集', 'Header 3': 'API 调用示例'} ``` #### **新增分段** ``` curl 'https://api.dify.ai/v1/datasets/aac47674-31a8-4f12-aab2-9603964c4789/documents/2034e0c1-1b75-4532-849e-24e72666595b/segment' \ --header 'Authorization: Bearer {api_key}' \ --header 'Content-Type: application/json' \ --data-raw $'"chunks":[ {"content":"Dify means Do it for you", "keywords":["Dify","Do"] } ]' --compressed ``` {'Header 1': '通过 API 维护数据集', 'Header 3': '错误信息'} * `document_indexing`,文档索引失败 * `provider_not_initialize`, Embedding 模型未配置 * `not_found`,文档不存在 * `dataset_name_duplicate` ,数据集名称重复 * `provider_quota_exceeded`,模型额度超过限制 * `dataset_not_initialized`,数据集还未初始化 * `unsupported_file_type`,不支持的文件类型 * 目前只支持:txt, markdown, md, pdf, html, htm, xlsx, docx, csv * `too_many_files`,文件数量过多,暂时只支持单一文件上传 * `file_too_large`,文件太大,支持15M以下 {'Header 1': '召回测试/引用归属', 'Header 3': '1 召回测试'} Dify 知识库内提供了文本召回测试的功能,用于调试不同检索方式及参数配置下的召回效果。你可以在 **源文本** 输入框输入常见的用户问题,点击 **测试** 并在右侧的 **召回段落** 查看召回结果。在 **最近查询** 内可以查看到历史的查询记录;若知识库已关联至应用内,由应用内触发的知识库查询也可以在此查看记录。

    召回测试

    {'Header 1': '召回测试/引用归属', 'Header 3': '1 召回测试'} 点击源文本输入框右上角的图标可以更换当前知识库的检索方式和具体参数,**保存之后仅在召回测试的调试过程中生效**。在召回测试完成调试并确认更改知识库的检索参数时,需要在 [知识库设置 > 检索设置](retrieval\_test\_and\_citation.md#zhi-shi-ku-she-zhi) 中进行更改。

    召回测试-检索设置

    **召回测试建议步骤:** 1. 设计和整理覆盖常见用户问题的测试用例/测试问题集; 2. 选择合适的检索策略:向量检索/全文检索/混合检索,不同检索方式的优缺点,请参考扩展阅读[检索增强生成(RAG)](../../learn-more/extended-reading/retrieval-augment/); {'Header 1': '召回测试/引用归属', 'Header 3': '1 召回测试'} 3. 调试召回分段数量(TopK)和召回分数阈值(Score),需根据应用场景、包括文档本身的质量来选择合适的参数组合。 **TopK 值和召回阈值(Score )如何配置** * **TopK 代表按相似分数倒排时召回分段的最大个数**。TopK 值调小,将会召回更少分段,可能导致召回的相关文本不全;TopK 值调大,将召回更多分段,可能导致召回语义相关性较低的分段使得 LLM 回复质量降低。 * **召回阈值(Score)代表允许召回分段的最低相似分数。**召回分数调小,将会召回更多分段,可能导致召回相关度较低的分段;召回分数阈值调大,将会召回更少分段,过大时将会导致丢失相关分段。 *** {'Header 1': '召回测试/引用归属', 'Header 3': '2 引用与归属'} 在应用内测试知识库效果时,你可以进入 **工作室 -- 添加功能 -- 引用归属**,打开引用归属功能。

    打开引用与归属功能

    开启功能后,当大语言模型回复问题时引用来自知识库的内容时,可以在回复内容下面查看到具体的引用段落信息,包括**原始分段文本、分段序号、匹配度**等。点击引用分段上方的 **跳转至知识库 ,**可以快捷访问该分段所在的知识库分段列表,方便开发者进行调试编辑。 {'Header 1': '召回测试/引用归属', 'Header 3': '2 引用与归属'}

    查看回复内容的引用信息

    {'Header 1': '日志与标注'} {% hint style="warning" %} 请确保您的应用在收集用户数据时遵守当地法规。通常的做法是发布隐私政策并征得用户的同意。 {% endhint %} 日志(Logs)功能用以观察与标记 Dify 应用的工作表现,Dify 为应用的全部交互过程记录了日志,无论你是通过 WebApp 或 API 调用的,如果你是 Prompt 工程师或 LLM 运营人员,它将为你提供可视化的 LLM 应用运营体验。 {'Header 1': '日志与标注', 'Header 3': '使用日志控制台'} 你可以在应用的左侧导航找到**日志(Logs)**,该页面通常展示了: * 所选时间内用户与用户的交互记录 * 用户输入与 AI 输出的结果,对于对话型应用通常是一系列的消息流 * 用户、运营人员的评价,以及运营人员的改进标注 注意,如果团队中的多位协作者对同一条日志进行标注,最后标注的记录将覆盖此前的标注。 {'Header 1': '日志与标注', 'Header 3': '改进标注'} {% hint style="info" %} 这些标记将在 Dify 的后续版本中供模型微调使用,以提升模型的准确性与回复风格,当前预览版仅支持标记。 {% endhint %}

    标记日志以改进

    点击一条日志会在界面右侧打开日志详情面板,在该面板中运营人员可以对一次互动进行标注: * 对表现较佳的消息点赞 * 对表现不佳的消息点踩 * 对改进的结果标记改进回复,这代表了你期望 AI 回复的文本 注意,如果团队中的多位管理员对同一条日志进行标注,最后标注的记录将覆盖此前的标注。 {'Header 1': '标注回复'} 标注回复功能通过人工编辑标注为应用提供了可定制的高质量问答回复能力。 适用情景: * **特定领域的定制化回答:** 在企业、政府等客服或知识库问答情景时,对于某些特定问题,服务提供方希望确保系统以明确的结果来回答问题,因此需要对在特定问题上定制化输出结果。比如定制某些问题的“标准答案”或某些问题“不可回答”。 * **POC 或 DEMO 产品快速调优:** 在快速搭建原型产品,通过标注回复实现的定制化回答可以高效提升问答结果的生成预期,提升客户满意度。 标注回复功能相当于提供了另一套检索增强系统,可以跳过 LLM 的生成环节,规避 RAG 的生成幻觉问题。 {'Header 1': '标注回复', 'Header 3': '使用流程'} 1. 在开启标注回复功能之后,你可以对 LLM 对话回复内容进行标注,你可以将 LLM 回复的高质量答案直接添加为一条标注,也可以根据自己的需求编辑一条高质量答案,这些编辑的标注内容会被持久化保存; 2. 当用户再次提问相似的问题时,会将问题向量化并查询中与之相似的标注问题; 3. 如果找到匹配项,则直接返回标注中与问题相对应的答案,不再传递至 LLM 或 RAG 过程进行回复; 4. 如果没有找到匹配项,则问题继续常规流程(传递至 LLM 或 RAG); 5. 关闭标注回复功能后,系统将一直不再继续从标注内匹配回复。

    标注回复流程

    {'Header 1': '标注回复', 'Header 3': '提示词编排中开启标注回复'} 通过进入“应用构建->添加功能”开启标注回复开关:

    提示词编排中开启标注回复

    开启时需要先设置标注回复的参数,可设置参数包括:Score 阈值 和 Embedding 模型 **Score 阈值**:用于设置标注回复的匹配相似度阈值,只有高于阈值分数的标注会被召回。 **Embedding 模型**:用于对标注文本进行向量化,切换模型时会重新生成嵌入。 点击保存并启用时,该设置会立即生效,系统将对所有已保存的标注利用 Embedding 模型生成嵌入保存。

    标注回复参数设置

    {'Header 1': '标注回复', 'Header 3': '在会话调试页添加标注'} 你可以在调试与预览页面直接在模型回复信息上添加或编辑标注。

    添加标注回复

    编辑成你需要的高质量回复并保存。

    编辑标注回复

    再次输入同样的用户问题,系统将使用已保存的标注直接回复用户问题。

    通过已保存的标注回复用户问题

    {'Header 1': '标注回复', 'Header 3': '日志与标注中开启标注回复'} 通过进入“应用构建->日志与标注->标注”开启标注回复开关:

    日志与标注中开启标注回复

    {'Header 1': '标注回复', 'Header 3': '在标注后台设置标注回复参数'} 标注回复可设置的参数包括:Score 阈值 和 Embedding 模型 **Score 阈值**:用于设置标注回复的匹配相似度阈值,只有高于阈值分数的标注会被召回。 **Embedding 模型**:用于对标注文本进行向量化,切换模型时会重新生成嵌入。

    设置标注回复参数

    {'Header 1': '标注回复', 'Header 3': '批量导入标注问答对'} 在批量导入功能内,你可以下载标注导入模板,按模版格式编辑标注问答对,编辑好后在此批量导入。

    批量导入标注问答对

    {'Header 1': '标注回复', 'Header 3': '批量导出标注问答对'} 通过标注批量导出功能,你可以一次性导出系统内已保存的所有标注问答对。

    批量导出标注问答对

    {'Header 1': '标注回复', 'Header 3': '查看标注回复命中历史'} 在标注命中历史功能内,你可以查看所有命中该条标注的编辑历史、命中的用户问题、回复答案、命中来源、匹配相似分数、命中时间等信息,你可以根据这些系统信息持续改进你的标注内容。

    查看标注回复命中历史

    {'Header 1': '应用发布'} 调试完成之后点击右上角的「发布」可以将该工作流保存并快速发布成为不同类型的应用。
    对话型应用支持发布为: * 直接运行 * 嵌入网站 * 访问 API 工作流应用支持发布为: * 直接运行 * 批处理 * 访问 API * 发布为工具 你也可以点击 **恢复** 预览上一次发布的应用版本,确认恢复将会使用上一次发布的工作流版本覆盖当前的工作流版本。 {'Header 1': '工作流', 'Header 3': '基本介绍'} 工作流通过将复杂的任务分解成较小的步骤(节点)降低系统复杂度,减少了对提示词技术和模型推理能力的依赖,提高了 LLM 应用面向复杂任务的性能,提升了系统的可解释性、稳定性和容错性。 Dify 工作流分为两种类型: * **Chatflow**:面向对话类情景,包括客户服务、语义搜索、以及其他需要在构建响应时进行多步逻辑的对话式应用程序。 * **Workflow**:面向自动化和批处理情景,适合高质量翻译、数据分析、内容生成、电子邮件自动化等应用程序。
    为解决自然语言输入中用户意图识别的复杂性,Chatflow 提供了问题理解类节点。相对于 Workflow 增加了 Chatbot 特性的支持,如:对话历史(Memory)、标注回复、Answer 节点等。 {'Header 1': '工作流', 'Header 3': '基本介绍'} 为解决自动化和批处理情景中复杂业务逻辑,工作流提供了丰富的逻辑节点,如代码节点、IF/ELSE 节点、模板转换、迭代节点等,除此之外也将提供定时和事件触发的能力,方便构建自动化流程。 {'Header 1': '工作流', 'Header 3': '常见案例'} * 客户服务 通过将 LLM 集成到您的客户服务系统中,您可以自动化回答常见问题,减轻支持团队的工作负担。 LLM 可以理解客户查询的上下文和意图,并实时生成有帮助且准确的回答。 * 内容生成 无论您需要创建博客文章、产品描述还是营销材料,LLM 都可以通过生成高质量内容来帮助您。只需提供一个大纲或主题,LLM将利用其广泛的知识库来制作引人入胜、信息丰富且结构良好的内容。 * 任务自动化 可以与各种任务管理系统集成,如 Trello、Slack、Lark、以自动化项目和任务管理。通过使用自然语言处理,LLM 可以理解和解释用户输入,创建任务,更新状态和分配优先级,无需手动干预。 * 数据分析和报告 可以用于分析大型数据集并生成报告或摘要。通过提供相关信息给 LLM,它可以识别趋势、模式和洞察力,将原始数据转化为可操作的智能。对于希望做出数据驱动决策的企业来说,这尤其有价值。 * 邮件自动化处理 {'Header 1': '工作流', 'Header 3': '常见案例'} * 邮件自动化处理 LLM 可以用于起草电子邮件、社交媒体更新和其他形式的沟通。通过提供简要的大纲或关键要点,LLM 可以生成一个结构良好、连贯且与上下文相关的信息。这样可以节省大量时间,并确保您的回复清晰和专业。 {'Header 1': '工作流', 'Header 3': '如何开始'} * 从一个空白的工作流开始构建或者使用系统模版帮助你开始; * 熟悉基础操作,包括在画布上创建节点、连接和配置节点、调试工作流、查看运行历史等; * 保存并发布一个工作流; * 在已发布应用中运行或者通过 API 调用工作流; {'Header 1': '导出/导入模板'} 你可以在工作室内导出/导入应用模板为 YAML 格式的 DSL 文件与你的团队成员分享应用。 在工作室应用列表内导入 DSL 文件:
    在工作室应用列表内导出 DSL 文件:
    在工作流编排页导出 DSL 文件:
    {'Header 1': '关键概念', 'Header 3': '节点'} **节点是工作流的关键构成**,通过连接不同功能的节点,执行工作流的一系列操作。 工作流的核心节点请查看[节点说明](node/)。 *** {'Header 1': '关键概念', 'Header 3': '变量'} **变量用于串联工作流内前后节点的输入与输出**,实现流程中的复杂处理逻辑。 ![](../../../img/zh-variables.png) * 工作流需要定义启动执行变量,如聊天机器人需要定义一个输入变量 `sys.query`; * 节点一般需要定义输入变量,如定义问题分类器的输入变量为 `sys.query`; * 引用变量时只可引用流程上游节点的变量; * 为避免变量名重复,节点命名不可重复; * 节点的输出变量一般为系统固定变量,不可编辑。 {'Header 1': '关键概念', 'Header 3': '环境变量'} **环境变量用于保护工作流内所涉及的敏感信息**,例如运行工作流时所涉及的 API 密钥、数据库密码等。它们被存储在工作流程中,而不是代码中,以便在不同环墋中共享。 ![](../../../img/zh-env-variables.png) 支持以下三种数据类型: - String 字符串 - Number 数字 - Secret 密钥 环境变量拥有以下特性: * 环境变量可在大部分节点内全局引用; * 环境变量命名不可重复; * 节点的输出变量一般为只读变量,不可写入; *** {'Header 1': '关键概念', 'Header 3': 'Chatflow 和 Workflow '} **应用场景** * **Chatflow**:面向对话类情景,包括客户服务、语义搜索、以及其他需要在构建响应时进行多步逻辑的对话式应用程序。 * **Workflow**:面向自动化和批处理情景,适合高质量翻译、数据分析、内容生成、电子邮件自动化等应用程序。 **使用入口**

    Chatflow 入口

    Workflow 入口

    **可用节点差异** 1. End 节点属于 Workflow 的结束节点,仅可在流程结束时选择。 2. Answer 节点属于 Chatflow ,用于流式输出文本内容,并支持在流程中间步骤输出。 {'Header 1': '关键概念', 'Header 3': 'Chatflow 和 Workflow '} 2. Answer 节点属于 Chatflow ,用于流式输出文本内容,并支持在流程中间步骤输出。 3. Chatflow 内置聊天记忆(Memory),用于存储和传递多轮对话的历史消息,可在 LLM 、问题分类等节点内开启,Workflow 无 Memory 相关配置,无法开启。 4. Chatflow 的开始节点内置变量包括:`sys.query`,`sys.files`,`sys.conversation_id`,`sys.user_id`。Workflow 的开始节点内置变量包括:`sys.files`,`sys_id` {'Header 1': '单步调试'} 工作流支持节点的单步调试,在单步调试中你可以重复测试当前节点的执行是否符合预期。
    单步测试运行后可以查看运行状态、输入/输出、元数据信息。
    {'Header 1': '运行历史'} 在「运行历史」中可以查看当前工作流历史调试的运行结果和日志信息。
    {'Header 1': '对话/运行日志'} 点击「查看日志—详情」可以在详情中查看运行总览信息、输入/输出 、元数据信息等。
    点击「查看日志-追踪」可以查看工作流完整运行过程各节点的输入/输出、Token 消耗、运行时长等。
    {'Header 1': '检查清单'} 在进入调试运行之前,你可以在检查清单内检查是否有未完成配置或者未连线的节点。
    {'Header 1': '预览与运行'} Dify Workflow 提供了一套完整的运行调试功能,在对话型应用中点击「预览」进入调试模式。
    在工作流应用中点击「运行」进入调试模式。
    进入调试模式内在界面右侧调试已配置好的工作流。
    {'Header 1': '模板转换', 'Header 3': '定义'} 允许借助 Jinja2 的 Python 模板语言灵活地进行数据转换、文本处理等。 {'Header 1': '模板转换', 'Header 3': '什么是 Jinja?'} > Jinja is a fast, expressive, extensible templating engine. > > Jinja 是一个快速、表达力强、可扩展的模板引擎。 —— [https://jinja.palletsprojects.com/en/3.1.x/](https://jinja.palletsprojects.com/en/3.1.x/) {'Header 1': '模板转换', 'Header 3': '场景'} 模板节点允许你借助 Jinja2 这一强大的 Python 模板语言,在工作流内实现轻量、灵活的数据转换,适用于文本处理、JSON 转换等情景。例如灵活地格式化并合并来自前面步骤的变量,创建出单一的文本输出。这非常适合于将多个数据源的信息汇总成一个特定格式,满足后续步骤的需求。 **示例1:**将多个输入(文章标题、介绍、内容)拼接为完整文本

    拼接文本

    **示例2:**将知识检索节点获取的信息及其相关的元数据,整理成一个结构化的 Markdown 格式 {% code fullWidth="false" %} ```Plain {% raw %} {% for item in chunks %} ### Chunk {{ loop.index }}. {'Header 1': '模板转换', 'Header 3': '场景'} ### Chunk {{ loop.index }}. ### Similarity: {{ item.metadata.score | default('N/A') }} {'Header 1': '模板转换', 'Header 3': '场景'} #### {{ item.title }} ##### Content {{ item.content | replace('\n', '\n\n') }} --- {% endfor %} {% endraw %} ``` {% endcode %}

    知识检索节点输出转换为 Markdown

    你可以参考 Jinja 的[官方文档](https://jinja.palletsprojects.com/en/3.1.x/templates/),创建更为复杂的模板来执行各种任务。 {'Header 1': 'HTTP 请求', 'Header 3': '1 定义'} 允许通过 HTTP 协议发送服务器请求,适用于获取外部数据、webhook、生成图片、下载文件等情景。它让你能够向指定的网络地址发送定制化的 HTTP 请求,实现与各种外部服务的互联互通。 该节点支持常见的 HTTP 请求方法: * **GET**,用于请求服务器发送某个资源。 * **POST**,用于向服务器提交数据,通常用于提交表单或上传文件。 * **HEAD**,类似于 GET 请求,但服务器不返回请求的资源主体,只返回响应头。 * **PATCH**,用于在请求-响应链上的每个节点获取传输路径。 * **PUT**,用于向服务器上传资源,通常用于更新已存在的资源或创建新的资源。 * **DELETE**,用于请求服务器删除指定的资源。 你可以通过配置 HTTP 请求的包括 URL、请求头、查询参数、请求体内容以及认证信息等。 {'Header 1': 'HTTP 请求', 'Header 3': '1 定义'}

    HTTP 请求配置

    *** {'Header 1': 'HTTP 请求', 'Header 3': '2 场景'} 这个节点的一个实用特性是能够根据场景需要,在请求的不同部分动态插入变量。比如在处理客户评价请求时,你可以将用户名或客户ID、评价内容等变量嵌入到请求中,以定制化自动回复信息或获取特定客户信息并发送相关资源至特定的服务器。

    客户评价分类

    HTTP 请求的返回值包括响应体、状态码、响应头和文件。值得注意的是,如果响应中包含了文件(目前仅支持图片类型),这个节点能够自动将文件保存下来,供流程后续步骤使用。这样的设计不仅提高了处理效率,也使得处理带有文件的响应变得简单直接。 {'Header 1': '节点说明'} **节点是工作流中的关键构成**,通过连接不同功能的节点,执行工作流的一系列操作。 {'Header 1': '节点说明', 'Header 3': '核心节点'}
    开始(Start)定义一个 workflow 流程启动的初始参数。
    结束(End)定义一个 workflow 流程结束的最终输出内容。
    回复(Answer)定义一个 Chatflow 流程中的回复内容。
    大语言模型(LLM)调用大语言模型回答问题或者对自然语言进行处理。
    知识检索(Knowledge Retrieval)从知识库中检索与用户问题相关的文本内容,可作为下游 LLM 节点的上下文。
    问题分类(Question Classifier)通过定义分类描述,LLM 能够根据用户输入选择与之相匹配的分类。
    条件分支(IF/ELSE)允许你根据 if/else 条件将 workflow 拆分成两个分支。
    代码执行(Code)运行 Python / NodeJS 代码以在工作流程中执行数据转换等自定义逻辑。
    模板转换(Template)允许借助 Jinja2 的 Python 模板语言灵活地进行数据转换、文本处理等。
    变量聚合(Variable {'Header 1': '节点说明', 'Header 3': '核心节点'} href="variable_assigner.md">变量聚合(Variable Aggregator)将多路分支的变量聚合为一个变量,以实现下游节点统一配置。
    参数提取器(Parameter Extractor)利用 LLM 从自然语言推理并提取结构化参数,用于后置的工具调用或 HTTP 请求。
    迭代(Iteration)对列表对象执行多次步骤直至输出所有结果。
    HTTP 请求(HTTP Request)允许通过 HTTP {'Header 1': '节点说明', 'Header 3': '核心节点'} 请求(HTTP Request)允许通过 HTTP 协议发送服务器请求,适用于获取外部检索结果、webhook、生成图片等情景。
    工具(Tools)允许在工作流内调用 Dify 内置工具、自定义工具、子工作流等。
    {'Header 1': '直接回复', 'Header 3': '定义'} 定义一个 Chatflow 流程中的回复内容。 你可以在文本编辑器中自由定义回复格式,包括自定义一段固定的文本内容、使用前置步骤中的输出变量作为回复内容、或者将自定义文本与变量组合后回复。 可随时加入节点将内容流式输出至对话回复,支持所见即所得配置模式并支持图文混排,如: 1. 输出 LLM 节点回复内容 2. 输出生成图片 3. 输出纯文本 **示例1:**输出纯文本
    **示例2:**输出图片+LLM回复 {'Header 1': '直接回复', 'Header 3': '定义'} **示例2:**输出图片+LLM回复
    {% hint style="info" %} 直接回复节点可以不作为最终的输出节点,作为流程过程节点时,可以在中间步骤流式输出结果。 {% endhint %} {'Header 1': '知识检索', 'Header 3': '1 定义'} 从知识库中检索与用户问题相关的文本内容,可作为下游 LLM 节点的上下文来使用。 *** {'Header 1': '知识检索', 'Header 3': '2 场景'} 常见情景:构建基于外部数据/知识的 AI 问答系统(RAG)。了解更多关于 RAG 的[基本概念](../../../learn-more/extended-reading/retrieval-augment/)。 下图为一个最基础的知识库问答应用示例,该流程的执行逻辑为:知识库检索作为 LLM 节点的前置步骤,在用户问题传递至 LLM 节点之前,先在知识检索节点内将匹配用户问题最相关的文本内容并召回,随后在 LLM 节点内将用户问题与检索到的上下文一同作为输入,让 LLM 根据检索内容来回复问题。

    知识库问答应用示例

    *** {'Header 1': '知识检索', 'Header 3': '3 如何配置'}

    知识检索配置

    **配置流程:** 1. 选择查询变量,用于作为输入来检索知识库中的相关文本分段,在常见的对话类应用中一般将开始节点的 `sys.query` 作为查询变量; 2. 选择需要查询的知识库,可选知识库需要在 Dify 知识库内预先[创建](../../knowledge-base/create\_knowledge\_and\_upload\_documents.md#id-1-chuang-jian-zhi-shi-ku); {'Header 1': '知识检索', 'Header 3': '3 如何配置'} 3. 配置[召回模式](../../../learn-more/extended-reading/retrieval-augment/retrieval.md)和[知识库设置](../../knowledge-base/knowledge\_and\_documents\_maintenance.md#id-8-zhi-shi-ku-she-zhi); 4. 连接并配置下游节点,一般为 LLM 节点; **输出变量**

    输出变量

    知识检索的输出变量 `result` 为从知识库中检索到的相关文本分段。其变量数据结构中包含了分段内容、标题、链接、图标、元数据信息。 **配置下游节点** {'Header 1': '知识检索', 'Header 3': '3 如何配置'} **配置下游节点** 在常见的对话类应用中,知识库检索的下游节点一般为 LLM 节点,知识检索的**输出变量** `result` 需要配置在 LLM 节点中的 **上下文变量** 内关联赋值。关联后你可以在提示词的合适位置插入 **上下文变量**。 {% hint style="info" %} 上下文变量是 LLM 节点内定义的特殊变量类型,用于在提示词内插入外部检索的文本内容。 {% endhint %} 当用户提问时,若在知识检索中召回了相关文本,文本内容会作为上下文变量中的值填入提示词,提供 LLM 回复问题;若未在知识库检索中召回相关的文本,上下文变量值为空,LLM 则会直接回复用户问题。

    配置下游 LLM 节点

    {'Header 1': '知识检索', 'Header 3': '3 如何配置'} 该变量除了可以作为 LLM 回复问题时的提示词上下文作为外部知识参考引用,另外由于其数据结构中包含了分段引用信息,同时可以支持应用端的 [**引用与归属**](../../knowledge-base/retrieval\_test\_and\_citation.md#id-2-yin-yong-yu-gui-shu) 功能。 {'Header 1': '迭代', 'Header 3': '定义'} 对数组执行多次步骤直至输出所有结果。 迭代步骤在列表中的每个条目(item)上执行相同的步骤。使用迭代的条件是确保输入值已经格式化为列表对象。迭代节点允许 AI 工作流处理更复杂的处理逻辑,迭代节点是循环节点的友好版本,它在自定义程度上做出了一些妥协,以便非技术用户能够快速入门。 *** {'Header 1': '迭代', 'Header 3': '场景 '} #### **示例1:长文章迭代生成器**

    长故事生成器

    1. 在 **开始节点** 内输入故事标题和大纲 2. 使用 **代码节点** 从用户输入中提取出完整内容 3. 使用 **参数提取节点** 将完整内容转换成数组格式 4. 通过 **迭代节点** 包裹的 **LLM 节点** 循环多次生成各章节内容 5. 将 **直接回复** 节点添加在迭代节点内部,实现在每轮迭代生成之后流式输出 **具体配置步骤** 1. 在 **开始节点** 配置故事标题(title)和大纲(outline);

    开始节点配置

    {'Header 1': '迭代', 'Header 3': '场景 '} 1. 通过 **Jinja-2 模板节点** 将故事标题与大纲转换为完整文本;

    模板节点

    3. 通过 **参数提取节点**,将故事文本转换成为数组(Array)结构。提取参数为 `sections` ,参数类型为 `Array[Object]`

    参数提取

    {% hint style="info" %} 参数提取效果受模型推理能力和指令影响,使用推理能力更强的模型,在**指令**内增加示例可以提高参数提取的效果。 {% endhint %} {'Header 1': '迭代', 'Header 3': '场景 '} {% endhint %} 4. 将数组格式的故事大纲作为迭代节点的输入,在迭代节点内部使用 **LLM 节点** 进行处理

    配置迭代节点

    在 LLM 节点内配置输入变量 `GenerateOverallOutline/output` 和 `Iteration/item`

    配置 LLM 节点

    {% hint style="info" %} 迭代的内置变量:`items[object]` 和 `index[number]` `items[object] 代表以每轮迭代的输入条目;` {'Header 1': '迭代', 'Header 3': '场景 '} `items[object] 代表以每轮迭代的输入条目;` `index[number] 代表当前迭代的轮次;` {% endhint %} 5. 在迭代节点内部配置 **直接回复节点** ,可以实现在每轮迭代生成之后流式输出。

    配置 Answer 节点

    6. 完整调试和预览

    按故事章节多轮迭代生成

    #### **示例 2:长文章迭代生成器(另一种编排方式)** {'Header 1': '迭代', 'Header 3': '场景 '} #### **示例 2:长文章迭代生成器(另一种编排方式)**
    * 在 **开始节点** 内输入故事标题和大纲 * 使用 **LLM 节点** 生成文章小标题,以及小标题对应的内容 * 使用 **代码节点** 将完整内容转换成数组格式 * 通过 **迭代节点** 包裹的 **LLM 节点** 循环多次生成各章节内容 * 使用 **模板转换** 节点将迭代节点输出的字符串数组转换为字符串 * 在最后添加 **直接回复节点** 将转换后的字符串直接输出 {'Header 1': '迭代', 'Header 3': '什么是数组内容'} 列表是一种特定的数据类型,其中的元素用逗号分隔,以 `[` 开头,以 `]` 结尾。例如: **数字型:** ``` [0,1,2,3,4,5] ``` **字符串型:** ``` ["monday", "Tuesday", "Wednesday", "Thursday"] ``` **JSON 对象:** ``` [ { "name": "Alice", "age": 30, "email": "alice@example.com" }, { "name": "Bob", "age": 25, "email": "bob@example.com" }, { "name": "Charlie", "age": 35, "email": "charlie@example.com" } ] ``` *** {'Header 1': '迭代', 'Header 3': '支持返回数组的节点'} * 代码节点 * 参数提取 * 知识库检索 * 迭代 * 工具 * HTTP 请求 {'Header 1': '迭代', 'Header 3': '如何获取数组格式的内容'} **使用 CODE 节点返回**

    code 节点输出 array

    **使用 参数提取 节点返回**

    参数提取节点输出 array

    {'Header 1': '迭代', 'Header 3': '如何将数组转换为文本'} 迭代节点的输出变量为数组格式,无法直接输出。你可以使用一个简单的步骤将数组转换回文本。 **使用代码节点转换**

    代码节点转换

    ```python def main(articleSections: list): data = articleSections return { "result": "\n".join(data) } ``` **使用模板节点转换**

    模板节点转换

    ```django {'Header 1': '迭代', 'Header 3': '如何将数组转换为文本'} ```django {{ articleSections | join("\n") }} ``` {'Header 1': 'LLM', 'Header 3': '定义'} 调用大语言模型回答问题或者处理自然语言。

    LLM 节点

    *** {'Header 1': 'LLM', 'Header 3': '场景'} LLM 是 Chatflow/Workflow 的核心节点,利用大语言模型的对话/生成/分类/处理等能力,根据给定的提示词处理广泛的任务类型,并能够在工作流的不同环节使用。 * **意图识别**,在客服对话情景中,对用户问题进行意图识别和分类,导向下游不同的流程。 * **文本生成**,在文章生成情景中,作为内容生成的节点,根据主题、关键词生成符合的文本内容。 * **内容分类**,在邮件批处理情景中,对邮件的类型进行自动化分类,如咨询/投诉/垃圾邮件。 * **文本转换**,在文本翻译情景中,将用户提供的文本内容翻译成指定语言。 * **代码生成**,在辅助编程情景中,根据用户的要求生成指定的业务代码,编写测试用例。 * **RAG**,在知识库问答情景中,将检索到的相关知识和用户问题重新组织回复问题。 * **图片理解,**使用 vision 能力的多模态模型,能对图像内的信息进行理解和问答。 选择合适的模型,编写提示词,你可以在 Chatflow/Workflow 中构建出强大、可靠的解决方案。 *** {'Header 1': 'LLM', 'Header 3': '如何配置'}

    LLM 节点配置-选择模型

    **配置步骤:** 1. **选择模型**,Dify 提供了全球主流模型的[支持](../../../getting-started/readme/model-providers.md),包括 OpenAI 的 GPT 系列、Anthropic 的 Claude 系列、Google 的 Gemini 系列等,选择一个模型取决于其推理能力、成本、响应速度、上下文窗口等因素,你需要根据场景需求和任务类型选择合适的模型。 2. **配置模型参数**,模型参数用于控制模型的生成结果,例如温度、TopP,最大标记、回复格式等,为了方便选择系统同时提供了 3 套预设参数:创意,平衡和精确。 3. **编写提示词**,LLM 节点提供了一个易用的提示词编排页面,选择聊天模型或补全模型,会显示不同的提示词编排结构。 {'Header 1': 'LLM', 'Header 3': '如何配置'} 4. **高级设置**,可以开关记忆,设置记忆窗口,使用 Jinja-2 模版语言来进行更复杂的提示词等。 {% hint style="info" %} 如果你是初次使用 Dify ,在 LLM 节点选择模型之前,需要在 **系统设置—模型供应商** 内提前完成[模型配置](../../model-configuration/)。 {% endhint %} #### **编写提示词** 在 LLM 节点内,你可以自定义模型输入提示词。如果选择聊天模型(Chat model),你可以自定义系统提示词(SYSTEM)/用户(USER)/助手(ASSISTANT)三部分内容。
    **提示生成器** 如果在编写系统提示词(SYSTEM)时没有好的头绪,也可以使用提示生成器功能,借助 AI 能力快速生成适合实际业务场景的提示词。 {'Header 1': 'LLM', 'Header 3': '如何配置'} ![](../../../../img/zh-node-llm-prompt-generator.png) 在提示词编辑器中,你可以通过输入**“/”**或者**“{”**呼出**变量插入菜单**,将**特殊变量块**或者**上游节点变量**插入到提示词中作为上下文内容。

    呼出变量插入菜单

    *** {'Header 1': 'LLM', 'Header 3': '特殊变量说明'} **上下文变量** 上下文变量是 LLM 节点内定义的特殊变量类型,用于在提示词内插入外部检索的文本内容。

    上下文变量

    在常见的知识库问答应用中,知识库检索的下游节点一般为 LLM 节点,知识检索的**输出变量** `result` 需要配置在 LLM 节点中的 **上下文变量** 内关联赋值。关联后在提示词的合适位置插入 **上下文变量** ,可以将外部检索到的知识插入到提示词中。 该变量除了可以作为 LLM 回复问题时的提示词上下文作为外部知识引入,由于其数据结构中包含了分段引用信息,同时可以支持应用端的 [**引用与归属**](../../knowledge-base/retrieval\_test\_and\_citation.md#id-2-yin-yong-yu-gui-shu) 功能。 {% hint style="info" %} {'Header 1': 'LLM', 'Header 3': '特殊变量说明'} {% hint style="info" %} 若上下文变量关联赋值的是上游节点的普通变量,例如开始节点的字符串类型变量,则上下文的变量同样可以作为外部知识引入,但 **引用与归属** 功能将会失效。 {% endhint %} **会话历史** 为了在文本补全类模型(例如 gpt-3.5-turbo-Instruct)内实现聊天型应用的对话记忆,Dify 在原[提示词专家模式(已下线)](../../../learn-more/extended-reading/prompt-engineering/prompt-engineering-1/)内设计了会话历史变量,该变量沿用至 Chatflow 的 LLM 节点内,用于在提示词中插入 AI 与用户之间的聊天历史,帮助 LLM 理解对话上文。 {% hint style="info" %} 会话历史变量应用并不广泛,仅在 Chatflow 中选择文本补全类模型时可以插入使用。 {% endhint %} {'Header 1': 'LLM', 'Header 3': '特殊变量说明'} {% endhint %}

    插入会话历史变量

    *** {'Header 1': 'LLM', 'Header 3': '高级功能'} **记忆:**开启记忆后问题分类器的每次输入将包含对话中的聊天历史,以帮助 LLM 理解上文,提高对话交互中的问题理解能力。 **记忆窗口:**记忆窗口关闭时,系统会根据模型上下文窗口动态过滤聊天历史的传递数量;打开时用户可以精确控制聊天历史的传递数量(对数)。 **对话角色名设置:**由于模型在训练阶段的差异,不同模型对于角色名的指令遵循程度不同,如 Human/Assistant,Human/AI,人类/助手等等。为适配多模型的提示响应效果,系统提供了对话角色名的设置,修改对话角色名将会修改会话历史的角色前缀。 **Jinja-2 模板:**LLM 的提示词编辑器内支持 Jinja-2 模板语言,允许你借助 Jinja2 这一强大的 Python 模板语言,实现轻量级数据转换和逻辑处理,参考[官方文档](https://jinja.palletsprojects.com/en/3.1.x/templates/)。 {'Header 1': '代码执行', 'Header 2': '目录'} - [介绍](#介绍) - [使用场景](#使用场景) - [本地部署](#本地部署) - [安全策略](#安全策略) {'Header 1': '代码执行', 'Header 2': '介绍'} 代码节点支持运行 Python / NodeJS 代码以在工作流程中执行数据转换。它可以简化您的工作流程,适用于Arithmetic、JSON transform、文本处理等情景。 该节点极大地增强了开发人员的灵活性,使他们能够在工作流程中嵌入自定义的 Python 或 Javascript 脚本,并以预设节点无法达到的方式操作变量。通过配置选项,你可以指明所需的输入和输出变量,并撰写相应的执行代码:
    {'Header 1': '代码执行', 'Header 2': '配置'} 如果您需要在代码节点中使用其他节点的变量,您需要在`输入变量`中定义变量名,并引用这些变量,可以参考[变量引用](../key_concept.md#变量)。 {'Header 1': '代码执行', 'Header 2': '使用场景'} 使用代码节点,您可以完成以下常见的操作: {'Header 1': '代码执行', 'Header 2': '使用场景', 'Header 3': '结构化数据处理'} 在工作流中,经常要面对非结构化的数据处理,如JSON字符串的解析、提取、转换等。最典型的例子就是HTTP节点的数据处理,在常见的API返回结构中,数据可能会被嵌套在多层JSON对象中,而我们需要提取其中的某些字段。代码节点可以帮助您完成这些操作,下面是一个简单的例子,它从HTTP节点返回的JSON字符串中提取了`data.name`字段: ```python def main(http_response: str) -> str: import json data = json.loads(http_response) return { # 注意在输出变量中声明result 'result': data['data']['name'] } ``` {'Header 1': '代码执行', 'Header 2': '使用场景', 'Header 3': '数学计算'} 当工作流中需要进行一些复杂的数学计算时,也可以使用代码节点。例如,计算一个复杂的数学公式,或者对数据进行一些统计分析。下面是一个简单的例子,它计算了一个数组的平方差: ```python def main(x: list) -> float: return { # 注意在输出变量中声明result 'result' : sum([(i - sum(x) / len(x)) ** 2 for i in x]) / len(x) } ``` {'Header 1': '代码执行', 'Header 2': '使用场景', 'Header 3': '拼接数据'} 有时,也许您需要拼接多个数据源,如多个知识检索、数据搜索、API调用等,代码节点可以帮助您将这些数据源整合在一起。下面是一个简单的例子,它将两个知识库的数据合并在一起: ```python def main(knowledge1: list, knowledge2: list) -> list: return { # 注意在输出变量中声明result 'result': knowledge1 + knowledge2 } ``` {'Header 1': '代码执行', 'Header 2': '本地部署'} 如果您是本地部署的用户,您需要启动一个沙盒服务,它会确保恶意代码不会被执行,同时,启动该服务需要使用Docker服务,您可以在[这里](https://github.com/langgenius/dify/tree/main/docker/docker-compose.middleware.yaml)找到Sandbox服务的具体信息,您也可以直接通过`docker-compose`启动服务: ```bash docker-compose -f docker-compose.middleware.yaml up -d ``` > 如果您的系统安装了 Docker Compose V2 而不是 V1,请使用 `docker compose` 而不是 `docker-compose`。通过`$ docker compose version`检查这是否为情况。在[这里](https://docs.docker.com/compose/#compose-v2-and-the-new-docker-compose-command)阅读更多信息。 {'Header 1': '代码执行', 'Header 2': '限制'} 无论是Python还是Javascript,它们的执行环境都被严格隔离(沙箱化),以确保安全性。这意味着开发者不能使用那些消耗大量系统资源或可能引发安全问题的功能,如直接访问文件系统、进行网络请求或执行操作系统级别的命令。这些限制保证了代码的安全执行,同时避免了对系统资源的过度消耗。 {'Header 1': '结束', 'Header 3': '1 定义'} 定义一个工作流程结束的最终输出内容。每一个工作流在完整执行后都需要至少一个结束节点,用于输出完整执行的最终结果。 结束节点为流程终止节点,后面无法再添加其他节点,工作流应用中只有运行到结束节点才会输出执行结果。若流程中出现条件分叉,则需要定义多个结束节点。 结束节点需要声明一个或多个输出变量,声明时可以引用任意上游节点的输出变量。 {% hint style="info" %} Chatflow 内不支持结束节点 {% endhint %} *** {'Header 1': '结束', 'Header 3': '2 场景'} 在以下[长故事生成工作流](iteration.md#shi-li-2-chang-wen-zhang-die-dai-sheng-cheng-qi-ling-yi-zhong-bian-pai-fang-shi)中,结束节点声明的变量 `Output` 为上游代码节点的输出,即该工作流会在 Code3 节点执行完成之后结束,并输出 Code3 的执行结果。

    结束节点-长故事生成示例

    **单路执行示例:**
    **多路执行示例:** {'Header 1': '结束', 'Header 3': '2 场景'} **多路执行示例:**
    {'Header 1': '问题分类', 'Header 3': '1 **定义**'} 通过定义分类描述,问题分类器能够根据用户输入推理与之相匹配的分类并输出分类结果。 *** {'Header 1': '问题分类', 'Header 3': '**2 场景**'} 常见的使用情景包括**客服对话意图分类、产品评价分类、邮件批量分类**等。 在一个典型的产品客服问答场景中,问题分类器可以作为知识库检索的前置步骤,对用户输入问题意图进行分类处理,分类后导向下游不同的知识库查询相关的内容,以精确回复用户的问题。 下图为产品客服场景的示例工作流模板:
    在该场景中我们设置了 3 个分类标签/描述: * 分类 1 :**与售后相关的问题** * 分类 2:**与产品操作使用相关的问题** * 分类 3 :**其他问题** 当用户输入不同的问题时,问题分类器会根据已设置的分类标签/描述自动完成分类: * “**iPhone 14 如何设置通讯录联系人?**” —> “**与产品操作使用相关的问题**” {'Header 1': '问题分类', 'Header 3': '**2 场景**'} * “**保修期限是多久?**” —> “**与售后相关的问题**” * “**今天天气怎么样?**” —> “**其他问题**” *** {'Header 1': '问题分类', 'Header 3': '3 如何配置'}
    **配置步骤:** 1. **选择输入变量**,指用于分类的输入内容,客服问答场景下一般为用户输入的问题 `sys.query`; 2. **选择推理模型**,问题分类器基于大语言模型的自然语言分类和推理能力,选择合适的模型将有助于提升分类效果; 3. **编写分类标签/描述**,你可以手动添加多个分类,通过编写分类的关键词或者描述语句,让大语言模型更好的理解分类依据。 4. **选择分类对应的下游节点,**问题分类节点完成分类之后,可以根据分类与下游节点的关系选择后续的流程路径。 #### **高级设置:** **指令:**你可以在 **高级设置-指令** 里补充附加指令,比如更丰富的分类依据,以增强问题分类器的分类能力。 {'Header 1': '问题分类', 'Header 3': '3 如何配置'} **记忆:**开启记忆后问题分类器的每次输入将包含对话中的聊天历史,以帮助 LLM 理解上文,提高对话交互中的问题理解能力。 **记忆窗口:**记忆窗口关闭时,系统会根据模型上下文窗口动态过滤聊天历史的传递数量;打开时用户可以精确控制聊天历史的传递数量(对数)。 **输出变量:** `class_name` 即分类之后输出的分类名。你可以在下游节点需要时使用分类结果变量。 {'Header 1': '开始', 'Header 3': '定义'} 为启动工作流设置初始参数。 在开始节点中,您可以自定义启动工作流的输入变量。每个工作流都需要一个开始节点。

    工作流开始节点

    开始节点支持定义四种类型输入变量: * 文本 * 段落 * 下拉选项 * 数字 * 文件(即将推出)

    配置开始节点的变量

    配置完成后,工作流在执行时将提示您提供开始节点中定义的变量值。 {'Header 1': '开始', 'Header 3': '定义'} 配置完成后,工作流在执行时将提示您提供开始节点中定义的变量值。
    {% hint style="info" %} Tip: 在Chatflow中,开始节点提供了内置系统变量:`sys.query` 和 `sys.files`。 `sys.query` 用于对话应用中的用户输入问题。 `sys.files` 用于对话中的文件上传,如上传图片,这需要与图片理解模型配合使用。 {% endhint %} {'Header 1': '条件分支', 'Header 3': '定义'} 根据 if/else/elif 条件将 workflow 拆分成多个分支。 条件分支节点有六个部分: * IF 条件:选择变量,设置条件和满足条件的值; * IF 条件判断为 `True`,执行 IF 路径; * IF 条件判断为 `False`,执行 ELSE 路径; * ELIF 条件判断为 `True`,执行 ELIF 路径; * ELIF 条件判断为 `False`,继续判断下一个 ELIF 路径或执行最后的 ELSE 路径; **条件类型** * 包含(Contains) * 不包含(Not contains) * 开始是(Start with) * 结束是(End with) * 是(Is) * 不是(Is not) * 为空(Is empty) * 不为空(Is not empty) *** {'Header 1': '条件分支', 'Header 3': '场景'}
    以**文本总结工作流**作为示例说明各个条件: * IF 条件: 选择开始节点中的 `summarystyle` 变量,条件为**包含** `技术`; * IF 条件判断为 `True`,执行 IF 路径,通过知识检索节点查询技术相关知识再到 LLM 节点回复(图中上半部分); * IF 条件判断为 `False`,但添加了 `ELIF` 条件,即 `summarystyle` 变量输入**不包含**`技术`,但 `ELIF` 条件内包含 `科技`,会检查 `ELIF` 内的条件是否为 `True`,然后执行路径内定义的步骤; * `ELIF` 内的条件为 `False`,即输入变量既不不包含 `技术`,也不包含 `科技`,继续判断下一个 ELIF 路径或执行最后的 ELSE 路径; {'Header 1': '条件分支', 'Header 3': '场景'} * IF 条件判断为 `False`,即 `summarystyle` 变量输入**不包含** `技术`,执行 ELSE 路径,通过 LLM2 节点进行回复(图中下半部分); **多重条件判断** 涉及复杂的条件判断时,可以设置多重条件判断,在条件之间设置**AND**或者**OR**,即在条件之间取**交集**或者**并集**。

    多重条件判断

    {'Header 1': '变量聚合', 'Header 3': '1 定义'} 将多路分支的变量聚合为一个变量,以实现下游节点统一配置。 变量聚合节点(原变量赋值节点)是工作流程中的一个关键节点,它负责整合不同分支的输出结果,确保无论哪个分支被执行,其结果都能通过一个统一的变量来引用和访问。这在多分支的情况下非常有用,可将不同分支下相同作用的变量映射为一个输出变量,避免下游节点重复定义。 *** {'Header 1': '变量聚合', 'Header 3': '2 场景'} 通过变量聚合,可以将诸如问题分类或条件分支等多路输出聚合为单路,供流程下游的节点使用和操作,简化了数据流的管理。 **问题分类后的多路聚合** 未添加变量聚合,分类1 和 分类 2 分支经不同的知识库检索后需要重复定义下游的 LLM 和直接回复节点。

    问题分类(无变量聚合)

    添加变量聚合,可以将两个知识检索节点的输出聚合为一个变量。

    问题分类后的多路聚合

    **IF/ELSE 条件分支后的多路聚合** {'Header 1': '变量聚合', 'Header 3': '2 场景'} **IF/ELSE 条件分支后的多路聚合**

    问题分类后的多路聚合

    {'Header 1': '变量聚合', 'Header 3': '3 格式要求'} 变量聚合器支持聚合多种数据类型,包括字符串(`String`)、数字(`Number`)、对象(`Object`)以及数组(`Array`)。 **变量聚合器只能聚合同一种数据类型的变量**。若第一个添加至变量聚合节点内的变量数据格式为 `String`,后续连线时会自动过滤可添加变量为 `String` 类型。 **聚合分组** v0.6.10 版本之后已支持聚合分组。 开启聚合分组后,变量聚合器可以聚合多组变量,各组内聚合时要求同一种数据类型。 {'Header 1': '参数提取', 'Header 3': '1 定义'} 利用 LLM 从自然语言推理并提取结构化参数,用于后置的工具调用或 HTTP 请求。 Dify 工作流内提供了丰富的[工具](../../gong-ju.md)选择,其中大多数工具的输入为结构化参数,参数提取器可以将用户的自然语言转换为工具可识别的参数,方便工具调用。 工作流内的部分节点有特定的数据格式传入要求,如[迭代](iteration.md#ding-yi)节点的输入要求为数组格式,参数提取器可以方便的实现[结构化参数的转换](iteration.md#shi-li-1-chang-wen-zhang-die-dai-sheng-cheng-qi)。 *** {'Header 1': '参数提取', 'Header 3': '2 场景'} 1. **从自然语言中提供工具所需的关键参数提取**,如构建一个简单的对话式 Arxiv 论文检索应用。 在该示例中:Arxiv 论文检索工具的输入参数要求为 **论文作者** 或 **论文编号**,参数提取器从问题“这篇论文中讲了什么内容:2405.10739”中提取出论文编号 **2405.10739**,并作为工具参数进行精确查询。

    Arxiv 论文检索工具

    2. **将文本转换为结构化数据**,如长故事迭代生成应用中,作为[迭代节点](iteration.md)的前置步骤,将文本格式的章节内容转换为数组格式,方便迭代节点进行多轮生成处理。 {'Header 1': '参数提取', 'Header 3': '2 场景'}
    3. **提取结构化数据并使用** [**HTTP 请求**](http\_request.md) ,可请求任意可访问的 URL ,适用于获取外部检索结果、webhook、生成图片等情景。 *** {'Header 1': '参数提取', 'Header 3': '3 如何配置'}
    **配置步骤** 1. 选择输入变量,一般为用于提取参数的变量输入 2. 选择模型,参数提取器的提取依靠的是 LLM 的推理和结构化生成能力 3. 定义提取参数,可以手动添加需要提取的参数,也可以**从已有工具中快捷导入** 4. 编写指令,在提取复杂的参数时,编写示例可以帮助 LLM 提升生成的效果和稳定性 **高级设置** **推理模式** 部分模型同时支持两种推理模式,通过函数/工具调用或是纯提示词的方式实现参数提取,在指令遵循能力上有所差别。例如某些模型在函数调用效果欠佳的情况下可以切换成提示词推理。 * Function Call/Tool Call * Prompt **记忆** {'Header 1': '参数提取', 'Header 3': '3 如何配置'} * Prompt **记忆** 开启记忆后问题分类器的每次输入将包含对话中的聊天历史,以帮助 LLM 理解上文,提高对话交互中的问题理解能力。 **输出变量** * 提取定义的变量 * 节点内置变量 `__is_success Number 提取是否成功` 成功时值为 1,失败时值为 0。 `__reason String` 提取错误原因 {'Header 1': '工具', 'Header 3': '定义'} 工作流内提供丰富的工具选择,工具分为三种类型: * **内置工具**,Dify 第一方提供的工具 * **自定义工具**,通过 OpenAPI/Swagger 标准格式导入或配置的工具 * **工作流**,已发布为工具的工作流 使用内置工具之前,你可能需要先给工具进行 **授权**。 若内置工具无法满足使用需求,你可以在 **Dify 菜单导航 --工具** 内先创建自定义工具。 你也可以编排一个更加复杂的工作流,并将其发布为工具。

    工具选择

    配置 Google 搜索工具检索外部知识

    {'Header 1': '工具', 'Header 3': '定义'} 配置工具节点一般分为两个步骤: 1. 对工具授权/创建自定义工具/将工作流发布为工具 2. 配置工具输入和参数 如何创建自定义工具和配置工具请参考[工具配置说明](https://docs.dify.ai/v/zh-hans/guides/tools)。 {'Header 1': '嵌入网站'} Dify 应用可以使用 iframe 嵌入到网站中。这允许你将 Dify 应用集成到你的网站、博客或任何其他网页中。 当你在网站中使用 Dify 聊天机器人气泡按钮时,你可以自定义按钮的样式、位置和其他设置。 {'Header 1': '嵌入网站', 'Header 2': '自定义 Dify 聊天机器人气泡按钮'} Dify 聊天机器人气泡按钮可以通过以下配置选项进行自定义: ```javascript window.difyChatbotConfig = { // 必填项,由 Dify 自动生成 token: 'YOUR_TOKEN', // 可选项,默认为 false isDev: false, // 可选项,当 isDev 为 true 时,默认为 '[https://dev.udify.app](https://dev.udify.app)',否则默认为 '[https://udify.app](https://udify.app)' baseUrl: 'YOUR_BASE_URL', // 可选项,可以接受除 `id` 以外的任何有效的 HTMLElement 属性,例如 `style`、`className` 等 containerProps: {}, // 可选项,是否允许拖动按钮,默认为 `false` draggable: false, // 可选项,允许拖动按钮的轴,默认为 `both`,可以是 `x`、`y`、`both` dragAxis: 'both', {'Header 1': '嵌入网站', 'Header 2': '自定义 Dify 聊天机器人气泡按钮'} dragAxis: 'both', // 可选项,在 dify 聊天机器人中设置的输入对象 inputs: { // 键是变量名 // 例如: // name: "NAME" } {'Header 1': '嵌入网站', 'Header 2': '自定义 Dify 聊天机器人气泡按钮'} }; ``` {'Header 1': '嵌入网站', 'Header 2': '覆盖默认按钮样式'} 你可以使用 CSS 变量或 `containerProps` 选项来覆盖默认按钮样式。根据 CSS 优先级使用这些方法实现自定义样式。 {'Header 1': '嵌入网站', 'Header 2': '覆盖默认按钮样式', 'Header 3': '1.修改 CSS 变量'} 支持以下 CSS 变量进行自定义: ```css /* 按钮距离底部的距离,默认为 `1rem` */ --dify-chatbot-bubble-button-bottom /* 按钮距离右侧的距离,默认为 `1rem` */ --dify-chatbot-bubble-button-right /* 按钮距离左侧的距离,默认为 `unset` */ --dify-chatbot-bubble-button-left /* 按钮距离顶部的距离,默认为 `unset` */ --dify-chatbot-bubble-button-top /* 按钮背景颜色,默认为 `#155EEF` */ --dify-chatbot-bubble-button-bg-color /* 按钮宽度,默认为 `50px` */ --dify-chatbot-bubble-button-width /* 按钮高度,默认为 `50px` */ --dify-chatbot-bubble-button-height {'Header 1': '嵌入网站', 'Header 2': '覆盖默认按钮样式', 'Header 3': '1.修改 CSS 变量'} /* 按钮边框半径,默认为 `25px` */ --dify-chatbot-bubble-button-border-radius /* 按钮盒阴影,默认为 `rgba(0, 0, 0, 0.2) 0px 4px 8px 0px)` */ --dify-chatbot-bubble-button-box-shadow /* 按钮悬停变换,默认为 `scale(1.1)` */ --dify-chatbot-bubble-button-hover-transform ``` 例如,要将按钮背景颜色更改为 #ABCDEF,请添加以下 CSS: ```css #dify-chatbot-bubble-button { --dify-chatbot-bubble-button-bg-color: #ABCDEF; } ``` {'Header 1': '嵌入网站', 'Header 2': '覆盖默认按钮样式', 'Header 3': '2.使用 `containerProps` 选项'} 使用 `style` 属性设置内联样式: ```javascript window.difyChatbotConfig = { // ... 其他配置 containerProps: { style: { backgroundColor: '#ABCDEF', width: '60px', height: '60px', borderRadius: '30px', }, // 对于较小的样式覆盖,也可以使用字符串作为 `style` 属性的值: // style: 'background-color: #ABCDEF; width: 60px;', }, } ``` 使用 `className` 属性应用 CSS 类: ```javascript window.difyChatbotConfig = { // ... 其他配置 containerProps: { className: 'dify-chatbot-bubble-button-custom my-custom-class', }, }; ``` {'Header 1': '嵌入网站', 'Header 2': '覆盖默认按钮样式', 'Header 3': '3. 传递 `inputs`'} 支持四种类型的输入: 1. **`text-input`**:接受任何值。如果输入字符串的长度超过允许的最大长度,将被截断。 2. **`paragraph`**:类似于 `text-input`,接受任何值并在字符串长度超过最大长度时截断。 3. **`number`**:接受数字或数字字符串。如果提供的是字符串,将使用 `Number` 函数将其转换为数字。 4. **`options`**:接受任何值,前提是它匹配预先配置的选项之一。 示例配置: ```javascript window.difyChatbotConfig = { // ... 其他配置 inputs: { name: 'apple', }, } ``` 注意:使用 embed.js 脚本创建 iframe 时,每个输入值将被处理——使用 GZIP 压缩并以 base64 编码——然后附加到 URL 上。 例如,处理后的输入值 URL 将如下所示: {'Header 1': '嵌入网站', 'Header 2': '覆盖默认按钮样式', 'Header 3': '3. 传递 `inputs`'} 例如,处理后的输入值 URL 将如下所示: `http://localhost/chatbot/{token}?name=H4sIAKUlmWYA%2FwWAIQ0AAACDsl7gLuiv2PQEUNAuqQUAAAA%3D`# 基于 APIs 开发 Dify 基于“**后端即服务**”理念为所有应用提供了 API,为 AI 应用开发者带来了诸多便利。通过这一理念,开发者可以直接在前端应用中获取大型语言模型的强大能力,而无需关注复杂的后端架构和部署过程。 #### 使用 Dify API 的好处 * 让前端应用直接安全地调用 LLM 能力,省去后端服务的开发过程 * 在可视化的界面中设计应用,并在所有客户端中实时生效 * 对 LLM 供应商的基础能力进行了良好封装 * 随时切换 LLM 供应商,并对 LLM 的密钥进行集中管理 * 在可视化的界面中运营你的应用,例如分析日志、标注及观察用户活跃 * 持续为应用提供更多工具能力、插件能力和数据集 #### 如何使用 {'Header 1': '嵌入网站', 'Header 2': '覆盖默认按钮样式', 'Header 3': '3. 传递 `inputs`'} * 持续为应用提供更多工具能力、插件能力和数据集 #### 如何使用 选择一个应用,在应用(Apps)左侧导航中可以找到**访问 API(API Access)**。在该页面中你可以查看 Dify 提供的 API 文档,并管理可访问 API 的凭据。 例如你是一个咨询公司的开发部分,你可以基于公司的私有数据库提供 AI 能力给终端用户或开发者,但开发者无法掌握你的数据和 AI 逻辑设计,从而使得服务可以安全、可持续的交付并满足商业目的。 {% hint style="warning" %} 在最佳实践中,API 密钥应通过后端调用,而不是直接以明文暴露在前端代码或请求中,这样可以防止你的应用被滥用或攻击。 {% endhint %} 你可以为一个应用**创建多个访问凭据**,以实现交付给不同的用户或开发者。这意味着 API 的使用者虽然使用了应用开发者提供的 AI 能力,但背后的 Promp 工程、数据集和工具能力是经封装的。 #### 文本生成型应用 {'Header 1': '嵌入网站', 'Header 2': '覆盖默认按钮样式', 'Header 3': '3. 传递 `inputs`'} #### 文本生成型应用 可用于生成高质量文本的应用,例如生成文章、摘要、翻译等,通过调用 completion-messages 接口,发送用户输入得到生成文本结果。用于生成文本的模型参数和提示词模版取决于开发者在 Dify 提示词编排页的设置。 你可以在**应用 -> 访问 API** 中找到该应用的 API 文档与范例请求。 例如,创建文本补全信息的 API 的调用示例: {% tabs %} {% tab title="cURL" %} ``` curl --location --request POST 'https://api.dify.ai/v1/completion-messages' \ --header 'Authorization: Bearer ENTER-YOUR-SECRET-KEY' \ --header 'Content-Type: application/json' \ --data-raw '{ "inputs": {}, "response_mode": "streaming", "user": "abc-123" }' ``` {'Header 1': '嵌入网站', 'Header 2': '覆盖默认按钮样式', 'Header 3': '3. 传递 `inputs`'} "user": "abc-123" }' ``` {% endtab %} {% tab title="Python" %} ```python import requests import json {'Header 1': '嵌入网站', 'Header 2': '覆盖默认按钮样式', 'Header 3': '3. 传递 `inputs`'} url = "https://api.dify.ai/v1/completion-messages" headers = { 'Authorization': 'Bearer ENTER-YOUR-SECRET-KEY', 'Content-Type': 'application/json', } data = { "inputs": {"text": 'Hello, how are you?'}, "response_mode": "streaming", "user": "abc-123" } response = requests.post(url, headers=headers, data=json.dumps(data)) {'Header 1': '嵌入网站', 'Header 2': '覆盖默认按钮样式', 'Header 3': '3. 传递 `inputs`'} print(response.text) ``` {% endtab %} {% endtabs %} #### 对话型应用 可用于大部分场景的对话型应用,采用一问一答模式与用户持续对话。要开始一个对话请调用 chat-messages 接口,通过继续传入返回的 conversation\_id 可持续保持该会话。 你可以在**应用 -> 访问 API** 中找到该应用的 API 文档与范例请求。 例如,发送对话信息的 API的调用示例: {% tabs %} {% tab title="cURL" %} ``` curl --location --request POST 'https://api.dify.ai/v1/chat-messages' \ --header 'Authorization: Bearer ENTER-YOUR-SECRET-KEY' \ --header 'Content-Type: application/json' \ --data-raw '{ "inputs": {}, "query": "eh", {'Header 1': '嵌入网站', 'Header 2': '覆盖默认按钮样式', 'Header 3': '3. 传递 `inputs`'} --data-raw '{ "inputs": {}, "query": "eh", "response_mode": "streaming", "conversation_id": "1c7e55fb-1ba2-4e10-81b5-30addcea2276" "user": "abc-123" }' {'Header 1': '嵌入网站', 'Header 2': '覆盖默认按钮样式', 'Header 3': '3. 传递 `inputs`'} ``` {% endtab %} {% tab title="Python" %} ```python import requests import json url = 'https://api.dify.ai/v1/chat-messages' headers = { 'Authorization': 'Bearer ENTER-YOUR-SECRET-KEY', 'Content-Type': 'application/json', } data = { "inputs": {}, "query": "eh", "response_mode": "streaming", "conversation_id": "1c7e55fb-1ba2-4e10-81b5-30addcea2276", "user": "abc-123" } response = requests.post(url, headers=headers, data=json.dumps(data)) {'Header 1': '嵌入网站', 'Header 2': '覆盖默认按钮样式', 'Header 3': '3. 传递 `inputs`'} print(response.json()) ``` {% endtab %} {% endtabs %} {'Header 1': '发布'} {% content-ref url="launch-your-webapp-quickly/" %} [launch-your-webapp-quickly](launch-your-webapp-quickly/) {% endcontent-ref %} {% content-ref url="embedding-in-websites.md" %} [embedding-in-websites.md](embedding-in-websites.md) {% endcontent-ref %} {% content-ref url="broken-reference" %} [Broken link](broken-reference) {% endcontent-ref %} {% content-ref url="based-on-frontend-templates.md" %} [based-on-frontend-templates.md](based-on-frontend-templates.md) {% endcontent-ref %} {'Header 1': '基于前端模版再开发'} 如果开发者是从头开发新产品或者在产品原型设计阶段,你可以使用 Dify 快速发布 AI 站点。与此同时,Dify 希望开发者能够充分自由的创造不同形式的前端应用,为此我们提供了: * **SDK**,用于在各种语言中快速接入 Dify API * **WebApp Template**,每种类型应用的 WebApp 开发脚手架 WebApp Template 是基于 MIT 协议开源的,你可以充分自由的修改并部署他们,以实现 Dify 的所有能力。或者作为你实现自己 App 的一份参考代码。 你可以在 GitHub 中找到这些 Template: * [对话型应用](https://github.com/langgenius/webapp-conversation) * [文本生成型应用](https://github.com/langgenius/webapp-text-generator) {'Header 1': '基于前端模版再开发'} 使用 WebApp 模版最快的方法就是在 GitHub 中点击「使用这个模版」,它相当于 Fork 了一个新的仓库。随后你需要配置 Dify 的 App ID 和 API Key,类似这样: ````javascript export const APP_ID = '' export const API_KEY = '' ``` More config in `config/index.ts`: ```js export const APP_INFO: AppInfo = { "title": 'Chat APP', "description": '', "copyright": '', "privacy_policy": '', "default_language": 'zh-Hans' } {'Header 1': '基于前端模版再开发'} export const isShowPrompt = true export const promptTemplate = '' ```` > App ID 可以在 App 的 URL 内获取,其中的长串英文字符为唯一的 App ID。 每一种 WebApp 模版都提供了 README 文件,内含部署方式的说明。通常,WebApp 模版都包含了一个轻后端服务,这是为了确保开发者的 API KEY 不会直接暴露给用户。 这些 WebApp 模版能够帮助你快速搭建起 AI 应用原型,并使用 Dify 的所有能力。如果你基于它们开发了自己的应用或新的模版,欢迎你与我们分享。 {'Header 1': '对话型应用'} 对话型应用采用一问一答模式与用户持续对话。对话型应用支持以下能力(请确认应用编排时有开启以下功能): * 对话前填写的变量。 * 对话的创建、置顶、删除。 * 对话开场白。 * 下一步问题建议。 * 语音转文字。 * 引用和归属 {'Header 1': '对话型应用', 'Header 3': '对话前填写的变量'} 如你在应用编排时有设置变量的填写要求,则在对话前需要按提示填写信息才可进入对话窗口:
    填写必要内容,点击 “开始对话” 按钮,开始聊天。
    移动到 AI 的回答上,可以复制会话内容,给回答 “赞” 和 “踩”。
    {'Header 1': '对话型应用', 'Header 3': '对话的创建、置顶和删除'} 点击 “新对话” 按钮开始一个新的对话。移动到一个会话上,可以对会话进行 “置顶” 和 “删除” 操作。
    {'Header 1': '对话型应用', 'Header 3': '对话开场白'} 若在应用编排时开启了「对话开场白」功能,则在创建一个新对话时 AI 应用会自动发起第一句对话:
    {'Header 1': '对话型应用', 'Header 3': '下一步问题建议'} 若在应用编排时开启了「下一步问题建议」功能,则在对话后系统自动生成 3 个相关问题建议:
    {'Header 1': '对话型应用', 'Header 3': '语音转文字'} 若在应用编排时开启了「语音转文字」功能,则在 Web 应用端的输入框看到语音输入的图标,点击图标即可语音输入转成文字: _请注意确保你使用的设备环境已经授权使用麦克风。_
    {'Header 1': '对话型应用', 'Header 3': '引用与归属'} 在应用内测试知识库效果时,你可以进入 **工作室 -- 添加功能 -- 引用归属**,打开引用归属功能。详细说明请参考[《引用与归属》](https://docs.dify.ai/v/zh-hans/guides/knowledge-base/retrieval_test_and_citation#id-2-yin-yong-yu-gui-shu)。 {'Header 1': '概览'} Web 应用是给应用使用者用的。应用开发者在 Dify 创建一个应用,就会获得一个对应的 Web 应用。Web 应用的使用者无需登陆,即可使用。Web 应用已适配不同尺寸的设备:PC,平板和手机。 Web 应用的内容和应用发布的配置一致。当修改了应用的配置,并在应用的提示词编排页点 “发布” 按钮发布后,Web 应用的内容也会根据当前应用的配置做更新。 我们可以在应用概览页开启和关闭对 Web 应用的访问,以及修改 Web 应用的站点信息: * 图标 * 名称 * 应用描述 * 界面语言 * 版权信息 * 隐私政策链接 Web 应用的功能表现取决于开发者在编排应用时是否开启该功能,例如: * 对话开场白 * 对话前填写的变量 * 下一步问题建议 * 语音转文字 * 引用和归属 * 更多类似的答案(文本型应用) * ...... 在下面的章节,我们会分别介绍 Web 应用的两种类型: * 文本生成型 * 对话型 {'Header 1': '发布为公开 Web 站点'} 使用 Dify 创建 AI 应用的一个好处在于,你可以在几分钟内就发布一个可供用户使用的 Web 应用,该应用将根据你的 Prompt 编排工作。 * 如果你使用的是自部署的开源版,该应用将运行在你的服务器上 * 如果你使用的是云服务,该应用将托管至 Udify.app *** {'Header 1': '发布为公开 Web 站点', 'Header 3': '发布 AI 站点'} 在应用概览页中,你可以找到关于AI 站点(WebApp)的卡片。只需开启 WebApp 的访问,就可以得到一个可分享可分享给用户的链接了。
    我们对以下两种应用均提供了一个漂亮的 WebApp 界面: * 文本生成型([前往预览](text-generator.md)) * 对话型([前往预览](conversation-application.md)) *** {'Header 1': '发布为公开 Web 站点', 'Header 3': '设置你的 AI 站点'} 点击 WebApp 卡片上的**设置**按钮,可以为 AI 站点配置一些选项。它们都会被最终用户所见: * 图标 * 名称 * 应用描述 * 界面语言 * 版权信息 * 隐私政策链接 * 自定义免责声明 {% hint style="info" %} 界面语言目前已支持:英文,中文,繁体中文,葡萄牙语,德语,日本语,韩语,乌克兰语,越南语。如果您需要增加更多语言,可以在 GitHub 内提交 Issue[ 寻求支持](../../../community/support.md)或者提交 PR 贡献代码。 {% endhint %} *** {'Header 1': '发布为公开 Web 站点', 'Header 3': '嵌入你的 AI 站点'} Dify 支持将你的 AI 应用嵌入到你的业务网站中,你可以使用该能力在几分钟内制作具有业务数据的官网 AI 客服、业务知识问答等应用。点击 WebApp 卡片上的嵌入按钮,复制嵌入代码,粘贴到你网站的目标位置。 * iframe 标签方式 将 iframe 代码复制到你网站用于显示 AI 应用的标签中,如 `
    `、`
    ` 等标签。 * script 标签方式 将 script 代码复制到你网站 `` 或 `` 标签中。
    例如,将 script 代码粘贴到官网的 `` 处,你将得到一个官网 AI 机器人: {'Header 1': '发布为公开 Web 站点', 'Header 3': '嵌入你的 AI 站点'}
    {'Header 1': '文本生成型应用'} 文本生成类应用是一种根据用户提供的提示,自动生成高质量文本的应用。它可以生成各种类型的文本,例如文章摘要、翻译等。 文本生成型应用支持如下功能: 1. 运行一次。 2. 批量运行。 3. 保存运行结果。 4. 生成更多类似结果。 下面我们分别来介绍。 {'Header 1': '文本生成型应用', 'Header 3': '运行一次'} 输入查询内容,点击运行按钮,右侧会生成结果,如下图所示:
    在生成的结果部分,点 “复制” 按钮可以将内容复制到剪贴板。点 “保存” 按钮可以保存内容。可以在 “已保存” 选项卡中看到保存过的内容。也可以对生成的内容点 “赞” 和 “踩”。 {'Header 1': '文本生成型应用', 'Header 3': '批量运行'} 有时,我们需要运行一个应用很多次。比如:有个 Web 应用可以根据主题来生成文章。现在要生成 100 篇不同主题的文章。那么这个任务要做 100 次,很麻烦。而且,必须等一个任务完成才能开始下一个任务。 上面的场景,用批量运行功能,操作便利(把主题录入一个 `csv` 文件,只需执行一次),也节约了生成的时间(多个任务同时运行)。使用方式如下: #### 第 1 步 进入批量运行页面 点击 “批量运行” 选项卡,则会进入批量运行页面。
    #### 第 2 步 下载模版并填写内容 点击下载模版按钮,下载模版。编辑模版,填写内容,并另存为 `.csv` 格式的文件。 {'Header 1': '文本生成型应用', 'Header 3': '批量运行'} 点击下载模版按钮,下载模版。编辑模版,填写内容,并另存为 `.csv` 格式的文件。
    #### 第 3 步 上传文件并运行
    如果需要导出生成的内容,可以点右上角的下载 “按钮” 来导出为 `csv` 文件。 **注意:** 上传的的 `csv` 文件的编码必须是 `Unicode` 的编码。否则会运行结果失败。解决方案:用 Excel,WPS 等导出为 `csv` 文件时,编码选择 `Unicode`。 {'Header 1': '文本生成型应用', 'Header 3': '保存运行结果'} 点击生成结果下面的 “保存” 按钮,可以保存运行结果。在 “已保存” 选项卡中,可以看到所有已保存的内容。
    {'Header 1': '文本生成型应用', 'Header 3': '生成更多类似结果'} 如果在应用编排时开启了 “更多类似” 的功能。在 Web 应用中可以点击 “更多类似” 的按钮来生成和当前结果相似的内容。如下图所示:
    {'Header 1': '数据分析'} **概览 -- 数据分析** 内显示了用量、活跃用户数和 LLM 调用消耗等,这使你可以持续改进应用运营的效果、活跃度、经济性。我们将逐步提供更多有用的可视化能力,请告诉我们你想要的。

    概览—数据分析

    *** **全部消息数(Total Messages)** 反映 AI 每天的互动总次数,每回答用户一个问题算一条 Message。提示词编排和调试的会话不计入。 **活跃用户数(Active Users)** 与 AI 有效互动,即有一问一答以上的唯一用户数。提示词编排和调试的会话不计入。 **平均会话互动数(Average Session Interactions)** 反映每个会话用户的持续沟通次数,如果用户与 AI 问答了 10 轮,即为 10。该指标反映了用户粘性。仅在对话型应用提供。 {'Header 1': '数据分析'} **Token 输出速度(Token Output Speed)** 每秒的 Token 输出数量,侧面反应模型的生成速率以及应用的使用频率。 **用户满意度(User Satisfaction Rate)** 每 1000 条消息的点赞数。反应了用户对回答十分满意的比例。 **Token 消耗(Token Usage)** 反映每日该应用请求语言模型的 Tokens 花费,用于成本控制。 {'Header 1': '监测'} 你可以在 **概览** 内监控、跟踪应用程序在生产环境中的性能,在数据分析仪表盘内分析生产环境中应用的使用成本、延迟、用户反馈、性能等指标,并通过持续调试、迭代不断改进你的应用程序。

    概览

    {'Header 1': '集成外部 Ops 工具', 'Header 3': '为什么需要 LLMOps 工具'} 尽管 LLM 拥有出色的推理和文本生成能力,但其内部运作机制仍然难以完全理解,这给基于 LLM 的应用开发带来了挑战。例如: * 评估输出**质量** * 推理**成本**评估 * 模型响应**延迟** * 链式调用、Agent 和工具引入的**调试复杂**性 * 复杂的用户意图理解 而 LangSmith、Langfuse 这类 LLMOps 工具,能够为 LLM 应用提供全面的追踪和深度评估能力,为开发者提供从应用的原型构建到生产、运营的完整生命周期支持。 * **原型阶段** LLM 应用在原型构建阶段通常涉及提示词测试、模型选择、RAG 检索策略和其他参数组合的快速实验。快速了解模型的执行效果对于此阶段非常重要。接入 Langfuse 可以在跟踪 dify 应用执行的每个步骤,提供清晰的可见性和调试信息,从而让开发者快速定位问题并减少调试时间。 * **测试阶段** {'Header 1': '集成外部 Ops 工具', 'Header 3': '为什么需要 LLMOps 工具'} * **测试阶段** 进入测试阶段后,需要继续收集数据以改进和提高性能。 LangSmith 能够将运行作为示例添加到数据集中,从而扩展实际场景的测试覆盖范围。这是将日志系统和评估/测试系统置于同一平台中的一个关键优势。 * **生产阶段** 进入生产环境后,开发团队还需要仔细检查应用关键数据点、增加基准数据集、人工注释以及深入分析运营数据结结果。尤其是在应用大规模使用中,运营和数据团队需要持续观测应用成本和性能,对模型以及应用表现进行优化。 {'Header 1': '集成外部 Ops 工具', 'Header 3': 'Dify 与 Ops 工具的集成'} 使用 Dify Workflow 编排 LLM 应用时,通常涵盖一系列节点和逻辑,具有较高的复杂性。 将 Dify 与外部 Ops 工具集成,有助于打破编排应用时可能面临的 LLM “黑盒”问题。开发者只需要在平台上进行简单的配置,即可追踪应用生命周期中的数据和指标,轻松评估在 Dify 上创建的 LLM 应用质量、性能和成本。 {'Header 1': '集成 LangSmith', 'Header 3': '什么是 LangSmith'} LangSmith 是一个用于构建生产级 LLM 应用程序的平台,它用于开发、协作、测试、部署和监控 LLM 应用程序。 {% hint style="info" %} LangSmith 官网介绍:[https://www.langchain.com/langsmith](https://www.langchain.com/langsmith) {% endhint %} *** {'Header 1': '集成 LangSmith', 'Header 3': '如何配置 LangSmith'} 本章节将指引你注册 LangSmith 并将其集成至 Dify 平台内。 #### 1. 注册/登录 [LangSmith](https://www.langchain.com/langsmith) #### 2. 创建项目 在 LangSmith 内创建项目,登录后在主页点击 **New Project** 创建一个自己的项目,**项目**将用于与 Dify 内的**应用**关联进行数据监测。

    在 LangSmith 内创建项目

    创建完成之后在 Projects 内可以查看该项目。

    在 LangSmith 内查看已创建项目

    {'Header 1': '集成 LangSmith', 'Header 3': '如何配置 LangSmith'} #### 3. 创建项目凭据 创建项目凭据,在左侧边栏内找到项目设置 **Settings**。

    项目设置

    点击 **Create API Key**,创建一个项目凭据。

    创建一个项目 API Key

    选择 **Personal Access Token** ,用于后续的 API 身份校验。 {'Header 1': '集成 LangSmith', 'Header 3': '如何配置 LangSmith'} 选择 **Personal Access Token** ,用于后续的 API 身份校验。

    创建一个 API Key

    将创建的 API key 复制保存。

    复制 API Key

    #### 4. 将 LangSmith 集成至 Dify 平台 在 Dify 应用内配置 LangSmith。打开需要监测的应用,在左侧边菜单内打开**监测**,点击页面内的**配置。** {'Header 1': '集成 LangSmith', 'Header 3': '如何配置 LangSmith'}

    配置 LangSmith

    点击配置后,将在 LangSmith 内创建的 **API Key** 和**项目名**粘贴到配置内并保存。

    配置 LangSmith

    {% hint style="info" %} 配置项目名需要与 LangSmith 内设置的项目一致,若项目名不一致,数据同步时 LangSmith 会自动创建一个新的项目。 {% endhint %} 成功保存后可以在当前页面查看监测状态。 {'Header 1': '集成 LangSmith', 'Header 3': '如何配置 LangSmith'} {% endhint %} 成功保存后可以在当前页面查看监测状态。

    查看配置状态

    {'Header 1': '集成 LangSmith', 'Header 3': '在 LangSmith 内查看监测数据'} 配置完成后, Dify 内应用的调试或生产数据可以在 LangSmith 查看监测数据。

    在 Dify 内调试应用

    在 LangSmith 内查看应用数据

    在 LangSmith 内查看应用数据

    {'Header 1': '集成 LangSmith', 'Header 3': '监测数据清单'} #### Workflow /Chatflow Trace信息 **用于追踪workflow以及chatflow** | Workflow | LangSmith Chain | | ---------------------------------------- | -------------------------- | | workflow\_app\_log\_id/workflow\_run\_id | id | | user\_session\_id | -放入metadata | | workflow\_{id} | name | {'Header 1': '集成 LangSmith', 'Header 3': '监测数据清单'} | start\_time | start\_time | | end\_time | end\_time | | inputs | inputs | | outputs | outputs | | 模型token消耗相关 | usage\_metadata | | metadata | extra | {'Header 1': '集成 LangSmith', 'Header 3': '监测数据清单'} | error | error | | \[workflow] | tags | | "conversation\_id/workflow时无" | metadata中的conversation\_id | | conversion\_id | parent\_run\_id | **Workflow Trace Info** * workflow\_id - Workflow的唯一标识 * conversation\_id - 对话ID * workflow\_run\_id - 此次运行的ID * tenant\_id - 租户ID * elapsed\_time - 此次运行耗时 * status - 运行状态 * version - Workflow版本 {'Header 1': '集成 LangSmith', 'Header 3': '监测数据清单'} * status - 运行状态 * version - Workflow版本 * total\_tokens - 此次运行使用的token总数 * file\_list - 处理的文件列表 * triggered\_from - 触发此次运行的来源 * workflow\_run\_inputs - 此次运行的输入数据 * workflow\_run\_outputs - 此次运行的输出数据 * error - 此次运行中发生的错误 * query - 运行时使用的查询 * workflow\_app\_log\_id - Workflow应用日志ID * message\_id - 关联的消息ID * start\_time - 运行开始时间 * end\_time - 运行结束时间 * workflow node executions - workflow节点运行信息 * Metadata * workflow\_id - Workflow的唯一标识 * conversation\_id - 对话ID * workflow\_run\_id - 此次运行的ID {'Header 1': '集成 LangSmith', 'Header 3': '监测数据清单'} * workflow\_run\_id - 此次运行的ID * tenant\_id - 租户ID * elapsed\_time - 此次运行耗时 * status - 运行状态 * version - Workflow版本 * total\_tokens - 此次运行使用的token总数 * file\_list - 处理的文件列表 * triggered\_from - 触发来源 #### Message Trace信息 **用于追踪llm对话相关** | Chat | LangSmith LLM | | -------------------------------- | -------------------------- | | message\_id | id | {'Header 1': '集成 LangSmith', 'Header 3': '监测数据清单'} | user\_session\_id | -放入metadata | | “message\_{id}" | name | | start\_time | start\_time | | end\_time | end\_time | | inputs | inputs | | outputs | outputs | | 模型token消耗相关 | usage\_metadata | {'Header 1': '集成 LangSmith', 'Header 3': '监测数据清单'} | metadata | extra | | error | error | | \["message", conversation\_mode] | tags | | conversation\_id | metadata中的conversation\_id | | conversion\_id | parent\_run\_id | **Message Trace Info** * message\_id - 消息ID * message\_data - 消息数据 * user\_session\_id - 用户的session\_id * conversation\_model - 对话模式 * message\_tokens - 消息中的令牌数 {'Header 1': '集成 LangSmith', 'Header 3': '监测数据清单'} * message\_tokens - 消息中的令牌数 * answer\_tokens - 回答中的令牌数 * total\_tokens - 消息和回答中的总令牌数 * error - 错误信息 * inputs - 输入数据 * outputs - 输出数据 * file\_list - 处理的文件列表 * start\_time - 开始时间 * end\_time - 结束时间 * message\_file\_data - 消息关联的文件数据 * conversation\_mode - 对话模式 * Metadata * conversation\_id - 消息所属对话的ID * ls\_provider - 模型提供者 * ls\_model\_name - 模型ID * status - 消息状态 * from\_end\_user\_id - 发送用户的ID * from\_account\_id - 发送账户的ID * agent\_based - 是否基于代理 * workflow\_run\_id - 工作流运行ID {'Header 1': '集成 LangSmith', 'Header 3': '监测数据清单'} * workflow\_run\_id - 工作流运行ID * from\_source - 消息来源 * message\_id - 消息ID #### Moderation Trace信息 **用于追踪对话审查** | Moderation | LangSmith Tool | | ------------- | --------------- | | user\_id | -放入metadata | | “moderation" | name | | start\_time | start\_time | | end\_time | end\_time | | inputs | inputs | | outputs | outputs | | metadata | extra | | \[moderation] | tags | {'Header 1': '集成 LangSmith', 'Header 3': '监测数据清单'} | \[moderation] | tags | | message\_id | parent\_run\_id | **Message Trace Info** * message\_id - 消息ID * user\_id: 用户id * workflow\_app\_log\_id workflow\_app\_log\_id * inputs - 审查的输入数据 * message\_data - 消息数据 * flagged - 是否被标记为需要注意的内容 * action - 执行的具体行动 * preset\_response - 预设响应 * start\_time - 审查开始时间 * end\_time - 审查结束时间 * Metadata * message\_id - 消息ID * action - 执行的具体行动 * preset\_response - 预设响应 #### Suggested Question Trace信息 **用于追踪建议问题** {'Header 1': '集成 LangSmith', 'Header 3': '监测数据清单'} #### Suggested Question Trace信息 **用于追踪建议问题** | Suggested Question | LangSmith LLM | | ---------------------- | --------------- | | user\_id | -放入metadata | | suggested\_question | name | | start\_time | start\_time | | end\_time | end\_time | | inputs | inputs | | outputs | outputs | | metadata | extra | | \[suggested\_question] | tags | {'Header 1': '集成 LangSmith', 'Header 3': '监测数据清单'} | \[suggested\_question] | tags | | message\_id | parent\_run\_id | **Message Trace Info** * message\_id - 消息ID * message\_data - 消息数据 * inputs - 输入的内容 * outputs - 输出的内容 * start\_time - 开始时间 * end\_time - 结束时间 * total\_tokens - 令牌数量 * status - 消息状态 * error - 错误信息 * from\_account\_id - 发送账户的ID * agent\_based - 是否基于代理 * from\_source - 消息来源 * model\_provider - 模型提供者 * model\_id - 模型ID * suggested\_question - 建议的问题 * level - 状态级别 * status\_message - 状态信息 * Metadata {'Header 1': '集成 LangSmith', 'Header 3': '监测数据清单'} * status\_message - 状态信息 * Metadata * message\_id - 消息ID * ls\_provider - 模型提供者 * ls\_model\_name - 模型ID * status - 消息状态 * from\_end\_user\_id - 发送用户的ID * from\_account\_id - 发送账户的ID * workflow\_run\_id - 工作流运行ID * from\_source - 消息来源 #### Dataset Retrieval Trace信息 **用于追踪知识库检索** | Dataset Retrieval | LangSmith Retriever | | --------------------- | ------------------- | | user\_id | -放入metadata | | dataset\_retrieval | name | {'Header 1': '集成 LangSmith', 'Header 3': '监测数据清单'} | dataset\_retrieval | name | | start\_time | start\_time | | end\_time | end\_time | | inputs | inputs | | outputs | outputs | | metadata | extra | | \[dataset\_retrieval] | tags | | message\_id | parent\_run\_id | **Dataset Retrieval Trace Info** * message\_id - 消息ID * inputs - 输入内容 * documents - 文档数据 * start\_time - 开始时间 {'Header 1': '集成 LangSmith', 'Header 3': '监测数据清单'} * documents - 文档数据 * start\_time - 开始时间 * end\_time - 结束时间 * message\_data - 消息数据 * Metadata * message\_id消息ID * ls\_provider模型提供者 * ls\_model\_name模型ID * status消息状态 * from\_end\_user\_id发送用户的ID * from\_account\_id发送账户的ID * agent\_based是否基于代理 * workflow\_run\_id工作流运行ID * from\_source消息来源 #### Tool Trace信息 **用于追踪工具调用** | Tool | LangSmith Tool | | --------------------- | --------------- | | user\_id | -放入metadata | {'Header 1': '集成 LangSmith', 'Header 3': '监测数据清单'} | user\_id | -放入metadata | | tool\_name | name | | start\_time | start\_time | | end\_time | end\_time | | inputs | inputs | | outputs | outputs | | metadata | extra | | \["tool", tool\_name] | tags | | message\_id | parent\_run\_id | **Tool Trace Info** * message\_id消息ID * tool\_name工具名称 * start\_time开始时间 * end\_time结束时间 {'Header 1': '集成 LangSmith', 'Header 3': '监测数据清单'} * start\_time开始时间 * end\_time结束时间 * tool\_inputs工具输入 * tool\_outputs工具输出 * message\_data消息数据 * error错误信息,如果存在 * inputs消息的输入内容 * outputs消息的回答内容 * tool\_config工具配置 * time\_cost时间成本 * tool\_parameters工具参数 * file\_url关联文件的URL * Metadata * message\_id消息ID * tool\_name工具名称 * tool\_inputs工具输入 * tool\_outputs工具输出 * tool\_config工具配置 * time\_cost时间成本 * error错误信息 * tool\_parameters工具参数 * message\_file\_id消息文件ID * created\_by\_role创建者角色 * created\_user\_id创建者用户ID #### Generate Name Trace信息 {'Header 1': '集成 LangSmith', 'Header 3': '监测数据清单'} #### Generate Name Trace信息 **用于追踪会话标题生成** | Generate Name | LangSmith Tool | | ----------------- | -------------- | | user\_id | -放入metadata | | generate\_name | name | | start\_time | start\_time | | end\_time | end\_time | | inputs | inputs | | outputs | outputs | | metadata | extra | | \[generate\_name] | tags | **Generate Name Trace Info** * conversation\_id对话ID {'Header 1': '集成 LangSmith', 'Header 3': '监测数据清单'} * conversation\_id对话ID * inputs输入数据 * outputs生成的会话名称 * start\_time开始时间 * end\_time结束时间 * tenant\_id租户ID * Metadata * conversation\_id对话ID * tenant\_id租户ID {'Header 1': '集成 Langfuse', 'Header 3': '1 什么是 Langfuse'} Langfuse 是一个开源的 LLM 工程平台,可以帮助团队协作调试、分析和迭代他们的应用程序。 {% hint style="info" %} Langfuse 官网介绍:[https://langfuse.com/](https://langfuse.com/) {% endhint %} *** {'Header 1': '集成 Langfuse', 'Header 3': '2 如何配置 Langfuse'} 1. 在[官网注册](https://langfuse.com/)并登录 Langfuse 2. 在 Langfuse 内创建项目,登录后在主页点击 **New** ,创建一个自己的项目,**项目**将用于与 Dify 内的**应用**关联进行数据监测。

    在 Langfuse 内创建项目

    为项目编辑一个名称。

    在 Langfuse 内创建项目

    3. 创建项目 API 凭据,在项目内左侧边栏中点击 **Settings** 打开设置 {'Header 1': '集成 Langfuse', 'Header 3': '2 如何配置 Langfuse'} 3. 创建项目 API 凭据,在项目内左侧边栏中点击 **Settings** 打开设置

    创建一个项目 API 凭据

    在 Settings 内点击 **Create API Keys** 创建一个项目 API 凭据。

    创建一个项目 API 凭据

    复制并保存 **Secret Key** ,**Public Key,Host** {'Header 1': '集成 Langfuse', 'Header 3': '2 如何配置 Langfuse'} 复制并保存 **Secret Key** ,**Public Key,Host**

    获取 API Key 配置

    4. 在 Dify 内配置 Langfuse,打开需要监测的应用,在侧边菜单打开**监测**,在页面中选择**配置。**

    配置 Langfuse

    点击配置后,将在 Langfuse 内创建的 **Secret Key, Public Key, Host** 粘贴到配置内并保存。 {'Header 1': '集成 Langfuse', 'Header 3': '2 如何配置 Langfuse'}

    配置 Langfuse

    成功保存后可以在当前页面查看到状态,显示已启动即正在监测。

    查看配置状态

    *** {'Header 1': '集成 Langfuse', 'Header 3': '3 在 Langfuse 内查看监测数据'} 配置完成后, Dify 内应用的调试或生产数据可以在 Langfuse 查看监测数据。

    在 Dify 内调试应用

    在 Langfuse 内查看应用数据

    在 Langfuse 内查看应用数据

    {'Header 1': '集成 Langfuse', 'Header 3': '4 监测数据清单'} #### Workflow /Chatflow Trace信息 **用于追踪workflow以及chatflow** | Workflow | LangFuse Trace | | ---------------------------------------- | ----------------------- | | workflow\_app\_log\_id/workflow\_run\_id | id | | user\_session\_id | user\_id | | workflow\_{id} | name | | start\_time | start\_time | {'Header 1': '集成 Langfuse', 'Header 3': '4 监测数据清单'} | end\_time | end\_time | | inputs | input | | outputs | output | | 模型token消耗相关 | usage | | metadata | metadata | | error | level | | error | status\_message | {'Header 1': '集成 Langfuse', 'Header 3': '4 监测数据清单'} | \[workflow] | tags | | conversation\_id/workflow时无 | session\_id | | conversion\_id | parent\_observation\_id | **Workflow Trace Info** * workflow\_id - Workflow的唯一标识 * conversation\_id - 对话ID * workflow\_run\_id - 此次运行的ID * tenant\_id - 租户ID * elapsed\_time - 此次运行耗时 * status - 运行状态 * version - Workflow版本 * total\_tokens - 此次运行使用的token总数 * file\_list - 处理的文件列表 * triggered\_from - 触发此次运行的来源 {'Header 1': '集成 Langfuse', 'Header 3': '4 监测数据清单'} * triggered\_from - 触发此次运行的来源 * workflow\_run\_inputs - 此次运行的输入数据 * workflow\_run\_outputs - 此次运行的输出数据 * error - 此次运行中发生的错误 * query - 运行时使用的查询 * workflow\_app\_log\_id - Workflow应用日志ID * message\_id - 关联的消息ID * start\_time - 运行开始时间 * end\_time - 运行结束时间 * workflow node executions - workflow节点运行信息 * Metadata * workflow\_id - Workflow的唯一标识 * conversation\_id - 对话ID * workflow\_run\_id - 此次运行的ID * tenant\_id - 租户ID * elapsed\_time - 此次运行耗时 * status - 运行状态 * version - Workflow版本 {'Header 1': '集成 Langfuse', 'Header 3': '4 监测数据清单'} * status - 运行状态 * version - Workflow版本 * total\_tokens - 此次运行使用的token总数 * file\_list - 处理的文件列表 * triggered\_from - 触发来源 #### Message Trace信息 **用于追踪llm对话相关** | Message | LangFuse Generation/Trace | | -------------------------------- | ------------------------- | | message\_id | id | | user\_session\_id | user\_id | | message\_{id} | name | {'Header 1': '集成 Langfuse', 'Header 3': '4 监测数据清单'} | start\_time | start\_time | | end\_time | end\_time | | inputs | input | | outputs | output | | 模型token消耗相关 | usage | | metadata | metadata | | error | level | {'Header 1': '集成 Langfuse', 'Header 3': '4 监测数据清单'} | error | status\_message | | \["message", conversation\_mode] | tags | | conversation\_id | session\_id | | conversion\_id | parent\_observation\_id | **Message Trace Info** * message\_id - 消息ID * message\_data - 消息数据 * user\_session\_id - 用户的session\_id * conversation\_model - 对话模式 * message\_tokens - 消息中的令牌数 * answer\_tokens - 回答中的令牌数 * total\_tokens - 消息和回答中的总令牌数 * error - 错误信息 {'Header 1': '集成 Langfuse', 'Header 3': '4 监测数据清单'} * total\_tokens - 消息和回答中的总令牌数 * error - 错误信息 * inputs - 输入数据 * outputs - 输出数据 * file\_list - 处理的文件列表 * start\_time - 开始时间 * end\_time - 结束时间 * message\_file\_data - 消息关联的文件数据 * conversation\_mode - 对话模式 * Metadata * conversation\_id - 消息所属对话的ID * ls\_provider - 模型提供者 * ls\_model\_name - 模型ID * status - 消息状态 * from\_end\_user\_id - 发送用户的ID * from\_account\_id - 发送账户的ID * agent\_based - 是否基于代理 * workflow\_run\_id - 工作流运行ID * from\_source - 消息来源 * message\_id - 消息ID #### Moderation Trace信息 {'Header 1': '集成 Langfuse', 'Header 3': '4 监测数据清单'} * message\_id - 消息ID #### Moderation Trace信息 **用于追踪对话审查** | Moderation | LangFuse Generation/Trace | | ------------- | ------------------------- | | user\_id | user\_id | | moderation | name | | start\_time | start\_time | | end\_time | end\_time | | inputs | input | | outputs | output | | metadata | metadata | {'Header 1': '集成 Langfuse', 'Header 3': '4 监测数据清单'} | metadata | metadata | | \[moderation] | tags | | message\_id | parent\_observation\_id | **Message Trace Info** * message\_id - 消息ID * user\_id: 用户id * workflow\_app\_log\_id workflow\_app\_log\_id * inputs - 审查的输入数据 * message\_data - 消息数据 * flagged - 是否被标记为需要注意的内容 * action - 执行的具体行动 * preset\_response - 预设响应 * start\_time - 审查开始时间 * end\_time - 审查结束时间 * Metadata * message\_id - 消息ID * action - 执行的具体行动 * preset\_response - 预设响应 {'Header 1': '集成 Langfuse', 'Header 3': '4 监测数据清单'} * action - 执行的具体行动 * preset\_response - 预设响应 #### Suggested Question Trace信息 **用于追踪建议问题** | Suggested Question | LangFuse Generation/Trace | | ---------------------- | ------------------------- | | user\_id | user\_id | | suggested\_question | name | | start\_time | start\_time | | end\_time | end\_time | | inputs | input | {'Header 1': '集成 Langfuse', 'Header 3': '4 监测数据清单'} | outputs | output | | metadata | metadata | | \[suggested\_question] | tags | | message\_id | parent\_observation\_id | **Message Trace Info** * message\_id - 消息ID * message\_data - 消息数据 * inputs - 输入的内容 * outputs - 输出的内容 * start\_time - 开始时间 * end\_time - 结束时间 * total\_tokens - 令牌数量 * status - 消息状态 * error - 错误信息 * from\_account\_id - 发送账户的ID * agent\_based - 是否基于代理 * from\_source - 消息来源 {'Header 1': '集成 Langfuse', 'Header 3': '4 监测数据清单'} * agent\_based - 是否基于代理 * from\_source - 消息来源 * model\_provider - 模型提供者 * model\_id - 模型ID * suggested\_question - 建议的问题 * level - 状态级别 * status\_message - 状态信息 * Metadata * message\_id - 消息ID * ls\_provider - 模型提供者 * ls\_model\_name - 模型ID * status - 消息状态 * from\_end\_user\_id - 发送用户的ID * from\_account\_id - 发送账户的ID * workflow\_run\_id - 工作流运行ID * from\_source - 消息来源 #### Dataset Retrieval Trace信息 **用于追踪知识库检索** | Dataset Retrieval | LangFuse Generation/Trace | {'Header 1': '集成 Langfuse', 'Header 3': '4 监测数据清单'} | --------------------- | ------------------------- | | user\_id | user\_id | | dataset\_retrieval | name | | start\_time | start\_time | | end\_time | end\_time | | inputs | input | | outputs | output | | metadata | metadata | | \[dataset\_retrieval] | tags | {'Header 1': '集成 Langfuse', 'Header 3': '4 监测数据清单'} | message\_id | parent\_observation\_id | **Dataset Retrieval Trace Info** * message\_id - 消息ID * inputs - 输入内容 * documents - 文档数据 * start\_time - 开始时间 * end\_time - 结束时间 * message\_data - 消息数据 * Metadata * message\_id消息ID * ls\_provider模型提供者 * ls\_model\_name模型ID * status消息状态 * from\_end\_user\_id发送用户的ID * from\_account\_id发送账户的ID * agent\_based是否基于代理 * workflow\_run\_id工作流运行ID * from\_source消息来源 #### Tool Trace信息 **用于追踪工具调用** {'Header 1': '集成 Langfuse', 'Header 3': '4 监测数据清单'} #### Tool Trace信息 **用于追踪工具调用** | Tool | LangFuse Generation/Trace | | --------------------- | ------------------------- | | user\_id | user\_id | | tool\_name | name | | start\_time | start\_time | | end\_time | end\_time | | inputs | input | | outputs | output | {'Header 1': '集成 Langfuse', 'Header 3': '4 监测数据清单'} | metadata | metadata | | \["tool", tool\_name] | tags | | message\_id | parent\_observation\_id | **Tool Trace Info** * message\_id消息ID * tool\_name工具名称 * start\_time开始时间 * end\_time结束时间 * tool\_inputs工具输入 * tool\_outputs工具输出 * message\_data消息数据 * error错误信息,如果存在 * inputs消息的输入内容 * outputs消息的回答内容 * tool\_config工具配置 * time\_cost时间成本 * tool\_parameters工具参数 * file\_url关联文件的URL * Metadata * message\_id消息ID * tool\_name工具名称 {'Header 1': '集成 Langfuse', 'Header 3': '4 监测数据清单'} * Metadata * message\_id消息ID * tool\_name工具名称 * tool\_inputs工具输入 * tool\_outputs工具输出 * tool\_config工具配置 * time\_cost时间成本 * error错误信息 * tool\_parameters工具参数 * message\_file\_id消息文件ID * created\_by\_role创建者角色 * created\_user\_id创建者用户ID #### Generate Name Trace信息 **用于追踪会话标题生成** | Generate Name | LangFuse Generation/Trace | | ----------------- | ------------------------- | | user\_id | user\_id | | generate\_name | name | {'Header 1': '集成 Langfuse', 'Header 3': '4 监测数据清单'} | generate\_name | name | | start\_time | start\_time | | end\_time | end\_time | | inputs | input | | outputs | output | | metadata | metadata | | \[generate\_name] | tags | **Generate Name Trace Info** * conversation\_id对话ID * inputs输入数据 * outputs生成的会话名称 * start\_time开始时间 * end\_time结束时间 * tenant\_id租户ID * Metadata {'Header 1': '集成 Langfuse', 'Header 3': '4 监测数据清单'} * end\_time结束时间 * tenant\_id租户ID * Metadata * conversation\_id对话ID * tenant\_id租户ID {'Header 1': '成为贡献者'} 所以你想为 Dify 做贡献 - 这太棒了,我们迫不及待地想看到你的贡献。作为一家人员和资金有限的初创公司,我们有着雄心勃勃的目标,希望设计出最直观的工作流程来构建和管理 LLM 应用程序。社区的任何帮助都是宝贵的。 考虑到我们的现状,我们需要灵活快速地交付,但我们也希望确保像你这样的贡献者在贡献过程中获得尽可能顺畅的体验。我们为此编写了这份贡献指南,旨在让你熟悉代码库和我们与贡献者的合作方式,以便你能快速进入有趣的部分。 这份指南,就像 Dify 本身一样,是一个不断改进的工作。如果有时它落后于实际项目,我们非常感谢你的理解,并欢迎任何反馈以供我们改进。 在许可方面,请花一分钟阅读我们简短的[许可证和贡献者协议](./open-source)。社区还遵守[行为准则](https://github.com/langgenius/.github/blob/main/CODE_OF_CONDUCT.md)。 {'Header 1': '成为贡献者', 'Header 2': '在开始之前'} [查找](https://github.com/langgenius/dify/issues?q=is:issue+is:closed)现有问题,或[创建](https://github.com/langgenius/dify/issues/new/choose)一个新问题。我们将问题分为两类: {'Header 1': '成为贡献者', 'Header 2': '在开始之前', 'Header 3': '功能请求:'} * 如果您要提出新的功能请求,请解释所提议的功能的目标,并尽可能提供详细的上下文。[@perzeusss](https://github.com/perzeuss)制作了一个很好的[功能请求助手](https://udify.app/chat/MK2kVSnw1gakVwMX),可以帮助您起草需求。随时尝试一下。 * 如果您想从现有问题中选择一个,请在其下方留下评论表示您的意愿。 相关方向的团队成员将参与其中。如果一切顺利,他们将批准您开始编码。在此之前,请不要开始工作,以免我们提出更改导致您的工作付诸东流。 根据所提议的功能所属的领域不同,您可能需要与不同的团队成员交流。以下是我们团队成员目前正在从事的各个领域的概述: | Member | Scope | {'Header 1': '成为贡献者', 'Header 2': '在开始之前', 'Header 3': '功能请求:'} | ------------------------------------------------------------ | ---------------------------------------------------- | | [@yeuoly](https://github.com/Yeuoly) | Architecting Agents | | [@jyong](https://github.com/JohnJyong) | RAG pipeline design | | [@GarfieldDai](https://github.com/GarfieldDai) | Building workflow orchestrations | {'Header 1': '成为贡献者', 'Header 2': '在开始之前', 'Header 3': '功能请求:'} | [@iamjoel](https://github.com/iamjoel) & [@zxhlyh](https://github.com/zxhlyh) | Making our frontend a breeze to use | | [@guchenhe](https://github.com/guchenhe) & [@crazywoola](https://github.com/crazywoola) | Developer experience, points of contact for anything | | [@takatost](https://github.com/takatost) | Overall product direction and architecture | How we prioritize: {'Header 1': '成为贡献者', 'Header 2': '在开始之前', 'Header 3': '功能请求:'} How we prioritize: | Feature Type | Priority | | ------------------------------------------------------------ | --------------- | | High-Priority Features as being labeled by a team member | High Priority | | Popular feature requests from our [community feedback board](https://github.com/langgenius/dify/discussions/categories/ideas) | Medium Priority | {'Header 1': '成为贡献者', 'Header 2': '在开始之前', 'Header 3': '功能请求:'} | Non-core features and minor enhancements | Low Priority | | Valuable but not immediate | Future-Feature | {'Header 1': '成为贡献者', 'Header 2': '在开始之前', 'Header 3': '其他任何事情(例如bug报告、性能优化、拼写错误更正):'} * 立即开始编码。 How we prioritize: | Issue Type | Priority | | ------------------------------------------------------------ | --------------- | | Bugs in core functions (cannot login, applications not working, security loopholes) | Critical | | Non-critical bugs, performance boosts | Medium Priority | | Minor fixes (typos, confusing but working UI) | Low Priority | {'Header 1': '成为贡献者', 'Header 2': '安装'} 以下是设置Dify进行开发的步骤: {'Header 1': '成为贡献者', 'Header 2': '安装', 'Header 3': '2. 克隆仓库'} 从终端克隆fork的仓库: ``` git clone git@github.com:/dify.git ``` {'Header 1': '成为贡献者', 'Header 2': '安装', 'Header 3': '3. 验证依赖项'} Dify 依赖以下工具和库: - [Docker](https://www.docker.com/) - [Docker Compose](https://docs.docker.com/compose/install/) - [Node.js v18.x (LTS)](http://nodejs.org) - [npm](https://www.npmjs.com/) version 8.x.x or [Yarn](https://yarnpkg.com/) - [Python](https://www.python.org/) version 3.10.x {'Header 1': '成为贡献者', 'Header 2': '安装', 'Header 3': '4. 安装'} Dify由后端和前端组成。通过`cd api/`导航到后端目录,然后按照[后端README](https://github.com/langgenius/dify/blob/main/api/README.md)进行安装。在另一个终端中,通过`cd web/`导航到前端目录,然后按照[前端README](https://github.com/langgenius/dify/blob/main/web/README.md)进行安装。 查看[安装常见问题解答](https://docs.dify.ai/getting-started/faq/install-faq)以获取常见问题列表和故障排除步骤。 {'Header 1': '成为贡献者', 'Header 2': '安装', 'Header 3': '5. 在浏览器中访问Dify'} 为了验证您的设置,打开浏览器并访问[http://localhost:3000](http://localhost:3000)(默认或您自定义的URL和端口)。现在您应该看到Dify正在运行。 {'Header 1': '成为贡献者', 'Header 2': '开发'} 如果您要添加模型提供程序,请参考[此指南](https://github.com/langgenius/dify/blob/main/api/core/model_runtime/README.md)。 如果您要向Agent或Workflow添加工具提供程序,请参考[此指南](https://github.com/langgenius/dify/blob/main/api/core/tools/README.md)。 为了帮助您快速了解您的贡献在哪个部分,以下是Dify后端和前端的简要注释大纲: {'Header 1': '成为贡献者', 'Header 2': '开发', 'Header 3': '后端'} Dify的后端使用Python编写,使用[Flask](https://flask.palletsprojects.com/en/3.0.x/)框架。它使用[SQLAlchemy](https://www.sqlalchemy.org/)作为ORM,使用[Celery](https://docs.celeryq.dev/en/stable/getting-started/introduction.html)作为任务队列。授权逻辑通过Flask-login进行处理。 ``` [api/] ├── constants // Constant settings used throughout code base. ├── controllers // API route definitions and request handling logic. ├── core // Core application orchestration, model integrations, and tools. {'Header 1': '成为贡献者', 'Header 2': '开发', 'Header 3': '后端'} ├── docker // Docker & containerization related configurations. ├── events // Event handling and processing ├── extensions // Extensions with 3rd party frameworks/platforms. ├── fields // field definitions for serialization/marshalling. ├── libs // Reusable libraries and helpers. ├── migrations // Scripts for database migration. ├── models // Database models & schema definitions. {'Header 1': '成为贡献者', 'Header 2': '开发', 'Header 3': '后端'} ├── services // Specifies business logic. ├── storage // Private key storage. ├── tasks // Handling of async tasks and background jobs. └── tests ``` {'Header 1': '成为贡献者', 'Header 2': '开发', 'Header 3': '前端'} 该网站使用基于Typescript的[Next.js](https://nextjs.org/)模板进行引导,并使用[Tailwind CSS](https://tailwindcss.com/)进行样式设计。[React-i18next](https://react.i18next.com/)用于国际化。 ``` [web/] ├── app // layouts, pages, and components │ ├── (commonLayout) // common layout used throughout the app │ ├── (shareLayout) // layouts specifically shared across token-specific sessions │ ├── activate // activate page │ ├── components // shared by pages and layouts {'Header 1': '成为贡献者', 'Header 2': '开发', 'Header 3': '前端'} │ ├── install // install page │ ├── signin // signin page │ └── styles // globally shared styles ├── assets // Static assets ├── bin // scripts ran at build step ├── config // adjustable settings and options ├── context // shared contexts used by different portions of the app ├── dictionaries // Language-specific translate files ├── docker // container configurations {'Header 1': '成为贡献者', 'Header 2': '开发', 'Header 3': '前端'} ├── hooks // Reusable hooks ├── i18n // Internationalization configuration ├── models // describes data models & shapes of API responses ├── public // meta assets like favicon ├── service // specifies shapes of API actions ├── test ├── types // descriptions of function params and return values └── utils // Shared utility functions ``` {'Header 1': '成为贡献者', 'Header 2': '提交你的 PR'} 最后,是时候向我们的仓库提交一个拉取请求(PR)了。对于重要的功能,我们首先将它们合并到 `deploy/dev` 分支进行测试,然后再合并到 `main` 分支。如果你遇到合并冲突或者不知道如何提交拉取请求的问题,请查看 [GitHub 的拉取请求教程](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests)。 就是这样!一旦你的 PR 被合并,你将成为我们 [README](https://github.com/langgenius/dify/blob/main/README.md) 中的贡献者。 {'Header 1': '成为贡献者', 'Header 2': '获取帮助'} 如果你在贡献过程中遇到困难或者有任何问题,可以通过相关的 GitHub 问题提出你的疑问,或者加入我们的 [Discord](https://discord.gg/AhzKf7dNgk) 进行快速交流。# 寻求支持 如果你阅读这套文档时,仍然对产品使用存在疑问和建议,可尝试以下方式寻求支持。我们的团队与社区会竭尽所能的为你提供帮助。 {'Header 1': '成为贡献者', 'Header 2': '获取帮助', 'Header 3': '社区支持'} {% hint style="info" %} 请不要将涉及你的 Dify 账户信息与其它密钥信息发至社区,我们的支持人员也不会索要您的账户信息。 {% endhint %} * 在 [Github](https://github.com/langgenius/dify) 上提交 Issue * 加入 [Discord ](https://discord.gg/8Tpq4AcN9c)社群 {'Header 1': '成为贡献者', 'Header 2': '获取帮助', 'Header 3': '联系我们'} 适用于除了寻求产品支持以外的其他事宜。 * 发邮件至 [hello@dify.ai](mailto:hello@dify.ai)