Dify的初步认识

Dify

Dify 是一款开源的大语言模型(LLM) 应用开发平台。它融合了后端即服务(Backend as Service)和 LLMOps 的理念,使开发者可以快速搭建生产级的生成式 AI 应用。即使你是非技术人员,也能参与到 AI 应用的定义和数据运营过程中。

由于 Dify 内置了构建 LLM 应用所需的关键技术栈,包括对数百个模型的支持、直观的 Prompt 编排界面、高质量的 RAG 引擎、稳健的 Agent 框架、灵活的流程编排,并同时提供了一套易用的界面和 API。这为开发者节省了许多重复造轮子的时间,使其可以专注在创新和业务需求上。

基于四种LLM构建的应用程序,可以针对不同的应用场景和需求进行优化和定制。

  1. 聊天助手
    • 基于LLM的对话助手,

优势:

  1. 低代码、无代码开发

    Dify通过可视化的方式允许开发者轻松定义Prompt,上下文和插件等,无需深入底层技术细节。

  2. 模块化设计

    Dify采用模块化的设计,每个模块都有清晰的功能和接口,开发者可以根据需求选择性地使用这些模块来构建自己的API应用。

  3. 丰富的功能组件

    平台提供了包括AI工作流,RAG管道,Agent,模型管理等丰富组件,帮助开发者从原型到生产的全过程。

  4. 支持多种大语言模型

    Dify已支持主流的模型,开发者能够根据自己的需求选择最适合的模型来构建AI应用。

模型编排

真正的价值在于——模型编排(不同的语境下也叫做智能体设计,Agent Design,现在还有一个专门的职业是Agent Designer,专门用于设计智能体的)

什么是模型编排呢?

简单理解就是负责通过智能体的组合设计,来实现更加复杂、更加智能,从而突破现有模型的能力边界。

Dify 允许你将不同的智能体组合在一起,构建出更加强大和复杂的 AI 应用。你可以让一个智能体负责理解用户的输入,根据输入的特点进行转发给另一组用于回答的智能体中最适合处理该问题的一个,用于负责生成回答,再由一个专门的智能体对回答进行优化和修正。通过这种方式,你可以发挥每个智能体的长处,弥补它们的不足,最终得到一个性能更好、更加稳定的 AI 系统。

此外,Dify 还提供了一个直观的图形化界面,让你可以方便地管理和编排这些智能体。你不需要编写复杂的代码,只需要通过拖拽和连线,就可以定义智能体之间的交互和数据流动。这大大降低了开发 AI 应用的门槛,让更多人可以参与到这个领域中来。

项目结构

后端

Dify 的后端使用 Python 编写,使用 Flask 框架。它使用 SQLAlchemy 作为 ORM,使用 Celery 作为任务队列。授权逻辑通过 Flask-login 进行处理。

[api/]
├── constants             // 用于整个代码库的常量设置。
├── controllers           // API 路由定义和请求处理逻辑。
├── core                  // 核心应用编排、模型集成和工具。
├── docker                // Docker 和容器化相关配置。
├── events                // 事件处理和处理。
├── extensions            // 与第三方框架/平台的扩展。
├── fields                // 用于序列化/封装的字段定义。
├── libs                  // 可重用的库和助手。
├── migrations            // 数据库迁移脚本。
├── models                // 数据库模型和架构定义。
├── services              // 指定业务逻辑。
├── storage               // 私钥存储。
├── tasks                 // 异步任务和后台作业的处理。
└── tests

前端

该网站使用基于 Typescript 的 Next.js 模板进行引导,并使用 Tailwind CSS 进行样式设计。React-i18next 用于国际化。

[web/]
├── app                   // 布局、页面和组件
│   ├── (commonLayout)    // 整个应用通用的布局
│   ├── (shareLayout)     // 在特定会话中共享的布局
│   ├── activate          // 激活页面
│   ├── components        // 页面和布局共享的组件
│   ├── install           // 安装页面
│   ├── signin            // 登录页面
│   └── styles            // 全局共享的样式
├── assets                // 静态资源
├── bin                   // 构建步骤运行的脚本
├── config                // 可调整的设置和选项
├── context               // 应用中不同部分使用的共享上下文
├── dictionaries          // 语言特定的翻译文件
├── docker                // 容器配置
├── hooks                 // 可重用的钩子
├── i18n                  // 国际化配置
├── models                // 描述数据模型和 API 响应的形状
├── public                // 如 favicon 等元资源
├── service               // 定义 API 操作的形状
├── test
├── types                 // 函数参数和返回值的描述
└── utils                 // 共享的实用函数

模型类型

在Dify中,按模型的使用场景将模型分为4类:

  1. 系统推理模型。 在创建的应用中,用的是该类型的模型。智聊、对话名称生成、下一步问题建议用的也是推理模型。

    已支持的系统推理模型供应商:OpenAIAzure OpenAI ServiceAnthropic、Hugging Face Hub、Replicate、Xinference、OpenLLM、讯飞星火文心一言通义千问Minimax、ZHIPU(ChatGLM)

  2. Embedding 模型。在数据集中,将分段过的文档做 Embedding 用的是该类型的模型。在使用了数据集的应用中,将用户的提问做 Embedding 处理也是用的该类型的模型。

    已支持的 Embedding 模型供应商:OpenAI、ZHIPU(ChatGLM)、Jina AI(Jina Embeddings)

  3. Rerank 模型Rerank 模型用于增强检索能力,改善 LLM 的搜索结果。

    已支持的 Rerank 模型供应商:Cohere、Jina AI(Jina Reranker)

  4. 语音转文字模型。将对话型应用中,将语音转文字用的是该类型的模型。

    已支持的语音转文字模型供应商:OpenAI

模型配置方式

预定义模型(predefined-model)

表示用户只需要配置统一的供应商凭据即可使用供应商下的预定义模型。

自定义模型(customizable-model)

用户只需要新增每个模型的凭据配置,如Xinference,它同时支持LLMText Embedding,但是每个模型都有唯一的model_uid,如果想要将两者同时接入,就需要为每个模型配置一个唯一的model_uid

从远程获取

和predefined-model配置方式一致,只需要配置统一的供应商凭据即可,模型通过凭据信息从供应商获取。

当配置为fetch-from-remote时,开发者只需要配置统一的 api_key 即可让 Dify Runtime 获取到开发者所有的微调模型并接入 Dify。

这三种配置方式支持共存,即存在供应商支持predefined-model + customizable-modelpredefined-model + fetch-from-remote等,也就是配置了供应商统一凭据可以使用预定义模型和从远程获取的模型,若新增了模型,则可以在此基础上额外使用自定义的模型。

用途

