通过自托管 HuggingFace 文本嵌入推理(TEI) 实现 Discourse AI 中帖子的情感与情绪分析。
什么是它
Discourse AI 中的 Sentiment 并非聊天/生成式 LLM。其底层是两个小型的 分类 RoBERTa 模型(每个约 1.25 亿参数),通过 HuggingFace TEI 启动。模型名称已在 Discourse 的仪表板 SQL 查询中硬编码,不可更改。
来源:Self-Hosting Sentiment and Emotion for DiscourseAI(Falco,Discourse 团队)。
| 模型 | model_name(必须与代码中一致) | 用途 |
|---|---|---|
| Sentiment | cardiffnlp/twitter-roberta-base-sentiment-latest |
正面 / 负面 / 中性 |
| Emotion | SamLowe/roberta-base-go_emotions |
28 种情绪(喜悦、愤怒、惊讶等) |
API 格式:POST {\"inputs\": \"text\", \"truncate\": true} → 返回数组 [{\"label\": \"...\", \"score\": 0.95}, ...]
特殊说明:cardiffnlp 模型无 tokenizer.json
TEI 需要 tokenizer.json,但 cardiffnlp/twitter-roberta-base-sentiment-latest 没有(旧格式为 vocab.json + merges.txt)。解决方案:本地下载模型文件,并从 SamLowe/roberta-base-go_emotions 中复制 tokenizer.json(二者使用相同的 RoBERTa-base 分词器)。
准备(仅需一次)
sudo mkdir -p /opt/tei-sentiment-cache/model
cd /opt/tei-sentiment-cache/model
for f in config.json vocab.json merges.txt special_tokens_map.json pytorch_model.bin; do
sudo curl -sL -o "$f" "https://huggingface.co/cardiffnlp/twitter-roberta-base-sentiment-latest/resolve/main/$f"
done
sudo curl -sL -o tokenizer.json "https://huggingface.co/SamLowe/roberta-base-go_emotions/resolve/main/tokenizer.json"
sudo curl -sL -o tokenizer_config.json "https://huggingface.co/SamLowe/roberta-base-go_emotions/resolve/main/tokenizer_config.json"
方案 A:GPU
镜像: ghcr.io/huggingface/text-embeddings-inference:cuda-1.9.3
标准标签
:latest(及:1.9)编译用于 compute cap 80(Ampere),不兼容 Blackwell(RTX 50x0,compute cap 120)。请务必使用cuda-1.9.3
docker pull ghcr.io/huggingface/text-embeddings-inference:cuda-1.9.3
sudo mkdir -p /opt/tei-emotion-cache
docker run -d --name tei-sentiment --gpus all --shm-size 1g -p 8081:80 -v /opt/tei-sentiment-cache/model:/data/model --restart unless-stopped ghcr.io/huggingface/text-embeddings-inference:cuda-1.9.3 --model-id /data/model
docker run -d --name tei-emotion --gpus all --shm-size 1g -p 8082:80 -v /opt/tei-emotion-cache:/data --restart unless-stopped ghcr.io/huggingface/text-embeddings-inference:cuda-1.9.3 --model-id SamLowe/roberta-base-go_emotions
在 Blackwell 上首次运行时,CUDA 内核的 JIT 编译约需 5 分钟(仅首次运行)
GPU 性能(RTX 5060 Ti)
| 指标 | 值 |
|---|---|
| Sentiment 推理 | 约 14ms |
| Emotion 推理 | 约 60ms |
| 单容器显存占用 | 约 428 MB |
| 两个容器总显存占用 | 约 856 MB |
方案 B:CPU(备用)
镜像: ghcr.io/huggingface/text-embeddings-inference:cpu-1.9
适用于无 GPU 或显存不足的情况,无需 NVIDIA 驱动。
docker pull ghcr.io/huggingface/text-embeddings-inference:cpu-1.9
sudo mkdir -p /opt/tei-emotion-cache
docker run -d --name tei-sentiment --shm-size 1g -p 8081:80 -v /opt/tei-sentiment-cache/model:/data/model --restart unless-stopped ghcr.io/huggingface/text-embeddings-inference:cpu-1.9 --model-id /data/model --dtype float32
docker run -d --name tei-emotion --shm-size 1g -p 8082:80 -v /opt/tei-emotion-cache:/data --restart unless-stopped ghcr.io/huggingface/text-embeddings-inference:cpu-1.9 --model-id SamLowe/roberta-base-go_emotions --dtype float32
```当 LA 较高时,可以限制 CPU:
```bash
docker update --cpus=0.1 tei-sentiment tei-emotion
CPU 性能
| 指标 | 数值 |
|---|---|
| 情感推理 | ~270ms |
| 情绪推理 | ~205ms |
| 容器内存 | ~500 MB |
| 使用 --cpus=0.1 | 每条帖子约 2-3 秒 |
切换 GPU ↔ CPU
docker stop tei-sentiment tei-emotion
docker rm tei-sentiment tei-emotion
然后根据需要启动容器。无需更改 Discourse 设置 —— endpoint 保持不变。
验证
curl -s http://localhost:8081/ -X POST -H 'Content-Type: application/json' -d '{"inputs": "I am happy"}'
curl -s http://localhost:8082/ -X POST -H 'Content-Type: application/json' -d '{"inputs": "I am happy"}'
预期情感响应:[{"label":"positive","score":0.96},...]
Discourse 设置
在 /admin/plugins/discourse-ai/settings?filter=sentiment 中:
- discourse_ai_enabled = true
- ai_sentiment_enabled = true
- ai_sentiment_model_configs - 两个对象:
| 字段 | 模型 1 | 模型 2 |
|---|---|---|
| model_name | cardiffnlp/twitter-roberta-base-sentiment-latest |
SamLowe/roberta-base-go_emotions |
| endpoint | http://<your-host>:8081 |
http://<your-host>:8082 |
| api_key | (空) | (空) |
仪表板
/admin/reports/overall_sentiment—— 整体情绪(积极 - 消极)/admin/reports/emotion_joy(及其他 27 种情绪)- 数据回填:约 2500 条帖子/小时,帖子不超过 60 天
条件与风险
- 模型仅在 英文 上训练。对于俄语文本,结果为近似值,但基础情感分析仍可运行。
- Endpoint 未启用 API 密钥保护 —— 生产环境建议通过反向代理关闭。
- 显存监控:
nvidia-smi --query-compute-apps=pid,name,used_memory --format=csv,noheader