#AI 实战营–上海站# 【末班车末班车】 OBCloud 构建 Dify x OceanBase 构建自己的 LLM 应用平台和智能体应用

一、前言:

实验环境

  • 系统版本:Centos 7.9
  • 内存:8G
  • 存储:70G
  • docker版本:26.1.4

上次广州ai搭建时部署过 AI 实践营实验,会有以下问题:

1.权限不足

Database migration skipped
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/celery/platforms.py:829: SecurityWarning: You're running the worker with superuser privileges: this is
absolutely not recommended!

2.表结构已存在

sqlalchemy.exc.OperationalError: (pymysql.err.OperationalError) (1050, "Table 'account_integrates' already exists")

解决方案:

  1. 创建一个新的超级用户,新的用户将具备 REFERENCES 权限
  2. 删除当前创建部分表的数据库,创建一个新的数据库用以连接

二、平台搭建步骤

1. 获取 OceanBase 数据库

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

1.1 注册并开通 OBCloud 实例

进入OB Cloud 云数据库 365 天免费试用页面,点击“立即试用”按钮,注册并登录账号,填写相关信息,开通实例,等待创建完成。

1.2 获取数据库实例连接串

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

1.3 创建多个数据库

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

2.安装docker

2.1安装依赖包
yum install -y yum-utils device-mapper-persistent-data lvm2
2.2docker-ce安装
sudo yum install -y docker-ce
2.3启动docker并设置开机自启
#启动docker命令
systemctl start docker
#设置开机自启命令
systemctl enable docker
#查看docker版本命令
docker version
2.4我的报错调整

我这里sudo 启动sudo sh scripts/setup-env.sh 一直报错,调整了权限(自己虚拟机给了777,大家别模仿)

[root@localhost ~]# ls -al /var/run/docker.sock
srw-rw----. 1 root docker 0 12月  9 17:09 /var/run/docker.sock
[root@localhost ~]# 
[root@localhost ~]# 
[root@localhost ~]# 
[root@localhost ~]# 
[root@localhost ~]# chmod 777 /var/run/docker.sock
[root@localhost ~]# 
检测数据库连接:

mysql: [Warning] Using a password on the command line interface can be insecure.

ERROR 2005 (HY000): Unknown MySQL server host 'obmt69g97qs7kio0-mi.aliyun-cn-hangzhou-internet.oceanbase.cloud' (-2)
test1 数据库连接失败!

mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 2005 (HY000): Unknown MySQL server host 'obmt69g97qs7kio0-mi.aliyun-cn-hangzhou-internet.oceanbase.cloud' (-2)
vectors 数据库连接失败!

3. 克隆项目

我们针对 Dify 的 0.12.1 版本进行了 MySQL 协议兼容的修改,并且上传到了我们 fork 的代码仓库中。大家网络条件好的话推荐克隆 Github 上的版本,否则克隆 Gitee 上的版本。

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

4. 拉取 Docker 镜像(有点慢)

root@localhost data]# cd dify/docker
[root@localhost docker]# 
[root@localhost docker]# 
[root@localhost docker]# 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 27/30
 ✔ worker Skipped - Image is already being pulled by api                                           0.0s 
 ⠏ web [⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀] Pulling                                                                  122.1s 
 ⠏ api [⣿⣿⣿⣿⣿⣿⣿⣿⣀⣿⣿⣿⣿] 481.5MB / 953.3MB Pulling                                              122.1s 
 ✔ redis Pulled                                                                                  103.8s 
 ✔ ssrf_proxy Pulled                                                                              35.5s 
 ⠏ nginx [⠀⠀⠀⠀⠀⠀⠀] Pulling                                                                       122.1s 
 ⠏ sandbox [⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀] Pulling                                                                 122.1s 

5. 修改环境变量

docker目录下存放着一个.env.example文件,其中包含了若干 Dify 运行所需的环境变量,我们需要把其中几个重要的配置项填写上。

我们在 docker/scripts 目录下提供了一个脚本 setup-env.sh 用来交互式地获取数据库连接信息,填入 .env 文件中并且完成数据库连接校验。你只需要执行:

[root@localhost docker]#sh scripts/setup-env.sh
请输入数据库配置信息:
数据库主机地址 [当前值: ob云连接ip]: 
数据库端口 [当前值: 3306]: 
数据库用户名 [当前值: xxx]: 
数据库密码 [当前值: 密码]: 
数据库名称 [当前值: test1]:       #自己创建的库
向量数据库名称 [当前值: vectors]: #自己创建的库

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

检测数据库连接:

mysql: [Warning] Using a password on the command line interface can be insecure.
Tables_in_test
call_center
catalog_page
catalog_returns
catalog_sales
corpus
customer
customer_address
customer_demographics
date_dim
household_demographics
income_band
inventory
item
promotion
reason
ship_mode
store
store_returns
store_sales
time_dim
warehouse
web_page
web_returns
web_sales
web_site
test 数据库连接成功~

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

[root@localhost docker]# 
[admin@localhost docker]$ sudo bash ./scripts/setup-env.sh -t
mysql: [Warning] Using a password on the command line interface can be insecure.
test1 数据库连接成功~

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

6. 启动 Dify 容器组

[admin@localhost docker]$ sudo docker compose --profile workshop up -d
[+] Running 9/9
 ✔ Network docker_ssrf_proxy_network  Created                        0.0s 
 ✔ Network docker_default             Created                        0.1s 
 ✔ Container docker-ssrf_proxy-1      Started                        1.1s 
 ✔ Container docker-sandbox-1         Started                        1.1s 
 ✔ Container docker-redis-1           Started                        1.2s 
 ✔ Container docker-web-1             Started                        1.2s 
 ✔ Container docker-worker-1          Started                        1.7s 
 ✔ Container docker-api-1             Started                        1.8s 
 ✔ Container docker-nginx-1           Started                        2.2s 
[admin@localhost docker]$ 

# 关闭
sudo docker compose stop 

7. 查看 Dify 后端服务日志

docker logs -f docker-api-1
docker logs -f docker-worker-1
7.1日志信息

正确的迁移:正常情况下会创建 72 张表,迁移完成的时候可能会有 Redis 相关的报错,这是 Redis 加锁超时的问题

[root@localhost docker]# docker logs -f docker-api-1
[root@localhost ~]# 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())
................................................................
# 有 Redis 相关的报错,这是 Redis 加锁超时的问题
  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.2云上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.05 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. 设置模型供应商和系统模型

填写API KEY 和模型名称qwen-turbo-2024-11-01

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

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

3.1 克隆文档仓库

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

[admin@localhost docker]$ git clone --single-branch --branch V4.3.4 https://gitee.com/oceanbase-devhub/oceanbase-doc.git ~/oceanbase-doc
正克隆到 '/home/admin/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
接收对象中: 100% (126520/126520), 69.60 MiB | 5.72 MiB/s, done.
处理 delta 中: 100% (55338/55338), done.
[admin@localhost docker]$ 
3.2 将指定文档上传到知识库中

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

为了节省时间和模型服务调用量,我们仅处理 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社区-分布式数据库

2 个赞

厉害厉害

2 个赞

大牛写得好详细,感谢分享 :+1:

2 个赞

随便玩玩,谢谢老师夸奖。 :handshake:

1 个赞