Commit 9fadbc52 authored by uuo00_n's avatar uuo00_n

docs: 更新README文档内容与格式

重构README文档结构,优化内容组织与可读性
- 重新组织功能亮点与系统要求部分
- 添加快速开始指南与详细配置说明
- 更新API文档格式与示例
- 补充常见问题解答与开发提示
- 优化项目结构说明
parent 5a2cce07
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AutoImportSettings">
<option name="autoReloadType" value="SELECTIVE" />
</component>
<component name="ChangeListManager">
<list default="true" id="e4808b27-03d7-4f87-99c5-f280665e27ae" name="更改" comment="" />
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="Git.Settings">
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
</component>
<component name="ProjectColorInfo"><![CDATA[{
"associatedIndex": 1
}]]></component>
<component name="ProjectId" id="350mjP6N9bwIjvPg5Z0uWHsdDvk" />
<component name="ProjectViewState">
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent"><![CDATA[{
"keyToString": {
"ModuleVcsDetector.initialDetectionPerformed": "true",
"RunOnceActivity.ShowReadmeOnStart": "true",
"RunOnceActivity.git.unshallow": "true",
"git-widget-placeholder": "main",
"last_opened_file_path": "/Users/uu/Desktop/dles_prj/llm-filter",
"node.js.detected.package.eslint": "true",
"node.js.detected.package.tslint": "true",
"node.js.selected.package.eslint": "(autodetect)",
"node.js.selected.package.tslint": "(autodetect)",
"nodejs_package_manager_path": "npm",
"settings.editor.selected.configurable": "preferences.pluginManager",
"vue.rearranger.settings.migration": "true"
}
}]]></component>
<component name="RunManager">
<configuration default="true" type="DjangoTestsConfigurationType">
<module name="llm-filter" />
<option name="ENV_FILES" value="" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<envs>
<env name="PYTHONUNBUFFERED" value="1" />
</envs>
<option name="SDK_HOME" value="" />
<option name="WORKING_DIRECTORY" value="" />
<option name="IS_MODULE_SDK" value="false" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
<option name="TARGET" value="" />
<option name="SETTINGS_FILE" value="" />
<option name="CUSTOM_SETTINGS" value="false" />
<option name="USE_OPTIONS" value="false" />
<option name="OPTIONS" value="" />
<method v="2" />
</configuration>
<configuration default="true" type="Python.FlaskServer">
<module name="llm-filter" />
<option name="ENV_FILES" value="" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<option name="SDK_HOME" value="" />
<option name="WORKING_DIRECTORY" value="" />
<option name="IS_MODULE_SDK" value="false" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
<option name="launchJavascriptDebuger" value="false" />
<method v="2" />
</configuration>
<configuration default="true" type="docs" factoryName="Docutils task">
<module name="llm-filter" />
<option name="ENV_FILES" value="" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<option name="SDK_HOME" value="" />
<option name="WORKING_DIRECTORY" value="" />
<option name="IS_MODULE_SDK" value="false" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<option name="docutils_input_file" value="" />
<option name="docutils_output_file" value="" />
<option name="docutils_params" value="" />
<option name="docutils_task" value="" />
<option name="docutils_open_in_browser" value="false" />
<method v="2" />
</configuration>
<configuration default="true" type="docs" factoryName="Sphinx task">
<module name="llm-filter" />
<option name="ENV_FILES" value="" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<option name="SDK_HOME" value="" />
<option name="WORKING_DIRECTORY" value="" />
<option name="IS_MODULE_SDK" value="false" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<option name="docutils_input_file" value="" />
<option name="docutils_output_file" value="" />
<option name="docutils_params" value="" />
<option name="docutils_task" value="" />
<option name="docutils_open_in_browser" value="false" />
<method v="2" />
</configuration>
</component>
<component name="SharedIndexes">
<attachedChunks>
<set>
<option value="bundled-js-predefined-d6986cc7102b-3aa1da707db6-JavaScript-PY-252.26830.99" />
<option value="bundled-python-sdk-164cda30dcd9-0af03a5fa574-com.jetbrains.pycharm.pro.sharedIndexes.bundled-PY-252.26830.99" />
</set>
</attachedChunks>
</component>
<component name="TaskManager">
<task active="true" id="Default" summary="默认任务">
<changelist id="e4808b27-03d7-4f87-99c5-f280665e27ae" name="更改" comment="" />
<created>1762255498972</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1762255498972</updated>
<workItem from="1762255500391" duration="1060000" />
</task>
<servers />
</component>
<component name="TypeScriptGeneratedFilesManager">
<option name="version" value="3" />
</component>
</project>
\ No newline at end of file
# LLM-Filter 智能对话过滤系统
## 项目概述
LLM-Filter 是一个基于大型语言模型(LLM)的智能对话系统,集成了敏感词过滤功能,可以安全地与用户进行对话交互。系统通过 Ollama 本地模型提供对话能力,同时实现了高效的敏感词检测和过滤,确保生成的内容符合安全标准。
### 核心功能特点
- **智能对话**:基于 Ollama 本地大语言模型提供自然、流畅的对话体验
- **敏感词过滤**:使用高效的 Trie 树数据结构实现敏感词检测和过滤
- **用户管理**:支持用户注册、登录和权限管理
- **对话历史**:保存和管理用户的对话历史记录
- **敏感词管理**:提供敏感词的添加、删除和查询功能
- **敏感词分类**:支持敏感词分类和子分类管理,可按类别筛选
- **批量导入**:支持批量导入敏感词,提高管理效率
- **敏感记录追踪**:记录并可查询敏感词触发情况,支持多维度筛选
## 系统架构
### 技术栈
- **后端框架**:FastAPI
- **数据库**:MongoDB
- **大语言模型**:Ollama (本地部署)
- **认证**:JWT (JSON Web Token)
- **文档**:Swagger UI / ReDoc
### 核心组件
- **API 层**:处理 HTTP 请求和响应
- **服务层**:实现业务逻辑
- **数据模型层**:定义数据结构
- **工具层**:提供敏感词过滤等功能
- **数据库层**:处理数据持久化
### 数据库结构
系统使用MongoDB作为数据库,包含以下集合:
#### 1. users 集合
用户信息存储,包含字段:
- `_id`: 用户唯一标识
- `username`: 用户名
- `email`: 电子邮箱
- `hashed_password`: 加密后的密码
- `role`: 用户角色,可为 "user" 或 "admin"
- `created_at`: 创建时间
- `updated_at`: 更新时间
#### 2. conversations 集合
对话信息存储,包含字段:
- `_id`: 对话唯一标识
- `user_id`: 关联的用户ID
- `messages`: 消息列表,每条消息包含:
- `role`: 消息角色,可为 "user" 或 "assistant"
- `content`: 消息内容
- `timestamp`: 消息时间戳
- `contains_sensitive_words`: 是否包含敏感词
- `sensitive_words_found`: 发现的敏感词列表
- `created_at`: 创建时间
- `updated_at`: 更新时间
#### 3. sensitive_words 集合
敏感词信息存储,包含字段:
- `_id`: 敏感词唯一标识
- `word`: 敏感词内容
- `category`: 敏感词主分类(如"违法活动"、"不良内容"等)
- `subcategory`: 敏感词子分类(如"赌博"、"自杀"等)
- `severity`: 严重程度(1-5级,5为最严重)
- `created_at`: 创建时间
- `updated_at`: 更新时间
#### 4. sensitive_records 集合
敏感词检测记录,包含字段:
- `_id`: 记录唯一标识
- `user_id`: 关联的用户ID
- `conversation_id`: 关联的对话ID
- `message_content`: 触发检测的消息内容
- `sensitive_words_found`: 发现的敏感词详细信息列表,每项包含:
- `word`: 敏感词
- `category`: 主分类
- `subcategory`: 子分类
- `severity`: 严重程度
- `highest_severity`: 记录中最高的严重程度
- `timestamp`: 记录时间
## 安装与配置
### 环境要求
一个基于 FastAPI + MongoDB + Ollama 的智能对话系统,内置高效敏感词过滤与管理员管理能力。
## 功能亮点
- 智能对话:基于本地 Ollama 模型生成回复
- 敏感词过滤:Trie(字典树)实现高效检测与标记
- 用户认证:JWT(OAuth2 密码模式),支持普通用户与管理员
- 对话历史:按用户保存会话与消息
- 敏感词管理:管理员可增删改查、批量导入、按分类/严重程度筛选
- 敏感记录追踪:记录触发详情与严重等级
---
## 兼容性与系统要求
- Python 3.9+
- MongoDB
- Ollama (本地安装)
- MongoDB 6.x 或 7.x(推荐 7.0;6.0 也可正常使用)
- Ollama(推荐在本机安装并运行,默认端口 11434)
### 安装步骤
> 驱动版本:PyMongo 4.6.0、Motor 3.3.1,已在 MongoDB 6/7 验证兼容。
1. 克隆项目仓库
---
```bash
git clone <repository-url>
cd llm-filter
```
2. 安装依赖
## 快速开始(Mac 示例)
```bash
pip install -r requirements.txt
```
3. 配置环境变量
创建 `.env` 文件并设置以下变量:
1) 创建并激活虚拟环境
```bash
python3 -m venv .venv
source .venv/bin/activate
python -V # 确认 Python 版本
```
```
MONGODB_URL=mongodb://localhost:27017
DATABASE_NAME=llm_filter
SECRET_KEY=your_secret_key
ALGORITHM=HS256
ACCESS_TOKEN_EXPIRE_MINUTES=30
OLLAMA_API_BASE_URL=http://localhost:11434
OLLAMA_MODEL=llama2
```
2) 安装依赖
```bash
pip install -r requirements.txt
```
**生成安全的SECRET_KEY**
为了确保系统安全,请使用以下方法生成一个强随机密钥:
3) 配置环境变量(.env)
在项目根目录新建或编辑 `.env`
```
# 数据库配置
MONGODB_URL=mongodb://localhost:27017
DB_NAME=llm_filter_db
# JWT配置
SECRET_KEY=请替换为强随机密钥
ALGORITHM=HS256
ACCESS_TOKEN_EXPIRE_MINUTES=30
# Ollama配置
OLLAMA_BASE_URL=http://localhost:11434
OLLAMA_MODEL=llama2
```
生成强随机密钥(二选一):
```bash
python -c "import secrets; print(secrets.token_hex(32))"
# 或
openssl rand -hex 32
```
将输出填入 `.env` 的 SECRET_KEY。
```python
# 在Python终端中运行
import secrets
print(secrets.token_hex(32)) # 生成一个64字符的随机十六进制字符串
```
4) 启动 MongoDB(任选其一)
```bash
brew install mongodb-community@7.0
brew services start mongodb-community@7.0
# 或 6.0 版本:
brew install mongodb-community@6.0
brew services start mongodb-community@6.0
```
确认端口:
```bash
nc -z localhost 27017 && echo "MongoDB is running" || echo "MongoDB is NOT running"
```
或者使用命令行:
5) 启动 Ollama 并确认(可选但推荐)
```bash
# 安装 Ollama(参考官方文档)
# 验证服务:
curl http://localhost:11434/api/tags
```
如需模型:
```bash
# 例如拉取 llama2(需网络)
ollama pull llama2
```
```bash
# Linux/Mac
openssl rand -hex 32
# 或者
python -c "import secrets; print(secrets.token_hex(32))"
```
6) 初始化数据库(创建演示数据与默认账户)
```bash
python init_db.py
```
默认测试账号:
- 管理员:admin / admin123
- 普通用户:user / user123
将生成的密钥复制到`.env`文件的`SECRET_KEY`变量中。
4. 初始化数据库
7) 启动服务
```bash
uvicorn app.main:app --reload
# 访问文档: http://localhost:8000/docs
```
```bash
python init_db.py
```
5. 启动应用
---
```bash
uvicorn app.main:app --reload
```
## 环境变量说明
与代码一致,配置由 `app/core/config.py` 读取:
- MONGODB_URL:MongoDB 连接串,默认 `mongodb://localhost:27017`
- DB_NAME:数据库名,默认 `llm_filter_db`
- SECRET_KEY:JWT 签名密钥(必须为强随机)
- ALGORITHM:JWT 算法,默认 `HS256`
- ACCESS_TOKEN_EXPIRE_MINUTES:访问令牌过期时间(分钟),默认 `30`
- OLLAMA_BASE_URL:Ollama 服务地址,默认 `http://localhost:11434`
- OLLAMA_MODEL:Ollama 模型名,默认 `llama2`
## API 端点
> 注意:原 README 中的 `DATABASE_NAME`、`OLLAMA_API_BASE_URL` 为旧命名,现统一为 `DB_NAME` 与 `OLLAMA_BASE_URL`。
### 用户相关
---
- `POST /api/v1/users/register` - 用户注册
- `POST /api/v1/users/login` - 用户登录
- `GET /api/v1/users/me` - 获取当前用户信息
## API 概览
根路径:`/` 返回应用信息
统一前缀:`/api/v1`
### 对话相关
### 认证(/auth)
- POST `/api/v1/auth/register` 注册用户(JSON)
- POST `/api/v1/auth/login` 登录,返回 `access_token`(表单:`application/x-www-form-urlencoded`
- `POST /api/v1/conversations` - 创建新对话
- `GET /api/v1/conversations` - 获取用户所有对话
- `GET /api/v1/conversations/{conversation_id}` - 获取特定对话详情
- `POST /api/v1/conversations/{conversation_id}/messages` - 发送消息
示例:注册
```bash
curl -X POST "http://localhost:8000/api/v1/auth/register" \
-H "Content-Type: application/json" \
-d '{"username": "testuser", "password": "password123", "email": "test@example.com"}'
```
示例:登录(OAuth2 密码模式)
```bash
curl -X POST "http://localhost:8000/api/v1/auth/login" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "username=testuser&password=password123"
# 响应示例:{"access_token":"<JWT>","token_type":"bearer"}
```
获取到 `access_token` 后,在后续请求头添加:
```
Authorization: Bearer <JWT>
```
### 敏感词相关
### 对话(/conversations)
- POST `/api/v1/conversations/` 创建新对话
- GET `/api/v1/conversations/` 获取当前用户的所有对话
- GET `/api/v1/conversations/{conversation_id}` 获取指定对话
- POST `/api/v1/conversations/{conversation_id}/messages` 发送消息并获取回复
- `POST /api/v1/sensitive-words` - 添加敏感词
- `DELETE /api/v1/sensitive-words/{word_id}` - 删除敏感词
- `GET /api/v1/sensitive-words` - 获取所有敏感词(支持按类别、子类别和严重程度筛选)
- `GET /api/v1/sensitive-records` - 获取敏感词记录(支持按用户、对话、时间范围、类别、子类别和严重程度筛选)
示例:创建对话
```bash
curl -X POST "http://localhost:8000/api/v1/conversations/" \
-H "Authorization: Bearer <JWT>"
```
示例:发送消息
```bash
curl -X POST "http://localhost:8000/api/v1/conversations/<ID>/messages" \
-H "Authorization: Bearer <JWT>" \
-H "Content-Type: application/json" \
-d '{"content": "你好,你是谁?"}'
# 响应会包含是否触发敏感词与模型回复
```
## 项目结构
### 管理员(/admin)
仅管理员可用,需使用管理员账号登录并携带 `Authorization: Bearer <JWT>`
- POST `/api/v1/admin/sensitive-words` 添加敏感词
- DELETE `/api/v1/admin/sensitive-words/{word_id}` 删除敏感词
- GET `/api/v1/admin/sensitive-words` 查询敏感词(支持分类/子分类/严重程度筛选)
- POST `/api/v1/admin/sensitive-words/bulk` 批量添加敏感词
- POST `/api/v1/admin/sensitive-words/import` 从 CSV/JSON 文件导入敏感词
- GET `/api/v1/admin/sensitive-records` 查询敏感词触发记录(支持多维度筛选)
- 分类相关:
- GET `/api/v1/admin/categories` 获取所有分类
- GET `/api/v1/admin/categories/default` 获取默认分类与子分类
- POST `/api/v1/admin/categories` 新增分类
- PUT `/api/v1/admin/categories/{category_name}` 更新分类子分类
- DELETE `/api/v1/admin/categories/{category_name}` 删除分类
CSV 导入示例(文件需包含表头:word,category,subcategory,severity):
```bash
curl -X POST "http://localhost:8000/api/v1/admin/sensitive-words/import" \
-H "Authorization: Bearer <JWT>" \
-F "file=@/path/to/words.csv"
```
JSON 导入示例(数组对象):
```bash
curl -X POST "http://localhost:8000/api/v1/admin/sensitive-words/import" \
-H "Authorization: Bearer <JWT>" \
-F "file=@/path/to/words.json"
# words.json 示例:[ {"word":"赌博","category":"违法活动","subcategory":"赌博","severity":3} ]
```
---
## 项目结构
```
llm-filter/
├── .env # 环境变量配置
......@@ -189,104 +203,44 @@ llm-filter/
│ ├── models/ # 数据模型
│ ├── schemas/ # 请求和响应模式
│ ├── services/ # 业务服务
│ └── utils/ # 工具函数
│ └── utils/ # 工具函数(敏感词过滤)
├── init_db.py # 数据库初始化脚本
└── requirements.txt # 项目依赖
```
## 核心模块说明
### 敏感词过滤器
系统使用 Trie 树(字典树)实现高效的敏感词检测:
- `TrieNode` 类:实现 Trie 树的节点结构
- `SensitiveWordFilter` 类:提供敏感词加载和检测功能
#### 敏感词分类系统
敏感词采用多层分类体系,便于管理和筛选:
1. **主分类**:包括违法活动、不良内容、政治内容、歧视言论、暴力内容、色情内容、毒品相关、赌博相关、诈骗相关等
2. **子分类**:每个主分类下设多个子分类,如:
- 违法活动:贩毒、赌博、诈骗、传销等
- 不良内容:自杀、自残、暴力、血腥等
- 歧视言论:种族歧视、性别歧视、地域歧视等
3. **严重程度**:1-5级,5级为最严重
这种分类系统使管理员能够:
- 精确定位和管理敏感内容
- 按类别和严重程度筛选敏感记录
- 针对不同类型的敏感内容制定不同的处理策略
### 对话服务
对话功能通过以下组件实现:
- `ConversationModel` 和 `MessageModel`:定义对话和消息的数据结构
- `add_message` 函数:处理用户消息,检测敏感词,生成 AI 回复
- `generate_response` 函数:调用 Ollama API 生成回复
### 用户认证
使用 JWT 实现用户认证:
- `create_access_token` 函数:生成访问令牌
- `get_current_user` 函数:验证用户身份
## 使用示例
### 用户注册
```bash
curl -X POST "http://localhost:8000/api/v1/users/register" \
-H "Content-Type: application/json" \
-d '{"username": "testuser", "password": "password123", "email": "test@example.com"}'
```
### 用户登录
---
```bash
curl -X POST "http://localhost:8000/api/v1/users/login" \
-H "Content-Type: application/json" \
-d '{"username": "testuser", "password": "password123"}'
```
## 敏感词过滤说明
- 使用 Trie(字典树)加载敏感词并检测文本,返回是否命中与命中的词列表
- 支持主分类与子分类,并记录严重程度(1-5,5 最严重)
- 管理员可通过导入/批量添加快速构建词库
### 创建对话
---
```bash
curl -X POST "http://localhost:8000/api/v1/conversations" \
-H "Authorization: Bearer {your_token}" \
-H "Content-Type: application/json" \
-d '{}'
```
### 发送消息
## 开发与部署提示
- CORS 已默认允许全部来源,生产环境请限制 `allow_origins`
- 开发模式使用 `--reload`;生产建议使用 `uvicorn`/`gunicorn` + 进程管理(如 `supervisor`/`systemd`
- 日志与安全:请务必使用强随机 `SECRET_KEY` 并妥善保管 `.env`
```bash
curl -X POST "http://localhost:8000/api/v1/conversations/{conversation_id}/messages" \
-H "Authorization: Bearer {your_token}" \
-H "Content-Type: application/json" \
-d '{"content": "你好,请问今天天气如何?"}'
```
---
## 开发者指南
## 常见问题(FAQ)
1) 登录始终 401?
- 确保使用 `application/x-www-form-urlencoded` 提交登录:`username=...&password=...`
- 后续请求携带 `Authorization: Bearer <JWT>`
### 添加新的敏感词
2) 连接 MongoDB 失败?
- 检查 `MONGODB_URL` 与数据库端口是否开放:`nc -z localhost 27017`
- 本地安装服务建议:`brew services start mongodb-community@6.0/7.0`
1. 通过 API 添加
2. 直接在数据库中添加
3) Ollama 连接失败?
- 检查 `OLLAMA_BASE_URL` 是否指向可用服务:`curl http://localhost:11434/api/tags`
- 确保已拉取并可用的模型(如 `ollama pull llama2`
### 自定义 Ollama 模型
修改 `.env` 文件中的 `OLLAMA_MODEL` 变量以使用不同的模型。
---
## 许可证
本项目使用 MIT 许可证,详见 `LICENSE`
MIT License
Copyright (c) 2025 uuo00_n
## 联系方式
作者:uuo00_n
## 贡献
欢迎提交 Issue 与 PR,一起完善敏感词分类与对话体验。
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment