303 lines
7.0 KiB
Markdown
303 lines
7.0 KiB
Markdown
# 图片物体智能标注功能 - 集成步骤(剩余工作)
|
||
|
||
## 📝 当前进度
|
||
|
||
### ✅ 已完成
|
||
1. **GPU 检测** - 4张 Tesla P40 显卡,CUDA 11.8
|
||
2. **后端环境** - Python 虚拟环境、依赖安装完成
|
||
3. **模型下载** - Florence-2 正在后台下载(进行中)
|
||
4. **前端组件** - ImagePreview 和 PreviewAttachment 已添加标注功能
|
||
|
||
### 🔄 进行中
|
||
- Florence-2 模型下载(后台运行)
|
||
- 查看进度:`ssh root@156.225.27.52 "tail -f /var/www/ai-chatbot-backend/logs/model_download.log"`
|
||
|
||
---
|
||
|
||
## 🔧 剩余集成步骤
|
||
|
||
### 步骤 1:修改 MultimodalInput 组件
|
||
|
||
**文件**:`components/multimodal-input.tsx`
|
||
|
||
**需要修改的位置**:
|
||
|
||
1. **添加状态管理**(在组件顶部添加):
|
||
```typescript
|
||
// 在组件内部添加
|
||
const [annotations, setAnnotations] = useState<Array<{
|
||
imageIndex: number;
|
||
description: string;
|
||
formattedText: string;
|
||
}>>([]);
|
||
|
||
// 添加标注处理函数
|
||
const handleAnnotate = (annotation: {
|
||
imageIndex: number;
|
||
description: string;
|
||
formattedText: string;
|
||
}) => {
|
||
setAnnotations((prev) => [...prev, annotation]);
|
||
|
||
// 自动插入到输入框(在当前光标位置或末尾)
|
||
setInput((prev) => {
|
||
const currentValue = prev || "";
|
||
// 如果输入框有内容,在末尾添加空格
|
||
const separator = currentValue ? " " : "";
|
||
return `${currentValue}${separator}${annotation.formattedText}`;
|
||
});
|
||
|
||
// 可选:添加视觉反馈
|
||
toast.success(`已添加标注:${annotation.description}`);
|
||
};
|
||
```
|
||
|
||
2. **传递 props 到 PreviewAttachment**(找到渲染 PreviewAttachment 的地方):
|
||
```typescript
|
||
// 在渲染 attachments 的地方修改
|
||
{attachments.map((attachment, index) => (
|
||
<PreviewAttachment
|
||
key={attachment.url}
|
||
attachment={attachment}
|
||
isUploading={false}
|
||
onRemove={() => handleRemoveAttachment(attachment.url)}
|
||
onAnnotate={handleAnnotate} // 新增
|
||
imageIndex={index + 1} // 新增(从 1 开始编号)
|
||
draggable={attachments.length > 1}
|
||
onDragStart={(e) => handleDragStart(e, index)}
|
||
onDragEnd={handleDragEnd}
|
||
onDragOver={handleDragOver}
|
||
onDrop={(e) => handleDrop(e, index)}
|
||
/>
|
||
))}
|
||
```
|
||
|
||
---
|
||
|
||
### 步骤 2:配置 Nginx 代理
|
||
|
||
**文件**:`/etc/nginx/sites-available/ai-chatbot`(服务器上)
|
||
|
||
**添加后端 API 代理**:
|
||
```nginx
|
||
# 在 server 块中添加
|
||
location /api/detect-object {
|
||
proxy_pass http://127.0.0.1:8001/api/detect-object;
|
||
proxy_http_version 1.1;
|
||
proxy_set_header Upgrade $http_upgrade;
|
||
proxy_set_header Connection 'upgrade';
|
||
proxy_set_header Host $host;
|
||
proxy_cache_bypass $http_upgrade;
|
||
proxy_set_header X-Real-IP $remote_addr;
|
||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||
|
||
# 增加超时时间(AI 推理需要时间)
|
||
proxy_connect_timeout 10s;
|
||
proxy_send_timeout 10s;
|
||
proxy_read_timeout 10s;
|
||
}
|
||
```
|
||
|
||
**应用配置**:
|
||
```bash
|
||
sudo nginx -t
|
||
sudo systemctl reload nginx
|
||
```
|
||
|
||
---
|
||
|
||
### 步骤 3:启动 Florence-2 API 服务
|
||
|
||
等模型下载完成后(检查日志显示"✅ 模型下载完成"),执行:
|
||
|
||
```bash
|
||
# SSH 到服务器
|
||
ssh -p 5204 root@156.225.27.52
|
||
|
||
# 启动服务
|
||
cd /var/www/ai-chatbot-backend
|
||
pm2 start ecosystem.config.js
|
||
|
||
# 查看日志
|
||
pm2 logs florence-api
|
||
|
||
# 检查状态
|
||
pm2 status
|
||
|
||
# 测试健康检查
|
||
curl http://localhost:8001/health
|
||
```
|
||
|
||
**预期响应**:
|
||
```json
|
||
{"status":"ok","model_loaded":true}
|
||
```
|
||
|
||
---
|
||
|
||
### 步骤 4:部署前端
|
||
|
||
```bash
|
||
# 本地构建并上传
|
||
cd /Users/lanmu/Desktop/ai-chatbot-main
|
||
npm run build
|
||
pm2 restart ai-chatbot
|
||
```
|
||
|
||
或使用 SSH 直接在服务器上构建:
|
||
```bash
|
||
ssh -p 5204 root@156.225.27.52 "
|
||
cd /var/www/ai-chatbot && \
|
||
npm run build && \
|
||
pm2 restart ai-chatbot
|
||
"
|
||
```
|
||
|
||
---
|
||
|
||
### 步骤 5:测试功能
|
||
|
||
1. **访问网站**:https://ai.yydd.ai
|
||
|
||
2. **上传测试图片**:
|
||
- 选择图片生成模型
|
||
- 上传 2 张包含明显物体的图片
|
||
|
||
3. **测试标注**:
|
||
- 点击第一张图片
|
||
- 点击"定位标注"按钮(Target 图标)
|
||
- 点击图片中的物体
|
||
- 等待识别结果
|
||
- 验证输入框中是否自动填入标注文本
|
||
|
||
4. **预期结果**:
|
||
```
|
||
输入框内容:📍图1: 绿色手提包
|
||
```
|
||
|
||
5. **继续测试第二张图**:
|
||
- 点击第二张图片,标注另一个物体
|
||
- 输入框应显示:`📍图1: 绿色手提包 📍图2: 红色背包`
|
||
|
||
---
|
||
|
||
## 🐛 常见问题排查
|
||
|
||
### 问题 1:点击标注按钮无反应
|
||
|
||
**检查**:
|
||
1. 浏览器控制台是否有错误
|
||
2. 后端 API 是否启动:`pm2 logs florence-api`
|
||
3. Nginx 代理是否配置正确:`sudo nginx -t`
|
||
|
||
### 问题 2:识别速度很慢
|
||
|
||
**优化**:
|
||
1. 确认使用 GPU:检查日志中是否显示"🚀 GPU 加速已启用"
|
||
2. 检查 GPU 使用率:`nvidia-smi`
|
||
3. 如果 GPU 未被使用,检查 CUDA_VISIBLE_DEVICES 环境变量
|
||
|
||
### 问题 3:识别结果不准确
|
||
|
||
**调整**:
|
||
1. 提示用户点击物体中心位置
|
||
2. 调整裁剪区域大小(florence_service.py 中的 crop_size)
|
||
3. 尝试不同的提示词(CAPTION、DENSE_REGION_CAPTION 等)
|
||
|
||
### 问题 4:502 Bad Gateway
|
||
|
||
**检查**:
|
||
1. 后端服务是否正常:`pm2 status`
|
||
2. 查看后端日志:`pm2 logs florence-api --lines 50`
|
||
3. 检查端口 8001 是否被占用:`lsof -i :8001`
|
||
|
||
---
|
||
|
||
## 📊 性能指标
|
||
|
||
### 预期性能(Tesla P40 GPU)
|
||
|
||
| 指标 | 数值 |
|
||
|------|------|
|
||
| 单次识别时间 | 0.15-0.25 秒 |
|
||
| 并发处理能力 | 4-6 QPS |
|
||
| GPU 显存占用 | ~2GB |
|
||
| CPU 内存占用 | ~1.5GB |
|
||
|
||
### 监控命令
|
||
|
||
```bash
|
||
# 实时监控 GPU
|
||
watch -n 1 nvidia-smi
|
||
|
||
# 查看 API 日志
|
||
tail -f /var/www/ai-chatbot-backend/logs/output.log
|
||
|
||
# 查看错误日志
|
||
tail -f /var/www/ai-chatbot-backend/logs/error.log
|
||
|
||
# 查看模型下载进度
|
||
tail -f /var/www/ai-chatbot-backend/logs/model_download.log
|
||
```
|
||
|
||
---
|
||
|
||
## 🎨 可选增强功能
|
||
|
||
### 1. 标注文本样式
|
||
|
||
在输入框中用特殊样式显示标注文本:
|
||
|
||
```typescript
|
||
// 可以添加一个组件来渲染标注标签
|
||
const AnnotationTag = ({ text, onRemove }: { text: string; onRemove: () => void }) => (
|
||
<span className="inline-flex items-center gap-1 rounded-md bg-blue-500/10 px-2 py-1 text-blue-600">
|
||
<span>{text}</span>
|
||
<button onClick={onRemove} className="hover:text-blue-800">
|
||
×
|
||
</button>
|
||
</span>
|
||
);
|
||
```
|
||
|
||
### 2. 标注历史
|
||
|
||
保存标注历史,允许用户重复使用:
|
||
|
||
```typescript
|
||
const [annotationHistory, setAnnotationHistory] = useLocalStorage<string[]>(
|
||
"annotation-history",
|
||
[]
|
||
);
|
||
```
|
||
|
||
### 3. 批量标注
|
||
|
||
允许用户一次标注多个物体,然后一起插入:
|
||
|
||
```typescript
|
||
const [pendingAnnotations, setPendingAnnotations] = useState<Annotation[]>([]);
|
||
|
||
const commitAnnotations = () => {
|
||
const text = pendingAnnotations.map(a => a.formattedText).join(" ");
|
||
setInput((prev) => `${prev} ${text}`);
|
||
setPendingAnnotations([]);
|
||
};
|
||
```
|
||
|
||
---
|
||
|
||
## 📞 联系支持
|
||
|
||
如果遇到问题,请检查:
|
||
1. 后端日志:`pm2 logs florence-api`
|
||
2. 前端控制台
|
||
3. Nginx 错误日志:`sudo tail -f /var/log/nginx/error.log`
|
||
|
||
---
|
||
|
||
**文档版本**: v1.0
|
||
**更新日期**: 2025-12-15
|
||
**作者**: AI Chatbot 开发团队
|
||
|