#AI 实战营–上海站# Dify x OceanBase 构建 “应用级” 的 AI 助手 搭建完成啦!

一、前言:

Dify 是一个开源的 LLM 应用开发平台。其直观的界面结合了 AI 工作流、RAG 管道、Agent、模型管理、可观测性功能等,OceanBase 从 4.3.3 版本开始支持了向量数据类型的存储和检索,在 Dify 0.11.0 中开始支持使用 OceanBase 作为其向量数据库,接下来将通过实际搭建使用。

实验环境

Git
Docker 和 Docker Compose
MySQL 客户端(可选,如果使用 Docker 部署 OceanBase 则必须)

以上安装环境mysql客户端可采取开通 OBCloud 实例,还需一台安装部署doker(compose)服务器
当前采取虚拟机方式:
- 系统版本:Centos 7.6
- 内存:8G
- 存储:30G
- docker版本:26.1.4
- 本地还需安装ob4.3版本单实例数据库

当前部署参考官网提供网址https://gitee.com/oceanbase-devhub/dify/blob/master/docs/dify@oceanbase-workshop.md

二、平台搭建步骤

1. 获取 OceanBase 数据库

进行实验之前,我们需要先获取 OceanBase 数据库,目前可行的方式有两种:使用 OBCloud 实例或者使用 Docker 本地部署单机版 OceanBase 数据库。我们在此推荐 OBCloud 实例,因为它部署和管理都更加简单,且不需要本地环境支持。

##### 1.1 注册并开通 OBCloud 实例

