News Sentiment Finbert logo

News Sentiment Finbert

CommunityPopular
qusong0627
news-sentiment-finbert

RSS 新闻情绪识别(FinBERT 中文金融情感)安装与运维 — 情绪管线架构、transformers 安装、FinBERT 权重下载、字典法扩充、全量重算、情绪筛选/条形图/个股资讯标签的使用。在 QuantBot / Claude Code 中排查新闻情绪不生效、重新安装 FinBERT、扩充情绪词、触发新闻情绪重算时使用。触发词:情绪识别、FinBERT、情绪不生效、情绪都是中性、字典法、新闻重算、news sentiment

Overview

Publisherqusong0627
RepositoryQuantMind
Skill namenews-sentiment-finbert
Stars
1.7K
Forks
387
Bundled files
Instructions only
LicenseAGPL-3.0
Links
  • Markdown instructions

    A SKILL.md file the model loads on demand, so it only costs tokens when a request actually matches.

  • Works with any LLM

    AI skills are plain Markdown, not provider-specific code, so this works with GPT, Claude, Gemini, Grok, or a local model.

  • Self-contained

    Everything the model needs lives in the instructions — no extra files to sync.

  • Open source

    Published by qusong0627 on GitHub. Read the source before you install it.

Installation

Install the News Sentiment Finbert AI skill in TypingMind to use it with any LLM, or drop it into another agent that reads SKILL.md.

1

Install in TypingMind

TypingMind installs a skill straight from its GitHub folder — it reads SKILL.md, bundles the resource files, and stores the result locally.

  1. Open the app and go to Plugins → Skills.
  2. Choose "Install from GitHub".
  3. Paste the skill folder URL below and confirm.
    https://github.com/qusong0627/QuantMind/tree/master/skills/news-sentiment-finbert
  4. Enable the skill in any chat where you want it available.
Plugins → Skills → Add skill → From GitHub URL, then paste the folder URL and press Continue.
2

Install in another agent

Any agent that reads the Agent Skills format can use this skill — copy the folder into that agent's skills directory.

Claude Code — .claude/skills
git clone --depth 1 https://github.com/qusong0627/QuantMind.git /tmp/QuantMind
mkdir -p .claude/skills
cp -r /tmp/QuantMind/skills/news-sentiment-finbert .claude/skills/news-sentiment-finbert
Restart Claude Code after copying so it picks up the new skill.

Use it in TypingMind

Enable News Sentiment Finbert in any TypingMind chat and the model takes it from there. Its name and description sit in the system prompt, and the moment a request matches, the model loads the full instructions itself — you never invoke it by hand, and it costs no tokens until it is actually used.

The model loads News Sentiment Finbert on its own as soon as a request matches it.

Works with any AI model

AI skills are plain Markdown instructions rather than provider-specific code, so News Sentiment Finbert is not tied to the model it was written for. Install it once in TypingMind and use it with GPT-5, Claude, Gemini, Grok, DeepSeek, Mistral, Llama, or a local model you run yourself — all on your own API keys.

  • Loaded only when it is needed

    The system prompt carries just the name and description. The instructions are fetched on the first matching request, so an idle skill costs nothing.

  • Switch models mid-chat

    Because the skill is instructions rather than code, changing model does not break it — the next model reads the same SKILL.md.

Skill instructions

This is the SKILL.md content the model loads. Read it before installing — a skill is instructions your model will follow.

⚙️ 本技能遵循公共运行环境契约(最高优先级,先于本文其余内容执行): 详见 _shared/env-contract.md,执行前先读它。

新闻情绪识别(FinBERT)安装与运维技能

QuantMind 的 RSS 新闻情绪识别管线:Huntly 抓取 → celery 每分钟 enrich → 股票/行业/事件标签 + 情绪分 → news_article_enrichment 表 → 前端 RSS 面板/个股资讯 Tab 展示利好/利空。

本技能覆盖情绪层的安装、验证、重算、排查、词库增强。

1. 架构与数据流

