🏘️ 社区百事通(baisitong)
社区政策咨询智能助手 · AI + 社会治理 RAG 知识库 + 多轮对话 + 来源引用 + SSE 流式输出,零配置、可离线运行
一分钟跑起来
方式 1:npm(任何装了 Python 3.9+ 的电脑)
npx baisitong # 自动建 venv、装依赖、启动,打开 http://localhost:8080
npx baisitong --port 9000 # 自定义端口
方式 2:pip 安装
pip install baisitong -i https://mirrors.aliyun.com/pypi/simple/
baisitong # 或 python -m baisitong
方式 3:源码运行
./startup.sh # Linux / macOS(Windows 用 startup.bat)
# 或手动:
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
python -m baisitong --port 8080
零配置即用:默认 SQLite + 内置本地 AI 引擎(TF-IDF 检索 + 抽取式生成), 无需数据库、无需 API Key、无需联网。配置大模型 Key 后自动切换真模型,见配置。
功能特性
| 模块 | 说明 |
|---|---|
| 🔍 RAG 政策问答 | 向量(TF-IDF/BGE)+ 关键词双路混合检索,答案附带 [1][2] 引用标注 |
| 📎 来源溯源 | 每条回答展示政策文档标题 + 原文片段 + 相关度进度条,可展开 |
| 💬 多轮对话 | 会话上下文保持,支持"费用是多少?"这类省略式追问(查询改写 + 同义词归一) |
| ⚡ SSE 流式 | 逐字打字机输出;生成前先推送"检索预览",用户可感知 AI 在查资料 |
| 🛟 无答案兜底 | 知识库外问题明确告知"未找到",并推荐热门问题,绝不编造 |
| 📚 知识库管理 | 内置 5 份政策文档(垃圾分类/养犬/物业/停车/补贴),支持 txt/md 上传自动分块入库 |
| 📊 运营看板 | 今日答疑数、满意度、热门问题统计 |
| 👍 反馈闭环 | 点赞/点踩计入当日统计 |
系统架构
┌────────────────────────────────────────────────────────────┐
│ 前端 原生 HTML/CSS/JS(无框架、无构建) │
│ 会话侧栏 · SSE流式聊天气泡 · 引用卡片(相关度条) · 热门问题 │
└──────────────────────┬─────────────────────────────────────┘
│ HTTP / SSE
┌──────────────────────▼─────────────────────────────────────┐
│ 接口层 routers/ │
│ chat(SSE) · conversations · knowledge · questions │
│ feedback · stats · health │
├────────────────────────────────────────────────────────────┤
│ 逻辑层 services/ │
│ rag(问答编排) · retriever(混合检索+查询改写) │
│ embeddings(向量引擎) · llm(大模型/本地引擎) │
│ documents(分块入库) · prompts(提示词模板) │
├────────────────────────────────────────────────────────────┤
│ 数据层 models/ + database.py │
│ SQLAlchemy ORM → SQLite(默认) / MySQL 8(可切换) │
└────────────────────────────────────────────────────────────┘
│ │
GLM / DeepSeek API 内置本地引擎(离线兜底)
(配置 Key 后启用) TF-IDF 检索 + 抽取式生成
AI 双引擎设计:LLM 与 Embedding 均为"远程 API / 本地引擎"双实现,统一接口。 未配置 Key 或远程调用失败时自动降级本地引擎,保证演示永不中断。
RAG 管线:查询改写(多轮指代+同义词归一) → 向量检索 + 关键词检索 → 相对归一化加权融合(α=0.7) → 双路绝对下限兜底 → Prompt 组装 → 流式生成 → 引用后处理
API 一览
| 方法 | 路径 | 说明 |
|---|---|---|
| POST | /api/chat |
问答(SSE 流式:retrieval/token/suggestions/done) |
| GET | /api/conversations |
会话列表 |
| GET/DELETE | /api/conversations/{id} |
会话详情 / 删除 |
| POST | /api/knowledge/init |
初始化预置知识库(force 重建) |
| POST | /api/knowledge/upload |
上传政策文档(自动分块+向量化) |
| GET | /api/knowledge/documents |
文档列表 |
| GET | /api/knowledge/search?q= |
手动检索(调试) |
| GET | /api/questions/hot |
热门问题 |
| POST | /api/feedback |
点赞/点踩 |
| GET | /api/stats |
运营统计 |
| GET | /api/health |
健康检查(运行模式) |
| GET | /docs |
FastAPI 自动生成的 OpenAPI 文档 |
SSE 事件示例:
data: {"type":"retrieval","sources":[{"citation_num":1,"doc_title":"…","snippet":"…","score":0.92}]}
data: {"type":"token","content":"根据《杭州市"}
data: {"type":"done","message_id":42,"sources":[…]}
data: [DONE]
配置
复制 .env.example 为 .env 按需修改(全部留空 = 零配置本地模式):
# 切换真实大模型(OpenAI 兼容协议,二选一)
LLM_API_KEY=sk-xxx
LLM_BASE_URL=https://api.deepseek.com/v1 # 或 https://open.bigmodel.cn/api/paas/v4
LLM_MODEL=deepseek-chat # 或 glm-4-flash
# 切换真实向量化(可选,留空用内置 TF-IDF)
EMBED_API_KEY=xxx
EMBED_BASE_URL=https://open.bigmodel.cn/api/paas/v4
EMBED_MODEL=embedding-3
# 切换 MySQL 8(默认 SQLite)
DATABASE_URL=mysql+pymysql://root:pwd@localhost:3306/community_assistant
RAG 参数(CHUNK_SIZE/RETRIEVAL_TOP_K/VECTOR_WEIGHT/SCORE_THRESHOLD 等)
同样在 .env 中调整。
项目结构
baisitong/
├── baisitong/ # Python 包(发布到 PyPI)
│ ├── __main__.py # CLI 入口(python -m baisitong)
│ ├── main.py # FastAPI 装配 + 生命周期
│ ├── config.py # 配置层(集中管理参数)
│ ├── database.py # 数据层:engine/session/建表
│ ├── routers/ # 接口层:6 个路由模块
│ ├── services/ # 逻辑层:RAG/检索/LLM/分块/Prompt
│ ├── models/ # ORM:documents/conversations/questions/stats
│ ├── schemas/ # Pydantic DTO
│ ├── data/ # 预置政策文档 ×5
│ └── static/ # 前端(index.html/css/js)
├── bin/cli.js # npm 启动器(找 Python → venv → 装依赖 → 启动)
├── tests/ # pytest 单元+集成测试(49 个用例)
├── sql/init.sql # MySQL 8 建表 DDL(含 ngram 全文索引)
├── package.json # npm 发布配置
├── pyproject.toml # PyPI 发布配置
├── requirements.txt # Python 依赖
├── startup.sh / startup.bat # 一键启动
└── .env.example # 环境变量模板
测试
pip install -r requirements-dev.txt
pytest tests/ -v # 49 个用例:分块/检索融合/查询改写/引用提取/
# SSE问答/多轮追问/无答案兜底/远程降级/断线落库/
# 会话CRUD/反馈统计
测试全程离线(自动使用本地引擎 + 临时 SQLite),无外部依赖。
常见问题
Q: 为什么检索引擎自己实现而不用 FAISS/ChromaDB? 社区政策语料通常 < 1000 块,纯 Python 内积耗时 < 10ms;零外部依赖 = 零安装风险, 在任何受限网络/离线环境下都可靠运行(竞赛可靠性优先原则)。
Q: 受限/断网环境怎么部署? 提前在有网电脑下载离线包:
pip download baisitong -d pkgs/ -i https://mirrors.aliyun.com/pypi/simple/
pip download -r requirements.txt -d pkgs/ -i https://mirrors.aliyun.com/pypi/simple/
把 pkgs/ 目录拷贝到目标机器后 pip install --no-index --find-links=pkgs/ baisitong,
全程无需联网。
License
MIT
Metadata
Release files for baisitong 1.0.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| baisitong-1.0.3.tar.gz | 54.6 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| baisitong-1.0.3-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 113.0 kB
Release files / baisitong-1.0.3.tar.gz
| Download URL | baisitong-1.0.3.tar.gz |
|---|---|
| Size | 54.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
781e652dff1db605ae91e6e806844718bd992349372c0fba17ee79e343ab67ba
|
|
BLAKE2b-256 checksum How to use checksums |
b7017513e4c5d9d45f0f5fc25782dc0a82c1642e55deecbf884aef7c74d836cd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.9.6
|
Release files / baisitong-1.0.3-py3-none-any.whl
| Download URL | baisitong-1.0.3-py3-none-any.whl |
|---|---|
| Size | 58.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
2787897ec4f664d3603e53ce1b17ebee0345e1df1f49bf0ebce8a6d9d54c08b5
|
|
BLAKE2b-256 checksum How to use checksums |
48b16227d10b43e0aab8994d0c843f94a49ba305fa4decd8d33e93633caf0b12
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.9.6
|
Security for baisitong 1.0.3
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.