进入[OB Cloud 云数据库 365 天免费试用](https://gitee.com/link?target=https%3A%2F%2Fwww.oceanbase.com%2Ffree-trial)页面,点击“立即试用”按钮,注册并登录账号,填写相关信息,开通实例,等待创建完成。

##### 1.2 获取数据库实例连接串

进入实例详情页的“实例工作台”,点击“连接”-“获取连接串”按钮来获取数据库连接串,将其中的连接信息填入后续步骤中创建的 .env 文件内。

![image](https://ask.oceanbase.com/uploads/default/original/3X/1/7/17961488c3ef27af6e2559c0ce53eb3f04681449.jpeg)

##### 1.3 创建多个数据库

为了分别存放结构化数据(满足 alembic 的数据库结构迁移方案要求)和向量数据,我们需要至少创建两个数据库。可在实例详情页面中的“数据库管理”功能中创建数据库。

![image](https://ask.oceanbase.com/uploads/default/original/3X/f/2/f293aea84401f2d09795eea6e3d9473072404432.jpeg)

2. 克隆项目

我们针对 Dify 的 0.12.1 版本进行了 MySQL 协议兼容的修改,并且上传到了我们 fork 的代码仓库中。大家网络条件好的话推荐克隆 Github 上的版本,否则克隆 Gitee 上的版本。
git命令如果没有可以 yum -y install git 安装

git clone https://github.com/oceanbase-devhub/dify.git
# 如果网络条件差
git clone https://gitee.com/oceanbase-devhub/dify.git

为保证 dify 目录的代码是最新的状态,需要执行 git pull 命令,拉取最新的代码
cd dify
git pull

3.安装docker到虚拟机

##### 3.1安装docker
这里我采取的是离线安装的方法
[root@localhost local]# tar -xvf docker-26.1.4.tgz
docker/
docker/docker-init
docker/runc
docker/docker
docker/docker-proxy
docker/containerd
docker/ctr
docker/dockerd
docker/containerd-shim
[root@localhost local]# ls -l docker
total 195504
-rwxr-xr-x. 1 lr lr 32751272 May 14 17:29 containerd
-rwxr-xr-x. 1 lr lr  6012928 May 14 17:29 containerd-shim
-rwxr-xr-x. 1 lr lr 18194536 May 14 17:29 ctr
-rwxr-xr-x. 1 lr lr 61113382 May 14 17:29 docker
-rwxr-xr-x. 1 lr lr 68874208 May 14 17:29 dockerd
-rwxr-xr-x. 1 lr lr   708616 May 14 17:29 docker-init
-rwxr-xr-x. 1 lr lr  2928514 May 14 17:29 docker-proxy
-rwxr-xr-x. 1 lr lr  9600696 May 14 17:29 runc
[root@localhost local]# mv docker/* /usr/bin/
vim /etc/systemd/system/docker.service
添加文件内容:
 
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service
Wants=network-online.target

[Service]
Type=notify
ExecStart=/usr/bin/dockerd --selinux-enabled=false
ExecReload=/bin/kill -s HUP $MAINPID
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
TimeoutStartSec=0
Delegate=yes
KillMode=process
Restart=on-failure
StartLimitBurst=3
StartLimitInterval=60s

[Install]
WantedBy=multi-user.target

赋执行权限
chmod +x /etc/systemd/system/docker.service
systemctl daemon-reload
#开机启动
systemctl enable docker.service
启动docker
systemctl start docker

root@zhz11g_dg docker]#  systemctl status docker
● docker.service - Docker Application Container Engine
   Loaded: loaded (/etc/systemd/system/docker.service; enabled; vendor preset: disabled)
   Active: active (running) since Wed 2024-04-10 15:57:42 CST; 4s ago
     Docs: https://docs.docker.com
 Main PID: 11471 (dockerd)
    Tasks: 17
   Memory: 39.4M
   CGroup: /system.slice/docker.service
           ├─11471 /usr/bin/dockerd --selinux-enabled=false
           └─11478 containerd --config /var/run/docker/containerd/containerd.toml --log-level info

##### 3.2安装docker Compose
 sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
  0     0    0     0    0     0      0      0 --:--:--  0:00:01 --:--:--     0
100 61.2M  100 61.2M    0     0  34070      0  0:31:24  0:31:24 --:--:-- 34053

下载完成后,确保文件具有执行权限。
sudo chmod +x /usr/local/bin/docker-compose

验证安装:最后,验证docker-compose是否正确安装。
docker-compose --version
Docker Compose version v2.31.0

4. 拉取 Docker 镜像

进入到 dify 的工作目录中的docker目录下,执行docker compose --profile workshop pull,拉取所需要的镜像
/usr/local/bin/docker-compose --profile workshop pull
WARN[0000] The "CERTBOT_EMAIL" variable is not set. Defaulting to a blank string. 
WARN[0000] The "CERTBOT_DOMAIN" variable is not set. Defaulting to a blank string. 
[+] Pulling 60/47
 ✔ worker Skipped - Image is already being pulled by api                                                                                                                                                           0.0s 
 ✔ web Pulled                                                                                                                                                                                                    162.6s 
 ✔ api Pulled                                                                                                                                                                                                    177.6s 
 ✔ redis Pulled                                                                                                                                                                                                  104.1s 
 ✔ sandbox Pulled                                                                                                                                                                                                100.9s 
 ✔ nginx Pulled                                                                                                                                                                                                  124.1s 
 ✔ ssrf_proxy Pulled                                                                                                                                                                                             145.4s 

5. ### 修改环境变量

在docker目录下存放着一个.env.example文件,其中包含了若干 Dify 运行所需的环境变量,我们需要把其中几个重要的配置项填写上
我们在 docker/scripts 目录下提供了一个脚本 setup-env.sh 用来交互式地获取数据库连接信息,填入 .env 文件中并且完成数据库连接校验。你只需要执行:
bash ./scripts/setup-env.sh
[root@postgres docker]# bash ./scripts/setup-env.sh
已从 .env.example 创建新的 .env 文件
请输入数据库配置信息:
数据库主机地址 [当前值: db]: 这里填写OBCloud的连接地址即可
数据库端口 [当前值: 5432]: 3306
数据库用户名 [当前值: postgres]: zhz
数据库密码 [当前值: difyai123456]: 密码
数据库名称 [当前值: dify]: zhz1
向量数据库名称 [当前值: test]: zhz2

数据库配置已更新到 .env 文件中

检测数据库连接:
mysql: [Warning] Using a password on the command line interface can be insecure.
zhz1 数据库连接成功~

mysql: [Warning] Using a password on the command line interface can be insecure.
zhz2 数据库连接成功~

6. 启动 Dify 容器组

启动之前先看看第 2 步开始拉取的镜像是否就绪,如果已经完成,可以使用下列命令启动 Dify 的容器组

/usr/local/bin/docker-compose --profile workshop up -d
[+] Running 4/6
[+] Running 6/7cker-ssrf_proxy-1  Running           0.0s 
[+] Running 7/7cker-ssrf_proxy-1  Running           0.0s 
 ✔ Container docker-ssrf_proxy-1  Running           0.0s 
 ✔ Container docker-redis-1       Running           0.0s 
 ✔ Container docker-worker-1      Started          19.2s 
 ✔ Container docker-web-1         Running           0.0s 
 ✔ Container docker-sandbox-1     Running           0.0s 
 ✔ Container docker-nginx-1       Started          19.7s 
 ✔ Container docker-api-1         Started           9.0s  

7. 查看 Dify 后端服务日志

docker logs -f docker-api-1
docker logs -f docker-worker-1
7.1日志信息报错情况
docker logs -f docker-api-1
Running migrations
None of PyTorch, TensorFlow >= 2.0, or Flax have been found. Models won't be available and only tokenizers, configuration and file/data utilities can be used.
/app/api/.venv/lib/python3.12/site-packages/tencentcloud/hunyuan/v20230901/models.py:5585: SyntaxWarning: invalid escape sequence '\_'
  """function名称,只能包含a-z,A-Z,0-9,\_或-
/app/api/.venv/lib/python3.12/site-packages/jieba/__init__.py:44: SyntaxWarning: invalid escape sequence '\.'
  re_han_default = re.compile("([\u4E00-\u9FD5a-zA-Z0-9+#&\._%\-]+)", re.U)
/app/api/.venv/lib/python3.12/site-packages/jieba/__init__.py:46: SyntaxWarning: invalid escape sequence '\s'
  re_skip_default = re.compile("(\r\n|\s)", re.U)
/app/api/.venv/lib/python3.12/site-packages/jieba/finalseg/__init__.py:78: SyntaxWarning: invalid escape sequence '\.'
  re_skip = re.compile("([a-zA-Z0-9]+(?:\.\d+)?%?)")
/app/api/.venv/lib/python3.12/site-packages/jieba/posseg/__init__.py:16: SyntaxWarning: invalid escape sequence '\.'
  re_skip_detail = re.compile("([\.0-9]+|[a-zA-Z0-9]+)")
/app/api/.venv/lib/python3.12/site-packages/jieba/posseg/__init__.py:17: SyntaxWarning: invalid escape sequence '\.'
  re_han_internal = re.compile("([\u4E00-\u9FD5a-zA-Z0-9+#&\._]+)")
/app/api/.venv/lib/python3.12/site-packages/jieba/posseg/__init__.py:18: SyntaxWarning: invalid escape sequence '\s'
  re_skip_internal = re.compile("(\r\n|\s)")
/app/api/.venv/lib/python3.12/site-packages/jieba/posseg/__init__.py:21: SyntaxWarning: invalid escape sequence '\.'
  re_num = re.compile("[\.0-9]+")
2024-12-11 02:34:40.394 INFO [pre_load_builtin_providers_cache] [font_manager.py:1578] - generated new fontManager
Preparing database migration...
Starting database migration.
INFO  [alembic.runtime.migration] Context impl MySQLImpl.
INFO  [alembic.runtime.migration] Will assume non-transactional DDL.
ERROR [root] Failed to execute database migration

这里报错ERROR [root] Failed to execute database migration,我这里采取的方法是切换非root用户,重新执行第5步,修改环境变量后启动就正常了。
7.2日志信息

执行成功后,显示Database migration successful! 即可完成操作

docker logs -f docker-api-1
docker logs -f docker-api-1
Running migrations
.................................................................
fontManager
Preparing database migration...
Starting database migration.
INFO  [alembic.runtime.migration] Context impl MySQLImpl.
INFO  [alembic.runtime.migration] Will assume non-transactional DDL.
INFO  [alembic.runtime.migration] Running upgrade  -> 01d6889832f7, snapshot

Database migration successful!                   
Traceback (most recent call last):
  File "/app/api/.venv/bin/flask", line 8, in <module>
    sys.exit(main())
  File "/app/api/commands.py", line 595, in upgrade_db
    lock.release()
  File "/app/api/.venv/lib/python3.12/site-packages/redis/lock.py", line 256, in release
    self.do_release(expected_token)
  File "/app/api/.venv/lib/python3.12/site-packages/redis/lock.py", line 262, in do_release
    raise LockNotOwnedError(
redis.exceptions.LockNotOwnedError: Cannot release a lock that's no longer owned

如果在其中任意一个容器的日志中看到了Database migration successful!这一条信息,则说明数据库结构升级完成(另一个容器中可能会有Database migration skipped表示在该容器中跳过了数据库结构迁移),如果没有其他ERROR信息,则说明可以正常打开 Dify 界面了。

7.3OBCloud上mysql中有 72 张表
mysql> show tables;
+-----------------------------------+
| Tables_in_test1                   |
+-----------------------------------+
| account_integrates                |
| accounts                          |
| alembic_version                   |
| api_based_extensions              |
| api_requests                      |
| api_tokens                        |
| app_annotation_hit_histories      |
| app_annotation_settings           |
| app_dataset_joins                 |
| app_model_configs                 |
| apps                              |
| celery_taskmeta                   |
| celery_tasksetmeta                |
| conversations                     |
| data_source_api_key_auth_bindings |
| data_source_oauth_bindings        |
| dataset_collection_bindings       |
| dataset_keyword_tables            |
| dataset_permissions               |
| dataset_process_rules             |
| dataset_queries                   |
| dataset_retriever_resources       |
| datasets                          |
| dify_setups                       |
| document_segments                 |
| documents                         |
| embeddings                        |
| end_users                         |
| external_knowledge_apis           |
| external_knowledge_bindings       |
| installed_apps                    |
| invitation_codes                  |
| load_balancing_model_configs      |
| message_agent_thoughts            |
| message_annotations               |
| message_chains                    |
| message_feedbacks                 |
| message_files                     |
| messages                          |
| operation_logs                    |
| pinned_conversations              |
| provider_model_settings           |
| provider_models                   |
| provider_orders                   |
| providers                         |
| recommended_apps                  |
| saved_messages                    |
| sites                             |
| tag_bindings                      |
| tags                              |
| tenant_account_joins              |
| tenant_default_models             |
| tenant_preferred_model_providers  |
| tenants                           |
| tidb_auth_bindings                |
| tool_api_providers                |
| tool_builtin_providers            |
| tool_conversation_variables       |
| tool_files                        |
| tool_label_bindings               |
| tool_model_invokes                |
| tool_providers                    |
| tool_published_apps               |
| tool_workflow_providers           |
| trace_app_config                  |
| upload_files                      |
| whitelists                        |
| workflow_app_logs                 |
| workflow_conversation_variables   |
| workflow_node_executions          |
| workflow_runs                     |
| workflows                         |
+-----------------------------------+
72 rows in set (0.03 sec)

8. 访问 Dify 应用

默认情况下,Dify 的前端页面会启动在本机的80端口上,也就是说可以通过访问当前机器的 IP 来访问 Dify 的界面。也就是说如果我在笔记本上运行的话,我在浏览器上访问localhost即可(或者是内网 IP);如果在服务器上部署 Dify,则需要访问服务器的公网 IP。初次访问 Dify 应用会进入“设置管理员账户”的页面,设置完成后即可使用该账号登录。

三、应用开发步骤

在该步骤当中我们将使用阿里云百炼的模型服务,通过 Dify 搭建一个文档 RAG 问答助手。

1. 开通阿里云百炼模型调用服务并获取 API KEY

首先,我们需要注册阿里云百炼账号,开通模型调用服务并获取 API Key

参考文档:docs/dify@oceanbase-workshop.md · oceanbase-devhub/dify - Gitee.com

2. 设置模型供应商和系统模型

设置完成模型供应商之后刷新网页,再向通义千问模型供应商中添加模型qwen-turbo-2024-11-01

完成系统模型设置,将系统推理模型设置为qwen-turbo-2024-11-01,Embedding 模型设置为text-embedding-v3

3. 创建知识库并上传文档

3.1 克隆文档仓库

我们将 OceanBase 数据库的开源文档仓库克隆下来,作为数据来源。

git clone --single-branch --branch V4.3.4 https://github.com/oceanbase/oceanbase-doc.git ~/oceanbase-doc
# 如果您访问 Github 仓库速度较慢,可以使用以下命令克隆 Gitee 的镜像版本
git clone --single-branch --branch V4.3.4 https://gitee.com/oceanbase-devhub/oceanbase-doc.git ~/oceanbase-doc

Cloning into '/root/oceanbase-doc'...
remote: Enumerating objects: 126520, done.
remote: Counting objects: 100% (126520/126520), done.
remote: Compressing objects: 100% (70851/70851), done.
remote: Total 126520 (delta 55338), reused 126520 (delta 55338), pack-reused 0
Receiving objects: 100% (126520/126520), 69.60 MiB | 6.89 MiB/s, done.
Resolving deltas: 100% (55338/55338), done.
3.2 将指定文档上传到知识库中

回到首页,顶端中部的“知识库”标签页,进入知识库管理界面,点击创建知识库。

![[Pasted image 20241211120126.png]]
为了节省时间和模型服务调用量,我们仅处理 OceanBase 向量检索有关的几篇文档,这些文档相对于oceanbase-doc目录的相对路径是zh-CN/640.ob-vector-search,我们需要将这个目录下面所有的文档都上传。

索引方式选择“高质量”,点击“保存并处理”。

Dify 会提示知识库“已创建”,后续可能会看到某些文档已经在此处理完成。点击“前往文档”。

点击“前往文档”后会看到该知识库中的文档列表。

4. 创建对话应用并选中知识库

点击“工作室”标签页,进入应用管理界面,点击“创建空白应用”。

保持默认选项“聊天助手”和“基础编排”即可,应用名称可以自行填写,例如 “OB 向量文档助手”。输入完成后点击“创建”按钮。

创建完成后会进入应用编排界面,首先关注右上角的默认模型设置,如果不是qwen-turbo-2024-11-01则修改为qwen-turbo-2024-11-01

点击“上下文”卡片中的“添加”按钮,选中刚才我们创建的知识库并点击“添加”按钮。

随后,在提示词的输入框中填写如下的提示词:

你是一个专注于回答 OceanBase 社区版问题的机器人。
你的目标是利用可能存在的历史对话和检索到的文档片段,回答用户的问题。
任务描述:根据可能存在的历史对话、用户问题和检索到的文档片段,尝试回答用户问题。如果用户的问题与 OceanBase 无关,则抱歉说明无法回答。如果所有文档都无法解决用户问题,首先考虑用户问题的合理性。如果用户问题不合理,需要进行纠正。如果用户问题合理但找不到相关信息,则表示抱歉并给出基于内在知识的可能解答。如果文档中的信息可以解答用户问题,则根据文档信息严格回答问题。

回答要求:
- 如果所有文档都无法解决用户问题,首先考虑用户问题的合理性。如果用户问题不合理,请回答:“您的问题可能存在误解,实际上据我所知……(提供正确的信息)”。如果用户问题合理但找不到相关信息,请回答:“抱歉,无法从检索到的文档中找到解决此问题的信息。请联系OceanBase的人工答疑以获取更多帮助。基于我的内在知识,可能的解答是……(根据内在知识给出可能解答)”。
- 如果文档中的信息可以解答用户问题,请回答:“根据文档库中的信息,……(严格依据文档信息回答用户问题)”。如果答案可以在某一篇文档中找到,请在回答时直接指出依据的文档名称及段落的标题(不要指出片段标号)。
- 如果某个文档片段中包含代码,请务必引起重视,给用户的回答中尽可能包含代码。请完全参考文档信息回答用户问题,不要编造事实,尤其是数据表名、SQL 语句等关键信息。
- 如果需要综合多个文档中的片段信息,请全面地总结理解后尝试给出全面专业的回答。
- 尽可能分点并且详细地解答用户的问题,回答不宜过短。

可以在右侧聊天框里进行应用调试,例如询问“请介绍一下 OceanBase 的向量功能”

5. 发布应用,开始对话!

点击应用详情右上角的“发布”下面的“运行”按钮,会打开该应用的专属页面。

点击 Start Chat 按钮即可开始聊天。

如果你是在服务器上部署的 Dify,也可以将该应用的链接分享给身边的朋友,让他们也一起来试用一下吧!

自此,你已经通过 Dify + OceanBase 搭建了你自己的 LLM 应用平台和智能体应用,恭喜你!:tada:

四、参考文档:

docs/dify@oceanbase-workshop.md · oceanbase-devhub/dify - Gitee.com

#AI 实战营–上海站# 基于 OBCloud 构建 Dify x OceanBase 构建 “应用级” 的 AI 助手 - 社区问答- OceanBase社区-分布式数据库

1 个赞