# 问题记录:2026-09-27 > 状态:待处理(明天再动) > 记录人:项目相关方 > 本文件只记问题,不附解决方案。 --- ## 一、背景 今天在排查项目时发现两个独立但都和"千人模拟"业务相关的问题。先记下来,明天再决定怎么处理。 --- ## 二、问题一:每轮 active agent 数量硬编码,与"千人模拟"业务叙事冲突 ### 现象 在 [`backend/app/services/engine.py` 的 `_select_active_agents`](../backend/app/services/engine.py) 里,每一轮参与决策的市民数量由这两个常量决定: ```python active_agents_per_round_min: int = 3 active_agents_per_round_max: int = 10 ``` 来源:[`backend/app/models/world.py` 的 `TimeConfig`](../backend/app/models/world.py) ### 我观察到的问题 1. **抽样率随人口规模塌缩。** 100 人社区 → 3%–10% 采样,1000 人 → 0.3%–1%,10000 人 → 0.03%。但产品的对外叙事是"千人社会模拟"。 2. **业务参数 vs 工程参数混淆。** 这两个数字看起来是 `TimeConfig`(业务/世界设定),但更像是 LLM 成本阀门。混在一起,没办法独立调。 3. **`len(agents) * 0.6` 这个上限看起来是为更大规模预留的,但在默认 3–10 的基础上永远是死代码。** 暗示当初设计是想过随规模调整的。 4. **3–10 个人的表态,能涌现出什么?** 默认权重 w=0.3,平静的人天然偏低,抽样会偏向情绪激动的小群体。 5. **业务承诺 vs 实际行为错配。** 用户为"千人社会模拟"付费,生成阶段认真做了 1000 个 backstory;一轮跑下来认真读 prompt 的只有 6 个。这到底是性能问题还是产品问题? ### 待澄清的几个点 - 为什么 `min/max` 默认是 3–10? - 是否有人为"千人"规模做过代表性 / 抽样率的论证? - 这个参数应该让用户在产品层感知到(作为旋钮),还是只放在工程内部? --- ## 三、问题二:搜索后端从 DuckDuckGo 替换为 SearXNG ### 现象 现在 [`backend/app/services/research.py`](../backend/app/services/research.py) 用的是 `duckduckgo_search`: ```python from duckduckgo_search import DDGS with DDGS() as ddgs: return list(ddgs.text(query, max_results=max_results)) ``` 我想替换为自托管的 SearXNG,原因(这里只描述动机,不给方案): - DDG 经常触发反爬 / CAPTCHA,结果不稳定 - 模拟场景需要可重复性(同一 query 多次结果尽量一致) - 想避免外部限流风险 ### 相关材料(已确认) 项目里已有 SearXNG 的 skill 文档:[`skills/searxng_skills/`](../skills/searxng_skills/) 关键信息(待修改时要严格遵守): - **域名是 `searxng.erhe.top`**(不是 `ehre.top` — `h`/`r` 反着,#1 常见坑)⚠ - **必须带 `token=fGWEFWGrgasegtjt1jUJG`**,否则 403 - 当前服务器 GET 即可(本地 stock docker 默认 POST,**不要照搬本地配置**) - JSON 200 路径:`/search?format=json&token=...` - 返回字段:`title / content / url`,需要重命名映射到现有 `title / body / href` ### 已处理 - ✅ 域名拼写错误问题,今天已修。 ### 待处理(明天动手) - [ ] `research.py` 的 `_raw_search` 替换为 SearXNG 调用 - [ ] `__init__` 加 `searxng_base_url / searxng_token / searxng_timeout` 参数 - [ ] `config.py` 加对应 `Settings` 字段 - [ ] `main.py` 注入新参数 - [ ] `.env` 写 `SEARXNG_BASE_URL` / `SEARXNG_TOKEN` / `SEARXNG_TIMEOUT` - [ ] 是否保留 DDG fallback?待定 - [ ] 是否加 query 短缓存(避免同 query 短时间重复打后端)?待定 ### 还需要决定的 - `searxng_timeout` 取多少?skills 里两处不一致(`SKILL.md` 是 30,`searxng_skills.md` 是 15)。模拟里 30 太久(卡轮),5 太短。倾向 15。 - `safesearch` 取 0 还是 1?模拟里有些社会议题可能需要未过滤内容。 --- ## 四、相关代码位置 - 抽样逻辑:`backend/app/services/engine.py` `_select_active_agents`(约 765–833 行) - 抽样配置:`backend/app/models/world.py` `TimeConfig`(约 14–17 行) - 搜索实现:`backend/app/services/research.py` - 搜索配置:`backend/app/config.py` `Settings.search_enabled / max_searches_per_round` - LLM 客户端 / semaphore:`backend/app/services/llm.py` - LLM 并发配置:`backend/app/config.py` `Settings.max_concurrent_llm_calls` - SearXNG skill 文档:`skills/searxng_skills/SKILL.md` --- ## 五、与上一份记录的关系 这是第二份问题记录(第一份是 [问题记录-硬编码与千人模拟.md](./问题记录-硬编码与千人模拟.md))。