前言

本文从零开始完成了基于Dify的法律咨询大模型平台搭建的全流程。流程中先解决环境部署问题,因单台服务器系统盘存储空间有限,采用两台服务器分别部署不同服务,一台部署Dify与Ollama实现大模型调用和平台交互,另一台部署Xinference以提供Dify混合检索所需的rerank模型,针对两台服务器间网络不通的问题,通过内网穿透实现相互访问。

在部署过程中,完成Docker安装与配置,随后通过Ollama拉取Qwen3相关模型并配置GPU环境变量保障运行。同时,在另一台服务器完成Xinference的安装,创建并启动rerank模型,进而完成其与Dify的对接配置。

接着搭建高级检索知识库,先安装MinerU工具,将《中华人民共和国民营经济促进法》的PDF非结构化文档转换为Markdown格式,随后编写Python脚本对转换后的文档做数据清洗,如为章节和条款添加标识、优化段落格式等,之后基于清洗后的文档创建向量知识库,并完成分段清洗验证以及靶场命中率、模糊访问命中两类测试以保障知识库检索效果。

最后在Dify上创建多轮工作流项目,设置了细致的问题分类规则,能精准区分法律相关与无关问题,同时配置了关键内容提炼与规范回答的提示词,明确要求回答需100%基于知识库并标注条款出处,还附加免责声明,最终通过法律相关问题测试,实现了法律条文精准查询与规范回复的功能。

在这里插入图片描述

使用的云平台:
muliao
autodl
项目相关软件包和文件已上传

平台私有化部署

docker安装

git clone 速度太慢 可以开启AudoDL学术资源加速:
source /etc/network_turbo
取消代理:
unset http_proxy && unset https_proxy

在这里插入图片描述

export http_proxy=http://10.132.19.35:7890

export https_proxy=http://10.132.19.35:7890

命令行:

sudo apt-get update
#这个步骤可以不做
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
#如果网络不好,这个文件用手动的方式下载,然后把文件改名叫docker.asc即可
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
#将Docker的APT仓库添加到Ubuntu系统的APT源列表中,
#以便后续可以通过APT包管理器安装Docker相关的软件包
# Add the repository to Apt sources:
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update

 # 安装Docker 建议开启学术资源加载
sudo apt-get install docker-ce docker-ce-cli containerd.io
    # 启动Docker服务
sudo systemctl start docker
sudo systemctl status docker

在这里插入图片描述

遇到的问题:
在这里插入图片描述

问题原因是:Ubuntu 系统的自动更新进程 unattended-upgr 占用了 dpkg 包管理器的锁文件,导致当前安装命令无法获取锁资源。等待自动更新完成即可。
unattended-upgr 是系统后台自动更新服务,通常会在几分钟内完成(具体耗时看网络和更新内容多少)。可执行以下命令,确认自动更新进程是否还在运行:

# 查看 unattended-upgr 进程状态(输出有结果说明正在运行)
ps aux | grep unattended-upgr

若输出为空,说明自动更新已结束。

在这里插入图片描述

看到running状态说明docker已经正常启动

配置daemon.json文件

vim /etc/docker/daemon.json 

{
"exec-opts": ["native.cgroupdriver=systemd"],
"registry-mirrors":[
"https://hub.fast360.xyz",
"https://hub.rat.dev",
"https://hub.littlediary.cn",
"https://docker.kejilion.pro",
"https://dockerpull.cn",
"https://docker-0.unsee.tech",
"https://docker.tbedu.top",
"https://docker.1panelproxy.com",
"https://docker.melikeme.cn",
"https://cr.laoyou.ip-ddns.com",
"https://hub.firefly.store",
"https://docker.hlmirror.com",
"https://docker.m.daocloud.io",
"https://docker.1panel.live",
"https://image.cloudlayer.icu",
"https://docker.1ms.run"
],
"insecure-registries": ["http://easzlab.io.local:5000"],
"max-concurrent-downloads": 10,
"log-driver": "json-file",
"log-level": "warn",
"log-opts": {
"max-size": "10m",
"max-file": "3"
},
"data-root": "/var/lib/docker"
}



systemctl daemon-reload

systemctl restart docker

模型下载

# 使⽤conda创建虚拟环境
conda create -n hybrid-retrieval python=3.11 -y

# 进入虚拟环境
conda activate hybrid-retrieval

-y 是 conda 的一个可选参数,作用是自动确认所有交互式提示,无需手动输入 y(yes)确认操作。

方案一: 魔塔社区下载模型

魔塔社区地址:https://modelscope.cn/models

# 下载工具
pip install modelscope -i https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple

#下载模型
mkdir /data/models -pv

modelscope download --model Qwen/Qwen3-0.6B --local_dir /data/models/qwen3-0.6B

在这里插入图片描述

方案二:HuggingFace下载模型

官⽹地址(需要科学上⽹才能访问):https://huggingface.co/

# 安装下载工具
pip install huggingface_hub -i https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple

# 配置国内源
export HF_ENDPOINT="https://hf-mirror.com"

# 下载模型
huggingface-cli download --resume-download --local-dir-use-symlinks False
Qwen/Qwen2.5-VL-7B-Instruct --local-dir /data/models/qwen2-vl-7b/

方案三: 直接使用ollama拉取里面已经做好的模型(本文使用此方法

ollama 启动模型

下载地址:https://github.com/ollama/ollama/releases/download/v0.6.8/ollama-linux-amd64.tgz

tar -zxvf ollama-linux-amd64.tgz -C /usr/
useradd -r -s /bin/false -m -d /usr/share/ollama ollama

配置ollama启动程序:

cat > /etc/systemd/system/ollama.service << EOF
[Unit]
Description=Ollama Service
After=network-online.target
[Service]
ExecStart=/usr/bin/ollama serve
Environment="OLLAMA_HOST=0.0.0.0:8891"
User=ollama
Group=ollama
Restart=always
RestartSec=3
[Install]
WantedBy=default.target
EOF

为了能在本地让Dify接入Ollama,所以我们需要修改Ollama的端口号 8891(因为是租的服务器的缘故)

配置GPU环境变量:在文件的最末尾加上

vim /root/.bashrc
export OLLAMA_GPU_OVERHEAD=524288000 # 保留 500MB 显存
export OLLAMA_SCHED_SPREAD=0 # 均匀分配负载到所有 GPU
export OLLAMA_FLASH_ATTENTION=1 # 启用 Flash Attention
export OLLAMA_KV_CACHE_TYPE=f16 # 使用半精度浮点数
export OLLAMA_MAX_LOADED_MODELS=1 # 每个 GPU 最多加载 1 个模型
# 加载环境变量
source /root/.bashrc

#启动服务程序
ollama serve

#拉取并运行模型
OLLAMA_HOST=127.0.0.1:8891 ollama pull qwen3:8b

在这里插入图片描述

vllm启动模型:(仅展示vllm启动流程,不用操作此步骤,存储空间会不够)

# 拉取镜像
docker pull vllm/vllm-openai

# 启动镜像
docker run --entrypoint /bin/bash --network host --name node --shm-size 24g --gpus all
-e VLLM_HOST_IP=192.168.2.133 -e NCCL_SOCKET_IFNAME=eno1 -v
"/data/models:/data/models" "vllm/vllm-openai:latest" -c "ray start --block --head --
port=8888 --node-ip-address=192.168.2.133"

# 进入容器
docker exec -it node bash

# 运行模型
vllm serve /data/models/qwen3-14b/ --served_model_name qwen3-14b --max_model_len 20480
--max_num_seqs 8

dify 部署

# 下载
git clone https://github.com/langgenius/dify.git

# 进入到环境目录
cd dify/docker

# 将环境变量模板生效
cp .env.example .env

.env.example 是项目提供的环境变量模板文件,包含了运行项目所需的各类配置项(如数据库地址、API 密钥等),但通常是示例值或占位符。
cp .env.example .env
将环境变量模板文件复制为实际生效的环境变量文件

修改Dify端口号
vim .env

在这里插入图片描述

在这里插入图片描述

启动 dify

# docker-compose启动dify
docker-compose up -d

遇到的问题:
在这里插入图片描述

docker-compose下载地址:docker-compose
(此安装包已上传到csdn)

chmod +x docker-compose

mv docker-compose /usr/local/bin/

设置管理员用户 ---- 登录
在这里插入图片描述

在这里插入图片描述

修改密码 :
docker exec -it docker-api-1 flask reset-password

遇到的错误:
在这里插入图片描述
这个报错是权限被拒绝错误,核心原因是程序尝试写入文件(private.pem)时,没有对应的文件系统权限。

# 回到 Dify 的 docker 目录(关键!所有操作需在该目录执行)
cd ~/dify/docker

# 查看 docker-compose.ymal 中的挂载配置(找 volumes 字段)
grep -E 'volumes|volume' docker-compose.yaml

在这里插入图片描述

从 docker-compose.yaml 的挂载配置来看,Dify 所有数据都存储在宿主机的 ./volumes/ 目录下(包含数据库、缓存、存储等所有子目录)。之前的权限报错,本质是 宿主机的 ./volumes/ 目录或其下子目录不存在 / 权限不足,导致容器内程序无法创建 private.pem 等文件。

# 确保当前在 ~/dify/docker 目录(关键!)
cd ~/dify/docker

# 1. 创建 volumes 父目录(若不存在)
mkdir -p ./volumes

# 2. 给 volumes 目录及所有子目录开放最大权限(确保容器能读写)
chmod -R 777 ./volumes

# 3. 验证目录权限(输出 drwxrwxrwx 即为成功)
ls -ld ./volumes

在线模型配置及召回率测试

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

离线安装插件:

访问:https://marketplace.dify.ai/

在这里插入图片描述

在这里插入图片描述

ollama 模型配置

# 启动模型
systemctl start ollama

模型导入:
在这里插入图片描述
在这里插入图片描述

使用的是公网地址:

在这里插入图片描述

模型调用:
在这里插入图片描述
在这里插入图片描述

如果显存不⾜运⾏qwen3-14b模型,可以先停掉ollama,如下命令:
systemctl stop ollama

普通知识库创建

上传文件:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

召回率测试

召回率很低,也没有命中评分,接下来实现⾼级命中配置内容。

在这里插入图片描述

embedding 模型

随着大家的深入使用,发现ollama部署大模型虽然方便,但是Dify知识库混合检索,需要有rerank模型,这一点上,ollama是不支持rerank模型的,因此,部署一个Xinference平台来部署rerank模型的呼声越来越强烈。

因为第一个服务器系统盘满了,这里第二台服务器在autodl平台租用:

修改 pip 缓存目录(解决磁盘空间不足问题) 和 配置 pip 使用清华 PyPI 镜像源(加速包下载)

Xinference安装步骤:

# 使⽤conda创建虚拟环境
conda create -n xinference python=3.11 -y

# 进入虚拟环境
conda activate xinference 

# 修改pip缓存
echo 'export PIP_CACHE_DIR=/data/pip/cache' >> ~/.bashrc 
source ~/.bashrc
# 验证缓存文件夹改变
pip cache dir

# 配置清华源
python -m pip install --upgrade pip
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple

# 使用清华源进行升级
python -m pip install -i https://pypi.tuna.tsinghua.edu.cn/simple --upgrade pip

# 安装所有依赖
# 直接执行
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple "xinference[all]"

# 启动服务
# 前台
xinference-local --host 0.0.0.0 --port 8893

# 后台
#nohup xinference-local --host 0.0.0.0 --port 8890 & > output.log

可能遇到的问题:
在这里插入图片描述

# 从清华源安装 xoscar 0.7.13(预编译 wheel 包,直接安装无需编译)
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple xoscar==0.7.13

可能遇到的问题:
在这里插入图片描述

systemctl daemon-reload
systemctl restart ollama.service
# 再次验证端口监听(必须有输出)
ss -tulpn | grep 8891

# 现在执行带端口的拉取,必然成功
OLLAMA_HOST=127.0.0.1:8891 ollama pull qwen3:8b

在这里插入图片描述
在这里插入图片描述

创建rerank模型 并启动:

在这里插入图片描述

配置embedding 与 rerank模型到 dify

在这里插入图片描述

配置embedding:

dify所在环境与 Xinference 服务的网络不通(Xinference 运行在服务器,dify在其他服务器运行,未开放端口);基于此问题使用内网穿透的方法实现访问。

内网穿透

在这里插入图片描述

配置rerank:在这里插入图片描述

高级检索知识库

安装转换工具:

mineru

MinerU 是 OpenDataLab(开放数据实验室)开发的开源数据处理工具集,核心定位是 高效解析、转换、处理非结构化文档(尤其是 PDF),常被用于大模型训练的数据预处理、文档内容提取等场景。

文档解析与转换支持 PDF、Word 等格式的文档解析,能将非结构化内容(如排版复杂的 PDF)转换为结构化格式(Markdown、JSON、文本等),同时保留章节、条款等层级关系。

在这里插入图片描述

git clone https://github.com/opendatalab/MinerU.git
cd MinerU
uv pip install -e .[core]

将pdf转为md

mv 中华人民共和国民营经济促进法.pdf china.pdf
mineru -p china.pdf -o ./output-china
# 主要文件
ls output-china/china/auto/china.md

数据清洗:

# 切换到转换目录下
cd output-china/china/auto

# 程序编写
vim prompt.py
#!/opt/miniconda3/envs/mineru/bin/python

import re

def process_file(input_file_path, output_file_path):
    try:
        with open(input_file_path, 'r', encoding='utf-8') as file:
            content = file.read()
        
        # 为章节添加 @
        chapter_pattern = r'(第[一二三四五六七八九十百千]+章\s+[^\n]*)'
        content = re.sub(chapter_pattern, lambda m: m.group(1).strip() + ' @', content)
        
        # 为条款添加 @,确保条款内容完整(修复换行截断问题)
        article_pattern = r'(第[一二三四五六七八九十百千]+条\s+.*?)(?=(第[一二三四五六七八九十百千]+条|第[一二三四五六七八九十百千]+章|$))'
        content = re.sub(article_pattern, lambda m: m.group(1).strip() + ' @', content, flags=re.S)
        
        # 修复段落格式:在句号和分号后添加换行
        content = re.sub(r'([。;])\s*', r'\1\n', content)
        
        # 去除多余的空行
        content = re.sub(r'\n{3,}', '\n\n', content)
        
        with open(output_file_path, 'w', encoding='utf-8') as file:
            file.write(content)
        
        print(f"处理完成,结果已保存到 {output_file_path}")
    
    except FileNotFoundError:
        print(f"错误:未找到文件 {input_file_path}")
    except Exception as e:
        print(f"发生未知错误: {e}")

if __name__ == "__main__":
    # 注意:文件路径要和你的实际文件位置对应!
    input_file = './china.md'  # 你的输入MD文件路径(当前目录下)
    output_file = './china-out.md'  # 输出文件路径
    process_file(input_file, output_file)

执行python程序:

python prompt.py

向量知识库创建:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
分段与清洗 验证查看:
在这里插入图片描述

靶场命中率测试:
在这里插入图片描述
模糊访问命中测试:
在这里插入图片描述

创建多轮工作流项目

在这里插入图片描述
工作流初始化:
在这里插入图片描述

问题分类流:
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

分类提示词:

分类1:
用于法律相关的任何问题查询的分支,如用户提问第几章、第几条,还有任何关于法律隐晦的表述,我做了什么事情,某某事情该如何处理等等,都视为法律。

分类21. 法律内容直接提及••
包含法律名称
引用具体条款
涉及法律概念
••2. 法律行为描述••
提及权利义务关系
描述法律程序
涉及法律主体
••3. 法律实务需求••
法律条文查询
法律解释需求
法律文书需求
••4. 法律关联特征••
包含法律术语
涉及司法程序
包含法律文件
••5. 特殊标识情形••
明确标注法律章节
引用条文编号
涉及法律修订
••执行规则••
••全字段匹配••:只要出现上述任一特征即触发法律分类
••优先级排序••:
直接引用法律条文(章节/条款) > 法律概念 > 法律行为描述
••动态兼容••:
新增法律条文自动纳入分类(无需调整规则)
法律概念库持续扩展(如新增"数据安全法"相关术语)

分类3:
与任何法律不相关的问题,比如生活常识与经验类、科学技术与知识类、社会文化与情感类等等任何不与法律相关的问题。

分类4:
与法律完全不相关的内容

在这里插入图片描述

相关问题:

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
不相关问题:
在这里插入图片描述

我是一名法律助手,请问法律相关的问题。
比如:因合同纠纷提起的诉讼该如何处理。离婚案件,涉及商业秘密的案件,当事人是否可以申请不公开审理等等。

在这里插入图片描述

提取关键内容:
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

## 任务
请精准提炼用户所提出的法律条文相关问题中的核心要点,转化为用于高效检索法律条文知识库的关键内容。
确保关键内容能够准确反映问题主旨,以便从知识库中获取相关且有用的信息。
## 输出
以多个关键字或关键句的形式输出提炼结果,各关键字或关键句之间用空格分隔,仅呈现关键内容,不得包含
任何多余文本,严禁直接对用户输入的问题进行回答。尤其注意针对法律条文类问题进行准确提炼。
## 知识库引用
在回答用户问题时,请优先参考已上传的知识库内容。
请确保所有引用的内容都来自知识库,不要编造。

在这里插入图片描述
在这里插入图片描述

根据关键内容回答问题:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

系统提示词:

【角色定位】
您作为法律咨询AI助手,必须严格扮演专业法律顾问角色,以知识库为唯一依据提供法律服务。
【核心指令】
回答规范:
所有回答必须100%基于知识库原文内容
禁止任何超出知识库范围的推测、解释或补充
对知识库未涵盖的问题必须明确声明"根据现有知识库无法回答"
特别要求:
时间信息必须逐字引用知识库表述(包括但不限于时效、期限、天数等)
法律条款必须完整标注知识库中的出处条目
专业术语必须保持与知识库完全一致
回答结构:
1.明确声明"根据知识库第几章第几条"
2.直接引用相关条文内容
3.必要时应分段展示关联条款
【免责声明】
每个回答结尾必须附加:
"温馨提示:本回答严格依据现有知识库生成,如需法律效力文本请咨询执业律师。"
这个版本通过:
更严格的知识库绑定要求
特别强调时间信息的逐字引用
增加结构化回答规范
强化免责声明
使用强调性措辞("必须""禁止""100%"等)
{{#context#}}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
工作流测试:

# 提问问题
国家对民营经济组织及其经营者原始创新的保护是如何定义的。
# 原始内容答案
第三十三条 国家加强对民营经济组织及其经营者原始创新的保护。
加大创新成果知识产权保护力度,实施知识产权侵权惩罚性赔偿制度,依法查处侵犯商标专用权、专利权、著
作权和侵犯商业秘密、仿冒混淆等违法行为。
加强知识产权保护的区域、部门协作,为民营经济组织提供知识产权快速协同保护、多元纠纷解决、维权援助
以及海外知识产权纠纷应对指导和风险预警等服务。

在这里插入图片描述

更多推荐