# jobqa **Repository Path**: wanzhixiao/jobqa ## Basic Information - **Project Name**: jobqa - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-07-26 - **Last Updated**: 2026-08-26 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # JobQA 个人项目 Demo:面向企业招聘 / 福利政策场景的 **RAG + Agent** 问答系统。 在线路径统一为 Agent:模型通过 Function Calling 自主调用检索与会话工具;意图路由与应答策略由 **Skills**(Markdown 手册)渐进加载,而不是写死在代码 if-else 里。 > 本项目用于学习与技术验证,**不是生产系统**。样例数据为演示用途,请勿当作真实公司政策。 --- ## 能演示什么 | 能力 | 说明 | |------|------| | Agent 单路径 | 闲聊 / 追问 / 福利对比 / 知识问答 / 越权升级,由 `intent-router` 注入 system | | Skills | `load_skill` 按需加载 `follow-up`、`benefits-compare`、`grounded-answer`、`escalate` 等 | | RAG 检索 | FAISS 向量检索;可选 BM25 混合检索 + Reranker | | 多轮记忆 | 会话窗口支持「那医疗保险呢?」类追问 | | 可观测性 | 控制台打印工具名 / 参数 / 结果摘要;可选 JSONL 轨迹 | | 本地 Web | Flask + HTML 聊天页,回答下方展示工具路径 | --- ## 架构一览 ``` 用户问题 │ ▼ QASystem ──► AgentOrchestrator │ ├─ system: intent-router(注入,无需 load_skill) ├─ tools: search_knowledge / search_qa / │ get_session_history / load_skill ├─ SkillLoader(全局 skills/ + 公司 skills_company/) └─ KnowledgeRetriever → FAISS(+ BM25 / Rerank) ``` 更细的流程图见 [`docs/架构流程图.md`](docs/架构流程图.md);设计说明见 [`docs/Agent单路径与意图Skill改造方案.md`](docs/Agent单路径与意图Skill改造方案.md)。 ### 核心模块 | 路径 | 职责 | |------|------| | `jobqa/core/qa_system.py` | 统一入口 `answer_question()` | | `jobqa/agent/orchestrator.py` | Agent 多轮工具编排 | | `jobqa/agent/tools.py` | 工具执行与 citations | | `jobqa/agent/skill_loader.py` | Skills 发现与加载(`inject: system \| tool`) | | `jobqa/retrieval/` | FAISS、混合检索、重排、query rewrite | | `jobqa/observability/` | RequestTracer + 工具轨迹 | | `web/app.py` | 本地浏览器聊天 | | `skills/` | 意图路由与细则 Skill 手册 | --- ## 环境要求 - Python 3.9+ - OpenAI 兼容的 LLM API Key(默认配置面向 Kimi / TokenHub;也兼容旧的 `HUNYUAN_*` 变量名) - 已构建的 FAISS 索引(见下方「构建向量索引」) --- ## 快速开始 ### 1. 安装依赖 ```bash cd jobqa python -m venv .venv # Windows: .venv\Scripts\activate # macOS / Linux: # source .venv/bin/activate pip install -r requirements.txt ``` 首次运行会下载 Embedding 模型(默认 `moka-ai/m3e-base`),可能较慢。 ### 2. 配置环境变量 ```bash cp .env.example .env ``` 编辑 `.env`,至少填入 API Key: | 变量 | 说明 | |------|------| | `MOONSHOT_API_KEY` | LLM API Key(**必填**;也可用 `HUNYUAN_API_KEY`) | | `OPENAI_BASE_URL` | API Base URL | | `MOONSHOT_MODEL_ID` | 模型名,默认 `kimi-k2.6` | | `EMBEDDING_MODEL` | Embedding 模型 | | `FAISS_INDEX_DIR` | 索引目录,默认 `data/faiss` | | `MAX_AGENT_STEPS` | Agent 最大步数,默认 `5` | | `SKILLS_ENABLED` | 是否启用 Skills,默认 `true` | | `AGENT_CONSOLE_TRACE` | 控制台打印工具轨迹,默认 `true` | **请勿把 `.env` 提交到 Git。** ### 3. 构建向量索引 仓库自带宝洁(P&G)风格样例数据(`data/sample/`): ```bash python scripts/build_index.py ``` 索引写入: - `data/faiss/baojie_knowledge_table` - `data/faiss/baojie_qa_table` ### 4. 运行 **命令行** ```bash # 内置 Demo(连续几个样例问题) python main.py # 交互模式 python main.py -i # 单次提问 python main.py -q "宝洁的福利待遇怎么样?" # 指定公司 / 会话 python main.py -i --company dayeechanpin --session demo01 ``` **浏览器聊天** ```bash python web/app.py ``` 打开 [http://127.0.0.1:5000](http://127.0.0.1:5000)。可切换公司、管理会话,并在回答下查看工具调用路径。 **冒烟脚本(多轮)** ```bash python scripts/smoke_agent_session.py ``` --- ## CLI 参数 ``` python main.py [选项] -q, --question TEXT 单次提问 -i, --interactive 交互模式(quit / exit / q 退出) --session ID 会话 ID,默认 demo --company CODE 公司代码,默认 dayeechanpin --trace 额外写入 JSONL 轨迹(data/traces/) --quiet-tools 关闭控制台工具明细 --agent 已废弃(始终为 Agent),仅兼容旧命令 ``` 公司代码见 `jobqa/config.py` 中 `COMPANY_MAPPING`: | code | 名称 | |------|------| | `dayeechanpin` | 宝洁公司 | | `yonyou` | 用友公司 | | `default` | 本公司 | --- ## Agent 与 Skills(简要) 每轮请求大致流程: 1. Harness 将 `intent-router` **注入 system**(模型不必再 `load_skill` 它) 2. 模型判定意图:`chitchat` / `escalate` / `follow_up` / `benefits_compare` / `knowledge_qa` 3. 按路由表调用工具;细则 Skill(如 `follow-up`)经 `load_skill` **按需加载** 4. 仅基于检索与 Skill 约束作答,控制编造 内置 Skills: ``` skills/ ├── intent-router/ # inject:system — 意图与工具契约 ├── follow-up/ # 追问改写与检索 ├── benefits-compare/ # 福利对比 ├── grounded-answer/ # grounded 作答约束 └── escalate/ # 超纲升级 ``` 公司定制可放在 `skills_company/{company_code}/`。 --- ## 代码调用 ```python from jobqa import QASystem qa = QASystem() result = qa.answer_question( "宝洁的福利待遇怎么样?", session_id="user_001", company_code="dayeechanpin", ) print(result["answer"]) print(result.get("skills_loaded")) print(result.get("tool_invocations")) # 工具名 / 参数 / 结果摘要 ``` 返回字段主要包括:`answer`、`source`、`tool_calls_made`、`tool_invocations`、`skills_loaded`、`citations`、`steps`、`request_id`。 --- ## 自定义知识库 **JSON 样例** ```bash python scripts/build_index.py \ --qa-json data/sample/baojie_qa.json \ --knowledge-json data/sample/baojie_knowledge.json \ --output data/faiss ``` **Excel + 文档目录** ```bash python scripts/build_index.py \ --qa-excel path/to/qa.xlsx \ --knowledge-dir path/to/docs/ \ --output data/faiss ``` - QA Excel:第 1 列问题,第 2 列答案 - 知识文档:`.pdf` / `.txt` / `.doc` / `.docx`(doc/docx 可能需额外依赖) --- ## 项目结构 ``` jobqa/ ├── jobqa/ # 核心包 │ ├── core/ # QASystem、会话记忆 │ ├── agent/ # Orchestrator、Tools、Skills、上下文压缩 │ ├── retrieval/ # FAISS、BM25、Rerank、query rewrite │ ├── llm/ # LLM 客户端 │ ├── observability/ # 轨迹与工具打印 │ └── eval/ # 评测相关 ├── skills/ # 全局 Skills ├── skills_company/ # 按公司覆盖的 Skills ├── web/ # Flask 聊天前端 ├── scripts/ # 建库、冒烟测试等 ├── tests/ ├── data/ # 样例、索引、traces(本地生成) ├── docs/ # 架构与改造方案 └── main.py # CLI ``` --- ## 测试 ```bash pytest tests/ -q ``` --- ## 常见问题 **启动报错 `FAISS index missing`** 先执行 `python scripts/build_index.py`。 **报错未找到 API Key** 检查 `.env` 中的 `MOONSHOT_API_KEY`(或 `HUNYUAN_API_KEY`)。 **Embedding / Reranker 下载慢** 可配置 HuggingFace / ModelScope 镜像,或把 `EMBEDDING_MODEL` 指到本地路径。`.env.example` 中可将 `USE_RERANKER=false` 以加快首次体验。 **Windows 控制台乱码 / 崩溃** `main.py` 已尝试将 stdout 设为 UTF-8;若仍异常,可在终端先执行 `chcp 65001`。 --- ## 已知限制(Demo) - 部分追问可能跳过工具、直接依赖上下文作答,稳定性仍在打磨 - 无鉴权 / 限流 / 多租户,不适合公网裸奔部署 - 依赖外部 LLM API,延迟与费用随调用变化 --- ## 许可证 仅供学习与个人技术展示。使用前请遵守所用模型、Embedding 与 API 服务的协议。