BettaFish 常见问题解答(持续更新)
Note
Agent 自动整理说明 :本页由 Agent 根据当前代码、主线提交、Tag / Release、Issue 与 PR 中的公开讨论汇总,并由项目维护者审核后更新。请不要把 API Key、Cookie、数据库密码或完整 .env 发到 Issue。
Important
适用基线 :本次整理截至 2026-07-20 ,当前 main 为 40327d7 。最新已发布 Release 仍是 v3.0.0,但当前 main 比它多 44 个提交,两者不能等同。以后如果代码继续变化,请以当时的 README 、.env.example 和源码为准。
一、版本、安装与配置
1. “最新版”到底是哪个?当前还有 GraphRAG 吗?
最新已发布版本是 v3.0.0 ;最新代码是 main,两者之间还有 44 个主线提交。
如果你要可重复地使用某个发布版,请记录 Tag;如果你在验证最新修复,请在干净分支上使用当前 main。
报告问题时不要只写“最新版”,请附上 git rev-parse HEAD 的输出。
GraphRAG 曾经合入,但后续已回退;当前 main 不包含 GraphRAG 模块 。不要根据旧的 v3 介绍推断当前行为。参考 PR #503 、回退提交 与 PR #592 。
2. 源码安装推荐哪个 Python 版本?为什么 MediaCrawler 目录是空的?
README 声明支持 Python 3.9+,但 Docker 镜像和当前主要示例都使用 Python 3.11 ,因此建议把 3.11 作为首选可复现基线。Python 3.14 目前会遇到锁定的 Pillow 9.5.0 安装失败,见 #337 。
MediaCrawler 现在是 Git 子模块,克隆时应当带上子模块:
git clone --recurse-submodules https://github.com/666ghj/BettaFish.git
cd BettaFish
如果已经克隆,但 MindSpider/DeepSentimentCrawling/MediaCrawler 为空,请在仓库根目录执行:
git submodule update --init --recursive
使用 uv 的常见安装流程:
uv venv --python 3.11
uv pip install -r requirements.txt
uv run playwright install chromium
PDF 导出的系统依赖是可选的;只需 HTML / Markdown 时可以先不安装。PDF 请按 PDF 依赖文档 配置。
3. .env 应该放在哪里?每个 Agent 可以共用一个模型吗?
当前统一使用仓库根目录 的 .env;旧文档中各子 Agent 独立配置的方式已过时。
加载器会先检查当前工作目录,再检查项目根目录;因此建议始终从仓库根目录启动,避免误读子目录中的另一份 .env。
Insight、Media、Query、Report、MindSpider、Forum Host 和 Keyword Optimizer 都有独立的 Key / Base URL / Model 配置。技术上可以填同一个模型,但不代表质量和能力都足够。Report 需要长上下文、稳定结构化输出与较强指令遵循;Media 的部分流程还需要模型具备相应的多模态能力。
模型和供应商会变化,具体推荐以当前 .env.example 为准;Report Agent 优先使用强模型。
Caution
不要上传完整 .env。只需提供去秘后的变量名、供应商、Base URL 格式和模型 ID,Key 只能显示为 ***。
4. 项目可以直接部署到公网吗?
不可以把默认 Web 应用直接暴露到公网。
当前配置接口没有完整的应用级认证边界,默认公网暴露可能泄露数据库凭据和 API Key,也可能导致配置被修改。请仅在本机或可信局域网内使用;如果确实需要远程访问,必须在前面增加真实的身份认证、TLS、访问控制和秘密管理。只修改 HOST、防火墙或端口映射并不等于安全。参考 #238 。
二、数据库、Docker 与启动
5. app.py 已经启动,为什么数据库还是空的?
python app.py 启动的是多 Agent 分析系统。它会检查/创建缺失的表,但不会自动爬取社交平台业务数据 。
MindSpider 负责将话题和平台数据写入共享数据库。
Query / Media / Insight 等分析 Agent 从数据库或其他数据源读取数据。
“表初始化成功”只代表结构就绪,不代表已经有业务数据。
源码模式下,需要先准备好可连接的 PostgreSQL / MySQL 实例、数据库和有建表权限的用户;Docker Compose 会根据 POSTGRES_* 初始化数据库容器。详见 #332 和 MindSpider 文档 。
6. Docker 里的 5432 和宿主机的 5444 有什么区别?
默认 Compose 网络中:
BettaFish 容器连数据库:DB_HOST=db、DB_PORT=5432。
宿主机直接连 PostgreSQL:localhost:5444。
DB_* 是 BettaFish 的应用连接参数;POSTGRES_USER、POSTGRES_PASSWORD、POSTGRES_DB 是 PostgreSQL 容器初始化参数。自定义时必须保持两组参数一致。
最常见的错误是:应用运行在容器中却填 localhost:5444,或应用运行在宿主机却填 db:5432。请先确认“连接是从哪里发起的”。
修改 .env 后容器仍然使用旧配置时,请先核对根 .env 的文件挂载,再执行 docker compose up -d --force-recreate。如果拉镜像出现 content size of zero,常见原因是 Docker 29 / containerd 与镜像加速器的兼容性,应先排查 Docker 和镜像源,而不是修改 BettaFish 业务代码。参考 #533 。
7. 旧数据库升级后报字段类型错误,自动初始化为什么没修好?
SQLAlchemy create_all() 会创建缺失表,但不会把已有列自动迁移到新类型 。例如旧库的 daily_topics.topic_id 是整数,而当前模型需要字符串,单纯更新 Python 代码不会修改旧表。
处理前先备份,然后按当前数据库方言做明确迁移;如果是可丢弃的空测试库,也可以重建后让当前代码创建结构。不要在未备份时删除生产数据库。
8. 主界面和三个 Agent 分别用哪些端口?端口占用怎么办?
完整主系统:默认 5000。
Insight Agent:8501。
Media Agent:8502。
Query Agent:8503。
源码启动时,主服务的 HOST / PORT 由根 .env 控制。macOS 上 5000 被系统服务占用时,可把主服务改为其他端口。Docker 对外端口需要改 Compose 映射,例如 5001:5000;只改 .env PORT 不会自动修改宿主机端口映射。
当前正常退出已有优雅清理;只有异常中断后才可能留下旧进程。此时应先查明端口对应的 PID 和命令,确认是旧的 BettaFish 子进程后再结束;不要盲目清理系统中的其他进程。
9. 启动时出现健康检查连接失败,或子应用启动了但主页连不上?
健康检查会访问本机 127.0.0.1 上对应 Streamlit 端口的 /_stcore/health,启动后有 15 秒宽限期,最多等待约 90 秒。启动初期一次 connection refused 或短时 starting 不一定代表任务失败;如果程序后续能正常打开和运行,通常可以忽略这条瞬时告警。超过等待上限仍未就绪时,应查看 logs/insight.log、logs/media.log、logs/query.log 和对应端口,不要只继续拉长超时来遮住子进程退出。
如果持续失败,请依次检查:
子进程是否还存活,8501 / 8502 / 8503 是否真正监听。
对应 Agent 日志中是否有依赖、配置或导入错误。
Docker 端口映射、本机防火墙、远程访问主机名是否正确。
本地子应用连接问题与外部 LLM / 搜索 / 爬虫网络问题要分开排查;当前本地健康检查已显式绕过代理,但外部请求仍可能受代理 / VPN 影响。
参考 #568 和 #693 。
三、MindSpider 与爬取流程
10. 第一次跑 MindSpider 的正确顺序是什么?
数据爬取和多 Agent 分析是两个步骤。请先按 MindSpider 文档 用小规模参数打通爬取:
cd MindSpider
# 检查环境、配置和数据库
uv run main.py --status
# 方式 A:分步跑,最容易定位问题
uv run main.py --broad-topic
uv run main.py --deep-sentiment --platforms xhs dy wb --test
# 方式 B:小规模完整流程
uv run main.py --complete --test
Broad Topic 先把话题和关键词写入 daily_topics,Deep Sentiment 再读取这批关键词去各平台搜索和入库。--setup 仍存在于兼容 CLI,但当前 MindSpider 文档已将它标为废弃,常规流程优先使用自动初始化和 --status。
11. 没有弹出二维码,或小红书等平台爬取失败,是不是不支持?
当前代码支持 xhs 等 MediaCrawler 平台,旧 FAQ 中“不支持小红书”的结论已经过时。但“代码包含支持”不等于第三方平台永远可用:登录、验证码、风控、签名和页面结构都可能变化。
首次运行每个目标平台时:
确认子模块和 Playwright Chromium 已安装。
将 MediaCrawler 的 HEADLESS 设为 False,观察真实登录页面。
手动扫码或完成验证,再确认登录状态已保存。
只有在登录状态已损坏且你明白后果时,才重置对应 browser_data;此操作会丢失已保存的会话,不要一上来就删。
12. --date 能爬取指定历史日期的平台内容吗?
不能把 --date 理解成第三方平台的“历史快照 API”。
--deep-sentiment --date YYYY-MM-DD 会优先选择数据库中该日期已有的 daily_topics 关键词批次,然后搜索当前平台能返回的内容。
截至本文基线,--broad-topic --date 的日期没有传递到 Broad Topic 子程序,子程序仍按当天写入。
因此 --complete --date 在历史日期上可能出现“Broad Topic 写今天,Deep Sentiment 查历史批次”的错位。
这是当前实现限制,请不要将它宣传为任意历史日期回溯功能。源码依据:MindSpider/main.py 与 BroadTopicExtraction/main.py 。
13. 如何指定自己的爬取关键词?
当前 BettaFish 的 MindSpider 高层 CLI 没有稳定的 --keywords 参数。标准流程是 Broad Topic 生成 daily_topics.keywords,Deep Sentiment 从数据库读取后再配置底层 MediaCrawler。
旧回复中提到的 MindSpider/data/daily_keywords.txt 现在会被 Broad Topic 写入,但 Deep Sentiment 不会把它当作当前关键词输入,因此手动改这个文件不是可靠方案。
如果必须使用自定义词,请把它作为高级操作:明确维护相应的 daily_topics 数据,或独立运行底层 MediaCrawler 并自行负责它的配置、数据表和登录状态。操作数据库前先备份。
14. 话题生成了,但爬取仍然是 0 条或返回码 1,怎么排查?
先用单平台、小规模参数复现,不要一开始就全平台大量爬取:
在 Broad Topic 日志和数据库中确认 daily_topics 确实有该批次的关键词。
看 Deep Sentiment 日志最终选中的话题日期和关键词,避免误以为它正在用你指定的批次。
只跑一个平台的 --test,并打开浏览器,确认登录、验证码、页面访问和搜索结果。
确认相应平台的数据表有新增记录,并核对容器/宿主机数据库地址。
附上该平台完整日志和当前提交;顶层“返回码 1”本身不足以定位原因。
四、LLM、搜索与 API 报错
15. 我没用 OpenAI 模型,为什么日志里仍然有 openai?本地模型能用吗?
openai 在这里主要是兼容客户端/请求协议,不代表你必须使用 OpenAI 官方模型。云端或本地服务只要实现项目需要的 OpenAI-compatible Chat Completions 接口,就可以尝试接入。
但“接口兼容”不等于“模型能力足够”。还要确认:
Base URL 是供应商实际的 Chat Completions 路由;
模型 ID 完全匹配(包括大小写);
上下文、结构化输出、指令遵循和超时限额能支撑相应 Agent;
Media 相关流程如果用到图像,模型和供应商路由也必须真正支持。
参考 #300 。
16. Tavily、Anspire 和 Bocha 怎么配?
Query / Web 搜索中的 Tavily Key 是独立配置。
Media 搜索工具通过 SEARCH_TOOL_TYPE 选择:使用 AnspireAPI 时,就填对应的 Anspire Key / Base URL;使用 BochaAPI 时,就填 Bocha AI Search 对应的 Key / Base URL。
旧 FAQ 中“改成 Bocha Web Search 地址”的说法已不适用于当前代码。变量名中即使仍含 WEB_SEARCH,也要使用当前代码要求的 AI Search 凭据。
Base URL 必须包含 http:// 或 https://,并且以当前 .env.example 的域名/路由为准;自动补协议的改动尚未合入当前主线。
这三类配置不要混用。选择器、Key 和 Base URL 必须作为一组保持一致。参考 #462 。
17. 400 / 404 / 429 / 503 / JSON 解析错误分别怎么处理?
现象
常见含义
首先处理
400 Content Exists Risk
上游供应商的内容审核/风控拒绝
检查输入是否合规,更换合适的合规输入或可用供应商;不是 BettaFish 业务代码的 400
401 / 鉴权类 403
Key、权限、账户或路由问题
检查去秘后的 Key 所属产品、Base URL、账户权限和余额
402
账户余额或付费配额不足
在供应商端检查余额、计费状态和模型权限
404 model_not_found
模型 ID 或 Base URL 路由不存在
从供应商控制台复制精确模型 ID,核对大小写与路由
429
限流、并发或配额限制
降低并发,查配额/账户状态,按供应商重试策略稍后再试
503 no available channel
分销渠道或上游服务当前无可用通道
查供应商状态,更换可用渠道/官方端点,持续失败不要只等待代码重试
连接失败 / 超时 / 5xx
网络、代理、供应商负载或服务异常
区分偶发与持续失败,检查代理、服务状态、配额与端点
JSON 解析失败
模型未遵循结构、输出被截断或接口兼容不完整
使用更强的模型,检查上下文/超时,保留去秘后原始模型输出与完整日志
当前代码有应用级退避重试,但它也会重试部分永久性 400 / 404。如果每次都是完全相同的 400 / 404,继续等待通常不会自愈;应停止本次任务,修正内容、模型 ID 或端点后再运行。详见 #691 、#695 和 #696 。
18. 明明有 JSON 修复和重试,为什么还会失败?
当前已有多层 JSON 清理/恢复和报告分章处理,但修复器不可能将任意一段截断、缺字段或不遵循协议的输出变成可靠结果。
持续出错时:
先更新到你要验证的明确提交,确保不是旧版 Report V1 问题。
替换为更强、更稳定的结构化输出模型,尤其是 Report Agent。
确认供应商没有截断输出,模型上下文和超时足够。
报 Issue 时附上去秘后的原始模型回复、失败阶段与完整日志。
参考 #681 。
五、Report Agent 与最终报告
19. 三个 Agent 看起来都跑了,为什么 Report Agent 仍然锁定?
Web 流程不是只看页面上的进度文字。Report Agent 初始化时会记录三个目录当时的 .md 文件数:
insight_engine_streamlit_reports
media_engine_streamlit_reports
query_engine_streamlit_reports
正常 Web 流程要求三个目录相对该基线都有新文件,并且 logs/forum.log 就绪。如果最后只保存了一份上游报告,就说明另外两个 Agent 没有完成这一轮的新输出,Report Agent 不会开始正常 Web 汇总。
请检查 /api/report/status 返回的 missing_files / 计数信息,以及三个 Agent 各自的日志。健康检查启动期的瞬时失败只要后续能正常运行,一般不是这里的根因。参考 #693 和 #470 。
20. 三份上游报告已经生成,只想重跑最终报告,怎么做?
不需要再跑三个 Agent,在仓库根目录使用独立命令行工具:
python report_engine_only.py
# 可选:指定主题
python report_engine_only.py --query " 你的报告主题"
# 可选:跳过 PDF
python report_engine_only.py --skip-pdf
该工具会从三个上游目录选择现有的最新 Markdown,显示文件后等待确认,并刻意跳过 Web 的“文件必须比启动时新增”检查。代码至少需要一份上游报告才能运行,但三份都齐全时信息更完整。
默认输出:
HTML:final_reports/
PDF:final_reports/pdf/
Markdown:final_reports/md/
Document IR:final_reports/ir/
如果只需要用已保存的章节 / IR 重新渲染,请使用 regenerate_latest_html.py、regenerate_latest_md.py 或 regenerate_latest_pdf.py。
21. 最终报告太短、被截断、排版错乱或图表空白,怎么办?
当前 Report Engine V2 已经是分阶段的 Document IR 管线,支持分章生成、结构修复、HTML / PDF / Markdown 渲染,并优先使用本地 Chart.js / MathJax 等资产。因此旧 FAQ 中“打开 VPN 就能修图表”或“一次模型输出就是整份报告”的判断已经过时。
建议按以下顺序排查:
确认 Query / Media / Insight 三份上游输入都是本轮新生成且内容完整。
使用长上下文、结构化输出稳定的强 Report 模型;更换模型是重要排查项,但不是唯一原因。
检查供应商是否截断长输出、超时或返回不完整 JSON。
保留本次章节输出、IR JSON、HTML 和完整日志;图表问题要区分“IR 没有/无效数据”与“浏览器渲染失败”。
如需自定义样式,使用当前支持的 .md / .txt 报告模板,不要沿用 Report V1 的假设。
已知边界:Markdown 不会保留完整交互式 Chart.js 图表,而是降级为表格/文本;超长表格在 PDF 中的分页仍可能不够自然。这些不应被描述为“所有格式都会逐像素完全一致”。
参考 #600 与 #681 。
22. PDF 生成失败会导致整个报告不能用吗?
不会。PDF 是可选输出,HTML 和 Markdown 仍可以正常生成。先运行:
python -m ReportEngine.utils.dependency_check
再根据 PDF 依赖文档 安装对应操作系统的 Pango / Cairo / GTK 等组件。Docker 镜像已包含相关系统依赖。如果暂时不需要 PDF,可以用 python report_engine_only.py --skip-pdf。
请优先使用 report_engine_only.py 或 regenerate_latest_pdf.py。当前旧 export_pdf.py 还包含开发机器的绝对路径,不适合作为通用跨机器命令。
六、结果质量与 Agent 协作
23. 报告出现幻觉、引用不可靠或计算不对,怎么减少?
BettaFish 的结构校验和报告管线可以改善输出格式,但不能保证 LLM 生成的每个事实、引用和计算都真实。特别是 Insight 需要依赖真实的私域数据;新建空库或上游 Agent 没有产出数据时,模型更容易用看似合理的内容补空。
建议:
先确认数据库真的有与任务相关的业务数据;
确认三个上游 Agent 都提供了本轮输入;
使用能力更强的模型,但不把“换模型”当成事实校验的替代品;
对重要结论、数字、引用链接和决策依据做人工复核。
请把报告当作研究辅助材料,不要当作未经验证的事实源。参考 #277 。
24. Insight、Query 和 Media 的数据源有什么区别?
Insight Agent :主要读取共享/私域数据库中的舆情数据;当前会对命中结果做聚类和代表性抽样,不保证把数据库所有记录逐条放入上下文。
Query Agent :主要使用 Tavily 做外部网络/新闻搜索,并对 URL 和相关性做基本规范化/过滤。
Media Agent :使用当前选定的 Anspire 或 Bocha 搜索服务。
因此,“报告没有引用”不一定只是 Report Agent 的问题;应先确认对应上游 Agent 是否真的取得了有效来源。参考 #532 。
25. Forum Host 为什么允许各 Agent 持续通报自己的调研进展?
这是效率、信息共享与相互影响之间的权衡:
各分析 Agent 应尽量独立推进,避免因为强同步而降低整体效率。
Host 的主要作用是共享必要信息、让其他 Agent 知道当前进展,同时避免彼此直接改写对方状态。
Agent 通报自己的调研进度符合这个设计目标,不等于它已经完成所有任务。
如果要评估 Host 是否真正带来了纠偏效果,建议基于具体案例做对照和消融实验,比较“无 Host”、“仅进度共享”与“允许纠偏信息”等策略,不要只凭一次运行下结论。参考 #687 。
26. 为什么我的结果和项目示例不一样?运行很久就是死锁吗?
示例报告取决于当时的数据库、时间、搜索结果、模型和供应商,不是确定性快照。官方武汉大学示例使用的是百万级数据库;少量本地样本不应被期待逐字复制相同内容和图表。参考 #174 。
多 Agent 搜索、反思、Forum 交流和分章 Report 本身会消耗大量 Token 和时间,运行很久本身不能证明死锁。应同时观察子进程是否存活、日志是否继续更新、供应商请求是否在重试,以及输出文件是否增长。如果日志长时间停在相同的永久性 4xx,应先修配置而不是继续等。
七、提 Issue 前请附上这些信息
仓库目前没有独立的 Issue 模板。为了避免反复追问,新 Issue 请尽量一次提供:
使用的 Tag 或 git rev-parse HEAD 完整 SHA;
Docker / 源码安装方式,操作系统,Python 版本;
git submodule status 输出(如涉及 MindSpider / MediaCrawler);
精确执行的命令和最小可复现步骤;
期望结果与实际结果;
完整 traceback,以及对应 Agent / MindSpider / Report 阶段的日志;
去秘后的供应商、Base URL 格式、模型 ID 和搜索工具类型;
UI 问题的截图,以及浏览器/端口信息。
Caution
请必须删除 API Key、Cookie、Authorization Header、数据库密码、个人数据和完整 .env。如果秘密已经误发到公开 Issue,请立即在对应平台吊销并更换,仅编辑删除文字并不能保证密密未被记录。
本 Issue 将保持作为常见问题入口。如果某条答案与当前代码不一致,请附上可复现信息和当前提交,我们会持续更新。
BettaFish 常见问题解答(持续更新)
Note
Agent 自动整理说明:本页由 Agent 根据当前代码、主线提交、Tag / Release、Issue 与 PR 中的公开讨论汇总,并由项目维护者审核后更新。请不要把 API Key、Cookie、数据库密码或完整
.env发到 Issue。Important
适用基线:本次整理截至 2026-07-20,当前
main为40327d7。最新已发布 Release 仍是v3.0.0,但当前main比它多 44 个提交,两者不能等同。以后如果代码继续变化,请以当时的 README、.env.example和源码为准。一、版本、安装与配置
1. “最新版”到底是哪个?当前还有 GraphRAG 吗?
v3.0.0;最新代码是main,两者之间还有 44 个主线提交。main。git rev-parse HEAD的输出。main不包含 GraphRAG 模块。不要根据旧的 v3 介绍推断当前行为。参考 PR #503、回退提交 与 PR #592。2. 源码安装推荐哪个 Python 版本?为什么 MediaCrawler 目录是空的?
README 声明支持 Python 3.9+,但 Docker 镜像和当前主要示例都使用 Python 3.11,因此建议把 3.11 作为首选可复现基线。Python 3.14 目前会遇到锁定的 Pillow 9.5.0 安装失败,见 #337。
MediaCrawler 现在是 Git 子模块,克隆时应当带上子模块:
git clone --recurse-submodules https://github.com/666ghj/BettaFish.git cd BettaFish如果已经克隆,但
MindSpider/DeepSentimentCrawling/MediaCrawler为空,请在仓库根目录执行:使用 uv 的常见安装流程:
PDF 导出的系统依赖是可选的;只需 HTML / Markdown 时可以先不安装。PDF 请按 PDF 依赖文档 配置。
3.
.env应该放在哪里?每个 Agent 可以共用一个模型吗?.env;旧文档中各子 Agent 独立配置的方式已过时。.env。.env.example为准;Report Agent 优先使用强模型。Caution
不要上传完整
.env。只需提供去秘后的变量名、供应商、Base URL 格式和模型 ID,Key 只能显示为***。4. 项目可以直接部署到公网吗?
不可以把默认 Web 应用直接暴露到公网。
当前配置接口没有完整的应用级认证边界,默认公网暴露可能泄露数据库凭据和 API Key,也可能导致配置被修改。请仅在本机或可信局域网内使用;如果确实需要远程访问,必须在前面增加真实的身份认证、TLS、访问控制和秘密管理。只修改
HOST、防火墙或端口映射并不等于安全。参考 #238。二、数据库、Docker 与启动
5.
app.py已经启动,为什么数据库还是空的?python app.py启动的是多 Agent 分析系统。它会检查/创建缺失的表,但不会自动爬取社交平台业务数据。源码模式下,需要先准备好可连接的 PostgreSQL / MySQL 实例、数据库和有建表权限的用户;Docker Compose 会根据
POSTGRES_*初始化数据库容器。详见 #332 和 MindSpider 文档。6. Docker 里的 5432 和宿主机的 5444 有什么区别?
默认 Compose 网络中:
DB_HOST=db、DB_PORT=5432。localhost:5444。DB_*是 BettaFish 的应用连接参数;POSTGRES_USER、POSTGRES_PASSWORD、POSTGRES_DB是 PostgreSQL 容器初始化参数。自定义时必须保持两组参数一致。最常见的错误是:应用运行在容器中却填
localhost:5444,或应用运行在宿主机却填db:5432。请先确认“连接是从哪里发起的”。修改
.env后容器仍然使用旧配置时,请先核对根.env的文件挂载,再执行docker compose up -d --force-recreate。如果拉镜像出现content size of zero,常见原因是 Docker 29 / containerd 与镜像加速器的兼容性,应先排查 Docker 和镜像源,而不是修改 BettaFish 业务代码。参考 #533。7. 旧数据库升级后报字段类型错误,自动初始化为什么没修好?
SQLAlchemy
create_all()会创建缺失表,但不会把已有列自动迁移到新类型。例如旧库的daily_topics.topic_id是整数,而当前模型需要字符串,单纯更新 Python 代码不会修改旧表。处理前先备份,然后按当前数据库方言做明确迁移;如果是可丢弃的空测试库,也可以重建后让当前代码创建结构。不要在未备份时删除生产数据库。
8. 主界面和三个 Agent 分别用哪些端口?端口占用怎么办?
5000。8501。8502。8503。源码启动时,主服务的
HOST/PORT由根.env控制。macOS 上 5000 被系统服务占用时,可把主服务改为其他端口。Docker 对外端口需要改 Compose 映射,例如5001:5000;只改.env PORT不会自动修改宿主机端口映射。当前正常退出已有优雅清理;只有异常中断后才可能留下旧进程。此时应先查明端口对应的 PID 和命令,确认是旧的 BettaFish 子进程后再结束;不要盲目清理系统中的其他进程。
9. 启动时出现健康检查连接失败,或子应用启动了但主页连不上?
健康检查会访问本机
127.0.0.1上对应 Streamlit 端口的/_stcore/health,启动后有 15 秒宽限期,最多等待约 90 秒。启动初期一次connection refused或短时starting不一定代表任务失败;如果程序后续能正常打开和运行,通常可以忽略这条瞬时告警。超过等待上限仍未就绪时,应查看logs/insight.log、logs/media.log、logs/query.log和对应端口,不要只继续拉长超时来遮住子进程退出。如果持续失败,请依次检查:
参考 #568 和 #693。
三、MindSpider 与爬取流程
10. 第一次跑 MindSpider 的正确顺序是什么?
数据爬取和多 Agent 分析是两个步骤。请先按 MindSpider 文档 用小规模参数打通爬取:
Broad Topic 先把话题和关键词写入
daily_topics,Deep Sentiment 再读取这批关键词去各平台搜索和入库。--setup仍存在于兼容 CLI,但当前 MindSpider 文档已将它标为废弃,常规流程优先使用自动初始化和--status。11. 没有弹出二维码,或小红书等平台爬取失败,是不是不支持?
当前代码支持
xhs等 MediaCrawler 平台,旧 FAQ 中“不支持小红书”的结论已经过时。但“代码包含支持”不等于第三方平台永远可用:登录、验证码、风控、签名和页面结构都可能变化。首次运行每个目标平台时:
HEADLESS设为False,观察真实登录页面。browser_data;此操作会丢失已保存的会话,不要一上来就删。12.
--date能爬取指定历史日期的平台内容吗?不能把
--date理解成第三方平台的“历史快照 API”。--deep-sentiment --date YYYY-MM-DD会优先选择数据库中该日期已有的daily_topics关键词批次,然后搜索当前平台能返回的内容。--broad-topic --date的日期没有传递到 Broad Topic 子程序,子程序仍按当天写入。--complete --date在历史日期上可能出现“Broad Topic 写今天,Deep Sentiment 查历史批次”的错位。这是当前实现限制,请不要将它宣传为任意历史日期回溯功能。源码依据:MindSpider/main.py 与 BroadTopicExtraction/main.py。
13. 如何指定自己的爬取关键词?
当前 BettaFish 的 MindSpider 高层 CLI 没有稳定的
--keywords参数。标准流程是 Broad Topic 生成daily_topics.keywords,Deep Sentiment 从数据库读取后再配置底层 MediaCrawler。旧回复中提到的
MindSpider/data/daily_keywords.txt现在会被 Broad Topic 写入,但 Deep Sentiment 不会把它当作当前关键词输入,因此手动改这个文件不是可靠方案。如果必须使用自定义词,请把它作为高级操作:明确维护相应的
daily_topics数据,或独立运行底层 MediaCrawler 并自行负责它的配置、数据表和登录状态。操作数据库前先备份。14. 话题生成了,但爬取仍然是 0 条或返回码 1,怎么排查?
先用单平台、小规模参数复现,不要一开始就全平台大量爬取:
daily_topics确实有该批次的关键词。--test,并打开浏览器,确认登录、验证码、页面访问和搜索结果。四、LLM、搜索与 API 报错
15. 我没用 OpenAI 模型,为什么日志里仍然有
openai?本地模型能用吗?openai在这里主要是兼容客户端/请求协议,不代表你必须使用 OpenAI 官方模型。云端或本地服务只要实现项目需要的 OpenAI-compatible Chat Completions 接口,就可以尝试接入。但“接口兼容”不等于“模型能力足够”。还要确认:
参考 #300。
16. Tavily、Anspire 和 Bocha 怎么配?
SEARCH_TOOL_TYPE选择:使用AnspireAPI时,就填对应的 Anspire Key / Base URL;使用BochaAPI时,就填 Bocha AI Search 对应的 Key / Base URL。WEB_SEARCH,也要使用当前代码要求的 AI Search 凭据。http://或https://,并且以当前.env.example的域名/路由为准;自动补协议的改动尚未合入当前主线。这三类配置不要混用。选择器、Key 和 Base URL 必须作为一组保持一致。参考 #462。
17. 400 / 404 / 429 / 503 / JSON 解析错误分别怎么处理?
400 Content Exists Risk401/ 鉴权类403402404 model_not_found429503 no available channel当前代码有应用级退避重试,但它也会重试部分永久性 400 / 404。如果每次都是完全相同的 400 / 404,继续等待通常不会自愈;应停止本次任务,修正内容、模型 ID 或端点后再运行。详见 #691、#695 和 #696。
18. 明明有 JSON 修复和重试,为什么还会失败?
当前已有多层 JSON 清理/恢复和报告分章处理,但修复器不可能将任意一段截断、缺字段或不遵循协议的输出变成可靠结果。
持续出错时:
参考 #681。
五、Report Agent 与最终报告
19. 三个 Agent 看起来都跑了,为什么 Report Agent 仍然锁定?
Web 流程不是只看页面上的进度文字。Report Agent 初始化时会记录三个目录当时的
.md文件数:insight_engine_streamlit_reportsmedia_engine_streamlit_reportsquery_engine_streamlit_reports正常 Web 流程要求三个目录相对该基线都有新文件,并且
logs/forum.log就绪。如果最后只保存了一份上游报告,就说明另外两个 Agent 没有完成这一轮的新输出,Report Agent 不会开始正常 Web 汇总。请检查
/api/report/status返回的missing_files/ 计数信息,以及三个 Agent 各自的日志。健康检查启动期的瞬时失败只要后续能正常运行,一般不是这里的根因。参考 #693 和 #470。20. 三份上游报告已经生成,只想重跑最终报告,怎么做?
不需要再跑三个 Agent,在仓库根目录使用独立命令行工具:
该工具会从三个上游目录选择现有的最新 Markdown,显示文件后等待确认,并刻意跳过 Web 的“文件必须比启动时新增”检查。代码至少需要一份上游报告才能运行,但三份都齐全时信息更完整。
默认输出:
final_reports/final_reports/pdf/final_reports/md/final_reports/ir/如果只需要用已保存的章节 / IR 重新渲染,请使用
regenerate_latest_html.py、regenerate_latest_md.py或regenerate_latest_pdf.py。21. 最终报告太短、被截断、排版错乱或图表空白,怎么办?
当前 Report Engine V2 已经是分阶段的 Document IR 管线,支持分章生成、结构修复、HTML / PDF / Markdown 渲染,并优先使用本地 Chart.js / MathJax 等资产。因此旧 FAQ 中“打开 VPN 就能修图表”或“一次模型输出就是整份报告”的判断已经过时。
建议按以下顺序排查:
.md/.txt报告模板,不要沿用 Report V1 的假设。已知边界:Markdown 不会保留完整交互式 Chart.js 图表,而是降级为表格/文本;超长表格在 PDF 中的分页仍可能不够自然。这些不应被描述为“所有格式都会逐像素完全一致”。
参考 #600 与 #681。
22. PDF 生成失败会导致整个报告不能用吗?
不会。PDF 是可选输出,HTML 和 Markdown 仍可以正常生成。先运行:
再根据 PDF 依赖文档 安装对应操作系统的 Pango / Cairo / GTK 等组件。Docker 镜像已包含相关系统依赖。如果暂时不需要 PDF,可以用
python report_engine_only.py --skip-pdf。请优先使用
report_engine_only.py或regenerate_latest_pdf.py。当前旧export_pdf.py还包含开发机器的绝对路径,不适合作为通用跨机器命令。六、结果质量与 Agent 协作
23. 报告出现幻觉、引用不可靠或计算不对,怎么减少?
BettaFish 的结构校验和报告管线可以改善输出格式,但不能保证 LLM 生成的每个事实、引用和计算都真实。特别是 Insight 需要依赖真实的私域数据;新建空库或上游 Agent 没有产出数据时,模型更容易用看似合理的内容补空。
建议:
请把报告当作研究辅助材料,不要当作未经验证的事实源。参考 #277。
24. Insight、Query 和 Media 的数据源有什么区别?
因此,“报告没有引用”不一定只是 Report Agent 的问题;应先确认对应上游 Agent 是否真的取得了有效来源。参考 #532。
25. Forum Host 为什么允许各 Agent 持续通报自己的调研进展?
这是效率、信息共享与相互影响之间的权衡:
如果要评估 Host 是否真正带来了纠偏效果,建议基于具体案例做对照和消融实验,比较“无 Host”、“仅进度共享”与“允许纠偏信息”等策略,不要只凭一次运行下结论。参考 #687。
26. 为什么我的结果和项目示例不一样?运行很久就是死锁吗?
示例报告取决于当时的数据库、时间、搜索结果、模型和供应商,不是确定性快照。官方武汉大学示例使用的是百万级数据库;少量本地样本不应被期待逐字复制相同内容和图表。参考 #174。
多 Agent 搜索、反思、Forum 交流和分章 Report 本身会消耗大量 Token 和时间,运行很久本身不能证明死锁。应同时观察子进程是否存活、日志是否继续更新、供应商请求是否在重试,以及输出文件是否增长。如果日志长时间停在相同的永久性 4xx,应先修配置而不是继续等。
七、提 Issue 前请附上这些信息
仓库目前没有独立的 Issue 模板。为了避免反复追问,新 Issue 请尽量一次提供:
git rev-parse HEAD完整 SHA;git submodule status输出(如涉及 MindSpider / MediaCrawler);Caution
请必须删除 API Key、Cookie、Authorization Header、数据库密码、个人数据和完整
.env。如果秘密已经误发到公开 Issue,请立即在对应平台吊销并更换,仅编辑删除文字并不能保证密密未被记录。本 Issue 将保持作为常见问题入口。如果某条答案与当前代码不一致,请附上可复现信息和当前提交,我们会持续更新。