Huntly (RSS 抓取, 381 源, 41.5 万文章)
  → celery-beat 每 60s: news-enrich-recent (run_enrichment_batch)
  → NewsMatcher (Aho-Corasick + finance_lexicon 5 万词: 股票/行业/事件/情感)
  → sentiment.score() (两级融合)
      字典法 dict_score (finance_lexicon sentiment_pos/neg 词权重差)
      + FinBERT (bardsai/finance-sentiment-zh-base, CPU, conf≥0.55 才融合)
  → 写入 news_article_enrichment 表 (model_version 带 +finbert 后缀表示 FinBERT 生效)
  → 前端:
      /rss-news  NewsPanel: 情绪筛选/利好利空强度排序/统计栏情绪分布条形图
      个股终端「个股资讯」Tab: 每篇利好/利空标签 (stock_news 关联 enrichment)

情绪词库:finance_lexicon 已从最初的 230 词扩充到 51,887 词(sentiment_pos 27,227 / sentiment_neg 24,089 / event 571),来源见第 6 节。

6. 情绪词库增强(从 230 词 → 5 万词)

情绪词分两级来源,统一存 finance_lexicon:

6.1 现成情感词典(通用,可复现导入)

来源词数说明
DLUT 情感本体库 (github.com/yizhanmiao/DLUT-Emotionontology)22,001中文情感词汇本体,强度 1-9,极性 1正/2负
pysenti (github.com/shibing624/pysenti)9,870内置情感词典,连续分数 -7~+7
NTUSD 台大词典 (github.com/ntunlplab/NTUSD)20,485繁体,Big5 编码,需转简体

6.2 RSS 标题提炼(金融语境,最精准)

用 41.5 万条 Huntly 标题 + enrichment 已有情绪标签,做共现统计(对数似然比 LLR 筛选):

  • bearish 标题高频词 → 负向金融情绪词(下跌/暴跌/跌破/违规/立案/警示)
  • bullish 标题高频词 → 正向金融情绪词(涨超/涨停/新高/买入/上调)
  • 产出 5,705 词,贴合 A股/监管/业绩语境,通用词典覆盖不到的(如"暂停开户""被重锤")都在这

6.3 复现导入

bash
# 词表已固化: backend/scripts/data/finance_sentiment_lexicon.tsv (51,213 词)
# 导入脚本: backend/scripts/import_sentiment_lexicon.py
# 本地
python3 backend/scripts/import_sentiment_lexicon.py
# 容器
docker exec quantmind python3 /app/backend/scripts/import_sentiment_lexicon.py

导入后重载 matcher:

bash
curl -s -X POST -H "$AUTH" "$BASE/api/v1/news/enrichment/run"  # 触发重算

6.4 新增情绪词的完整流程

  1. 从新数据源提取词(如再跑 RSS 统计)
  2. 写入 backend/scripts/data/finance_sentiment_lexicon.tsv(term\tpos|neg\tweight)
  3. 跑 import_sentiment_lexicon.py 导入
  4. 触发 /enrichment/run 或 rebuild 让新词生效

2. 情绪不生效 / 全是中性 的排查(最常见)

症状:RSS 面板里利好/利空占比极低(<5%),几乎全 neutral,置信度恒 0.3。

根因:FinBERT 模型没装上(容器缺 transformers),回退纯字典法,而字典法词太少打不出分。

判断方法:查 model_version 有没有 +finbert 后缀。

bash
docker exec quantmind python3 -c "
import asyncio
from backend.shared.database_manager_v2 import get_session
from sqlalchemy import text
async def main():
    async with get_session() as s:
        r = await s.execute(text(\"SELECT sentiment_label, COUNT(*) FROM news_article_enrichment WHERE model_version LIKE '%finbert%' GROUP BY sentiment_label ORDER BY 2 DESC\"))
        print('+finbert 分布:', r.fetchall())
        r = await s.execute(text(\"SELECT COUNT(*) FROM news_article_enrichment WHERE model_version NOT LIKE '%finbert%'\"))
        print('无 finbert 条数:', r.fetchone()[0])
asyncio.run(main())
"
  • 有 +finbert 且有 bullish/bearish 分布 → FinBERT 正常
  • 全 neutral / 无 +finbert → FinBERT 没生效,按第 3 节处理

3. 安装 / 修复 FinBERT

3.1 检查 transformers 是否在容器里

bash
docker exec quantmind python3 -c "import transformers; print(transformers.__version__)"
# celery worker 也要有(enrich/rebuild 在 celery 里跑)
docker exec quantmind-celery python3 -c "import transformers; print(transformers.__version__)"

3.2 缺的话手动装(临时修复,镜像重建后固化)

bash
docker exec quantmind pip install --no-cache-dir transformers
docker exec quantmind-celery pip install --no-cache-dir transformers

3.3 下载/同步 FinBERT 权重(~100MB,离线可用)

bash
# 触发下载(首次)
docker exec quantmind python3 -c "
from backend.services.api.news import sentiment as s
s._model_ready=False; s._model_failed=False
s._try_load(); print('ready=', s._model_ready)
"
# 权重缓存位置: /root/.cache/huggingface/hub/models--bardsai--finance-sentiment-zh-base
# celery worker 复用(主容器导出 → tar 管道 → celery 导入)
docker exec quantmind tar -C /root/.cache/huggingface/hub -cf - models--bardsai--finance-sentiment-zh-base \
  | docker exec -i quantmind-celery sh -c 'mkdir -p /root/.cache/huggingface/hub && tar -C /root/.cache/huggingface/hub -xf -'

3.4 验证 FinBERT 可用

bash
docker exec quantmind-celery python3 -c "
import os
os.environ['HF_HUB_OFFLINE']='1'
from transformers import pipeline
p = pipeline('sentiment-analysis', model='bardsai/finance-sentiment-zh-base', device=-1)
print(p('公司业绩暴雷,股价暴跌')[0])   # 期望 label=negative, score>0.9
"

3.5 重启 celery worker 让新代码/新依赖生效

bash
docker restart quantmind-celery
sleep 8
# 确认后台加载成功
docker exec quantmind-celery python3 -c "
from backend.services.api.news import sentiment as s
s._ensure_loading()
import time
for _ in range(40):
    if s.is_available(): break
    time.sleep(1)
print('FinBERT ready:', s.is_available())
"

4. 触发全量重算(历史情绪重打)

model_version 变了(比如补上 +finbert 后)需要重算历史才能让旧文章带上情绪。force=true 全量重算 41 万条 Huntly 文章,约 3-4 小时后台跑。

bash
TOKEN=$(curl -s -X POST $BASE/api/v1/auth/login -H "Content-Type: application/json" \
  -d '{"username":"admin","password":"admin123","tenant_id":"default"}' \
  | python3 -c "import sys,json; print(json.load(sys.stdin).get('access_token',''))")

# 全量重算(force=true 覆盖已 enrich 的)
curl -s -X POST -H "Authorization: Bearer $TOKEN" \
  "$BASE/api/v1/news/enrichment/rebuild-all?force=true"
# 或增量(跳过 model_version 已是最新的)
curl -s -X POST -H "Authorization: Bearer $TOKEN" \
  "$BASE/api/v1/news/enrichment/rebuild-all"

# 查进度
curl -s -H "Authorization: Bearer $TOKEN" "$BASE/api/v1/news/enrichment/rebuild-progress"

注意:rebuild 在 celery worker 的后台线程跑,重启 celery 会中断 rebuild。重算期间别重启 celery。

5. 字典法增强(FinBERT 不可用时的兜底)

情绪是两级融合,FinBERT 置信度 <0.55 或不可用时用字典法。字典词在 finance_lexicon 表(kind=sentiment_pos/neg,weight 为强度)。

扩充方式:

  1. 改仓库 backend/scripts/seed_a_share_stocks.py 的 _BUILTIN_SENTIMENT_POS/NEG 常量(已含 2026-08 扩充的 ~80 个词)
  2. 重跑 seed:
bash
docker exec quantmind python3 /app/backend/scripts/seed_a_share_stocks.py
  1. 或直接 SQL 插入(幂等,先查后插):
bash
docker exec quantmind python3 -c "
import asyncio
from backend.shared.database_manager_v2 import get_session
from sqlalchemy import text
async def main():
    async with get_session() as s:
        await s.execute(text(\"INSERT INTO finance_lexicon (term, kind, weight, enabled) VALUES ('涨停','sentiment_pos',1.0,true)\"))
        await s.commit()
asyncio.run(main())
"
  1. 词表改动立即生效(NewsMatcher 每 600s 重载 / 可触发 /enrichment/run 重算新文章)

6. 情绪数据怎么用(前端已就绪)

位置说明
/rss-news NewsPanel情绪筛选(利好/利空/中性)、利好/利空强度排序、统计栏情绪分布条形图(红利好/绿利空/灰中性)
个股终端 → 个股资讯 Tab每篇标题前利好/利空标签(stock_news 按 huntly_page_id join enrichment)
/news/articles APIsentiment=bullish/bearish/neutral 过滤 + sort=sentiment_bullish/sentiment_bearish
/news/enrichment/stats当前筛选下的情绪分布计数(前端统计栏数据源)

7. 相关代码文件

  • backend/services/api/news/sentiment.py — FinBERT 懒加载/后台加载/失败重试(_RETRY_AFTER 冷却 300s)
  • backend/services/api/news/enricher.py — enrich 管线,0.6字典+0.4FinBERT 融合
  • backend/services/api/news/matcher.py — Aho-Corasick 匹配 + 字典分
  • backend/scripts/seed_a_share_stocks.py — finance_lexicon 内置词(含情绪词)
  • backend/scripts/import_sentiment_lexicon.py — 5 万情绪词批量导入脚本(可复现)
  • backend/scripts/data/finance_sentiment_lexicon.tsv — 合并情绪词表 51,213 词(RSS提炼+DLUT+pysenti+NTUSD)
  • backend/services/api/routers/news.py — /news/* 路由(articles/enrichment/stats/sources)
  • backend/services/api/routers/stock_terminal.py — /stock-terminal/news 个股资讯(带情绪标签)
  • electron/src/features/news/components/NewsPanel.tsx — RSS 面板(情绪分布条形图)
  • electron/src/features/stock-terminal/components/tabs/NewsTab.tsx — 个股资讯情绪标签
  • docker/Dockerfile.oss + requirements/ai.txt — transformers 依赖 + FinBERT 权重预下载

8. 相关技能

  • [[quantmind-operations]] — RSS 新闻对接与分析(文章拉取/过滤/富化统计)
  • [[quantdb-fields]] — 数据字段口径

Frequently asked questions

What does the News Sentiment Finbert AI skill do?

RSS 新闻情绪识别(FinBERT 中文金融情感)安装与运维 — 情绪管线架构、transformers 安装、FinBERT 权重下载、字典法扩充、全量重算、情绪筛选/条形图/个股资讯标签的使用。在 QuantBot / Claude Code 中排查新闻情绪不生效、重新安装 FinBERT、扩充情绪词、触发新闻情绪重算时使用。触发词:情绪识别、FinBERT、情绪不生效、情绪都是中性、字典法、新闻重算、news sentiment

Why use News Sentiment Finbert on TypingMind?

Because you install it once and use it with any model. News Sentiment Finbert is plain Markdown rather than provider-specific code, so the same skill runs on GPT-5, Claude, Gemini, Grok, or a local model — and you can switch model mid-chat without it breaking. TypingMind runs on your own API keys, so you pay providers directly instead of a per-seat subscription, and your skills and chats stay in your own storage.

How do I install News Sentiment Finbert in TypingMind?

Open Plugins → Skills → Install from GitHub in TypingMind and paste https://github.com/qusong0627/QuantMind/tree/master/skills/news-sentiment-finbert. TypingMind reads its SKILL.md and installs it as a skill you can enable per chat.

Which AI models can use News Sentiment Finbert?

Any model you connect in TypingMind. AI skills are plain Markdown instructions rather than provider-specific code, so GPT, Claude, Gemini, Grok, and local models can all load this skill when a request matches it.

How many AI models can I use with News Sentiment Finbert?

As many as you like. As long as a model supports skills, you can use News Sentiment Finbert with it — GPT, Claude, Gemini, Grok, DeepSeek, Mistral, Llama and more — all on TypingMind with your own API keys.

Is the News Sentiment Finbert AI skill free?

Yes. It is published on GitHub by qusong0627 under the AGPL-3.0 license. You only pay your own AI provider for the tokens you use.

What are AI skills?

An AI skill is a reusable instruction bundle that teaches an AI model how to do one specific task. It follows the open Agent Skills format: a SKILL.md file with a name and description, plus any scripts, templates or reference files the model may need. The model reads the instructions only when your request matches the skill, so an installed skill costs nothing until it is used.

How are AI skills different from plugins or MCP servers?

A plugin or MCP server gives a model new tools to call — code that runs somewhere and returns a result. An AI skill gives the model knowledge and process instead: how to approach a task, which steps to follow, what good output looks like. Skills are plain Markdown, so they need no server, no API key and no runtime, and they work with any model.

View all

Set up your own AI workspace now

Get notified about new features and future giveaways by subscribing to our newsletter 👇