Dify 一词源自 Define + Modify,意指定义并且持续的改进你的 AI 应用,它是为你而做的(Do it for you)。

  • 创业,快速的将你的 AI 应用创意变成现实,无论成功和失败都需要加速。在真实世界,已经有几十个团队通过 Dify 构建 MVP(最小可用产品)获得投资,或通过 POC(概念验证)赢得了客户的订单。
  • 将 LLM 集成至已有业务,通过引入 LLM 增强现有应用的能力,接入 Dify 的 RESTful API 从而实现 Prompt 与业务代码的解耦,在 Dify 的管理界面是跟踪数据、成本和用量,持续改进应用效果。
  • 作为企业级 LLM 基础设施,一些银行和大型互联网公司正在将 Dify 部署为企业内的 LLM 网关,加速 GenAI 技术在企业内的推广,并实现中心化的监管。
  • 探索 LLM 的能力边界,即使你是一个技术爱好者,通过 Dify 也可以轻松的实践 Prompt 工程和 Agent 技术,在 GPTs 推出以前就已经有超过 60,000 开发者在 Dify 上创建了自己的第一个应用。

常用的国内镜像源

摘要由CSDN通过智能技术生成
国内镜像地址:
阿里云
http://mirrors.aliyun.com/pypi/simple/

中国科技大学
https://pypi.mirrors.ustc.edu.cn/simple/

豆瓣(douban)
http://pypi.douban.com/simple/

清华大学
https://pypi.tuna.tsinghua.edu.cn/simple/

中国科学技术大学
http://pypi.mirrors.ustc.edu.cn/simple/

使用方法:以Python环境下pip安装keras为例

pip install keras==2.3.1 -i http://pypi.douban.com/simple/
//2.3.1为所需版本号,尾部url为对应镜像源地址

在虚拟机里部署 Dify 模型的步骤:

  1. 准备虚拟机环境:
    • 选择操作系统:

常见的选择有 Ubuntu、CentOS 等 Linux 发行版。确保虚拟机的配置满足 Dify 的最低系统要求,一般建议 CPU 核心数不少于 2 个,内存不少于 4GB。

  • 安装必要软件:

在虚拟机中安装 Docker(用于容器化部署)、Git(用于拉取代码)、Python 3.10.x(Dify 的后端服务基于 Python)、Anaconda(方便管理 Python 环境,如果需要)、PostgreSQL(数据库)、Redis(缓存)等。具体的安装步骤可以参考相关软件的官方文档或网络上的教程。

在 Ubuntu 系统中安装 Docker:

一、安装前准备

  1. 更新软件包列表:

sudo apt update

二、安装 Docker

  1. 安装必要的依赖:

sudo apt install apt-transport-https ca-certificates curl software-properties-common

  1. 添加 Docker 的官方 GPG 密钥:
  1. 验证密钥是否成功添加:

可以使用以下命令列出已添加的密钥:

sudo apt-key list

在输出中查找与 Docker 相关的密钥信息,确认密钥添加成功。

  1. 添加 Docker 软件源:

sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu focal stable"

  1. 更新软件包列表以包含新添加的 Docker 源:

sudo apt update

  1. 安装 Docker 引擎:

sudo apt install docker-ce

三、验证安装

  1. 检查 Docker 服务状态:

sudo systemctl status docker

  1. 运行一个简单的 Docker 容器来验证安装是否成功,例如运行一个 hello-world 容器:

sudo docker run hello-world

如果看到“Hello from Docker!”的消息,说明 Docker 安装成功并正常运行。

在 Ubuntu 系统中安装 Git

  1. 打开终端。

  2. 执行以下命令更新软件包列表:

sudo apt update

  1. 安装 Git:

sudo apt install git

  1. 安装完成后,可以通过以下命令检查 Git 版本,以确认安装成功:

git --version

  1. 拉取 Dify 代码:
  • 使用 Git 命令行工具在虚拟机中拉取 Dify 的源代码。

例如,如果使用 Ubuntu 系统且已经安装了 Git,可以打开终端,执行 git clone https://github.com/langgenius/dify.git 命令,将 Dify 的代码仓库克隆到虚拟机中。

  1. 配置中间件:
  • 配置数据库:

根据你选择的数据库(如 PostgreSQL),创建相应的数据库和用户,并确保数据库服务正在运行。你可能需要修改 Dify 项目中的数据库连接配置文件(通常是 .env 或类似的配置文件),将数据库连接信息修改为你虚拟机中数据库的实际信息。

  • 配置缓存:

如果使用 Redis 作为缓存,同样需要确保 Redis 服务已经启动,并在 Dify 的配置文件中正确设置 Redis 的连接信息。

  • 配置其他中间件:

根据 Dify 的要求,可能还需要配置其他中间件,如 Weaviate(用于向量存储)、Squid(用于代理)等。按照 Dify 的文档说明,确保这些中间件的安装和配置正确。

  1. 构建和启动 Dify 服务:
  • 进入项目目录:

使用命令行进入到拉取的 Dify 代码目录中。

  • 安装依赖:

根据 Dify 的文档,安装项目所需的依赖。如果 Dify 使用 poetry 管理依赖,可以执行 poetry install 命令来安装依赖;如果使用 pip ,则执行 pip install -r requirements.txt 命令。在安装过程中,可能会遇到一些依赖包无法安装的情况,可以根据错误提示进行相应的处理,或者参考 Dify 的社区论坛或文档获取解决方案。

  • 启动服务:

根据 Dify 的架构,可能需要启动多个服务,如后端 API 服务、Worker 异步队列消费服务等。通常可以在项目的根目录或相应的服务目录下,执行特定的启动命令。例如,如果是 Flask 应用,可以使用 flask run 命令启动后端 API 服务;如果有其他的脚本或命令用于启动 Worker 服务,也需要执行相应的命令。

  1. 配置前端(如果有前端界面):
  • 如果 Dify 有前端界面,需要在虚拟机中安装前端所需的环境,如 Node.js 和 npm(或 yarn)。进入前端项目目录,执行 npm install 或 yarn install 命令安装前端依赖。

  • 配置前端的环境变量。

在前端项目目录下创建 .env.local 文件,并复制 .env.example 中的内容,然后根据实际情况修改环境变量的值,如后端 API 的地址等。

  • 构建和启动前端服务。

执行 npm run build 命令构建前端代码,然后执行 npm run start 命令启动前端服务。在浏览器中访问前端服务的地址,即可查看 Dify 的界面。

以上步骤仅为一般性的指导,实际的部署过程可能会根据 Dify 的版本、虚拟机的环境以及具体的需求而有所不同。在部署过程中,建议参考 Dify 的官方文档、社区论坛以及相关的技术博客,以获取更详细和准确的信息。

Clone Dify 代码:

git clone https://github.com/langgenius/dify.git

在启用业务服务之前,我们需要先部署 PostgresSQL / Redis / Weaviate(如果本地没有的话),可以通过以下命令启动:

cd docker
cp middleware.env.example middleware.env
docker compose -f docker-compose.middleware.yaml up -d

Pyenv

是什么?

pyenv 可让您轻松地在多个 Python 版本之间切换。

推荐使用:pyenv 管理版本 + poetry 管理依赖

参考
https://github.com/pyenv/pyenv

https://github.com/pyenv/pyenv/wiki

https://github.com/pyenv/pyenv/wiki/Plugins

安装

# 安装环境依赖以供pyenv编译安装python时使用
$ brew install openssl readline sqlite3 xz zlib tcl-tk

# 安装pyenv
$ git clone https://github.com/pyenv/pyenv.git ~/.pyenv

# 为 Pyenv 设置 shell 环境
echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bash_profile
echo 'command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bash_profile
echo 'eval "$(pyenv init -)"' >> ~/.bash_profile

# 重新加载 Shell 配置文件并将更改应用于当前会话
$ exec "$SHELL"

# 查看pyenv版本
$ pyenv -v

当您执行 shim 时,pyenv 通过按以下顺序从以下源读取来确定要使用的 Python 版本:

  1. 环境PYENV_VERSION变量(如果指定)。您可以使用该pyenv shell命令在当前 shell 会话中设置此环境变量。
  2. .python-version当前目录中的应用程序特定文件(如果存在)。.python-version您可以使用命令修改当前目录的 文件pyenv local 。
  3. 通过搜索每个父目录找到的第一个.python-version文件(如果有),直到到达文件系统的根目录。
  4. 全局$(pyenv root)/version文件。您可以使用pyenv global命令修改此文件。如果全局版本文件不存在,pyenv 假设您想要使用“系统”Python(见下文)。

基本命令

# 查看 pyenv 的版本
$ pyenv -v
# 查看当前使用版本
$ pyenv version
# 罗列当前已安装的所有 python 环境,如果是当前正在使用的环境,则前面会有个 *
$ pyenv versions
# 查看帮助
$ pyenv help
# 如果输入 pyenv 之后使用 tab 不补全,可以使用该命令进行初始即可使用补全命令
$ pyenv init

安装Python

# 列出所有可安装的Python 版本
$ pyenv install -l

# 安装CPython 3.9.17
# pyenv 会尽力下载并编译想要的 Python 版本
$ pyenv install 3.9.17

# 安装 CPython 3.9.17 并为编译过程传递优化参数以获得最佳性能
$ env PYTHON_CONFIGURE_OPTS='--enable-optimizations --with-lto' PYTHON_CFLAGS='-march=native -mtune=native' pyenv install 3.9.17

切换Python

# 仅选择当前 shell 会话,临时生效,优先级高于 global
$ pyenv shell <version>
# 会在当前目录创建 .python-version 文件,并记录设置的 python 环境,每次进入该目录会自动设置成该 python 环境
$ pyenv local <version>
# 为您的用户帐户全局选择,重启不会造成再次更改
$ pyenv global <version>

卸载

$ pyenv uninstall <version>

$ rm -rf ~/.pyenv
# 最后在~/.bash_profile中删除相关配置即可

说明:

不要安装pyenv-virtualenv,而是应该使用Poetry进行虚拟环境的管理,这样可以做到思路清晰,Poetry的虚拟环境更方便好用。 再次强调:有了 Poetry,就不要再装pyenv-virtualenv了。

Poetry的安装及使用

Poetry 是一个Python 中的好用的包管理工具。在 Python 中,打包系统和依赖管理非常复杂:一个项目经常要同时创建多个文件,例如:

setup.py
requirements.txt
setup.cfg
MANIFEST.in
Pipfile

基于此, poetry 将所有的配置都放置在一个 toml 文件中,包括:依赖管理、构建、打包、发布等,可谓是简单方便。

Poetry用一个简单的基于pyproject.toml的项目格式取代了setup.pyrequirements.txtsetup.cfgMANIFEST.inPipfile

原理

  • pyproject.toml:这是一个配置文件,它用于定义项目的元数据和依赖关系。在pyproject.toml文件中,您可以指定项目的名称、版本、作者等信息,并列出项目所需的依赖项及其版本范围。该文件还可以包含构建和发布项目的相关配置。

  • poetry.lock:这是一个生成的锁定文件,它记录了确切的依赖关系版本。当运行poetry install命令时,Poetry会解析pyproject.toml文件并生成poetry.lock文件。锁定文件中列出了每个依赖项及其确切的版本号。这确保了在不同的开发环境或部署环境中都使用相同的依赖版本,从而增加项目的可重现性和稳定性。
    实际上就相当于pip 的requirements.txt,详细记载了所有安装的包与版本。

区别:

pyproject.toml是用于定义项目的元数据和依赖关系的配置文件,而poetry.lock是根据pyproject.toml文件生成的锁定文件,记录了确切的依赖版本。

pyproject.toml提供了依赖范围(例如,指定一个范围的最小和最大版本),而poetry.lock提供了精确的版本号。

作为应用程序开发人员:您应该将该poetry.lock文件提交到您的项目存储库,以便所有从事该项目的人员都被锁定到相同版本的依赖项。

作为库开发人员:库开发人员需要考虑更多。您的用户是应用程序开发人员,您的库将在您无法控制的 Python 环境中运行。您应该省略poetry.lock文件。

参考: https://python-poetry.org/docs/#installing-with-the-official-installer

安装

Poetry的安装需要 Python 环境来运行,因为默认会采用Python虚拟环境的方式安装Poetry。

