chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,192 @@
|
||||
# API Key 外部集成
|
||||
|
||||
Yuxi 平台提供了 API Key 认证机制,允许外部系统在无需用户登录的情况下调用智能体对话接口。本文档详细介绍 API Key 的使用方法、接口调用方式以及安全注意事项。
|
||||
|
||||
## API Key 概述
|
||||
|
||||
API Key 是一种用于身份验证的密钥字符串,外部系统可以通过它在请求头中携带凭据来访问 Yuxi 的对话接口。与传统的用户名密码登录方式相比,API Key 更加适合用于系统间的自动化调用场景。Yuxi 的 API Key 以 `yxkey_` 为前缀,长度为 54 个字符,采用 SHA-256 哈希存储,确保密钥本身不会在数据库中明文保存。系统会记录每个 API Key 的最后使用时间,方便管理员追踪使用情况。
|
||||
|
||||
## 创建 API Key
|
||||
|
||||
登录系统后,进入 API Key 管理界面,可以创建新的密钥。创建时需要为 API Key 设置一个名称,用于标识其用途,例如"外部客服系统"或"数据同步服务"。创建的 API Key 会自动绑定到当前登录用户,绑定后的 API Key 在调用接口时会以该用户的身份执行操作。API Key 还支持设置过期时间,过期后该密钥将自动失效。
|
||||
|
||||
需要特别注意的是,创建 API Key 时返回的完整密钥(secret)只会显示一次,务必在创建时将其安全保存。如果遗失,需要通过"重新生成"功能生成新的密钥,原有的密钥将立即失效。
|
||||
|
||||
管理接口同样走通用认证:
|
||||
|
||||
- `GET /api/user/apikey/`:列出当前用户可见的 API Key
|
||||
- `POST /api/user/apikey/`:创建 API Key
|
||||
- `PUT /api/user/apikey/{api_key_id}`:更新名称、状态或过期时间
|
||||
- `POST /api/user/apikey/{api_key_id}/regenerate`:重新生成密钥
|
||||
- `DELETE /api/user/apikey/{api_key_id}`:删除密钥
|
||||
|
||||
## 确定 API 访问地址
|
||||
|
||||
Yuxi 后端服务绑定在 `0.0.0.0:5050`,不会自动探测或对外宣告本机 IP。实际访问地址取决于部署环境:
|
||||
|
||||
- **本地开发**:`http://localhost:5050`
|
||||
- **生产部署(Nginx 反向代理)**:**强烈建议使用 HTTPS**,即 `https://<服务器域名>`(443 端口)。由于 API Key 会在请求头中以明文形式传输,使用 HTTP(80 端口)会导致密钥在网络传输过程中被窃听或篡改,必须避免
|
||||
|
||||
完整的 API 交互流程可参考自动生成的 Swagger 文档:`{base_url}/docs`。
|
||||
|
||||
## 接口调用方式
|
||||
|
||||
> **关于 `agent_id` / `agent_slug` 的说明**:创建会话线程时仍使用 `agent_id` 绑定目标 Agent;创建运行任务时使用 `agent_slug` 快照本次运行目标。二者的取值都是智能体的 **slug**(如 `default-chatbot`),不是数据库自增 ID 或 `agent_config_id`。
|
||||
|
||||
外部系统通过 HTTP 请求调用 Yuxi 接口时,需要在请求头中携带 API Key:
|
||||
|
||||
```http
|
||||
Authorization: Bearer yxkey_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
```
|
||||
|
||||
当前智能体对话采用 run + SSE 流程:
|
||||
|
||||
1. 创建对话线程:`POST /api/chat/thread`
|
||||
2. 创建运行任务:`POST /api/agent/runs`
|
||||
3. 订阅事件流:`GET /api/agent/runs/{run_id}/events`
|
||||
|
||||
`POST /api/agent/runs` 请求体必填 `query`、`agent_slug` 和 `thread_id`,可选字段包括 `meta`、`image_content`、`resume`、`created_by_run_id`。接口返回 `run_id`、`thread_id`、`status`、`request_id` 和 `stream_url`。
|
||||
|
||||
以下是一个典型的 Python 调用示例:
|
||||
|
||||
```python
|
||||
import json
|
||||
import requests
|
||||
|
||||
base_url = "https://your-yuxi-server" # 生产环境务必使用 HTTPS;本地开发可改为 http://localhost:5050
|
||||
headers = {
|
||||
"Authorization": "Bearer yxkey_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
|
||||
"Content-Type": "application/json",
|
||||
}
|
||||
|
||||
thread_resp = requests.post(
|
||||
f"{base_url}/api/chat/thread",
|
||||
headers=headers,
|
||||
json={
|
||||
"agent_id": "default-chatbot",
|
||||
"title": "外部系统会话",
|
||||
"metadata": {},
|
||||
},
|
||||
)
|
||||
thread_resp.raise_for_status()
|
||||
thread_id = thread_resp.json()["id"]
|
||||
|
||||
run_resp = requests.post(
|
||||
f"{base_url}/api/agent/runs",
|
||||
headers=headers,
|
||||
json={
|
||||
"query": "你好,请介绍一下你自己",
|
||||
"agent_slug": "default-chatbot",
|
||||
"thread_id": thread_id,
|
||||
"meta": {"request_id": "external-request-001"},
|
||||
},
|
||||
)
|
||||
run_resp.raise_for_status()
|
||||
run = run_resp.json()
|
||||
|
||||
with requests.get(f"{base_url}{run['stream_url']}", headers=headers, stream=True) as response:
|
||||
response.raise_for_status()
|
||||
event_type = None
|
||||
data_lines = []
|
||||
|
||||
for line in response.iter_lines(decode_unicode=True):
|
||||
if line is None:
|
||||
continue
|
||||
if line.startswith(":"):
|
||||
continue
|
||||
|
||||
if line == "":
|
||||
if event_type and data_lines:
|
||||
payload = json.loads("\n".join(data_lines))
|
||||
print(event_type, payload)
|
||||
if event_type == "end":
|
||||
break
|
||||
event_type = None
|
||||
data_lines = []
|
||||
continue
|
||||
|
||||
if line.startswith("event:"):
|
||||
event_type = line.removeprefix("event:").strip()
|
||||
elif line.startswith("data:"):
|
||||
data_lines.append(line.removeprefix("data:").strip())
|
||||
```
|
||||
|
||||
如果已经有会话线程,可以复用已有 `thread_id` 直接创建 run:
|
||||
|
||||
```json
|
||||
{
|
||||
"query": "继续上一轮话题",
|
||||
"agent_slug": "default-chatbot",
|
||||
"thread_id": "existing-thread-id",
|
||||
"meta": {}
|
||||
}
|
||||
```
|
||||
|
||||
### 读取运行结果
|
||||
|
||||
如果不需要逐事件消费 SSE,可以在 run 终态后直接拉取最终结果:
|
||||
|
||||
```http
|
||||
GET /api/agent/runs/{run_id}/result
|
||||
```
|
||||
|
||||
返回结构包含运行状态、最终 assistant 输出、Langfuse trace id 和错误信息。该接口只读,不会再次触发 run。对外部系统只关心「最终答案」、不需要展示中间过程的场景,比订阅 SSE 更简单。
|
||||
|
||||
### 外部系统调用入口
|
||||
|
||||
除通用 `/api/agent/runs` 之外,Yuxi 还提供专为外部系统设计的 `agent-invocation` 路由,复用同一套 AgentRun 队列与结果读取能力:
|
||||
|
||||
| 接口 | 用途 | 关键字段 |
|
||||
|------|------|----------|
|
||||
| `POST /api/agent-invocation/agent-call/runs` | 外部系统调用 Agent;`async_mode=true` 时立即返回 `run_id`,否则阻塞到 run 终态返回结果 | `agent_slug`、`messages`、`thread_id`、`request_id`、`model_spec`、`async_mode` |
|
||||
| `POST /api/agent-invocation/agent-call/runs/result` | 读取 agent-call run 的 OpenAI 兼容结果结构 | `run_id`、可选 `agent_slug` |
|
||||
| `POST /api/agent-invocation/eval/runs` | 运行一次评估样例,阻塞到 run 终态后返回最终输出与可选轨迹摘要 | `query`、`agent_slug`、`evaluation`、`include_trajectory_summary` |
|
||||
|
||||
agent-call 的 `messages[].content` 兼容 OpenAI 风格的 `text`/`image_url` 多模态数组:纯文本数组不会触发 422,图片输入会保留原始 LangChain 多模态消息供 worker 恢复。出于安全考虑,**不允许通过 `agent_call_meta.context` 覆盖 Agent 运行上下文**;运行时模型覆盖只允许走独立 `model_spec` 字段。Agent Eval 通常通过 `yuxi agent eval` CLI 触发,详见[智能体评估](../agents/agent-evaluation.md)。
|
||||
|
||||
## 响应格式
|
||||
|
||||
运行事件流采用 Server-Sent Events 格式,响应头为 `text/event-stream`。每个事件包含:
|
||||
|
||||
- `event`:事件类型,可能是模型输出、工具调用、子智能体输出等语义事件,也可能是 `error` 或终止事件 `end`
|
||||
- `data`:JSON 编码的事件 envelope,包含 `run_id`、`thread_id`、事件载荷等字段
|
||||
- `id`:Redis Stream 序号,可作为断线重连游标
|
||||
|
||||
服务端还会定期发送以 `:` 开头的 heartbeat 注释,客户端应忽略。断线重连时,可以在请求头中传 `Last-Event-ID`,或在 query 参数中传 `after_seq`,服务端会从该序号后继续回放事件。
|
||||
|
||||
事件流默认返回完整载荷,便于排查 LangGraph/Langfuse 运行细节。如果只需要渲染消息、工具调用、工具结果、Agent state 和终止状态,可以在订阅地址追加 `?verbose=false`。精简模式会保留 SSE `event/data/id`、data 中的 `run_id/thread_id/request_id/payload` 以及客户端消费所需字段;同一 data 内的 `request_id` 会外提为单个字段。精简模式还会跳过 `metadata` 和空 `yuxi.agent_state`,并去掉每个 chunk 中重复的 `meta`、`metadata`、`thread_id`、`response`、空 `namespace` 和图片 base64 等调试字段。
|
||||
|
||||
每次创建 run 都会返回 `request_id`,可用于日志追踪和问题排查。如果需要在多轮对话中使用同一个会话,请复用 `thread_id`,系统会将同一线程的消息串联起来形成连贯的对话上下文。
|
||||
|
||||
## 认证方式
|
||||
|
||||
Yuxi 的 API 接口统一支持两种认证方式:
|
||||
|
||||
1. **API Key 认证**:使用 `Authorization: Bearer <api_key>` 格式,其中 API Key 必须以 `yxkey_` 前缀开头
|
||||
2. **JWT Token 认证**:使用 `Authorization: Bearer <jwt_token>` 格式
|
||||
|
||||
系统根据 token 的前缀自动判断认证方式。以 `yxkey_` 开头的 token 被视为 API Key,其他 token 则作为 JWT Token 处理。这种设计使得同一个接口可以同时支持外部系统(使用 API Key)和内部前端应用(使用用户登录态)调用。
|
||||
|
||||
## 安全注意事项
|
||||
|
||||
**传输层安全**:API Key 在请求头中以明文形式传输,**生产环境必须通过 HTTPS(443 端口)调用**,避免在公网上以 HTTP 明文传输造成密钥泄露。建议在 Nginx 反向代理层启用 TLS 并强制 HTTP 重定向到 HTTPS。
|
||||
|
||||
保管好 API Key 密钥是最重要的安全原则。由于 API Key 一旦泄露就可能被滥用,建议不要将密钥硬编码在代码中,而是通过环境变量或配置中心来管理。如果怀疑密钥泄露,应立即在管理界面禁用该 API Key 并重新生成。启用密钥过期功能是一种良好的安全实践,可以设置较短的有效期并定期轮换。
|
||||
|
||||
在生产环境中,建议为不同的外部系统创建独立的 API Key,这样可以在某个密钥泄露时快速定位问题并限制影响范围。同时,建议在管理界面定期查看 API Key 的使用记录,检查是否存在异常调用情况。
|
||||
|
||||
关于权限控制,API Key 的权限等同于其绑定的用户在系统中的角色。如果 API Key 绑定到特定用户,则该用户的所有权限都会体现在 API Key 的操作中,因此务必妥善保管。
|
||||
|
||||
## 常见问题
|
||||
|
||||
**Q: API Key 认证失败返回什么错误?**
|
||||
A: 认证失败时返回 401 Unauthorized 错误,错误信息为"无效的凭证"。请检查请求头中 `Authorization` 字段的格式是否正确,是否包含完整的密钥,且密钥必须以 `yxkey_` 开头。
|
||||
|
||||
**Q: 可以同时使用 API Key 和 JWT Token 吗?**
|
||||
A: 不可以。系统根据 token 前缀自动判断认证方式。以 `yxkey_` 开头的 token 使用 API Key 认证,其他 token 使用 JWT 认证。
|
||||
|
||||
**Q: API Key 是否有调用频率限制?**
|
||||
A: 目前没有单独的频率限制,但 API Key 的行为等同于其绑定的用户身份,因此会受到用户角色相关的一些限制。
|
||||
|
||||
**Q: 对话返回的内容是乱码怎么办?**
|
||||
A: 确保客户端正确处理了 UTF-8 编码。流式响应中可能包含中文字符,需要使用正确的编码方式解析。如果在终端显示乱码,可以检查终端的编码设置。
|
||||
@@ -0,0 +1,86 @@
|
||||
# 品牌自定义
|
||||
|
||||
Yuxi 支持完整的品牌自定义,包括 Logo、组织名称、版权信息、登录协议等,方便企业用户进行品牌定制。
|
||||
|
||||
## 品牌信息配置
|
||||
|
||||
### 步骤 1:复制模板文件
|
||||
|
||||
```bash
|
||||
cp backend/package/yuxi/config/static/info.template.yaml backend/package/yuxi/config/static/info.local.yaml
|
||||
```
|
||||
|
||||
### 步骤 2:编辑品牌信息
|
||||
|
||||
在 `backend/package/yuxi/config/static/info.local.yaml` 中配置你的品牌信息:
|
||||
|
||||
- 应用名称
|
||||
- 组织名称
|
||||
- Logo
|
||||
- 版权信息
|
||||
- 登录页用户协议/隐私协议链接
|
||||
|
||||
### 步骤 3:指定配置文件
|
||||
|
||||
在 `.env` 中指定配置文件路径:
|
||||
|
||||
```env
|
||||
YUXI_BRAND_FILE_PATH=backend/package/yuxi/config/static/info.local.yaml
|
||||
```
|
||||
|
||||
::: tip 配置优先级
|
||||
`info.local.yaml` > `info.template.yaml`(默认)
|
||||
:::
|
||||
|
||||
## 登录协议配置
|
||||
|
||||
登录页支持从品牌配置中读取用户协议与隐私协议链接。
|
||||
|
||||
### 配置项
|
||||
|
||||
在 `backend/package/yuxi/config/static/info.local.yaml` 的 `footer` 下新增以下字段:
|
||||
|
||||
```yaml
|
||||
footer:
|
||||
copyright: "© your org 2026"
|
||||
user_agreement_url: "/protocols/user-agreement.template.html"
|
||||
privacy_policy_url: "/protocols/privacy-policy.template.html"
|
||||
```
|
||||
|
||||
### 显示规则
|
||||
|
||||
- 当 `user_agreement_url` 和 `privacy_policy_url` 都有值时,登录页会显示协议勾选项。
|
||||
- 任一字段为空时,登录页不显示协议勾选项。
|
||||
- 未勾选协议时,提交登录/初始化会通过消息提示用户先同意协议。
|
||||
|
||||
### 协议模板文件
|
||||
|
||||
系统默认提供两个 HTML 模板文件:
|
||||
|
||||
- `web/public/protocols/user-agreement.template.html`
|
||||
- `web/public/protocols/privacy-policy.template.html`
|
||||
|
||||
你可以直接编辑这两个文件中的协议内容,并替换占位符(如 `{{ORG_NAME}}`、`{{PRODUCT_NAME}}`、`{{EFFECTIVE_DATE}}`)。
|
||||
|
||||
如果你有自己的协议页面,也可以将 `user_agreement_url` 和 `privacy_policy_url` 指向自定义路径或外部链接。
|
||||
|
||||
### Icon 定制
|
||||
|
||||
系统预设了多种 Icon,如需更多图标,可以从 `lucide-vue-next` 中引入。
|
||||
|
||||
## 样式定制
|
||||
|
||||
系统支持完整的主题色定制。配置文件位于 `web/src/assets/css/base.css`,以及 `web/src/assets/css/base.dark.css`:
|
||||
|
||||
```css
|
||||
:root {
|
||||
--main-color: #1890ff; /* 主色调 */
|
||||
--main-1000: #f0f2f5; /* 色板 */
|
||||
--main-900: #e6f7ff; /* 色板 */
|
||||
/* ... 其他色板 */
|
||||
}
|
||||
```
|
||||
|
||||
修改配色变量后,界面会实时更新,无需重启服务。
|
||||
|
||||
此外,`web/src/stores/theme.js` 中的 `colorPrimary` 也需要同步修改。
|
||||
@@ -0,0 +1,37 @@
|
||||
# 配置系统详解
|
||||
|
||||
## 概述
|
||||
|
||||
系统采用多层配置架构,模型配置由网页界面管理,应用配置基于 Pydantic + TOML。
|
||||
|
||||
## 配置层级
|
||||
|
||||
```
|
||||
代码默认值 → TOML 文件 → 环境变量
|
||||
(低) (高)
|
||||
```
|
||||
|
||||
## 模型配置
|
||||
|
||||
由网页统一管理,详见 [模型配置](../intro/model-config.md)。
|
||||
|
||||
## 应用配置
|
||||
|
||||
配置项定义于 `backend/package/yuxi/config/app.py`,用户修改保存至 `saves/config/base.toml`。
|
||||
|
||||
### 修改配置
|
||||
|
||||
```python
|
||||
from yuxi.config import config
|
||||
|
||||
config.default_model = "provider-id:model-id"
|
||||
config.save()
|
||||
```
|
||||
|
||||
配置会在保存 `base.toml` 后写入 Redis 快照(`yuxi:runtime_config`)。快照包含可运行时同步的公开配置字段,不包含 `_` 开头的内部属性和 `save_dir`;API/worker 进程在启动时各拉起一个后台同步线程,按 5 秒间隔从该快照刷新内存值,读取端无需感知。Redis 不可用时继续使用当前内存值。
|
||||
|
||||
`save_dir` 是启动期内部路径配置,不在管理员配置中展示,也不支持通过管理员配置接口、`base.toml` 或运行时 Redis 快照修改。sandbox 相关配置仍属于启动期敏感配置,运行中的已初始化组件不承诺完整热更新,修改后需要重启服务保证生效。
|
||||
|
||||
## 常见问题
|
||||
|
||||
**配置文件损坏**:删除 `saves/config/base.toml`,系统将重新生成默认配置。
|
||||
@@ -0,0 +1,83 @@
|
||||
# 生产部署指南
|
||||
|
||||
本文档介绍如何在生产环境中部署 Yuxi。
|
||||
|
||||
## 前置要求
|
||||
|
||||
- Docker Engine (v24.0+)
|
||||
- Docker Compose (v2.20+)
|
||||
- NVIDIA Container Toolkit(如需使用 GPU 服务)
|
||||
|
||||
::: warning 注意事项
|
||||
1. 生产环境和开发环境建议使用不同的机器,避免端口和资源冲突
|
||||
2. 虽然名为「生产环境」,但这只是基本配置,真正上线需要根据实际情况调整
|
||||
3. 前端有调试面板(长按侧边栏触发),生产环境建议关闭
|
||||
:::
|
||||
|
||||
## 部署步骤
|
||||
|
||||
### 1. 准备配置文件
|
||||
|
||||
为避免与开发环境冲突,生产环境建议使用 `.env.prod` 文件:
|
||||
|
||||
```bash
|
||||
cp .env.template .env.prod
|
||||
```
|
||||
|
||||
编辑 `.env.prod`,设置强密码和必要的 API 密钥:
|
||||
|
||||
- `NEO4J_PASSWORD`:修改默认密码
|
||||
- `MINIO_ACCESS_KEY` / `MINIO_SECRET_KEY`:修改默认密钥
|
||||
- `SILICONFLOW_API_KEY` 等模型密钥
|
||||
|
||||
### 2. 启动服务
|
||||
|
||||
使用生产环境配置文件启动:
|
||||
|
||||
```bash
|
||||
# 仅启动核心服务(CPU 模式)
|
||||
docker compose -f docker-compose.prod.yml up -d --build
|
||||
|
||||
# 启动所有服务(包含 GPU OCR)
|
||||
docker compose -f docker-compose.prod.yml --profile all up -d --build
|
||||
```
|
||||
|
||||
### 3. 验证部署
|
||||
|
||||
- Web 访问:http://localhost(直接通过 80 端口)
|
||||
- API 健康检查:`curl http://localhost/api/system/health`
|
||||
|
||||
## 跨域(CORS)配置
|
||||
|
||||
`docker-compose.prod.yml` 默认把 `YUXI_ENV` 设为 `production`,后端在该环境下会按 `YUXI_CORS_ORIGINS` 显式声明允许的来源。**未配置时返回空列表,浏览器跨域请求会被拒绝**。生产部署前请根据前端与 API 的相对位置选择策略:
|
||||
|
||||
| 部署形态 | 推荐配置 |
|
||||
|----------|----------|
|
||||
| 前端与 API 同源(Nginx 同端口反代) | 不需要设置,留空即可 |
|
||||
| 前端与 API 跨域部署 | `YUXI_CORS_ORIGINS=https://your-frontend.example.com` |
|
||||
| 多个前端域名 | 逗号分隔,如 `https://a.example.com,https://b.example.com` |
|
||||
| 完全放开(不推荐) | `YUXI_CORS_ORIGINS=*`,会自动关闭 credentials,登录态/JWT 无法跨域携带 |
|
||||
|
||||
开发环境(`YUXI_ENV=development` 且未设置该变量)默认允许 `http://localhost:5173` 与 `http://127.0.0.1:5173`,方便本地前后端独立启动调试。从 0.7.0 升级到 0.7.1 时,如果此前是跨域部署但未显式声明来源,必须补上 `YUXI_CORS_ORIGINS`,否则前端跨域请求会被拒绝。
|
||||
|
||||
## 维护与更新
|
||||
|
||||
### 更新代码
|
||||
|
||||
```bash
|
||||
# 拉取最新代码
|
||||
git pull
|
||||
|
||||
# 重新构建并启动
|
||||
docker compose -f docker-compose.prod.yml up -d --build
|
||||
```
|
||||
|
||||
### 查看日志
|
||||
|
||||
```bash
|
||||
# API 日志
|
||||
docker logs -f api-prod
|
||||
|
||||
# Nginx 访问日志
|
||||
docker logs -f web-prod
|
||||
```
|
||||
@@ -0,0 +1,152 @@
|
||||
# 文档处理与 OCR
|
||||
|
||||
Yuxi 支持多种文档格式的智能解析,从简单的文本文件到复杂的 PDF 文档,都能自动提取内容并转换为可检索的格式。
|
||||
|
||||
## 支持的文件类型
|
||||
|
||||
### 常规文档
|
||||
|
||||
| 类型 | 格式 | 说明 |
|
||||
|------|------|------|
|
||||
| 文本 | .txt, .md, .html, .htm | 直接提取内容 |
|
||||
| Word | .docx | 保留格式和结构 |
|
||||
| PowerPoint | .pptx | 保留主要文本结构 |
|
||||
| PDF | .pdf | 支持文本和图片 PDF |
|
||||
| 表格 | .csv, .xls, .xlsx | 识别表格结构 |
|
||||
| JSON | .json | 结构化数据 |
|
||||
|
||||
### 图片文件
|
||||
|
||||
对于图片文件,需要启用 OCR 才能提取文字:
|
||||
- .jpg, .jpeg, .png, .bmp, .tiff, .tif
|
||||
|
||||
### 压缩包
|
||||
|
||||
支持上传 ZIP 压缩包,系统会:
|
||||
- 自动提取并处理其中的 Markdown 文件
|
||||
- 处理图片并上传到对象存储
|
||||
- 智能识别 `full.md` 或第一个 `.md` 文件
|
||||
|
||||
### 网页内容
|
||||
|
||||
支持通过 URL 直接抓取网页内容:
|
||||
|
||||
1. 配置 `YUXI_URL_WHITELIST` 环境变量启用白名单机制
|
||||
2. 系统自动将 HTML 转换为 Markdown
|
||||
3. 内置去重机制,避免重复抓取
|
||||
|
||||
::: tip URL 白名单配置
|
||||
示例:`YUXI_URL_WHITELIST=github.com,*.wikipedia.org,docs.python.org`
|
||||
:::
|
||||
|
||||
## OCR 方案选择
|
||||
|
||||
系统提供多种 OCR 方案,适用于不同场景:
|
||||
|
||||
### 方案对比
|
||||
|
||||
| 方案 | 适用场景 | 硬件要求 | 特点 |
|
||||
|------|----------|----------|------|
|
||||
| RapidOCR | 基础文字识别 | CPU | 免费开源,速度快 |
|
||||
| MinerU | 复杂 PDF、表格 | GPU | 精度高,版面分析好 |
|
||||
| MinerU Official | 复杂文档 | 无 | 官方云服务,开箱即用 |
|
||||
| PP-Structure-V3 | 表格、票据 | GPU | 专业版面解析 |
|
||||
| DeepSeek OCR | 智能理解 | 无 | 云端服务,Markdown 输出 |
|
||||
| PaddleOCR-VL-1.6 | 复杂文档、表格、图片 PDF | 无 | 百度 AI Studio 云端服务,输出 Markdown |
|
||||
| PP-OCRv6 | 基础文字识别 | 无 | 百度 AI Studio 云端 OCR,输出纯文本 |
|
||||
|
||||
### 选择建议
|
||||
|
||||
- **个人使用或 CPU 环境**:选择 RapidOCR,免费且资源占用低
|
||||
- **高精度需求**:选择 MinerU(需要 GPU)或 MinerU Official
|
||||
- **表格密集型文档**:选择 PP-Structure-V3
|
||||
- **云端版面解析**:选择 PaddleOCR-VL-1.6,适合希望输出 Markdown 的 PDF 或图片文档
|
||||
- **云端纯文字识别**:选择 PP-OCRv6,适合只需要提取图片文字的场景
|
||||
- **简单云服务**:选择 DeepSeek OCR 或 PaddleOCR API
|
||||
|
||||
## 快速配置
|
||||
|
||||
### RapidOCR
|
||||
|
||||
启动后会默认下载,无需配置
|
||||
|
||||
### MinerU(高精度)
|
||||
|
||||
项目已内置 mineru-api 服务(位于 docker-compose.yml,属于 all profile),无需额外下载官方 compose 文件。首次构建镜像时会基于 docker/mineru.Dockerfile 下载模型,该过程耗时较长。
|
||||
|
||||
启动服务(需要 GPU):
|
||||
|
||||
```bash
|
||||
docker compose --profile all up -d --build mineru-api
|
||||
```
|
||||
|
||||
该服务在 `30001` 端口提供 `/file_parse` 接口,后端 `api` / `worker` 默认通过 `MINERU_API_URI=http://mineru-api:30001` 连接,通常无需额外配置。
|
||||
|
||||
::: tip 显存不足
|
||||
若显存有限导致启动失败,可在 `docker-compose.yml` 的 `mineru-api` 服务下放开 `--gpu-memory-utilization` 参数(如 `0.5`,必要时进一步降低)。
|
||||
:::
|
||||
|
||||
### MinerU Official(云服务)
|
||||
|
||||
从 [MinerU 官网](https://mineru.net) 获取 API 密钥,在 .env 配置环境变量
|
||||
|
||||
```env
|
||||
MINERU_API_KEY=your-api-key-here
|
||||
```
|
||||
|
||||
### PP-Structure-V3(结构化)
|
||||
|
||||
启动服务(需要 GPU)
|
||||
|
||||
```bash
|
||||
docker compose up paddlex -d
|
||||
```
|
||||
|
||||
### DeepSeek OCR(简单云服务)
|
||||
|
||||
在 .env 配置(使用已有的 SiliconFlow 密钥)
|
||||
|
||||
```env
|
||||
SILICONFLOW_API_KEY=your-api-key-here
|
||||
```
|
||||
|
||||
### PaddleOCR API(百度 AI Studio 云服务)
|
||||
|
||||
PaddleOCR API 使用百度 AI Studio 的 Access Token。获取方式:
|
||||
|
||||
1. 登录 [百度 AI Studio Access Token 页面](https://aistudio.baidu.com/account/accessToken)
|
||||
2. 在页面中复制 Access Token
|
||||
3. 在 `.env` 中配置为 `PADDLEOCR_API_TOKEN`
|
||||
|
||||
```env
|
||||
PADDLEOCR_API_TOKEN=your-access-token-here
|
||||
```
|
||||
|
||||
如需使用自定义 PaddleOCR API 地址,可额外配置:
|
||||
|
||||
```env
|
||||
PADDLEOCR_API_URL=https://paddleocr.aistudio-app.com/api/v2/ocr/jobs
|
||||
```
|
||||
|
||||
配置完成后,重启后端服务,在上传文件或解析临时附件时可以选择:
|
||||
|
||||
- `PaddleOCR-VL-1.6`:对应 `paddleocr_vl_1_6`,用于文档版面解析,返回 Markdown
|
||||
- `PP-OCRv6`:对应 `paddleocr_pp_ocrv6`,用于基础 OCR,返回按行拼接的纯文本
|
||||
|
||||
## 图片显示配置
|
||||
|
||||
上传文档中的图片需要正确配置才能在外部显示:
|
||||
|
||||
在 `.env` 中设置服务器 IP:
|
||||
|
||||
```
|
||||
HOST_IP=your_server_ip
|
||||
```
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. **图片文件必须启用 OCR**:否则无法提取内容
|
||||
2. **GPU 要求**:MinerU 和 PP-Structure-V3 需要 GPU 支持
|
||||
3. **API 密钥**:MinerU Official、DeepSeek OCR、PaddleOCR API 等云服务需要额外的 API 密钥或 Access Token 配置
|
||||
4. **超时处理**:复杂文档解析可能耗时较长,可通过 `MINERU_TIMEOUT` 环境变量调整超时时间
|
||||
5. **文件大小限制**:单个上传文件大小不超过 100 MB
|
||||
@@ -0,0 +1,37 @@
|
||||
# Langfuse 集成
|
||||
|
||||
## 为什么 Yuxi 需要 Langfuse
|
||||
|
||||
Langfuse 是一套面向大模型应用的可观测性平台,适合用来观察一次智能体执行过程中到底发生了什么。在 Yuxi 里,一轮用户消息通常不会只对应一次简单的模型调用,它往往会伴随 LangGraph 图执行、工具调用、知识库检索以及多轮中间状态切换。仅靠普通后端日志,虽然也能定位问题,但往往需要在多个文件和多个服务日志之间来回跳转,阅读成本高,而且很难从用户、线程和智能体三个维度统一查看。Langfuse 的价值就在于,它把这些原本分散的执行细节收拢到同一条 trace 里,让你能够从一次对话出发,回看模型输入输出、工具链路、耗时和错误位置。
|
||||
|
||||
在 Yuxi 当前的实现中,Langfuse 主要承担的是智能体执行观测层,而不是业务主流程的一部分。换句话说,它不会替代模型服务,也不会替代聊天接口本身,而是帮助你在智能体已经能够工作的前提下,看清楚它是如何工作的。对于调试复杂 Agent、排查工具调用失败、评估多轮会话质量以及分析不同智能体的耗时与成本来说,这类观测能力非常关键。尤其是在一个线程里连续发生多轮交互时,Langfuse 可以帮助你把“这轮请求是谁发起的、落在哪个 thread、触发了哪个 agent、调用了哪些模型和工具”这些信息统一串起来。
|
||||
|
||||
## 在 Yuxi 中能做什么
|
||||
|
||||
Yuxi 对 Langfuse 的映射方式比较直接。一个 Yuxi 用户会映射为 Langfuse 中的 `user_id`,一个对话线程会映射为 `session_id`,而每次用户输入触发的一轮智能体执行会形成一条独立的 trace。这样做的好处是,既能按单轮请求排查问题,也能在同一个线程维度下连续查看多轮会话。对于需要长期分析使用质量、成本和延迟的场景,这种映射方式能够兼顾可读性和后续统计需求。
|
||||
|
||||
当 Langfuse 与 Yuxi 连通之后,它最直接的作用是帮助你看清一轮智能体请求内部发生了哪些步骤。你可以看到这一轮调用关联的是哪个用户、哪个线程、哪个智能体,也可以进一步观察模型调用、工具调用和整体耗时表现。对于日常调试来说,它让“问题到底出在模型、工具、配置还是图流程”这件事变得更容易判断。对于长期运行的系统来说,它也为后续做延迟分析、成本分析和用户反馈分析提供了统一的观察入口。
|
||||
|
||||
用户在对话界面对助手消息提交点赞或点踩后,Yuxi 会继续把反馈保存在本地业务表中;如果该助手消息已经关联 Langfuse trace,则会同步写入 Langfuse score。同步到 Langfuse 的 score 名称为 `user-feedback`,点赞值为 `1`,点踩值为 `0`,点踩原因会作为 score comment 保存,便于在 Langfuse 中按低分反馈筛选和分析具体 trace。
|
||||
|
||||
## 如何配置
|
||||
|
||||
如果你准备启用 Langfuse,首先需要在 Langfuse Cloud 中创建项目并获取访问凭证。当前版本推荐优先使用云端模式,因为接入成本最低,也更适合先把 tracing 跑通。你需要在运行 Yuxi 的环境中配置 `LANGFUSE_PUBLIC_KEY`、`LANGFUSE_SECRET_KEY` 和 `LANGFUSE_BASE_URL`。其中前两个字段用于鉴权,`LANGFUSE_BASE_URL` 用于指定 Langfuse 服务地址;如果你使用官方云服务,通常可以直接填写 `https://cloud.langfuse.com`。在大多数部署场景下,只要把这些变量写入 `.env` 并通过 Docker Compose 传给 `api` 服务即可生效。
|
||||
|
||||
从当前实现来看,Langfuse 只有在 key 配置完整时才会被启用。如果没有配置 `LANGFUSE_PUBLIC_KEY` 或 `LANGFUSE_SECRET_KEY`,Yuxi 会自动退化为“不启用 tracing”的状态,正常聊天功能不会因此中断。这意味着 Langfuse 是一个可选增强项,而不是系统启动的前置依赖。对于希望先验证主流程、后续再逐步补全观测能力的部署者来说,这种行为比较友好,因为它降低了接入门槛,也减少了配置错误对主业务的影响。
|
||||
|
||||
## 配置后系统会如何工作
|
||||
|
||||
理解 Langfuse 的另一个关键点在于,它并不等于“所有调试信息都会立即显示在界面里”。当前 Yuxi 的设计重点是先把 trace id 与执行上下文稳定关联起来,再把这些信息作为后续调试和分析的基础。也正因为如此,系统会优先保证聊天主链路的稳定性,而不是为了获取额外的可点击 URL 去同步等待 Langfuse 的远程接口。换句话说,Langfuse 在 Yuxi 里首先是观测数据的来源,其次才是一个方便跳转查看的外部页面入口。
|
||||
|
||||
这也意味着,Langfuse 接入的目标并不是改变用户聊天体验,而是在不破坏主流程稳定性的前提下,为系统补上一层可观测性。只要配置正确,用户的对话仍然按照原有方式执行,只是在后台额外留下可追踪的执行记录。对于运维和开发来说,这类“尽量不影响主流程”的接入方式更适合在现有系统中逐步落地。
|
||||
|
||||
## 如何查看是否生效
|
||||
|
||||
启用完成后,你最常见的查看方式是在 Langfuse 控制台中按项目查看 traces。进入项目后,可以按照用户、线程、Agent 或时间范围来筛选,定位到某一轮具体的请求。打开单条 trace 之后,你通常可以看到这一轮智能体执行的整体耗时、模型调用、工具调用以及相关 metadata。对于排查问题来说,这比直接翻阅后端日志更高效,因为你不需要自己手动拼装上下文。对于性能分析来说,也可以更直观地看出某个智能体是否在某类请求上耗时异常,或者某个工具是否经常成为慢点。
|
||||
|
||||
如果你是系统管理员或开发者,希望快速确认 Yuxi 是否已经成功把 tracing 打到 Langfuse,最简单的方法不是先看代码,而是先发起一条真实对话,再到 Langfuse 控制台中按最近时间排序查看是否出现新的 trace。如果配置正确,你应该可以看到对应线程下新增的一轮执行记录;如果没有看到,则优先检查 `.env` 中的三个关键变量是否正确传入 `api` 容器,以及容器内依赖是否已经包含 Langfuse SDK。对于基于 Docker Compose 的开发环境,这一步尤其重要,因为仅修改 `pyproject.toml` 并不会自动把新依赖装进已经运行中的镜像,通常还需要重新构建或更新容器。
|
||||
|
||||
## 当前建议的接入方式
|
||||
|
||||
目前 Yuxi 推荐的接入顺序是先完成 tracing,再使用反馈 score 分析用户满意度,后续再扩展到更完整的运营面板。这样做的原因很简单:只有在 trace 关联已经稳定、用户和线程维度映射已经一致的前提下,后续的评分、质量分析和使用统计才会真正可靠。也正因如此,当前文档重点介绍的是 Langfuse 的定位、接入方式和查看路径,而不是一次性覆盖所有更复杂的高级功能。对于大多数项目来说,先把“能看清每轮智能体执行发生了什么”这件事做好,已经能显著改善调试和运维体验。
|
||||
@@ -0,0 +1,83 @@
|
||||
# 其他配置
|
||||
|
||||
本文档介绍 Yuxi 的其他配置选项,包括内容安全、网页搜索和服务端口等。
|
||||
|
||||
## 内容安全
|
||||
|
||||
系统内置内容审查机制,帮助保障服务内容的合规性。
|
||||
|
||||
### 启用方式
|
||||
|
||||
在「系统设置」→「基本设置」页面中配置,可选择启用关键词过滤和 LLM 内容审查。
|
||||
|
||||
### 检测流程
|
||||
|
||||
系统会在以下时机进行检测:
|
||||
|
||||
1. **用户输入检测**:接收到用户消息后立即检测
|
||||
2. **流式输出检测**:实时检测输出的关键词(仅关键词模式)
|
||||
3. **输出完成检测**:流式输出结束后进行全面检测
|
||||
|
||||
### 检测模式
|
||||
|
||||
**关键词检测**
|
||||
|
||||
敏感词库位于 `backend/package/yuxi/config/static/bad_keywords.txt`,每行一个关键词。修改后实时生效,无需重启服务。
|
||||
|
||||
**LLM 检测**
|
||||
|
||||
使用大模型对内容进行审查,可以更好地识别提示词注入等复杂问题,但会增加响应延迟。
|
||||
|
||||
::: warning 性能考虑
|
||||
LLM 检测会增加用户交互的延迟,请根据实际需求选择是否启用。
|
||||
:::
|
||||
|
||||
## 网页搜索
|
||||
|
||||
系统集成了 Tavily 联网搜索能力,让大模型能够获取实时网页信息。
|
||||
|
||||
### 配置步骤
|
||||
|
||||
1. 访问 [Tavily 官网](https://app.tavily.com/) 注册并创建 API Key
|
||||
2. 在 `.env` 文件中添加:
|
||||
```env
|
||||
TAVILY_API_KEY=sk-xxxxxxxxxxxxxxxx
|
||||
```
|
||||
3. 重启服务:
|
||||
```bash
|
||||
docker compose up -d api-dev web-dev
|
||||
```
|
||||
|
||||
### 使用方式
|
||||
|
||||
配置完成后,在智能体的工具配置区域会看到 Tavily 搜索工具。模型会自动判断何时需要调用搜索来获取最新信息。
|
||||
|
||||
如需关闭,删除或清空 `TAVILY_API_KEY` 后重启服务即可。
|
||||
|
||||
## 服务端口
|
||||
|
||||
系统各服务通过以下端口提供访问:
|
||||
|
||||
| 端口 | 服务 | 说明 |
|
||||
|------|------|------|
|
||||
| 5173 | Web 前端 | 用户界面 |
|
||||
| 5050 | API 后端 | 核心服务接口 |
|
||||
| 7474 | Neo4j HTTP | 图数据库管理界面 |
|
||||
| 7687 | Neo4j Bolt | 图数据库连接 |
|
||||
| 9000/9001 | MinIO | 对象存储 |
|
||||
| 19530/9091 | Milvus | 向量数据库 |
|
||||
| 5432 | PostgreSQL | 业务数据库 |
|
||||
|
||||
### 可选服务端口
|
||||
|
||||
| 端口 | 服务 | 说明 |
|
||||
|------|------|------|
|
||||
| 30000 | MinerU | PDF 解析服务 |
|
||||
| 8080 | PP-Structure-V3 | OCR 服务 |
|
||||
| 8081 | vLLM | 本地推理服务 |
|
||||
|
||||
### 快速访问
|
||||
|
||||
- Web 界面:http://localhost:5173
|
||||
- API 文档:http://localhost:5050/docs
|
||||
- Neo4j 管理:http://localhost:7474
|
||||
@@ -0,0 +1,103 @@
|
||||
# 第三方登录认证
|
||||
Yuxi 支持以OIDC接入第三方登录认证,方便企业用户集成现有的身份认证系统。
|
||||
> 此功能默认关闭,需要在配置文件中启用并提供相关参数。
|
||||
|
||||
## 配置步骤
|
||||
### 1. 前提条件
|
||||
在你的SSO系统中注册一个新的客户端应用,获取以下信息:
|
||||
- 客户端ID(Client ID)
|
||||
- 客户端密钥(Client Secret)
|
||||
- ISSUER URL
|
||||
|
||||
填入回调地址(Redirect URI):https://<your_yuxi_host>/api/auth/oidc/callback
|
||||
|
||||
### 2. 配置Yuxi
|
||||
在Yuxi的.env文件中添加以下配置项:
|
||||
|
||||
```sh
|
||||
# 是否启用 OIDC 认证 (true/false)
|
||||
# OIDC_ENABLED=false
|
||||
|
||||
# 认证源名称(显示在登录按钮上的文字,建议简短且具有辨识度, 默认: OIDC登录)
|
||||
# OIDC_PROVIDER_NAME="OIDC登录"
|
||||
|
||||
# OIDC Provider 的 Issuer URL (例如: https://auth.example.com)
|
||||
# OIDC_ISSUER_URL=
|
||||
|
||||
# OIDC Client ID
|
||||
# OIDC_CLIENT_ID=
|
||||
|
||||
# OIDC Client Secret
|
||||
# OIDC_CLIENT_SECRET=
|
||||
|
||||
# OIDC 回调 URL (可选,默认自动构建为 /api/auth/oidc/callback, 不建议自定义)
|
||||
# 填写完整的地址:https://<your_yuxi_host>/api/auth/oidc/callback
|
||||
# 需要确保此 URL 在 OIDC Provider 中已注册
|
||||
# OIDC_REDIRECT_URI=
|
||||
|
||||
# 授权端点 (可选,自动从 discovery 获取)
|
||||
# OIDC_AUTHORIZATION_ENDPOINT=
|
||||
|
||||
# Token 端点 (可选,自动从 discovery 获取)
|
||||
# OIDC_TOKEN_ENDPOINT=
|
||||
|
||||
# UserInfo 端点 (可选,自动从 discovery 获取)
|
||||
# OIDC_USERINFO_ENDPOINT=
|
||||
|
||||
# 登出端点 (可选,自动从 discovery 获取)
|
||||
# OIDC_END_SESSION_ENDPOINT=
|
||||
|
||||
# 请求的 scope (默认: openid profile email)
|
||||
# OIDC_SCOPES=openid profile email
|
||||
|
||||
# 是否自动创建用户 (true/false,默认: true)
|
||||
# OIDC_AUTO_CREATE_USER=true
|
||||
|
||||
# OIDC 用户的默认角色 (user/admin,默认: user)
|
||||
# OIDC_DEFAULT_ROLE=user
|
||||
|
||||
# OIDC 用户的默认部门名称 (默认: OIDC用户)
|
||||
# OIDC_DEFAULT_DEPARTMENT=OIDC用户
|
||||
|
||||
# 用户名映射字段 (默认: preferred_username)
|
||||
# OIDC_USERNAME_CLAIM=preferred_username
|
||||
|
||||
# 邮箱映射字段 (默认: email)
|
||||
# OIDC_EMAIL_CLAIM=email
|
||||
|
||||
# 姓名映射字段 (默认: name)
|
||||
# OIDC_NAME_CLAIM=name
|
||||
|
||||
# 是否使用原始用户名(不带 oidc: 前缀),允许映射到 Yuxi 已有的本地账号 (true/false,默认: false)
|
||||
# 开启后,OIDC 返回的 username 会直接作为业务登录标识 uid 登录,需要管理员提前创建好用户账号
|
||||
# OIDC_USE_RAW_USERNAME=false
|
||||
|
||||
# 是否从OIDC userinfo 中获取部门信息并自动创建关联部门 (true/false,默认: false)
|
||||
# OIDC_FETCH_DEPARTMENT_INFO=false
|
||||
|
||||
# 部门名称字段映射 (默认: department)
|
||||
# OIDC_DEPARTMENT_CLAIM=department
|
||||
|
||||
# OIDC 登录时是否强制提示用户重新登录 (添加 prompt=login 参数,true/false,默认: true)
|
||||
# OIDC_FORCE_PROMPT_LOGIN=true
|
||||
|
||||
```
|
||||
### 3. 重启Yuxi服务使配置生效
|
||||
```bash
|
||||
docker restart api-dev web-dev
|
||||
```
|
||||
|
||||
## 功能说明
|
||||
|
||||
### 使用原始用户名(OIDC_USE_RAW_USERNAME=true)
|
||||
当你需要将 Yuxi 系统中已有的本地账号与 OIDC SSO 绑定,可以开启此选项。
|
||||
|
||||
**绑定原理**(无需修改数据库):
|
||||
系统会创建一个标记为删除的占位用户 `oidc:{sub}:{target_user_id}` 来记录 OIDC sub 与 Yuxi 用户的绑定关系,确保只有绑定过的 OIDC 身份才能登录对应的账号,**防止账号冒用**。其中 `target_user_id` 是数据库中的数值 `users.id`;用户登录标识仍使用字符串 `uid`。
|
||||
|
||||
### 自动获取部门信息(OIDC_FETCH_DEPARTMENT_INFO=true)
|
||||
开启后,系统会从 OIDC userinfo 中读取部门名称和描述,自动在 Yuxi 中创建部门并将用户关联到该部门。
|
||||
|
||||
- 对从 OIDC 获取的部门名称会自动做 `strip()` 去空格,并截断到 50 字符
|
||||
- 部门描述会自动截断到 255 字符
|
||||
- 如果部门名称处理后为空,会回退到使用 `OIDC_DEFAULT_DEPARTMENT` 默认部门
|
||||
Reference in New Issue
Block a user