From e6f76aee9de21ac3a21343d93f81de6853b42ac6 Mon Sep 17 00:00:00 2001 From: Wenjie Zhang Date: Fri, 28 Feb 2025 14:39:03 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dollama?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 176 ++++++++++++++++++++-------------- docker/docker-compose.dev.yml | 3 + docker/web.Dockerfile | 8 +- src/models/__init__.py | 4 +- src/models/chat_model.py | 12 ++- 5 files changed, 123 insertions(+), 80 deletions(-) diff --git a/README.md b/README.md index 02242e1a..448ce1b2 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ -

语析 (基于大模型的知识库+知识图谱问答平台)

+

语析 - 基于大模型的知识库与知识图谱问答平台

![](https://img.shields.io/badge/Docker-2496ED?style=flat&logo=docker&logoColor=ffffff) -![Vue.js](https://img.shields.io/badge/vuejs-%2335495e.svg?style=flat&logo=vuedotjs&logoColor=%234FC08D)  +![Vue.js](https://img.shields.io/badge/vuejs-%2335495e.svg?style=flat&logo=vuedotjs&logoColor=%234FC08D) ![FastAPI](https://img.shields.io/badge/FastAPI-005571?style=flat&logo=fastapi) ![](https://img.shields.io/github/issues/xerrors/Yuxi-Know?color=F48D73) ![](https://img.shields.io/github/license/bitcookies/winrar-keygen.svg?logo=github) @@ -10,52 +10,61 @@
-## 概述 +## 📝 项目概述 -基于大模型 RAG 知识库与知识图谱的问答平台。Llamaindex + VueJS + Flask + Neo4j。大模型适配 OpenAI、国内主流大模型平台的模型调用、本地 vllm 部署。只需要配置对应服务平台的 `API_KEY` 即可使用。 +语析是一个强大的问答平台,结合了大模型 RAG 知识库与知识图谱技术,基于 Llamaindex + VueJS + FastAPI + Neo4j 构建。 -![image](https://github.com/user-attachments/assets/75010511-4ac5-4924-8268-fea9a589839c) +**核心特点:** -> [!NOTE] -> 当前项目还处于开发的早期,还存在一些 BUG,有问题随时提 issue。 +- 🤖 多模型支持:适配 OpenAI、各大国内主流大模型平台,以及本地 vllm 部署 +- 📚 灵活知识库:支持 PDF、TXT、MD 等多种格式文档 +- 🕸️ 知识图谱集成:基于 Neo4j 的知识图谱问答能力 +- 🚀 简单配置:只需配置对应服务平台的 `API_KEY` 即可使用 -代办清单 +![系统界面预览](https://github.com/user-attachments/assets/75010511-4ac5-4924-8268-fea9a589839c) -- [ ] Ollma Embedding 支持(Open-like Embedding 支持) -- [ ] embedding 过程添加进度显示 -- [X] 知识图谱索引支持自定义 Embedding 模型 -- [X] DeepSeek-R1 支持 +## 📋 更新日志 -## 更新日志 +- **2025.02.24** - 新增网页检索以及内容展示,需配置 `TAVILY_API_KEY`,感谢 [littlewwwhite](https://github.com/littlewwwhite) +- **2025.02.23** - SiliconFlow 的 Rerank 和 Embedding model 支持,现默认使用 SiliconFlow +- **2025.02.20** - DeepSeek-R1 支持,需配置 `DEEPSEEK_API_KEY` 或 `SILICONFLOW_API_KEY` +- **2024.10.12** - 后端修改为 [FastAPI](https://github.com/fastapi),添加 [Milvus-Standalone](https://github.com/milvus-io) 独立部署 -- 2025.02.24 新增网页检索以及内容展示,需要配置 `TAVILY_API_KEY`, 感谢 [littlewwwhite](https://github.com/littlewwwhite)。 -- 2025.02.23 SiliconFlow 的 Rerank 和 Embedding model 支持。现在默认使用 SiliconFlow。 -- 2025.02.20 DeepSeek-R1 支持,需配置 `DEEPSEEK_API_KEY` 或者 `SILICONFLOW_API_KEY` 使用 -- 2024.10.12 后端修改为 [FastAPI](https://github.com/fastapi),并添加了 [Milvus-Standalone](https://github.com/milvus-io) 的独立部署。 +![功能展示](https://github.com/user-attachments/assets/8416a933-cc43-45d0-bf06-00df0ba6c4fb) -![image](https://github.com/user-attachments/assets/8416a933-cc43-45d0-bf06-00df0ba6c4fb) +## 🚀 快速上手 -## 快速上手 +### 环境配置 -在启动之前,提供 API 服务商的 API_KEY,并放置在 `src/.env` 文件中。默认使用的是硅基流动。因此务必需要配置 `SILICONFLOW_API_KEY=`。其余模型的配置可以参考 [src/static/models.yaml](src/static/models.yaml) 中的 env。 +在启动前,您需要提供 API 服务商的 API_KEY,并放置在 `src/.env` 文件中。 + +默认使用硅基流动的服务,因此**必须**配置: ``` SILICONFLOW_API_KEY=sk-270ea********8bfa97.e3XOMd****Q1Sk ``` -本项目的基础对话服务可以在不含显卡的设备上运行,大模型使用在线服务商的接口。如果需要指定本地模型(如 Embedding、Rerank 模型)所在路径,需要配置 `MODEL_DIR` 参数。并在 Docker Compose 中启用映射。 +> 本项目的基础对话服务可在不含显卡的设备上运行,大模型使用在线服务商的接口。 -**提醒**:下面的脚本会启动开发版本,源代码的修改会自动更新(含前端和后端)。如果生产环境部署,请使用 `docker/docker-compose.yml` 启动。 +### 启动服务 + +**开发环境启动**(源代码修改会自动更新): ```bash docker compose -f docker/docker-compose.dev.yml --env-file src/.env up --build ``` -**也可以加上 `-d` 参数,后台运行。* +> 添加 `-d` 参数可在后台运行 -下面的这些容器都会启动: +**生产环境部署**请使用: ```bash +docker compose -f docker/docker-compose.yml --env-file src/.env up --build -d +``` + +成功启动后,会看到以下容器: + +``` [+] Running 7/7 ✔ Network docker_app-network Created ✔ Container graph-dev Started @@ -66,37 +75,31 @@ docker compose -f docker/docker-compose.dev.yml --env-file src/.env up --build ✔ Container web-dev Started ``` -然后打开 [http://localhost:5173/](http://localhost:5173/) 就可以看到结果了。 +访问 [http://localhost:5173/](http://localhost:5173/) 即可使用系统。 -**预览** +### 系统预览 -![DEMO.GIF](./images/demo.gif) +![系统演示](./images/demo.gif) -关闭 docker 服务: +### 服务管理 + +**关闭服务**: ```bash docker compose -f docker/docker-compose.dev.yml --env-file src/.env down ``` -查看日志: +**查看日志**: ```bash -docker logs # 例如:docker logs api-dev +docker logs <容器名称> # 例如:docker logs api-dev ``` -**生产环境部署**:本项目同时支持使用 Docker 部署生产环境,只需要更换 `docker-compose` 文件就可以了。 +## 💻 模型支持 -```bash -docker compose -f docker/docker-compose.yml --env-file src/.env up --build -``` +### 1. 对话模型 -注:如果想要在本地使用 PyCharm 等 IDE 加断点调试,可以使用 Docker 运行除 API 以外的容器,然后本地运行 main.py,但是需要注意将对应的环境变量添加到 .env 文件中 - -## 模型支持 - -### 1. 对话模型支持 - -模型仅支持通过API调用的模型,如果是需要运行本地模型,则建议使用 vllm 转成 API 服务之后使用。使用前请在 `.env` 配置 APIKEY 后使用,配置项目参考:[src/static/models.yaml](src/static/models.yaml) +本项目支持通过 API 调用的模型,本地模型需使用 vllm、ollama 转成 API 服务后使用。 | 模型供应商 | 默认模型 | 配置项目 | | :--------------------- | :---------------------------------- | :--------------------------------------------- | @@ -108,62 +111,89 @@ docker compose -f docker/docker-compose.yml --env-file src/.env up --build | `dashscope`(阿里) | `qwen-max-latest` | `DASHSCOPE_API_KEY` | | `qianfan`(百度) | `ernie_speed` | `QIANFAN_ACCESS_KEY`, `QIANFAN_SECRET_KEY` | -此外,如果想要添加供应商的模型,确认知识 OpenAI 调用的方法之后,只需要在 [src/static/models.yaml](src/static/models.yaml) 中添加对应的模型配置即可。配置示例如下: +#### 添加新模型供应商 + +如需添加供应商模型,了解 OpenAI 调用方法后,只需在 [src/static/models.yaml](src/static/models.yaml) 中添加对应配置: ```yaml - ark: - name: 豆包(Ark) - url: https://console.volcengine.com/ark/region:ark+cn-beijing/model # 模型列表 - default: doubao-1-5-pro-32k-250115 # 默认模型 - base_url: https://ark.cn-beijing.volces.com/api/v3 - env: # 需要配置的环境变量,仅限API key - - ARK_API_KEY - models: - - doubao-1-5-pro-32k-250115 - - doubao-1-5-lite-32k-250115 - - deepseek-r1-250120 +ark: + name: 豆包(Ark) + url: https://console.volcengine.com/ark/region:ark+cn-beijing/model # 模型列表 + default: doubao-1-5-pro-32k-250115 # 默认模型 + base_url: https://ark.cn-beijing.volces.com/api/v3 + env: # 需要配置的环境变量,仅限API key + - ARK_API_KEY + models: + - doubao-1-5-pro-32k-250115 + - doubao-1-5-lite-32k-250115 + - deepseek-r1-250120 ``` -同样支持添加以 OpenAI 的兼容模式运行的单个模型,可以直接在 Web 设置里面添加。比如使用 vllm 和 Ollama 运行本地模型时。 +#### 本地模型部署 -![](./images/custom_models.png) +支持添加以 OpenAI 兼容模式运行的本地模型,可在 Web 设置中直接添加(适用于 vllm 和 Ollama 等)。 -### 2. 向量模型支持和重排序模型支持 +> [!注意] +> 使用 docker 运行此项目时,ollama 或 vllm 需监听 `0.0.0.0` -建议直接使用硅基流动部署的 bge-m3,这样不需要做任何修改,且免费。其余模型参考:[src/static/models.yaml](src/static/models.yaml) +![本地模型配置](./images/custom_models.png) -> [!Warning] -> 需要注意,由于知识库和图数据库的构建都依赖于向量模型,如果中途更改向量模型,会导致知识库不可用。此外,知识图谱的向量索引的建立默认使用 embedding-3 构建,因此检索的时候必须使用 embedding-3(现阶段还不支持修改) +### 2. 向量模型与重排序模型 -对于**语言模型**,并不支持直接运行本地语言模型,请使用 vllm 或者 ollama 转成 API 服务之后使用。 +建议使用硅基流动部署的 bge-m3(免费且无需修改)。其他模型配置参考 [src/static/models.yaml](src/static/models.yaml)。 -对于**向量模型**和**重排序模型**,选择以 `local` 前缀开头的模型,可以不做修改会自动下载模型,如果下载过程中出现问题,请参考 [HF-Mirror](https://hf-mirror.com/) 配置相关内容。(但请注意,如果是 Docker 运行,模型仅会缓存到 Docker 里面) +对于**向量模型**和**重排序模型**,选择 `local` 前缀的模型会自动下载。如遇下载问题,请参考 [HF-Mirror](https://hf-mirror.com/) 配置。 -如果想要使用本地已经下载好的模型,可以在网页的 settings 里面做映射。或者修改 `saves/config/base.yaml` 来配置映射关系。但请记得,本地模型的路径要在 docker-compose 的文件中映射 volumes。 +要使用已下载的本地模型,可在网页设置中映射,或修改 `saves/config/base.yaml`。记得在 docker-compose 中映射相应的 volumes。 -## 知识库支持 +## 📚 知识库支持 -本项目支持多种格式的知识库,目前支持的格式有:pdf、txt、md。文件上传后,会首先转换为纯文本,然后使用向量模型将文本转换为向量,然后存储到向量数据库中。这个过程可能会花费不少时间。 +本项目支持多种格式的知识库文件: -## 知识图谱支持 +- PDF +- Txt +- Markdown +- Docx -> [!NOTE] -> 现阶段项目所使用的 OneKE 自动创建知识图谱的效果并不是很好,暂时移除了,建议在项目外创建知识图谱** +文件上传后,系统会: -本项目支持 Neo4j 作为知识图谱的存储。需要将图谱整理成 jsonl 的格式,每一行都是 {"h": "北京", "t": "中国", "r": "首都"} 这样的格式,然后在网页的图谱管理里面添加这个文件。 +1. 将文件转换为纯文本 +2. 使用向量模型将文本转换为向量 +3. 存储到向量数据库中 -项目启动后会自动启动 neo4j 服务,可以直接使用 [http://localhost:7474/](http://localhost:7474/) 去访问和管理图数据库,初始默认的账户密码是 `neo4j` 和 `0123456789`。可以在 `docker/docker-compose.yml` 和 `docker\docker-compose.dev.yml` 中修改(注:`api.environment` 和 `graph.environment` 都需要修改)。 +> 此过程可能需要一定时间,请耐心等待。 -目前项目中暂不支持同时查询多个知识图谱,短期内也没有计划支持。不过倒是可以通过配置不同的 `NEO4J_URI` 服务来切换知识图谱。如果已经有了基于 neo4j 的知识图谱,可以将 `docker-compose.yml` 中的 `graph` 配置项删除,并将 `api.environment` 中的 `NEO4J_URI` 配置项修改为 neo4j 的服务地址。 +## 🕸️ 知识图谱支持 -## 相关问题 +本项目使用 Neo4j 作为知识图谱存储。您需要将图谱整理成 jsonl 格式,每行格式为: + +``` +{"h": "北京", "t": "中国", "r": "首都"} +``` + +然后在网页的图谱管理中添加此文件。 + +> [!说明] +> 现阶段项目使用的 OneKE 自动创建知识图谱效果不佳,已暂时移除,建议在项目外创建知识图谱 + +系统启动后会自动启动 neo4j 服务: + +- 访问地址:[http://localhost:7474/](http://localhost:7474/) +- 默认账户:`neo4j` +- 默认密码:`0123456789` + +可在 `docker/docker-compose.yml` 和 `docker/docker-compose.dev.yml` 中修改配置(注意同时修改 `api.environment` 和 `graph.environment`)。 + +目前项目暂不支持同时查询多个知识图谱。如已有基于 neo4j 的知识图谱,可删除 `docker-compose.yml` 中的 `graph` 配置项,并修改 `api.environment` 中的 `NEO4J_URI` 为您的 neo4j 服务地址。 + +## ❓ 常见问题 ### 镜像下载问题 -如果无法直接下载相关镜像,参考 [DaoCloud/public-image-mirror](https://github.com/DaoCloud/public-image-mirror?tab=readme-ov-file#%E5%BF%AB%E9%80%9F%E5%BC%80%E5%A7%8B),尝试将前缀替换为: +如无法直接下载相关镜像,可参考 [DaoCloud/public-image-mirror](https://github.com/DaoCloud/public-image-mirror?tab=readme-ov-file#%E5%BF%AB%E9%80%9F%E5%BC%80%E5%A7%8B),尝试替换前缀: ```bash -# 以 neo4j 为例,其余一样 +# 以 neo4j 为例,其余类似 docker pull m.daocloud.io/docker.io/library/neo4j:latest # 然后重命名镜像 diff --git a/docker/docker-compose.dev.yml b/docker/docker-compose.dev.yml index 5eb9939e..4bc42601 100644 --- a/docker/docker-compose.dev.yml +++ b/docker/docker-compose.dev.yml @@ -16,12 +16,15 @@ services: - milvus networks: - app-network + extra_hosts: + - "host.docker.internal:host-gateway" environment: - NEO4J_URI=bolt://graph:7687 - NEO4J_USERNAME=neo4j - NEO4J_PASSWORD=0123456789 - MILVUS_URI=http://milvus:19530 - MODEL_DIR=${MODEL_DIR} # 优先级高于 .env 中的 MODEL_DIR + - RUNNING_IN_DOCKER=true command: uvicorn src.main:app --host 0.0.0.0 --port 5050 --reload web: diff --git a/docker/web.Dockerfile b/docker/web.Dockerfile index 3a3624fb..20737eb3 100644 --- a/docker/web.Dockerfile +++ b/docker/web.Dockerfile @@ -6,8 +6,8 @@ WORKDIR /app COPY ./web/package*.json ./ # 安装依赖 -# RUN npm install --verbose --force -RUN npm install --registry http://mirrors.cloud.tencent.com/npm/ --verbose --force +RUN npm install --verbose --force +# RUN npm install --registry http://mirrors.cloud.tencent.com/npm/ --verbose --force # 复制源代码 COPY ./web . @@ -22,8 +22,8 @@ FROM node:latest AS build-stage WORKDIR /app COPY ./web/package*.json ./ -# RUN npm install --force -RUN npm install --registry https://registry.npmmirror.com --force +RUN npm install --force +# RUN npm install --registry https://registry.npmmirror.com --force COPY ./web . RUN npm run build diff --git a/src/models/__init__.py b/src/models/__init__.py index e4ec33e4..99655a2c 100644 --- a/src/models/__init__.py +++ b/src/models/__init__.py @@ -7,8 +7,8 @@ from src.models.chat_model import OpenAIBase def select_model(config, model_provider=None, model_name=None): model_provider = model_provider or config.model_provider - model_info = config.model_names[model_provider] - model_name = model_name or config.model_name or model_info["default"] + model_info = config.model_names.get(model_provider, {}) + model_name = model_name or config.model_name or model_info.get("default", "") logger.info(f"Selecting model from `{model_provider}` with `{model_name}`") diff --git a/src/models/chat_model.py b/src/models/chat_model.py index 49f1df9b..d146b3bf 100644 --- a/src/models/chat_model.py +++ b/src/models/chat_model.py @@ -44,11 +44,21 @@ class OpenModel(OpenAIBase): super().__init__(api_key=api_key, base_url=base_url, model_name=model_name) +def get_docker_safe_url(base_url): + if os.getenv("RUNNING_IN_DOCKER") == "true": + # 替换所有可能的本地地址形式 + base_url = base_url.replace("http://localhost", "http://host.docker.internal") + base_url = base_url.replace("http://127.0.0.1", "http://host.docker.internal") + logger.info(f"Running in docker, using {base_url} as base url") + return base_url + + class CustomModel(OpenAIBase): def __init__(self, model_info): model_name = model_info["name"] api_key = model_info["api_key"] - base_url = model_info["api_base"] + base_url = get_docker_safe_url(model_info["api_base"]) + super().__init__(api_key=api_key, base_url=base_url, model_name=model_name)