"""
使用官方安装脚本:
打开命令提示符或 PowerShell。
运行以下命令:
"""
$ (Invoke-WebRequest -Uri https://install.python-poetry.org -UseBasicParsing).Content | python -

"""
这将从官方网站下载安装脚本并执行安装。安装完成后,记得将 Poetry 的安装目录(通常是 %USERPROFILE%\.poetry\bin)添加到系统环境变量中的 Path,以便在任何位置都能使用 poetry 命令。
"""


# 确认python环境
$ python -V

# 使用官方安装脚本进行安装
$ curl -sSL --insecure https://install.python-poetry.org | python3 -

# 添加Poetry可执行文件目录到环境变量中
$ echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bash_profile

# 重新加载 Shell 配置文件并将更改应用于当前会话
$ exec "$SHELL"

# 查看poetry版本
$ poetry --version

# 为Zsh 启用 poetry 命令的 Tab 键补全功能 或查看poetry help completions
$ mkdir ~/.zfunc
$ poetry completions zsh > ~/.zfunc/_poetry
$ echo 'fpath+=~/.zfunc' >> ~/.zshrc
$ echo 'autoload -Uz compinit && compinit' >> ~/.zshrc
$ exec "$SHELL"

默认情况下,Poetry安装到特定平台和用户的目录中

更新Poetry

# 更新至最新
$ poetry self update

# 指定要升级到的特定版本
$ poetry self update <version>

配置

可以通过config命令进行配置,也可以在配置文件中配置。

# 列出poetry配置,如果在poetry项目中会使用本地配置覆盖全局部分配置
$ poetry config --list

# 设置如果虚拟环境不存在,则自动创建虚拟环境
$ poetry config virtualenvs.create true

# 在项目根目录创建虚拟环境
$ poetry config virtualenvs.in-project true

# 不让虚拟环境有获取系统包的权限
$ poetry config virtualenvs.options.system-site-packages false

# 在创建新的虚拟环境时,环境中不会安装pip,生产环境非常建议
$ poetry config virtualenvs.options.no-pip true

# 在创建新的虚拟环境时,环境中不会安装setuptools,生产环境非常建议
$ poetry config virtualenvs.options.no-setuptools true

# poetry本地配置,实现针对于项目的设置,会在项目中创建poetry.toml文件
$ poetry config virtualenvs.create false --local

# 删除该字段的配置,自动恢复成默认值
$ poetry config virtualenvs.path --unset

使用

$ poetry new poetry-demo

poetry-demo						# 你的项目名称
├── README.md
├── poetry_demo				# 真正的项目代码放在这里
│   └── __init__.py
├── pyproject.toml		# 项目配置文件,不止能管理依赖版本,也可以在里面塞自己项目的配置
└── tests							# 测试用代码放在这里
    └── __init__.py

# 使用 src 布局进行创建,效果就是poetry_demo文件夹的名字改为src
$ poetry new --src <my-package>

把已有的项目交给Poetry来管理

$ cd <project-dir>
# 进入交互式界面配置pyproject.toml
$ poetry init
# 不问任何问题
$ poetry init --no-interaction




Package name [项目名]: 这是问你要给项目/包起什么名字,敲回车键即默认为文件夹的名字
Version [0.1.0]: 项目/包的版本,如果你没有特别需求也可以直接敲回车
Description []: 你对这个项目的详细描述,只有在发布到PyPI时有用
Author [姓名 <邮箱>, n to skip]: 你的作者信息,输入n可以忽略不填
License []: 项目用什么开源协议,看你心情
Compatible Python versions [^3.x]: 项目能兼容哪些py版本,没有特殊需求就敲回车
Would you like to define your main dependencies interactively? (yes/no) [yes]: 询问你是否要在这个交互式界面直接添加/安装项目依赖,建议选no,因为没必要在这里添加
Would you like to define your development dependencies interactively? (yes/no) [yes]: 同样建议选no
Generated file ...... Do you confirm generation? (yes/no) [yes]: 显然这里直接敲回车yes就可以

  • 只会pyproject.toml文件,不会生成lock文件
  • 在生成pyproject.toml文件中可以看到其中有一行[readme = "README.md"],此时,项目目录中必须要有README.md,否则会找不到并在未来使用中可能报错,一般直接删除。

接手别人的项目并安装所需依赖

# 推荐
$ poetry install --sync --no-root --only main

# 从当前项目中读取pyproject.toml文件,解析依赖项并安装这些模块
$ poetry install

# 只安装依赖,将防止安装项目本身作为依赖项
$ poetry install --no-root

# 输出安装依赖操作,但不真正执行
$ poetry install --dry-run

# 只安装mian环境的依赖,一般用作部署时
$ poetry install --only main

# 安装main+dev环境的依赖,一般用于开发
$ poetry install --with dev

# 同步当前环境并与lock文件完全一致,会自动卸载不在lock文件中的模块
$ poetry install --sync
  • pyproject.toml文件不存在,则会报错

  • 如不存在virtualenv,则会自动创建virtualenv,虚拟环境目录为{project-dir}/.venv前提是配置了poetry config virtualenvs.create true

  • 从当前项目中读取pyproject.toml文件,解析依赖项并安装这些模块。如果当前目录中有poetry.lock文件,它将使用lock那里的确切版本,而不是解析它们。这可以确保使用这个库的每个人都将获得相同版本的依赖项。

    如果没有poetry.lock文件,Poetry会在依赖解析后创建一个lock文件。

  • poetry install预设安装pyproject.toml中的所有环境的所有包。所有如果只想安装main环境的,也就是tool.poetry.dependencies区块的包,务必使用--only main

  • --with:代表[和]的关系,也就是说会安装main的包也要安装指定环境的包。

生成lock文件

# 根据pyproject.toml文件生成poetry.lock锁定文件,并不会安装任何模块
$ poetry lock

# 验证poetry.lock与pyproject.toml是否一致
$ poetry lock --check
  • 当自行修改了pyproject.toml内容,比如变更特定包的版本(这是有可能得,尤其在手动处理版本冲突的时候),此时poetry.lock的内容与pyproject.toml出现了“脱钩”,必须让它依照新的pyproject.toml内容更新、同步、使用指令poetry lock。如此一来,才能确保手动修改的内容,也更新到poetry.lock中,毕竟虚拟环境如果要重新建立,是基本poetry.lock的内容来安装包,而非pyproject.toml
  • poetry.lock相当于Poetry的requirements.txt
  • poetry lock指令,仅仅会更新poetry.lock,【不会】同时安装包至虚拟环境。

因此,在执行完poetry lock指令后,你必须再使用poetry install来安装套件,否则就会出现poetry.lock和虚拟环境不一致的状况。

搜索安装模块

# 搜索远程索引上的包
$ poetry search 包名

# 安装模块
$ poetry add 包名

# 为开发分组安装模块
$ poetry add 包名 --group-dev

# 安装特定版本的Python的模块
$ poetry add 包名>=2.0.5

# 允许>=2.0.5,<2.1.0的版本
$ poetry add <包名>@~2.0.5

# 允许>=2.0.5的版本
$ poetry add "包名>=2.0.5"

# 获取已存在Python包的最新版本
$ poetry add 包名@latest

# 安装本地Python模块
$ poetry add ../my-package/dist/my_package-0.1.0.whl

# 如果您要安装的软件包提供了额外功能,您可以在添加软件包时指定它们
$ poetry add "requests[security,socks]"

# 将包添加到dev依赖组中,组不会存在则自动创建
$ poetry add 包名 --group dev

# poetry不直接支持这一点,可以使用shell命令将其作为参数传递给Poetry的add命令
$ cat requirements.txt | xargs poetry add

#  使用pypi源安装此模块
$ poetry add --source pypi 包名
  • 如果没有virtualenv,则会自动创建virtualenv,前提是配置了``poetry config virtualenvs.create true`
  • 会自动配置pyproject.toml
  • pyproject.toml文件不存在则会报错
  • 在已有pyproject.toml文件的情况下,如不存在poetry.lock,则会自动创建poetry.lock
  • 如果尝试添加已存在的包,则会报错
  • 有些包,比如pytest,flake8等等,只会在开发环境中使用,产品的部署环境并不需要。Poetry允许你区分这两者,将上述的包安装在group.dev.dependencies区块,方便轻松建立一份不包含group.dev.dependencies开发包的安装清单。需使用--group参数。明确区分开发环境专用的套件非常必要。

常见的group.dev.dependencies区块项目,示例如下:

# poetry1.1老版本是[tool.poetry.dev-dependencies]
[tool.poetry.group.dev.dependencies] 
flake8 = "4.0.1" 
yapf = "0.32.0" 
pytest = "7.1.2" 
pytest-django = "4.5.2" 
pytest-cov = "3.0.0" 
pytest-env = "0.6.2" 
pytest-sugar = "0.9.4" 
pre-commit = "2.20.0"

当你使用poetry add指令时,Poetry会自动依序做完下面三件事:

  1. 更新pyproject.toml
  2. 依照

Docker Cmpose部署

前提条件

安装 Dify 之前, 请确保你的机器已满足最低安装要求:

  • CPU >= 2 Core

    • RAM >= 4GB
操作系统 软件 描述
macOS 10.14 or later Docker Desktop 为 Docker 虚拟机(VM)至少分配 2 个虚拟 CPU(vCPU) 和 8GB 初始内存,否则安装可能会失败。有关更多信息,请参考 《在 Mac 内安装 Docker 桌面端》
Linux platforms Docker 19.03 or later Docker Compose 1.28 or later 请参阅安装 Docker安装 Docker Compose 以获取更多信息。
Windows with WSL 2 enabled Docker Desktop 我们建议将源代码和其他数据绑定到 Linux 容器中时,将其存储在 Linux 文件系统中,而不是 Windows 文件系统中。有关更多信息,请参阅使用 WSL 2 后端在 Windows 上安装 Docker Desktop

克隆 Dify 代码仓库

克隆 Dify 源代码至本地环境。

git clone https://github.com/langgenius/dify.git

启动 Dify

  1. 进入 Dify 源代码的 Docker 目录

    cd dify/docker
    
  2. 复制环境配置文件

    cp .env.example .env
    
  3. 启动 Docker 容器

    根据你系统上的 Docker Compose 版本,选择合适的命令来启动容器。你可以通过 $ docker compose version 命令检查版本,详细说明请参考 Docker 官方文档

    • 如果版本是 Docker Compose V2,使用以下命令:
    docker compose up -d
    
    • 如果版本是 Docker Compose V1,使用以下命令:
    docker-compose up -d
    

运行命令后,你应该会看到类似以下的输出,显示所有容器的状态和端口映射:

[+] Running 11/11
 ✔ Network docker_ssrf_proxy_network  Created                                                                 0.1s 
 ✔ 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 
 ✔ 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 
 ✔ Container docker-worker-1          Started                                                                 6.4s 
 ✔ Container docker-nginx-1           Started                                                                 7.1s

最后检查是否所有容器都正常运行:

docker compose ps

在这个输出中,你应该可以看到包括 3 个业务服务 api / worker / web,以及 6 个基础组件 weaviate / db / redis / nginx / ssrf_proxy / sandbox

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
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
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             
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

通过这些步骤,你应该可以成功在本地安装 Dify。

启动docker-compose.yaml失败

一、网络相关问题

(针对Error response from daemon: Get "https://registry - 1.docker.io/v2/": net/http: request canceled while waiting for connection

  1. 检查网络连接
    • 确保你的计算机可以正常访问互联网。尝试在浏览器中打开https://registry - 1.docker.io/v2/,如果无法打开,可能是网络代理、防火墙或者网络配置的问题。
    • 如果是在公司网络环境下,可能需要配置代理。可以在 Docker 的设置中设置代理,具体步骤如下:
      • 右键点击系统托盘中的 Docker 图标,选择 “Settings”。
      • 在左侧导航栏中选择 “Resources”>“Proxies”。
      • 根据你的网络代理设置填写相应的代理服务器地址和端口。
  2. 调整 Docker 网络超时设置
    • 可以尝试增加 Docker 的网络超时时间。这可能需要编辑 Docker 的配置文件(通常在C:\ProgramData\Docker\config\daemon.json,如果文件不存在可以创建它)。
    • daemon.json文件中添加或修改以下内容:
     {
       "registry - mirrors": [],
       "max - concurrent - downloads": 10,
       "debug": true,
       "hosts": ["tcp://0.0.0.0:2375", "npipe://"],
       "http - headers": {
         "User - Agent": "Docker - Client/19.03.12 (windows)"
       },
       "network - timeout": 120
     }
  • 其中network - timeout的值(这里设置为 120 秒)可以根据需要调整,设置完成后重启 Docker 服务。
  1. 检查 DNS 设置
    • 不正确的 DNS 设置可能导致无法解析registry - 1.docker.io等域名。你可以尝试修改 DNS 服务器地址。
    • 在 Windows 系统中,可以通过以下步骤修改:
      • 打开 “控制面板”>“网络和共享中心”>“更改适配器设置”。
      • 右键点击正在使用的网络连接(如以太网或 Wi - Fi),选择 “属性”。
      • 在网络连接属性中,选择 “Internet 协议版本 4(TCP/IPv4)”,然后点击 “属性”。
      • 选择 “使用下面的 DNS 服务器地址”,并输入公共 DNS 服务器地址,如谷歌的8.8.8.88.8.4.4或者国内的114.114.114.114
二、针对每个容器的context canceled错误
  1. 资源不足
    • 检查系统资源,如内存和 CPU。如果资源不足,可能导致容器启动失败。关闭一些不必要的程序来释放资源。
    • 例如,如果内存不足,可以考虑增加虚拟机(如果在虚拟机中运行 Docker)或者物理机的内存。
  2. 镜像拉取问题(可能间接导致context canceled
    • 对于每个容器(如sandboxworker等),可能是因为相关镜像没有正确拉取。可以尝试手动拉取镜像,例如对于weaviate容器,可以先执行docker pull weaviate/weaviate:latest(根据实际使用的镜像标签进行调整)。
    • 如果镜像拉取过程中出现问题,参考上述网络相关的解决方法来确保可以正常拉取镜像。
  3. 检查docker - compose.yaml文件本身
    • 确保docker - compose.yaml文件的语法正确。可以使用在线的 YAML 验证工具(如https://yamllint.com/)来检查文件的语法。
    • 检查容器之间的依赖关系是否正确定义,以及每个容器的配置是否正确,例如端口是否冲突、环境变量是否设置正确等。

更新 Dify

进入 dify 源代码的 docker 目录,按顺序执行以下命令:

cd dify/docker
docker compose down
git pull origin main
docker compose pull
docker compose up -d

同步环境变量配置 (重要!)

  • 如果 .env.example 文件有更新,请务必同步修改您本地的 .env 文件。
  • 检查 .env 文件中的所有配置项,确保它们与您的实际运行环境相匹配。您可能需要将 .env.example 中的新变量添加到 .env 文件中,并更新已更改的任何值。

访问 Dify

你可以先前往管理员初始化页面设置设置管理员账户:

# 本地环境
http://localhost/install

# 服务器环境

http://your_server_ip/install

Dify 主页面:

# 本地环境
http://localhost

# 服务器环境
http://your_server_ip

自定义配置

编辑 .env 文件中的环境变量值。然后重新启动 Dify:

docker compose down
docker compose up -d

完整的环境变量集合可以在 docker/.env.example 中找到。

在启用业务服务之前,我们需要先部署 PostgresSQL / Redis / Weaviate(如果本地没有的话),可以通过以下命令启动:

cd docker
cp middleware.env.example middleware.env
docker compose -f docker-compose.middleware.yaml up -d

服务端部署

  • API 接口服务
  • Worker 异步队列消费服务

安装基础环境

服务器启动需要 Python 3.10.x。建议使用 pyenv 快速安装 Python 环境。

要安装其他 Python 版本,请使用 pyenv install

pyenv install 3.10

要切换到 "3.10" Python 环境,请使用以下命令:

pyenv global 3.10

启动步骤

  1. 进入 api 目录

    cd api
    
  2. 复制环境变量配置文件

    cp .env.example .env
    
  3. 生成随机密钥,并替换 .envSECRET_KEY 的值

    openssl rand -base64 42
    sed -i 's/SECRET_KEY=.*/SECRET_KEY=<your_value>/' .env
    
  4. 安装依赖包

    Dify API 服务使用 Poetry 来管理依赖。您可以执行 poetry shell 来激活环境。

    poetry env use 3.10
    poetry install
    
    pip install grpcio
    pip install -r requirements.txt
    pip install pytest-cov==2.8.1
    pip install pytest==5.3.0
    pip install coveralls==1.5.1
    pip install pydantic-settings
    pip install python-dotenv
    pip install pyyaml
    pip install flask_sqlalchemy
    conda install -c conda-forge pycryptodome\pip install pycryptodome
    pip install redis
    pip install Flask-Migrate
    pip install oss2
    pip install obs
    
  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)
     * 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 系统启动,请替换为该命令:

    celery -A app.celery worker -P solo --without-gossip --without-mingle -Q dataset,generation,mail,ops_trace --loglevel INFO
    

    正确输出:

  8.  -------------- 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
    - ** ---------- .> 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
    
    [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
      . 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
      . tasks.update_segment_keyword_index_task.update_segment_keyword_index_task
    
    [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.
    

前端页面部署

Web 前端客户端页面服务

安装基础环境

Web 前端服务启动需要用到 Node.js v18.x (LTS)NPM 版本 8.x.x Yarn

  • 安装 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
    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.
    # example: http://udify.app/api
    NEXT_PUBLIC_PUBLIC_API_PREFIX=http://localhost:5001/api
    
    # 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.
info  - Thank you for testing `appDir` please leave your feedback at https://nextjs.link/app-feedback

这里需要检查一下package.json文件中的代码,如下:

{
  "name": "dify-web",
  "version": "0.8.3",
  "private": true,
  "engines": {
    "node": ">=18.17.0"
  },
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "cp -r .next/static .next/standalone/.next/static && cp -r public .next/standalone/public && cross-env PORT=$npm_config_port HOSTNAME=$npm_config_host node .next/standalone/server.js",
    "lint": "next lint",
    "fix": "next lint --fix",
    "eslint-fix": "eslint --fix",
    "prepare": "cd ../ && node -e \"if (process.env.NODE_ENV !== 'production'){process.exit(1)} \" || husky install ./web/.husky",
    "gen-icons": "node ./app/components/base/icons/script.js",
    "uglify-embed": "node ./bin/uglify-embed",
    "check-i18n": "node ./i18n/check-i18n.js",
    "auto-gen-i18n": "node ./i18n/auto-gen-i18n.js",
    "test": "jest",
    "test:watch": "jest --watch"
  },
  "dependencies": {
    "@babel/runtime": "^7.22.3",
    "@dagrejs/dagre": "^1.1.2",
    "@emoji-mart/data": "^1.1.2",
    "@floating-ui/react": "^0.25.2",
    "@formatjs/intl-localematcher": "^0.5.4",
    "@headlessui/react": "^1.7.13",
    "@heroicons/react": "^2.0.16",
    "@hookform/resolvers": "^3.3.4",
    "@lexical/react": "^0.16.0",
    "@mdx-js/loader": "^2.3.0",
    "@mdx-js/react": "^2.3.0",
    "@monaco-editor/react": "^4.6.0",
    "@next/mdx": "^14.0.4",
    "@remixicon/react": "^4.2.0",
    "@sentry/react": "^7.54.0",
    "@sentry/utils": "^7.54.0",
    "@svgdotjs/svg.js": "^3.2.4",
    "@tailwindcss/line-clamp": "^0.4.4",
    "@tailwindcss/typography": "^0.5.9",
    "ahooks": "^3.7.5",
    "class-variance-authority": "^0.7.0",
    "classnames": "^2.3.2",
    "copy-to-clipboard": "^3.3.3",
    "crypto-js": "^4.2.0",
    "dayjs": "^1.11.7",
    "echarts": "^5.4.1",
    "echarts-for-react": "^3.0.2",
    "emoji-mart": "^5.5.2",
    "fast-deep-equal": "^3.1.3",
    "i18next": "^22.4.13",
    "i18next-resources-to-backend": "^1.1.3",
    "immer": "^9.0.19",
    "js-audio-recorder": "^1.0.7",
    "js-cookie": "^3.0.1",
    "katex": "^0.16.10",
    "lamejs": "^1.2.1",
    "lexical": "^0.16.0",
    "lodash-es": "^4.17.21",
    "mermaid": "10.4.0",
    "negotiator": "^0.6.3",
    "next": "^14.1.1",
    "next-nprogress-bar": "^2.3.8",
    "pinyin-pro": "^3.23.0",
    "qrcode.react": "^3.1.0",
    "qs": "^6.11.1",
    "rc-textarea": "^1.5.2",
    "react": "~18.2.0",
    "react-18-input-autosize": "^3.0.0",
    "react-dom": "~18.2.0",
    "react-easy-crop": "^5.0.8",
    "react-error-boundary": "^4.0.2",
    "react-headless-pagination": "^1.1.4",
    "react-hook-form": "^7.51.4",
    "react-i18next": "^12.2.0",
    "react-infinite-scroll-component": "^6.1.0",
    "react-markdown": "^8.0.6",
    "react-multi-email": "^1.0.14",
    "react-papaparse": "^4.1.0",
    "react-slider": "^2.0.4",
    "react-sortablejs": "^6.1.4",
    "react-syntax-highlighter": "^15.5.0",
    "react-tooltip": "5.8.3",
    "react-window": "^1.8.9",
    "react-window-infinite-loader": "^1.0.9",
    "reactflow": "^11.11.3",
    "recordrtc": "^5.6.2",
    "rehype-katex": "^6.0.2",
    "rehype-raw": "^7.0.0",
    "remark-breaks": "^3.0.2",
    "remark-gfm": "^3.0.1",
    "remark-math": "^5.1.1",
    "scheduler": "^0.23.0",
    "server-only": "^0.0.1",
    "sharp": "^0.33.2",
    "sortablejs": "^1.15.0",
    "swr": "^2.1.0",
    "tailwind-merge": "^2.4.0",
    "use-context-selector": "^1.4.1",
    "uuid": "^9.0.1",
    "zod": "^3.23.6",
    "zundo": "^2.1.0",
    "zustand": "^4.5.2"
  },
  "devDependencies": {
    "@antfu/eslint-config": "^0.36.0",
    "@faker-js/faker": "^7.6.0",
    "@rgrove/parse-xml": "^4.1.0",
    "@testing-library/dom": "^10.3.2",
    "@testing-library/jest-dom": "^6.4.6",
    "@testing-library/react": "^16.0.0",
    "@types/crypto-js": "^4.1.1",
    "@types/dagre": "^0.7.52",
    "@types/jest": "^29.5.12",
    "@types/js-cookie": "^3.0.3",
    "@types/lodash-es": "^4.17.7",
    "@types/negotiator": "^0.6.1",
    "@types/node": "18.15.0",
    "@types/qs": "^6.9.7",
    "@types/react": "~18.2.0",
    "@types/react-dom": "~18.2.0",
    "@types/react-slider": "^1.3.1",
    "@types/react-syntax-highlighter": "^15.5.6",
    "@types/react-window": "^1.8.5",
    "@types/react-window-infinite-loader": "^1.0.6",
    "@types/recordrtc": "^5.6.11",
    "@types/sortablejs": "^1.15.1",
    "@types/uuid": "^9.0.8",
    "autoprefixer": "^10.4.14",
    "bing-translate-api": "^4.0.2",
    "code-inspector-plugin": "^0.13.0",
    "cross-env": "^7.0.3",
    "eslint": "^8.36.0",
    "eslint-config-next": "^14.0.4",
    "husky": "^8.0.3",
    "jest": "^29.7.0",
    "jest-environment-jsdom": "^29.7.0",
    "lint-staged": "^13.2.2",
    "magicast": "^0.3.4",
    "postcss": "^8.4.31",
    "sass": "^1.61.0",
    "tailwindcss": "^3.4.4",
    "ts-node": "^10.9.2",
    "typescript": "4.9.5",
    "uglify-js": "^3.17.4"
  },
  "resolutions": {
    "@types/react": "~18.2.0",
    "@types/react-dom": "~18.2.0",
    "string-width": "4.2.3"
  },
  "lint-staged": {
    "**/*.js?(x)": [
      "eslint --fix"
    ],
    "**/*.ts?(x)": [
      "eslint --fix"
    ]
  }
}

这里注意scripts中的代码:

  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "cp -r .next/static .next/standalone/.next/static && cp -r public .next/standalone/public && cross-env PORT=$npm_config_port HOSTNAME=$npm_config_host node .next/standalone/server.js",
    "lint": "next lint",
    "fix": "next lint --fix",
    "eslint-fix": "eslint --fix",
    "prepare": "cd ../ && node -e \"if (process.env.NODE_ENV !== 'production'){process.exit(1)} \" || husky install ./web/.husky",
    "gen-icons": "node ./app/components/base/icons/script.js",
    "uglify-embed": "node ./bin/uglify-embed",
    "check-i18n": "node ./i18n/check-i18n.js",
    "auto-gen-i18n": "node ./i18n/auto-gen-i18n.js",
    "test": "jest",
    "test:watch": "jest --watch"
  },

这里注意:

#  这里的cp是Unix系统中的命令,yongyu7复制文件和目录
"start": "cp -r .next/static .next/standalone/.next/static && cp -r public .next/standalone/public && cross-env PORT=$npm_config_port HOSTNAME=$npm_config_host node .next/standalone/server.js",

# 在Windows系统中,需要使用copy或xcopy命令来实现相同的功能
# 1,使用copy命令,修改package.json文件中的start脚本,将cp替换为copy
     "start": "copy /r .next\\static .next\\standalone\\.next\\static && copy /r public .next\\standalone\\public && cross-env PORT=$npm_config_port HOSTNAME=$npm_config_host node .next\\standalone\\server.js"
# 2,使用xcopy命令,提供了更多的选项,适用于更复杂的复制操作
     "start": "xcopy /e /i .next\\static .next\\standalone\\.next\\static && xcopy /e /i public .next\\standalone\\public && cross-env PORT=$npm_config_port HOSTNAME=$npm_config_host node .next\\standalone\\server.js"
# 3,使用rimraf和copyfiles包        
# 安装rimraf和copyfiles包,这些包可以跨平台复制文件和目录
npm install --save-dev rimraf copyfiles
# 然后修改
     "start": "rimraf .next/standalone/.next/static && copyfiles -u 1 .next/static/* .next/standalone/.next/static && rimraf .next/standalone/public && copyfiles -u 1 public/* .next/standalone/public && cross-env PORT=$npm_config_port HOSTNAME=$npm_config_host node .next/standalone/server.js"

如果你经常在不同操作系统之间切换,考虑使用 cross-env 和 rimraf 这样的跨平台工具,以确保脚本在不同系统上都能正常工作。
在开发过程中,可以使用 npm run start:dev 脚本来启动开发服务器,避免频繁修改生产环境的配置。

访问 Dify

最后,访问 http://127.0.0.1:3000 即可使用本地部署的 Dify。

PreviousDocker Compose 部署Next单独启动前端 Docker 容器

接口方法

继承__base.model_provider.ModelProvider基类,实现接口:

def validate_provider_credentials(self,credentials:dict) -> None:
    """
    validate provider credentials
    验证提供者凭证
	您可以选择任何模型类型的validate credentials方法,或者实现validate me,例如:get model list API.
如果验证失败,提出异常
	:param credentials:提供者凭据,在`provider crede'中定义的凭据形式
    """
	pass

credentials(object)凭据信息

  • 凭据信息的参数由供应商 YAML 配置文件的 provider_credential_schema 定义,传入如:api_key 等。

验证失败请抛出 errors.validate.CredentialsValidateFailedError 错误。

注:预定义模型需完整实现该接口,自定义模型只需简单实现下面的即可:

class XinferenceProvider(Provider):
    def validate_provider_credentials(self,credentials:dict) -> None:
        pass

模型

模型分为5种不同的模型类型,不同的模型类型继承的模型基类不同,其实现方法也不同。

通用接口

所有模型均需要统一实现下面2个方法:

  • 模型凭据校验

    与供应商凭据校验类似,这里针对单个进行模型校验。

    def validate_credentials(self,models:str,credentials:dict) -> None:
        """
        validate credentials
        :params model:model name模型名字(string)
        :params credentials:model credentials凭据信息(objects)
        :return
        """
        pass
    
    • 凭据信息的参数由供应商 YAML 配置文件的 provider_credential_schema 定义,传入如:api_key 等。

    验证失败请抛出 errors.validate.CredentialsValidateFailedError 错误。

将远程服务器上的项目下载到本地

方法一:

命令行

# 用rsync命令
$ rsync -avz [远程服务器名]@[远程服务器的IP地址或主机名]:[远程服务器上项目的完整路径] [本地电脑上的目标路径]
    
# 用scp命令
$ scp -r [远程服务器名]@[远程服务器的IP地址或主机名]:[远程服务器上项目的完整路径] [本地电脑上的目标路径]

方法二:

直接点击Download,但

在 Windows 的命令提示符或 PowerShell 中可以使用 Chocolatey 包管理器来安装 OpenSSL。如果你的系统上没有安装 Chocolatey,可以先按照以下步骤安装 Chocolatey:

  1. 以管理员身份打开 PowerShell。

  2. 运行以下命令安装 Chocolatey: - Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))

安装好 Chocolatey 后,可以使用以下命令安装 OpenSSL:

  1. 在命令提示符或 PowerShell 中运行: -

    choco install openssl
    
  2. 这将使用 Chocolatey 下载并安装 OpenSSL。安装完成后,你可以在命令提示符或 PowerShell 中验证 openssl 命令是否可用。

在 Windows 系统下检查和解决 psycopg2.OperationalError 错误,可以按照以下步骤进行:

  1. 检查 PostgreSQL 服务状态
    确保 PostgreSQL 服务已经启动。你可以通过以下步骤来检查和启动服务:
    打开“服务”管理器:
    按 Win + R 打开运行对话框,输入 services.msc,然后按回车键。
    查找 PostgreSQL 服务:
    在服务列表中找到与 PostgreSQL 相关的服务,例如 postgresql-x64-12(具体名称取决于你安装的 PostgreSQL 版本)。
    检查服务状态:
    确认服务状态为“正在运行”。如果不是,右键点击服务,选择“启动”。
  2. 检查数据库连接字符串
    确保你的数据库连接字符串配置正确。常见的连接字符串格式如下:
DATABASE_URL = "postgresql://username:password@host:port/database"

用户名 (username):数据库用户名。
密码 (password):数据库密码。
主机 (host):数据库服务器的 IP 地址或主机名。
端口 (port):默认端口为 5432。
数据库名 (database):你要连接的数据库名称。

  1. 测试网络连接
    确保应用服务器能够访问数据库服务器。你可以使用 ping 和 telnet 命令来测试网络连接:
    打开命令提示符:
    按 Win + R 打开运行对话框,输入 cmd,然后按回车键。
    Ping 数据库服务器:
ping host

替换 host 为数据库服务器的 IP 地址或主机名。

  1. 测试端口连接:
   telnet host 5432

替换 host 为数据库服务器的 IP 地址或主机名。
如果 telnet 未安装,可以通过以下步骤安装:
打开“控制面板” -> “程序” -> “程序和功能” -> “启用或关闭 Windows 功能”。
勾选“Telnet 客户端”,然后点击“确定”。
4. 检查防火墙设置
确保防火墙允许从应用服务器到数据库服务器的连接:
打开 Windows 防火墙设置:
按 Win + R 打开运行对话框,输入 wf.msc,然后按回车键。
添加入站规则:
点击“入站规则” -> “新建规则”。
选择“端口”,点击“下一步”。
选择“TCP”,指定特定本地端口(例如 5432),点击“下一步”。
选择“允许连接”,点击“下一步”。
选择适用的网络类型(域、私有、公共),点击“下一步”。
输入规则名称(例如“PostgreSQL”),点击“完成”。
5. 查看 PostgreSQL 日志
检查 PostgreSQL 的日志文件,以获取更多关于连接失败的详细信息:
找到日志文件位置:
默认情况下,日志文件位于 PostgreSQL 安装目录下的 data 文件夹中,例如 C:\Program Files\PostgreSQL\12\data\pg_log。
查看日志文件:
使用文本编辑器(如 Notepad++)打开日志文件,查找与连接失败相关的错误信息。
6. 更新依赖库
确保 psycopg2 和 SQLAlchemy 的版本是最新的:
打开命令提示符:
按 Win + R 打开运行对话框,输入 cmd,然后按回车键。
更新库:

pip install --upgrade psycopg2-binary SQLAlchemy
   
poetry update psycopg2-binary SQLAlchemy
  1. 检查数据库配置
    确保 PostgreSQL 的配置文件(如 postgresql.conf 和 pg_hba.conf)允许来自应用服务器的连接:
    找到配置文件:
    默认情况下,配置文件位于 PostgreSQL 安装目录下的 data 文件夹中,例如 C:\Program Files\PostgreSQL\12\data。
    编辑 pg_hba.conf:
    添加或修改以下行,允许来自特定 IP 地址或子网的连接:
     host    all             all             192.168.1.0/24          md5

替换 192.168.1.0/24 为你的应用服务器的 IP 地址或子网。
重启 PostgreSQL 服务:
打开“服务”管理器,找到 PostgreSQL 服务,右键点击选择“重启”。
通过以上步骤,你应该能够定位并解决 psycopg2.OperationalError 错误。如果问题仍然存在,请提供更多详细信息以便进一步诊断。

posted @ 2024-10-25 11:18  澄小兮  阅读(319)  评论(0编辑  收藏  举报