This commit is contained in:
parent
b2ad58e30c
commit
22ee4fbaaa
|
|
@ -0,0 +1,308 @@
|
|||
# Docker 部署指南(硬编码 KEY 版本)
|
||||
|
||||
## 📋 配置说明
|
||||
|
||||
本 Dockerfile 已经将所有 API 配置和密钥硬编码在镜像中:
|
||||
|
||||
### 已硬编码的配置
|
||||
|
||||
| 配置项 | 值 |
|
||||
|--------|-----|
|
||||
| API 端点 | `https://api.coze.cn/v1` ✅(包含 /v1 前缀) |
|
||||
| COZE_API_KEY | `Bearer eyJhbGci...` ✅ |
|
||||
| LLM_API_KEY | `Bearer eyJhbGci...` ✅ |
|
||||
| COZE_WORKSPACE_ID | `7622238752642957347` ✅ |
|
||||
| LLM_MODEL_NAME | `doubao-seed-2-0-pro-260215` ✅ |
|
||||
|
||||
### Workspace ID 来源
|
||||
|
||||
从 JWT Token 的 `sub` 字段提取:
|
||||
```
|
||||
spiffe://api.coze.cn/workload_identity/id:7622238752642957347
|
||||
```
|
||||
|
||||
## 🚀 快速部署
|
||||
|
||||
### 步骤 1:构建镜像
|
||||
|
||||
```bash
|
||||
# 进入项目根目录
|
||||
cd /workspace/projects
|
||||
|
||||
# 构建镜像
|
||||
docker build -t math-grading:latest .
|
||||
```
|
||||
|
||||
### 步骤 2:运行容器
|
||||
|
||||
```bash
|
||||
# 运行容器(简单方式)
|
||||
docker run -d \
|
||||
--name math-grading \
|
||||
-p 8000:8000 \
|
||||
--restart unless-stopped \
|
||||
math-grading:latest
|
||||
|
||||
# 运行容器(完整方式,挂载日志和缓存)
|
||||
docker run -d \
|
||||
--name math-grading \
|
||||
-p 8000:8000 \
|
||||
-v $(pwd)/logs:/app/work/logs \
|
||||
-v $(pwd)/cache:/tmp/homework_cache \
|
||||
--restart unless-stopped \
|
||||
math-grading:latest
|
||||
```
|
||||
|
||||
### 步骤 3:验证服务
|
||||
|
||||
```bash
|
||||
# 查看容器状态
|
||||
docker ps | grep math-grading
|
||||
|
||||
# 查看日志
|
||||
docker logs -f math-grading
|
||||
|
||||
# 检查健康状态
|
||||
curl http://localhost:8000/health
|
||||
```
|
||||
|
||||
## 🧪 测试接口
|
||||
|
||||
### 测试 LLM 调用
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8000/stream_run \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"student_homework": [
|
||||
{
|
||||
"student_id": 1,
|
||||
"student_name": "测试学生",
|
||||
"homework_images": [
|
||||
"https://dpcclass.oss-cn-beijing.aliyuncs.com/umsupload/2026/03/18/69baa4f5-4826-4901-00e1-c6e66f02947f.jpg?x-oss-process=image/resize,w_1000"
|
||||
]
|
||||
}
|
||||
],
|
||||
"answer_doc_url": "",
|
||||
"comment_max_length": 50,
|
||||
"max_concurrent": 1
|
||||
}'
|
||||
```
|
||||
|
||||
### 测试多图片批改
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8000/stream_run \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"student_homework": [
|
||||
{
|
||||
"student_id": 1,
|
||||
"student_name": "张三",
|
||||
"homework_images": [
|
||||
"https://dpcclass.oss-cn-beijing.aliyuncs.com/umsupload/2026/03/18/69baa4f5-4826-4901-00e1-c6e66f02947f.jpg?x-oss-process=image/resize,w_1000",
|
||||
"https://dpcclass.oss-cn-beijing.aliyuncs.com/umsupload/2026/03/25/69c344ba-4826-4901-00e1-c6ff235a12b2.jpg?x-oss-process=image/resize,w_1000"
|
||||
]
|
||||
}
|
||||
],
|
||||
"answer_doc_url": "https://dpcclass.oss-cn-beijing.aliyuncs.com/umsupload/2026/03/25/69c353d0-4826-4901-00e1-c7081bcab988.docx",
|
||||
"comment_max_length": 50,
|
||||
"max_concurrent": 2
|
||||
}'
|
||||
```
|
||||
|
||||
## 🔧 常用命令
|
||||
|
||||
### 容器管理
|
||||
|
||||
```bash
|
||||
# 停止容器
|
||||
docker stop math-grading
|
||||
|
||||
# 启动容器
|
||||
docker start math-grading
|
||||
|
||||
# 重启容器
|
||||
docker restart math-grading
|
||||
|
||||
# 删除容器
|
||||
docker rm -f math-grading
|
||||
|
||||
# 删除镜像
|
||||
docker rmi math-grading:latest
|
||||
```
|
||||
|
||||
### 日志查看
|
||||
|
||||
```bash
|
||||
# 查看实时日志
|
||||
docker logs -f math-grading
|
||||
|
||||
# 查看最近 100 行日志
|
||||
docker logs --tail 100 math-grading
|
||||
|
||||
# 查看错误日志
|
||||
docker logs math-grading 2>&1 | grep ERROR
|
||||
```
|
||||
|
||||
### 进入容器
|
||||
|
||||
```bash
|
||||
# 进入容器 shell
|
||||
docker exec -it math-grading /bin/bash
|
||||
|
||||
# 查看环境变量
|
||||
docker exec math-grading env | grep COZE
|
||||
|
||||
# 运行 Python 脚本
|
||||
docker exec math-grading python assets/check_env.py
|
||||
```
|
||||
|
||||
## 📊 验证配置成功
|
||||
|
||||
### 成功标志
|
||||
|
||||
1. **容器启动成功**
|
||||
```bash
|
||||
docker ps | grep math-grading
|
||||
# 应该显示容器运行中(Up status)
|
||||
```
|
||||
|
||||
2. **日志无错误**
|
||||
```bash
|
||||
docker logs math-grading | grep ERROR
|
||||
# 不应该有认证错误(401)或端点错误(404)
|
||||
```
|
||||
|
||||
3. **健康检查通过**
|
||||
```bash
|
||||
curl http://localhost:8000/health
|
||||
# 应该返回 200 OK
|
||||
```
|
||||
|
||||
4. **LLM 调用成功**
|
||||
```bash
|
||||
# 运行测试请求,日志应该显示:
|
||||
# ✅ HTTP Request: POST https://api.coze.cn/v1/chat/completions "HTTP/1.1 200 OK"
|
||||
```
|
||||
|
||||
### 错误排查
|
||||
|
||||
#### 错误 1:容器无法启动
|
||||
|
||||
```bash
|
||||
# 查看详细日志
|
||||
docker logs math-grading
|
||||
|
||||
# 检查端口是否被占用
|
||||
netstat -tuln | grep 8000
|
||||
```
|
||||
|
||||
#### 错误 2:LLM 调用 401 错误
|
||||
|
||||
```bash
|
||||
# 检查环境变量是否正确设置
|
||||
docker exec math-grading env | grep COZE_API_KEY
|
||||
|
||||
# 应该看到:
|
||||
# COZE_API_KEY=Bearer eyJhbGci...
|
||||
```
|
||||
|
||||
#### 错误 3:LLM 调用 404 错误
|
||||
|
||||
```bash
|
||||
# 检查 API 端点配置
|
||||
docker exec math-grading env | grep BASE_URL
|
||||
|
||||
# 应该看到:
|
||||
# COZE_INTEGRATION_BASE_URL=https://api.coze.cn/v1
|
||||
# 注意要有 /v1 前缀
|
||||
```
|
||||
|
||||
## 🔐 安全说明
|
||||
|
||||
### ⚠️ 密钥已硬编码
|
||||
|
||||
当前 Dockerfile 将 API Key 硬编码在镜像中:
|
||||
- ✅ 优点:部署简单,无需额外配置
|
||||
- ❌ 缺点:密钥会暴露在镜像中,存在安全风险
|
||||
|
||||
### 安全建议
|
||||
|
||||
1. **私有仓库**
|
||||
- 使用私有 Docker Registry(如阿里云容器镜像服务)
|
||||
- 不要将镜像推送到公共仓库
|
||||
|
||||
2. **访问控制**
|
||||
- 限制镜像访问权限
|
||||
- 使用 RBAC 控制镜像拉取
|
||||
|
||||
3. **定期更换密钥**
|
||||
- 定期在 Coze 平台更换 API Key
|
||||
- 重新构建镜像
|
||||
|
||||
4. **生产环境建议**
|
||||
- 使用环境变量方式(推荐)
|
||||
- 参考 `assets/docker-compose.yml`
|
||||
|
||||
## 📝 配置说明
|
||||
|
||||
### 环境变量列表
|
||||
|
||||
| 变量名 | 说明 | 值 |
|
||||
|--------|------|-----|
|
||||
| `COZE_API_KEY` | Coze API 认证密钥 | Bearer eyJhbGci... |
|
||||
| `LLM_API_KEY` | LLM API 认证密钥 | Bearer eyJhbGci... |
|
||||
| `COZE_WORKSPACE_ID` | 工作区 ID | 7622238752642957347 |
|
||||
| `COZE_INTEGRATION_BASE_URL` | API 基础 URL | https://api.coze.cn/v1 |
|
||||
| `COZE_INTEGRATION_MODEL_BASE_URL` | 模型 API 基础 URL | https://api.coze.cn/v1 |
|
||||
| `LLM_BASE_URL` | LLM API 基础 URL | https://api.coze.cn/v1 |
|
||||
| `LLM_MODEL_NAME` | LLM 模型名称 | doubao-seed-2-0-pro-260215 |
|
||||
| `COZE_INTEGRATION_API_KEY` | 集成 API 密钥 | Bearer eyJhbGci... |
|
||||
|
||||
### 端口说明
|
||||
|
||||
| 端口 | 说明 |
|
||||
|------|------|
|
||||
| 8000 | HTTP 服务端口 |
|
||||
|
||||
### 目录说明
|
||||
|
||||
| 目录 | 说明 |
|
||||
|------|------|
|
||||
| /app | 应用工作目录 |
|
||||
| /app/work/logs/bypass | 日志目录 |
|
||||
| /tmp/homework_cache | 缓存目录 |
|
||||
|
||||
## 🎯 总结
|
||||
|
||||
### 一键部署命令
|
||||
|
||||
```bash
|
||||
# 构建并运行
|
||||
docker build -t math-grading:latest .
|
||||
docker run -d --name math-grading -p 8000:8000 --restart unless-stopped math-grading:latest
|
||||
|
||||
# 查看日志
|
||||
docker logs -f math-grading
|
||||
|
||||
# 测试接口
|
||||
curl -X POST http://localhost:8000/stream_run \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"student_homework": [{"student_id": 1, "homework_images": ["https://example.com/image.jpg"]}]}'
|
||||
```
|
||||
|
||||
### 预期结果
|
||||
|
||||
- ✅ 容器正常运行
|
||||
- ✅ 日志显示服务启动成功
|
||||
- ✅ LLM 调用返回 200 OK
|
||||
- ✅ 批改功能正常工作
|
||||
|
||||
### 关键修复点
|
||||
|
||||
1. ✅ API 端点包含 `/v1/` 前缀
|
||||
2. ✅ COZE_WORKSPACE_ID 已配置
|
||||
3. ✅ API Key 已硬编码
|
||||
4. ✅ 健康检查已添加
|
||||
5. ✅ 日志和缓存目录已创建
|
||||
45
Dockerfile
45
Dockerfile
|
|
@ -6,50 +6,40 @@ WORKDIR /app
|
|||
RUN sed -i 's/deb.debian.org/mirrors.aliyun.com/g' /etc/apt/sources.list.d/debian.sources 2>/dev/null || \
|
||||
sed -i 's/deb.debian.org/mirrors.aliyun.com/g' /etc/apt/sources.list
|
||||
|
||||
# 安装完整的系统依赖(包含所有 PyGObject 需要的库)
|
||||
# 安装系统依赖
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
# 编译工具
|
||||
gcc \
|
||||
g++ \
|
||||
make \
|
||||
pkg-config \
|
||||
cmake \
|
||||
# D-Bus 相关
|
||||
dbus \
|
||||
dbus-x11 \
|
||||
libdbus-1-dev \
|
||||
libdbus-glib-1-dev \
|
||||
# GLib 和 GObject 相关
|
||||
libglib2.0-dev \
|
||||
libgirepository1.0-dev \
|
||||
gobject-introspection \
|
||||
# Cairo 图形库
|
||||
libcairo2-dev \
|
||||
libcairo-gobject2 \
|
||||
# GTK 相关(如果需要)
|
||||
libgtk-3-dev \
|
||||
# 其他常用库
|
||||
libffi-dev \
|
||||
libxml2-dev \
|
||||
libxslt1-dev \
|
||||
curl \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||||
|
||||
# 设置 pip 国内镜像源
|
||||
# 设置 pip 国内镜像源和 API 配置(硬编码 KEY)
|
||||
ENV PIP_INDEX_URL=https://mirrors.aliyun.com/pypi/simple/ \
|
||||
PIP_TRUSTED_HOST=mirrors.aliyun.com \
|
||||
# API 端点配置(包含 /v1 前缀)
|
||||
COZE_INTEGRATION_BASE_URL=https://api.coze.cn/v1 \
|
||||
COZE_INTEGRATION_MODEL_BASE_URL=https://api.coze.cn/v1 \
|
||||
COZE_WORKLOAD_IDENTITY_API_KEY="Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6ImRmZmU2NmYxLTg0MDMtNDc5Ni05ZmRhLTViMmJjZWExM2ViOCJ9.eyJpc3MiOiJodHRwczovL2FwaS5jb3plLmNuIiwiYXVkIjpbIkZVS1kzOVR0dFlSdmlNaldGVmNjaUg0NWFPblp2TGxpIl0sImV4cCI6ODIxMDI2Njg3Njc5OSwiaWF0IjoxNzc0NjkyOTc0LCJzdWIiOiJzcGlmZmU6Ly9hcGkuY296ZS5jbi93b3JrbG9hZF9pZGVudGl0eS9pZDo3NjIyMjM4NzUyNjQyOTU3MzQ3Iiwic3JjIjoiaW5ib3VuZF9hdXRoX2FjY2Vzc190b2tlbl9pZDo3NjIyMjQ4Mjg1OTMxMDQ0ODkxIn0.XSJaTryHWYzQaHxd9g9rOX2Y3YRY8kGAlvSFH9UkWR9EFDfZESG1GFEdWDelYeoHBqtdiQhxTcYdGPA87_PweMfh0wJXTdCEzTDHAOlUUupJEKTpkUAMEoEZpYBrwKQxjzGglkMHUoXqM5I0tQsARaqZ-j-JOW9Y6fHot56squm8GSt7WZkVSj6ZC2Us4cpO_RIgsN_pBU0CFSlUpOU5AdQQ8LvHzp60-DGaXVU0mFIYKhnXKbTf3PSXpJlH-W78FULh2FcdOTxMIcNkL5nuIHGakoNNDxs-k5Ucp06kFEMcbvec4iB1njbkHrsilYeJOFRoqkXJpQujDngZxKecLA" \
|
||||
LLM_API_KEY="Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6ImRmZmU2NmYxLTg0MDMtNDc5Ni05ZmRhLTViMmJjZWExM2ViOCJ9.eyJpc3MiOiJodHRwczovL2FwaS5jb3plLmNuIiwiYXVkIjpbIkZVS1kzOVR0dFlSdmlNaldGVmNjaUg0NWFPblp2TGxpIl0sImV4cCI6ODIxMDI2Njg3Njc5OSwiaWF0IjoxNzc0NjkyOTc0LCJzdWIiOiJzcGlmZmU6Ly9hcGkuY296ZS5jbi93b3JrbG9hZF9pZGVudGl0eS9pZDo3NjIyMjM4NzUyNjQyOTU3MzQ3Iiwic3JjIjoiaW5ib3VuZF9hdXRoX2FjY2Vzc190b2tlbl9pZDo3NjIyMjQ4Mjg1OTMxMDQ0ODkxIn0.XSJaTryHWYzQaHxd9g9rOX2Y3YRY8kGAlvSFH9UkWR9EFDfZESG1GFEdWDelYeoHBqtdiQhxTcYdGPA87_PweMfh0wJXTdCEzTDHAOlUUupJEKTpkUAMEoEZpYBrwKQxjzGglkMHUoXqM5I0tQsARaqZ-j-JOW9Y6fHot56squm8GSt7WZkVSj6ZC2Us4cpO_RIgsN_pBU0CFSlUpOU5AdQQ8LvHzp60-DGaXVU0mFIYKhnXKbTf3PSXpJlH-W78FULh2FcdOTxMIcNkL5nuIHGakoNNDxs-k5Ucp06kFEMcbvec4iB1njbkHrsilYeJOFRoqkXJpQujDngZxKecLA" \
|
||||
COZE_INTEGRATION_CHAT_BASE_URL=https://api.coze.cn/v1 \
|
||||
LLM_BASE_URL=https://api.coze.cn/v1 \
|
||||
LLM_MODEL_NAME=doubao-seed-2-0-pro-260215 \
|
||||
# API Key 配置(硬编码)
|
||||
COZE_API_KEY="Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6ImRmZmU2NmYxLTg0MDMtNDc5Ni05ZmRhLTViMmJjZWExM2ViOCJ9.eyJpc3MiOiJodHRwczovL2FwaS5jb3plLmNuIiwiYXVkIjpbIkZVS1kzOVR0dFlSdmlNaldGVmNjaUg0NWFPblp2TGxpIl0sImV4cCI6ODIxMDI2Njg3Njc5OSwiaWF0IjoxNzc0NjkyOTc0LCJzdWIiOiJzcGlmZmU6Ly9hcGkuY296ZS5jbi93b3JrbG9hZF9pZGVudGl0eS9pZDo3NjIyMjM4NzUyNjQyOTU3MzQ3Iiwic3JjIjoiaW5ib3VuZF9hdXRoX2FjY2Vzc190b2tlbl9pZDo3NjIyMjQ4Mjg1OTMxMDQ0ODkxIn0.XSJaTryHWYzQaHxd9g9rOX2Y3YRY8kGAlvSFH9UkWR9EFDfZESG1GFEdWDelYeoHBqtdiQhxTcYdGPA87_PweMfh0wJXTdCEzTDHAOlUUupJEKTpkUAMEoEZpYBrwKQxjzGglkMHUoXqM5I0tQsARaqZ-j-JOW9Y6fHot56squm8GSt7WZkVSj6ZC2Us4cpO_RIgsN_pBU0CFSlUpOU5AdQQ8LvHzp60-DGaXVU0mFIYKhnXKbTf3PSXpJlH-W78FULh2FcdOTxMIcNkL5nuIHGakoNNDxs-k5Ucp06kFEMcbvec4iB1njbkHrsilYeJOFRoqkXJpQujDngZxKecLA" \
|
||||
COZE_INTEGRATION_API_KEY="Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6ImRmZmU2NmYxLTg0MDMtNDc5Ni05ZmRhLTViMmJjZWExM2ViOCJ9.eyJpc3MiOiJodHRwczovL2FwaS5jb3plLmNuIiwiYXVkIjpbIkZVS1kzOVR0dFlSdmlNaldGVmNjaUg0NWFPblp2TGxpIl0sImV4cCI6ODIxMDI2Njg3Njc5OSwiaWF0IjoxNzc0NjkyOTc0LCJzdWIiOiJzcGlmZmU6Ly9hcGkuY296ZS5jbi93b3JrbG9hZF9pZGVudGl0eS9pZDo3NjIyMjM4NzUyNjQyOTU3MzQ3Iiwic3JjIjoiaW5ib3VuZF9hdXRoX2FjY2Vzc190b2tlbl9pZDo3NjIyMjQ4Mjg1OTMxMDQ0ODkxIn0.XSJaTryHWYzQaHxd9g9rOX2Y3YRY8kGAlvSFH9UkWR9EFDfZESG1GFEdWDelYeoHBqtdiQhxTcYdGPA87_PweMfh0wJXTdCEzTDHAOlUUupJEKTpkUAMEoEZpYBrwKQxjzGglkMHUoXqM5I0tQsARaqZ-j-JOW9Y6fHot56squm8GSt7WZkVSj6ZC2Us4cpO_RIgsN_pBU0CFSlUpOU5AdQQ8LvHzp60-DGaXVU0mFIYKhnXKbTf3PSXpJlH-W78FULh2FcdOTxMIcNkL5nuIHGakoNNDxs-k5Ucp06kFEMcbvec4iB1njbkHrsilYeJOFRoqkXJpQujDngZxKecLA" \
|
||||
COZE_WORKSPACE_ID=7622238752642957347
|
||||
LLM_API_KEY="Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6ImRmZmU2NmYxLTg0MDMtNDc5Ni05ZmRhLTViMmJjZWExM2ViOCJ9.eyJpc3MiOiJodHRwczovL2FwaS5jb3plLmNuIiwiYXVkIjpbIkZVS1kzOVR0dFlSdmlNaldGVmNjaUg0NWFPblp2TGxpIl0sImV4cCI6ODIxMDI2Njg3Njc5OSwiaWF0IjoxNzc0NjkyOTc0LCJzdWIiOiJzcGlmZmU6Ly9hcGkuY296ZS5jbi93b3JrbG9hZF9pZGVudGl0eS9pZDo3NjIyMjM4NzUyNjQyOTU3MzQ3Iiwic3JjIjoiaW5ib3VuZF9hdXRoX2FjY2Vzc190b2tlbl9pZDo3NjIyMjQ4Mjg1OTMxMDQ0ODkxIn0.XSJaTryHWYzQaHxd9g9rOX2Y3YRY8kGAlvSFH9UkWR9EFDfZESG1GFEdWDelYeoHBqtdiQhxTcYdGPA87_PweMfh0wJXTdCEzTDHAOlUUupJEKTpkUAMEoEZpYBrwKQxjzGglkMHUoXqM5I0tQsARaqZ-j-JOW9Y6fHot56squm8GSt7WZkVSj6ZC2Us4cpO_RIgsN_pBU0CFSlUpOU5AdQQ8LvHzp60-DGaXVU0mFIYKhnXKbTf3PSXpJlH-W78FULh2FcdOTxMIcNkL5nuIHGakoNNDxs-k5Ucp06kFEMcbvec4iB1njbkHrsilYeJOFRoqkXJpQujDngZxKecLA" \
|
||||
# Workspace ID 配置(硬编码,从 JWT Token 提取)
|
||||
COZE_WORKSPACE_ID=7622238752642957347 \
|
||||
# LLM 模型配置
|
||||
LLM_MODEL_NAME=doubao-seed-2-0-pro-260215 \
|
||||
COZE_INTEGRATION_API_KEY="Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6ImRmZmU2NmYxLTg0MDMtNDc5Ni05ZmRhLTViMmJjZWExM2ViOCJ9.eyJpc3MiOiJodHRwczovL2FwaS5jb3plLmNuIiwiYXVkIjpbIkZVS1kzOVR0dFlSdmlNaldGVmNjaUg0NWFPblp2TGxpIl0sImV4cCI6ODIxMDI2Njg3Njc5OSwiaWF0IjoxNzc0NjkyOTc0LCJzdWIiOiJzcGlmZmU6Ly9hcGkuY296ZS5jbi93b3JrbG9hZF9pZGVudGl0eS9pZDo3NjIyMjM4NzUyNjQyOTU3MzQ3Iiwic3JjIjoiaW5ib3VuZF9hdXRoX2FjY2Vzc190b2tlbl9pZDo3NjIyMjQ4Mjg1OTMxMDQ0ODkxIn0.XSJaTryHWYzQaHxd9g9rOX2Y3YRY8kGAlvSFH9UkWR9EFDfZESG1GFEdWDelYeoHBqtdiQhxTcYdGPA87_PweMfh0wJXTdCEzTDHAOlUUupJEKTpkUAMEoEZpYBrwKQxjzGglkMHUoXqM5I0tQsARaqZ-j-JOW9Y6fHot56squm8GSt7WZkVSj6ZC2Us4cpO_RIgsN_pBU0CFSlUpOU5AdQQ8LvHzp60-DGaXVU0mFIYKhnXKbTf3PSXpJlH-W78FULh2FcdOTxMIcNkL5nuIHGakoNNDxs-k5Ucp06kFEMcbvec4iB1njbkHrsilYeJOFRoqkXJpQujDngZxKecLA"
|
||||
|
||||
# 升级 pip 和构建工具
|
||||
RUN pip install --no-cache-dir --upgrade pip setuptools wheel meson ninja
|
||||
RUN pip install --no-cache-dir --upgrade pip setuptools wheel
|
||||
|
||||
# 复制并安装依赖
|
||||
COPY requirements.txt .
|
||||
|
|
@ -58,5 +48,12 @@ RUN pip install --no-cache-dir -r requirements.txt
|
|||
# 复制项目文件
|
||||
COPY . .
|
||||
|
||||
# 创建必要的目录
|
||||
RUN mkdir -p /app/work/logs/bypass /tmp/homework_cache
|
||||
|
||||
# 添加健康检查
|
||||
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
|
||||
CMD curl -f http://localhost:8000/health || exit 1
|
||||
|
||||
EXPOSE 8000
|
||||
CMD ["python", "src/main.py", "-m", "http", "-p", "8000"]
|
||||
CMD ["python", "src/main.py", "-m", "http", "-p", "8000"]
|
||||
|
|
|
|||
|
|
@ -0,0 +1,202 @@
|
|||
# 数学作业批改系统 - Docker 部署
|
||||
|
||||
## 📦 快速开始
|
||||
|
||||
### 一键部署
|
||||
|
||||
```bash
|
||||
# 运行部署脚本
|
||||
./deploy.sh
|
||||
```
|
||||
|
||||
### 手动部署
|
||||
|
||||
```bash
|
||||
# 构建镜像
|
||||
docker build -t math-grading:latest .
|
||||
|
||||
# 启动容器
|
||||
docker run -d \
|
||||
--name math-grading \
|
||||
-p 8000:8000 \
|
||||
-v $(pwd)/logs:/app/work/logs \
|
||||
-v $(pwd)/cache:/tmp/homework_cache \
|
||||
--restart unless-stopped \
|
||||
math-grading:latest
|
||||
```
|
||||
|
||||
## 🧪 测试验证
|
||||
|
||||
```bash
|
||||
# 运行测试脚本
|
||||
./test.sh
|
||||
```
|
||||
|
||||
## 📝 配置说明
|
||||
|
||||
### 已硬编码的配置
|
||||
|
||||
| 配置项 | 值 | 说明 |
|
||||
|--------|-----|------|
|
||||
| API 端点 | `https://api.coze.cn/v1` | 包含 /v1 前缀 |
|
||||
| COZE_API_KEY | `Bearer eyJhbGci...` | Coze API 认证密钥 |
|
||||
| COZE_WORKSPACE_ID | `7622238752642957347` | 工作区 ID |
|
||||
| LLM_MODEL_NAME | `doubao-seed-2-0-pro-260215` | LLM 模型名称 |
|
||||
|
||||
### 配置来源
|
||||
|
||||
- **API Key**: 从原始 Dockerfile 中提取
|
||||
- **Workspace ID**: 从 JWT Token 的 `sub` 字段提取
|
||||
```
|
||||
spiffe://api.coze.cn/workload_identity/id:7622238752642957347
|
||||
```
|
||||
|
||||
## 🔧 常用命令
|
||||
|
||||
### 容器管理
|
||||
|
||||
```bash
|
||||
# 查看状态
|
||||
docker ps | grep math-grading
|
||||
|
||||
# 查看日志
|
||||
docker logs -f math-grading
|
||||
|
||||
# 停止服务
|
||||
docker stop math-grading
|
||||
|
||||
# 启动服务
|
||||
docker start math-grading
|
||||
|
||||
# 重启服务
|
||||
docker restart math-grading
|
||||
|
||||
# 进入容器
|
||||
docker exec -it math-grading /bin/bash
|
||||
```
|
||||
|
||||
## 📊 API 接口
|
||||
|
||||
### 批改接口
|
||||
|
||||
**请求**:
|
||||
```bash
|
||||
curl -X POST http://localhost:8000/stream_run \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"student_homework": [
|
||||
{
|
||||
"student_id": 1,
|
||||
"student_name": "张三",
|
||||
"homework_images": [
|
||||
"https://example.com/image1.jpg",
|
||||
"https://example.com/image2.jpg"
|
||||
]
|
||||
}
|
||||
],
|
||||
"answer_doc_url": "https://example.com/answers.docx",
|
||||
"comment_max_length": 50,
|
||||
"max_concurrent": 5
|
||||
}'
|
||||
```
|
||||
|
||||
**参数说明**:
|
||||
- `student_homework`: 学生作业列表
|
||||
- `answer_doc_url`: 答案文档 URL(可选)
|
||||
- `comment_max_length`: 评语最大字数(默认 50)
|
||||
- `max_concurrent`: 并发批改数量(默认 5)
|
||||
|
||||
## 📁 目录结构
|
||||
|
||||
```
|
||||
.
|
||||
├── Dockerfile # Docker 镜像配置(硬编码 KEY)
|
||||
├── deploy.sh # 一键部署脚本
|
||||
├── test.sh # 快速测试脚本
|
||||
├── DOCKER_DEPLOY.md # 详细部署文档
|
||||
├── logs/ # 日志目录
|
||||
├── cache/ # 缓存目录
|
||||
└── src/ # 源代码
|
||||
```
|
||||
|
||||
## 🔍 故障排查
|
||||
|
||||
### 问题 1: 容器无法启动
|
||||
|
||||
```bash
|
||||
# 查看详细日志
|
||||
docker logs math-grading
|
||||
|
||||
# 检查端口占用
|
||||
netstat -tuln | grep 8000
|
||||
```
|
||||
|
||||
### 问题 2: LLM 调用失败
|
||||
|
||||
```bash
|
||||
# 检查环境变量
|
||||
docker exec math-grading env | grep COZE
|
||||
|
||||
# 应该看到:
|
||||
# COZE_API_KEY=Bearer eyJhbGci...
|
||||
# COZE_WORKSPACE_ID=7622238752642957347
|
||||
# COZE_INTEGRATION_BASE_URL=https://api.coze.cn/v1
|
||||
```
|
||||
|
||||
### 问题 3: 认证错误 (401)
|
||||
|
||||
- 确认 COZE_API_KEY 和 COZE_WORKSPACE_ID 都已设置
|
||||
- 检查 Token 是否有效
|
||||
|
||||
### 问题 4: 端点错误 (404)
|
||||
|
||||
- 确认 API 端点包含 /v1 前缀
|
||||
- 检查 COZE_INTEGRATION_BASE_URL 配置
|
||||
|
||||
## 📚 详细文档
|
||||
|
||||
- [完整部署指南](DOCKER_DEPLOY.md)
|
||||
- [项目文档](AGENTS.md)
|
||||
- [Docker 404 错误修复](assets/fix_docker_404.md)
|
||||
|
||||
## ⚠️ 安全提示
|
||||
|
||||
当前 Dockerfile 将 API Key 硬编码在镜像中:
|
||||
- ✅ 优点:部署简单,无需额外配置
|
||||
- ❌ 缺点:密钥会暴露在镜像中
|
||||
|
||||
### 安全建议
|
||||
|
||||
1. **使用私有仓库**:不要推送到公共 Docker Registry
|
||||
2. **访问控制**:限制镜像拉取权限
|
||||
3. **定期更换密钥**:在 Coze 平台定期更换 API Key
|
||||
4. **生产环境**:考虑使用环境变量方式(参考 docker-compose.yml)
|
||||
|
||||
## 🎯 验证成功标志
|
||||
|
||||
部署成功后,应该看到:
|
||||
|
||||
```bash
|
||||
# 1. 容器运行中
|
||||
docker ps | grep math-grading
|
||||
# Up 5 minutes
|
||||
|
||||
# 2. 健康检查通过
|
||||
curl http://localhost:8000/health
|
||||
# 200 OK
|
||||
|
||||
# 3. 日志无错误
|
||||
docker logs math-grading | grep ERROR
|
||||
# (无输出)
|
||||
|
||||
# 4. LLM 调用成功
|
||||
# 日志显示:
|
||||
# HTTP Request: POST https://api.coze.cn/v1/chat/completions "HTTP/1.1 200 OK"
|
||||
```
|
||||
|
||||
## 📞 支持
|
||||
|
||||
如遇问题,请:
|
||||
1. 查看日志: `docker logs -f math-grading`
|
||||
2. 运行测试: `./test.sh`
|
||||
3. 参考文档: `DOCKER_DEPLOY.md`
|
||||
|
|
@ -0,0 +1,124 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
从 JWT Token 中提取 Workspace ID
|
||||
"""
|
||||
|
||||
import json
|
||||
import base64
|
||||
import sys
|
||||
|
||||
def extract_workspace_id(token):
|
||||
"""
|
||||
从 JWT Token 中提取 Workspace ID
|
||||
|
||||
Args:
|
||||
token: JWT Token(带或不带 "Bearer " 前缀)
|
||||
|
||||
Returns:
|
||||
workspace_id: 工作区 ID
|
||||
"""
|
||||
try:
|
||||
# 移除 "Bearer " 前缀
|
||||
if token.startswith("Bearer "):
|
||||
token = token[7:]
|
||||
|
||||
# 分割 JWT
|
||||
parts = token.split(".")
|
||||
if len(parts) != 3:
|
||||
print("❌ Token 格式错误:应该是 JWT 格式(header.payload.signature)")
|
||||
return None
|
||||
|
||||
# 解码 payload
|
||||
payload_b64 = parts[1]
|
||||
# 添加 padding
|
||||
padding = 4 - len(payload_b64) % 4
|
||||
if padding != 4:
|
||||
payload_b64 += "=" * padding
|
||||
|
||||
payload = json.loads(base64.b64decode(payload_b64))
|
||||
|
||||
# 显示 Token 信息
|
||||
print("\n" + "=" * 80)
|
||||
print("JWT Token 信息")
|
||||
print("=" * 80)
|
||||
print(f"Issuer (iss): {payload.get('iss')}")
|
||||
print(f"Audience (aud): {payload.get('aud')}")
|
||||
print(f"Subject (sub): {payload.get('sub')}")
|
||||
print(f"Expires (exp): {payload.get('exp')}")
|
||||
print(f"Issued At (iat): {payload.get('iat')}")
|
||||
print(f"Source (src): {payload.get('src')}")
|
||||
print()
|
||||
|
||||
# 提取 workspace_id
|
||||
sub = payload.get('sub', '')
|
||||
|
||||
# 尝试不同的格式
|
||||
if 'workload_identity/id:' in sub:
|
||||
workspace_id = sub.split('workload_identity/id:')[-1]
|
||||
print(f"✅ 格式 1: workload_identity/id:{workspace_id}")
|
||||
elif 'workspace/id:' in sub:
|
||||
workspace_id = sub.split('workspace/id:')[-1]
|
||||
print(f"✅ 格式 2: workspace/id:{workspace_id}")
|
||||
else:
|
||||
# 尝试直接使用 sub
|
||||
workspace_id = sub
|
||||
print(f"⚠️ 格式 3: 直接使用 sub: {workspace_id}")
|
||||
|
||||
print()
|
||||
print("=" * 80)
|
||||
print(f"🔑 提取的 Workspace ID: {workspace_id}")
|
||||
print("=" * 80)
|
||||
print()
|
||||
|
||||
return workspace_id
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ 解析 Token 失败: {str(e)}")
|
||||
return None
|
||||
|
||||
def main():
|
||||
print()
|
||||
print("=" * 80)
|
||||
print("Workspace ID 提取工具")
|
||||
print("=" * 80)
|
||||
print()
|
||||
|
||||
# 方式 1:从环境变量读取
|
||||
token = None
|
||||
|
||||
# 1. 尝试从命令行参数读取
|
||||
if len(sys.argv) > 1:
|
||||
token = sys.argv[1]
|
||||
# 2. 尝试从环境变量读取
|
||||
else:
|
||||
token = __import__('os').environ.get('COZE_API_KEY')
|
||||
|
||||
if not token:
|
||||
print("❌ 未找到 Token")
|
||||
print()
|
||||
print("使用方法:")
|
||||
print(" 方式 1: python extract_workspace_id.py 'Bearer eyJhbGci...'")
|
||||
print(" 方式 2: COZE_API_KEY='Bearer eyJhbGci...' python extract_workspace_id.py")
|
||||
print()
|
||||
return 1
|
||||
|
||||
# 提取 workspace_id
|
||||
workspace_id = extract_workspace_id(token)
|
||||
|
||||
if workspace_id:
|
||||
print()
|
||||
print("✅ 提取成功!")
|
||||
print()
|
||||
print("下一步:")
|
||||
print(f"1. 在 docker-compose.yml 中设置:")
|
||||
print(f" COZE_WORKSPACE_ID={workspace_id}")
|
||||
print()
|
||||
return 0
|
||||
else:
|
||||
print()
|
||||
print("❌ 提取失败,请检查 Token 格式")
|
||||
print()
|
||||
return 1
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
#!/bin/bash
|
||||
# Docker 快速部署脚本
|
||||
|
||||
set -e
|
||||
|
||||
echo "=========================================="
|
||||
echo "数学作业批改系统 - Docker 部署脚本"
|
||||
echo "=========================================="
|
||||
echo ""
|
||||
|
||||
# 检查 Docker 是否安装
|
||||
if ! command -v docker &> /dev/null; then
|
||||
echo "❌ Docker 未安装,请先安装 Docker"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✅ Docker 已安装"
|
||||
echo ""
|
||||
|
||||
# 检查旧容器
|
||||
if docker ps -a | grep -q math-grading; then
|
||||
echo "⚠️ 检测到旧容器 math-grading"
|
||||
read -p "是否删除旧容器? (y/n) " -n 1 -r
|
||||
echo
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
echo "🗑️ 删除旧容器..."
|
||||
docker rm -f math-grading
|
||||
else
|
||||
echo "❌ 取消部署"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "🏗️ 开始构建镜像..."
|
||||
docker build -t math-grading:latest .
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "✅ 镜像构建成功"
|
||||
else
|
||||
echo "❌ 镜像构建失败"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "🚀 启动容器..."
|
||||
|
||||
# 创建日志和缓存目录
|
||||
mkdir -p logs cache
|
||||
|
||||
# 启动容器
|
||||
docker run -d \
|
||||
--name math-grading \
|
||||
-p 8000:8000 \
|
||||
-v $(pwd)/logs:/app/work/logs \
|
||||
-v $(pwd)/cache:/tmp/homework_cache \
|
||||
--restart unless-stopped \
|
||||
math-grading:latest
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "✅ 容器启动成功"
|
||||
else
|
||||
echo "❌ 容器启动失败"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "⏳ 等待服务启动..."
|
||||
sleep 5
|
||||
|
||||
echo ""
|
||||
echo "=========================================="
|
||||
echo "部署完成!"
|
||||
echo "=========================================="
|
||||
echo ""
|
||||
echo "服务地址: http://localhost:8000"
|
||||
echo ""
|
||||
echo "常用命令:"
|
||||
echo " 查看日志: docker logs -f math-grading"
|
||||
echo " 停止服务: docker stop math-grading"
|
||||
echo " 启动服务: docker start math-grading"
|
||||
echo " 重启服务: docker restart math-grading"
|
||||
echo ""
|
||||
echo "测试接口:"
|
||||
echo " curl -X POST http://localhost:8000/stream_run \\"
|
||||
echo " -H 'Content-Type: application/json' \\"
|
||||
echo " -d '{\"student_homework\": [{\"student_id\": 1, \"homework_images\": [\"https://example.com/image.jpg\"]}]}'"
|
||||
echo ""
|
||||
echo "详细文档: DOCKER_DEPLOY.md"
|
||||
echo ""
|
||||
|
|
@ -0,0 +1,125 @@
|
|||
#!/bin/bash
|
||||
# 快速测试脚本
|
||||
|
||||
echo "=========================================="
|
||||
echo "数学作业批改系统 - 快速测试"
|
||||
echo "=========================================="
|
||||
echo ""
|
||||
|
||||
# 检查容器是否运行
|
||||
if ! docker ps | grep -q math-grading; then
|
||||
echo "❌ 容器未运行,请先启动容器"
|
||||
echo "运行: docker start math-grading"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✅ 容器正在运行"
|
||||
echo ""
|
||||
|
||||
# 测试 1: 健康检查
|
||||
echo "测试 1: 健康检查"
|
||||
echo "----------------------------------------"
|
||||
response=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:8000/health)
|
||||
if [ "$response" = "200" ]; then
|
||||
echo "✅ 健康检查通过 (200 OK)"
|
||||
else
|
||||
echo "❌ 健康检查失败 (HTTP $response)"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# 测试 2: 环境变量检查
|
||||
echo "测试 2: 环境变量检查"
|
||||
echo "----------------------------------------"
|
||||
echo "检查关键环境变量..."
|
||||
|
||||
# COZE_API_KEY
|
||||
if docker exec math-grading env | grep -q "COZE_API_KEY=Bearer"; then
|
||||
echo "✅ COZE_API_KEY 已设置"
|
||||
else
|
||||
echo "❌ COZE_API_KEY 未设置"
|
||||
fi
|
||||
|
||||
# COZE_WORKSPACE_ID
|
||||
if docker exec math-grading env | grep -q "COZE_WORKSPACE_ID=7622238752642957347"; then
|
||||
echo "✅ COZE_WORKSPACE_ID 已设置 (7622238752642957347)"
|
||||
else
|
||||
echo "❌ COZE_WORKSPACE_ID 未设置或值不正确"
|
||||
fi
|
||||
|
||||
# API 端点
|
||||
if docker exec math-grading env | grep -q "COZE_INTEGRATION_BASE_URL=https://api.coze.cn/v1"; then
|
||||
echo "✅ API 端点已配置 (https://api.coze.cn/v1)"
|
||||
else
|
||||
echo "❌ API 端点未配置或缺少 /v1 前缀"
|
||||
fi
|
||||
|
||||
# LLM 模型
|
||||
if docker exec math-grading env | grep -q "LLM_MODEL_NAME=doubao-seed-2-0-pro-260215"; then
|
||||
echo "✅ LLM 模型已配置 (doubao-seed-2-0-pro-260215)"
|
||||
else
|
||||
echo "❌ LLM 模型未配置"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# 测试 3: LLM 调用测试
|
||||
echo "测试 3: LLM 调用测试"
|
||||
echo "----------------------------------------"
|
||||
echo "发送测试请求..."
|
||||
|
||||
response=$(curl -s -X POST http://localhost:8000/stream_run \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"student_homework": [
|
||||
{
|
||||
"student_id": 1,
|
||||
"student_name": "测试学生",
|
||||
"homework_images": [
|
||||
"https://dpcclass.oss-cn-beijing.aliyuncs.com/umsupload/2026/03/18/69baa4f5-4826-4901-00e1-c6e66f02947f.jpg?x-oss-process=image/resize,w_1000"
|
||||
]
|
||||
}
|
||||
],
|
||||
"answer_doc_url": "",
|
||||
"comment_max_length": 50,
|
||||
"max_concurrent": 1
|
||||
}' \
|
||||
--max-time 120)
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "✅ 请求发送成功"
|
||||
echo ""
|
||||
echo "响应预览:"
|
||||
echo "$response" | head -c 500
|
||||
echo "..."
|
||||
else
|
||||
echo "❌ 请求失败"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# 测试 4: 日志检查
|
||||
echo "测试 4: 日志检查"
|
||||
echo "----------------------------------------"
|
||||
echo "检查最近日志中的错误..."
|
||||
|
||||
errors=$(docker logs --tail 100 math-grading 2>&1 | grep -i "401\|404\|authentication is invalid" | wc -l)
|
||||
|
||||
if [ "$errors" -eq 0 ]; then
|
||||
echo "✅ 未发现认证错误或端点错误"
|
||||
else
|
||||
echo "❌ 发现 $errors 个错误"
|
||||
echo "最近的错误:"
|
||||
docker logs --tail 50 math-grading 2>&1 | grep -i "401\|404\|authentication is invalid" | tail -5
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# 总结
|
||||
echo "=========================================="
|
||||
echo "测试总结"
|
||||
echo "=========================================="
|
||||
echo ""
|
||||
echo "如果所有测试都通过,说明部署成功!"
|
||||
echo ""
|
||||
echo "下一步:"
|
||||
echo " 1. 查看详细日志: docker logs -f math-grading"
|
||||
echo " 2. 测试完整功能: 使用上面的测试请求"
|
||||
echo " 3. 部署到生产环境: 参考 DOCKER_DEPLOY.md"
|
||||
echo ""
|
||||
Loading…
Reference in New Issue