Files
OpenCode 68a9071cf1 feat: reconcile local master with origin (exa/hot-platform hunters, leaks ledger, latest results)
Local branch had diverged from origin/master (sibling commits on the same base). Rewrote local history linearly on top of origin/master, folding in all local content: exa/hot-platform discovery hunters, leaks ledger, nightly sweep orchestrator, updated .gitignore and skill docs, plus the latest hunt output and vault state. Remote-only files (vault keys, channel scripts) were restored rather than dropped, so the resulting tree is a full union of both sides.
2026-08-07 12:53:47 +08:00

1 line
9.1 KiB
JSON
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{"repo": "bzanniupoiiu/be-ai-chat", "files": {"ai-chat-service/pkg/config/config.go": {"0353cb3fe18ac22fb31445ef7ce2195c57358b35": {"t": 1785745644.6893995, "n": 2309, "h": "dbb32347a13d5f52", "c": "package config\n\nimport (\n\t\"github.com/spf13/viper\"\n\t\"log\"\n\t\"strings\"\n)\n\ntype Config struct {\n\tServer struct {\n\t\tIP string\n\t\tPort int\n\t\tAccessToken string\n\t}\n\tLog struct {\n\t\tLevel string\n\t\tLogPath string `mapstructure:\"logPath\"`\n\t} `mapstructure:\"log\"`\n\tChat struct {\n\t\tApiKey string `mapstructure:\"api_key\"`\n\t\tBaseUrl string `mapstructure:\"base_url\"`\n\t\tModel string `mapstructure:\"model\"`\n\t\tMaxTokens int `mapstructure:\"max_tokens\"`\n\t\tTemperature float32 `mapstructure:\"temperature\"`\n\t\tTopP float32 `mapstructure:\"top_p\"`\n\t\tPresencePenalty float32 `mapstructure:\"presence_penalty\"`\n\t\tFrequencyPenalty float32 `mapstructure:\"frequency_penalty\"`\n\t\tBotDesc string `mapstructure:\"bot_desc\"`\n\t\tMinResponseTokens int `mapstructure:\"min_response_tokens\"`\n\t\tContextTTL int `mapstructure:\"context_ttl\"`\n\t\tContextLen int `mapstructure:\"context_len\"`\n\t}\n\n\tKVStore struct {\n\t\tMasterAddr string `mapstructure:\"master_addr\"`\n\t\tSlaveAddr string `mapstructure:\"slave_addr\"`\n\t\tModelPath string `mapstructure:\"model_path\"`\n\t\tONNXFilename string `mapstructure:\"onnx_filename\"`\n\t\tSearchTopK int `mapstructure:\"search_top_k\"`\n\t\tMinScore float64 `mapstructure:\"min_score\"`\n\t\tMinScoreMargin float64 `mapstructure:\"min_score_margin\"`\n\t} `mapstructure:\"kvstore\"`\n\n\tRAG struct {\n\t\tBaseURL string `mapstructure:\"base_url\"`\n\t\tTimeoutMS int `mapstructure:\"timeout_ms\"`\n\t\tTopK int `mapstructure:\"top_k\"`\n\t\tEvidenceTopK int `mapstructure:\"evidence_top_k\"`\n\t} `mapstructure:\"rag\"`\n\n\tDependOn struct {\n\t\tSensitive struct {\n\t\t\tAddress string\n\t\t\tAccessToken string\n\t\t}\n\t\tKeywords struct {\n\t\t\tAddress string\n\t\t\tAccessToken string\n\t\t}\n\t\tTokenizer struct {\n\t\t\tAddress string\n\t\t}\n\t}\n}\n\nvar conf *Config\n\nfunc InitConfig(filePath string, typ ...string) {\n\tv := viper.New()\n\tv.SetConfigFile(filePath)\n\tv.SetEnvKeyReplacer(strings.NewReplacer(\".\", \"_\"))\n\tv.AutomaticEnv()\n\t_ = v.BindEnv(\"chat.api_key\", \"DEEPSEEK_API_KEY\")\n\tif len(typ) > 0 {\n\t\tv.SetConfigType(typ[0])\n\t}\n\terr := v.ReadInConfig()\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tconf = &Config{}\n\terr = v.Unmarshal(conf)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n}\n\nfunc GetConfig() *Config {\n\treturn conf\n}\n"}, "90a5be9893665dd63afa1803ee06fb6deeffa978": {"t": 1785755267.536035, "n": 1660, "h": "8b89c3044c63106d", "c": "package config\n\nimport (\n\t\"github.com/spf13/viper\"\n\t\"log\"\n)\n\ntype Config struct {\n\tServer struct {\n\t\tIP string\n\t\tPort int\n\t\tAccessToken string\n\t}\n\tLog struct {\n\t\tLevel string\n\t\tLogPath string `mapstructure:\"logPath\"`\n\t} `mapstructure:\"log\"`\n\tChat struct {\n\t\tApiKey string `mapstructure:\"api_key\"`\n\t\tBaseUrl string `mapstructure:\"base_url\"`\n\t\tModel string `mapstructure:\"model\"`\n\t\tMaxTokens int `mapstructure:\"max_tokens\"`\n\t\tTemperature float32 `mapstructure:\"temperature\"`\n\t\tTopP float32 `mapstructure:\"top_p\"`\n\t\tPresencePenalty float32 `mapstructure:\"presence_penalty\"`\n\t\tFrequencyPenalty float32 `mapstructure:\"frequency_penalty\"`\n\t\tBotDesc string `mapstructure:\"bot_desc\"`\n\t\tMinResponseTokens int `mapstructure:\"min_response_tokens\"`\n\t\tContextTTL int `mapstructure:\"context_ttl\"`\n\t\tContextLen int `mapstructure:\"context_len\"`\n\t}\n\t\n\tKVStore struct {\n\t\tMasterAddr string `mapstructure:\"master_addr\"`\n\t\tSlaveAddr string `mapstructure:\"slave_addr\"`\n\t} `mapstructure:\"kvstore\"`\n\n\n\tDependOn struct {\n\t\tSensitive struct {\n\t\t\tAddress string\n\t\t\tAccessToken string\n\t\t}\n\t\tKeywords struct {\n\t\t\tAddress string\n\t\t\tAccessToken string\n\t\t}\n\t\tTokenizer struct {\n\t\t\tAddress string\n\t\t}\n\t}\n\t\n}\n\nvar conf *Config\n\nfunc InitConfig(filePath string, typ ...string) {\n\tv := viper.New()\n\tv.SetConfigFile(filePath)\n\tif len(typ) > 0 {\n\t\tv.SetConfigType(typ[0])\n\t}\n\terr := v.ReadInConfig()\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tconf = &Config{}\n\terr = v.Unmarshal(conf)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n}\n\nfunc GetConfig() *Config {\n\treturn conf\n}\n"}}, "knowledge-agent/README.md": {"0353cb3fe18ac22fb31445ef7ce2195c57358b35": {"t": 1786068581.994027, "n": 3048, "h": "461513245b33fb29", "c": "# knowledge-agent\n\nPDF-only SCI 论文知识服务。生产链路固定为 GROBID -> 结构化切块 -> BGE-M3 1024 维向量 -> Qdrant Top-20 -> BGE reranker -> 严格证据门控。\n\n## 目录\n\n| 文件/目录 | 责任 |\n| --- | --- |\n| `grobid_client.py` | 调用 GROBID Fulltext API,并把 TEI XML 转成论文结构 |\n| `paper_chunker.py` | 按摘要/章节/段落切分父子块,保存页码和内容类型 |\n| `qdrant_store.py` | 本地或服务模式 Qdrant 持久化索引 |\n| `reranker.py` | `BAAI/bge-reranker-v2-m3` 精排 |\n| `paper_repository.py` | SQLite 保存论文、入库任务和 chunk 元数据 |\n| `document_ingest.py` | PDF-only 入库编排与命令行入口 |\n| `agent_core.py` | Top-20 召回、阈值、rerank、证据与 prompt 编排 |\n| `server.py` | 上传、任务状态、论文列表、evidence 和 ask API |\n| `sci_paper/` | 上传和手动放置的 PDF 论文目录 |\n\n## 入库过程\n\n1. 校验 `.pdf` 后缀、`%PDF-` 文件签名和上传大小。\n2. 计算 SHA-256,前 32 位作为稳定 `paper_id`。\n3. GROBID `/api/processFulltextDocument` 返回 TEI XML。\n4. 提取标题、作者、DOI、摘要、层级章节、正文块和可获得的页码标记。\n5. 按章节切块:目标 380 tokens、最大 480、重叠 60;不会跨章节拼接。\n6. embedding 输入包含论文标题、章节路径和原文,BGE-M3 输出并归一化为 1024 维。\n7. 同一 `paper_id` 在 Qdrant 中采用先删除后写入,避免重复 chunk。\n8. SQLite 原子更新论文/chunk 元数据,任务状态变为 `READY`。\n\nGROBID 页码来自 TEI page-break 标记,扫描版或版式复杂论文可能无法可靠映射。回答端会显示“页码待校验”,不会编造页码。\n\n## 检索过程\n\n```text\nquestion\n -> BGE-M3 query vector (1024)\n -> Qdrant cosine Top-20\n -> dense_score >= RAG_MIN_DENSE_SCORE\n -> BGE reranker\n -> evidence Top-6\n -> top1 rerank_score >= RAG_MIN_RERANK_SCORE\n -> grounded prompt with [E1]...[E6]\n```\n\n没有可靠证据时返回:\n\n```json\n{\n \"answerable\": false,\n \"reason\": \"NO_RELEVANT_EVIDENCE\",\n \"sources\": [],\n \"prompt\": null\n}\n```\n\n此分支不会调用 DeepSeek。\n\n## 启动\n\n```bash\ndocker compose up -d\npython3 -m venv .venv\nsource .venv/bin/activate\npip install -r requirements-bge.txt\n\ncp .env.example .env\nset -a\nsource .env\nset +a\npython server.py\n```\n\nCPU 环境保持 `RAG_BGE_USE_FP16=0`。支持 CUDA 的环境可设为 `1`,但上线前必须验证模型输出与召回指标。\n\n## 手动批量入库\n\n把论文放进 `sci_paper/` 后执行:\n\n```bash\npython document_ingest.py\n```\n\n也可以指定一个或多个文件:\n\n```bash\npython document_ingest.py sci_paper/paper-a.pdf sci_paper/paper-b.pdf\n```\n\n## HTTP API\n\n上传 PDF:\n\n```bash\ncurl -F \"file=@paper.pdf\" http://127.0.0.1:8090/v1/papers\n```\n\n任务状态:\n\n```bash\ncurl http://127.0.0.1:8090/v1/ingest-jobs/<job_id>\n```\n\n证据检索:\n\n```bash\ncurl http://127.0.0.1:8090/internal/v1/evidence \\\n -H 'Content-Type: application/json' \\\n -d '{\"question\":\"论文如何融合光谱和空间信息?\",\"top_k\":20,\"evidence_top_k\":6}'\n```\n\n严格问答:\n\n```bash\ncurl http://127.0.0.1:8090/v1/ask \\\n -H 'Content-Type: application/json' \\\n -d '{\"question\":\"论文如何融合光谱和空间信息?\"}'\n```\n\n`/v1/ask` 需要 `DEEPSEEK_API_KEY`;`/internal/v1/evidence` 不需要大模型 key。\n\n## 关键配置\n\n| 环境变量 | 默认值 |\n| --- | --- |\n| `GROBID_URL` | `http://127.0.0.1:8070` |\n| `QDRANT_URL` | `http://127.0.0.1:6333` |\n| `QDRANT_COLLECTION` | `sci_paper_chunks_bge_m3_v1` |\n| `RAG_EMBEDDING_MODEL` | `BAAI/bge-m3` |\n| `RAG_RERANKER_MODEL` | `BAAI/bge-reranker-v2-m3` |\n| `RAG_MIN_DENSE_SCORE` | `0.25` |\n| `RAG_MIN_RERANK_SCORE` | `0.55` |\n| `RAG_MAX_PDF_BYTES` | `104857600` |\n| `DEEPSEEK_API_KEY` | 空,必须由运行环境填写 |\n\n默认阈值只是冷启动值。应使用自己的科研问答标注集调参,优先控制错误引用和错误回答,而不是追求命中率。\n\n## 测试\n\n```bash\nmake check\nmake test\ndocker compose config --quiet\n```\n\n测试覆盖 GROBID TEI 解析、页码、结构化切块、Top-20 限制、rerank 门控、无证据不调用 LLM,以及真实本地 Qdrant 的写入和过滤检索。\n"}}}}