23 Feb, 2026

1 commit


22 Feb, 2026

1 commit

  • 一、命名与引用统一
    -----------------
    - 全文将 [SEARCH_REF:ref_id] 统一为 [SEARCH_RESULTS_REF:ref_id]。
    - README_prompts.md: 文档中两处 SEARCH_REF 改为 SEARCH_RESULTS_REF。
    - app/agents/shopping_agent.py: 系统提示与注释中的 SEARCH_REF、make_search_products_tool 改为 SEARCH_RESULTS_REF、search_products。
    - app/search_registry.py: 注释与 docstring 中的 SEARCH_REF 改为 SEARCH_RESULTS_REF。
    - app.py: SEARCH_REF_PATTERN 重命名为 SEARCH_RESULTS_REF_PATTERN,正则与注释同步。
    - app/tools/search_tools.py: 工具返回与注释中的 SEARCH_REF 改为 SEARCH_RESULTS_REF。
    
    二、search_registry:ref_id 改为会话内自增
    -----------------------------------------
    - 移除 new_ref_id()(原 uuid 短码);ref_id 改为按 session 自增:sr_1, sr_2, ...
    - SearchResultRegistry 新增 _session_counter 与 next_ref_id(session_id)。
    - register 逻辑不变;clear_session 时同时清除 _session_counter。
    
    三、search_tools:搜索逻辑统一、去除重复
    ---------------------------------------
    - 新增 _call_search_api(query, size):仅调用搜索 API,返回 (raw_results, total_hits) 或 None。
    - 新增 _raw_to_product_items(raw_results, labels=None):将 API 原始结果转为 list[ProductItem];有 labels 时按 Relevant/Partially Relevant 过滤并打标,否则全部打 Partially Relevant。
    - 新增 search_products_impl(query, limit, *, assess_quality=True, session_id=None, registry=None):唯一搜索实现;返回 (ref_id_or_none, products, assessed_count)。assess_quality 且提供 session_id/registry 时执行 LLM 评估并写入 registry,否则仅调 API 并返回产品列表。
    - make_search_products_tool 内 search_products 改为调用 search_products_impl(..., assess_quality=True, session_id, registry),根据返回值拼工具说明文案;使用 registry.next_ref_id(session_id)。
    - 新增 search_products_api_only(query, limit=12):薄封装,调用 search_products_impl(..., assess_quality=False),返回 list[ProductItem],供前端「找相似」侧栏使用(仅 API,不做 LLM 评估)。
    
    四、app.py:前端性能与交互优化
    -----------------------------
    1) 图片缓存
       - 模块级 _IMAGE_CACHE (OrderedDict),最多 100 条;key 为 image_url 或 "local:{path}"。
       - _load_product_image:先查缓存,命中则 move_to_end 并返回;未命中则请求/读本地后写入缓存并做 LRU 淘汰。
    
    2) 减少全量 rerun(fragment)
       - render_referenced_products_in_input、render_bottom_actions_bar 加 @st.fragment,删除引用 / 点 Ask·Compare 时只重跑对应片段。
       - 侧栏内容用 @st.fragment 的 _sidebar_fragment() 包裹,在 with st.sidebar 内调用,Clear Chat 时只重跑侧栏。
    
    3) 「找相似」:先 loading,再仅调搜索 API
       - 点击 Similar products 时只设置 side_panel.payload = { query, loading: True } 并 rerun,侧栏先显示「加载中…」。
       - main() 中若 side_panel.mode=="similar" 且 payload.loading,则调用 search_products_api_only(payload["query"], 12),将结果写入 payload.products、loading=False,再 rerun。
       - render_side_drawer:payload.loading 显示加载中;payload.products 存在则用该列表渲染卡片;否则保留基于 ref_id + registry 的兼容逻辑。
       - 删除 _run_similar_search(原完整 search tool + LLM 评估),改为上述流程。
    
    4) 长对话渲染
       - 仅渲染最近 50 条消息(MAX_MESSAGES=50),msg_index 用 start_idx + i 保持 widget key 稳定;超过 50 条时顶部显示「仅显示最近 50 条,共 N 条消息」。
    
    Co-authored-by: Cursor <cursoragent@cursor.com>
    tangwang
     

21 Feb, 2026

2 commits


20 Feb, 2026

4 commits

  • ## 搜索工具与质量评估
    - _assess_search_quality 仅返回 (labels, quality_summary):去掉 verdict(优质/一般/较差)及依赖逻辑;prompt 要求 LLM 输出 labels + quality_summary(1–2 句:结果主要包含什么、是否基本满足意图、匹配度)。
    - 工具返回格式统一为:【搜索完成】query='...' + 结果引用 [SEARCH_REF:ref_id] + 搜索结果质量情况(评估总条数、Highly Relevant / Partially Relevant 条数)+ results list(top10 标题)。
    - 精简 prompt 与日志:评估输入仅保留序号+标题;删除 verdict_hint、逐条 SEARCH_RESULT_ITEM/SEARCH_RESULT_PRODUCT 日志,保留单行注册日志。
    
    ## 三级标签改为英文
    - 完美匹配 → Highly Relevant;部分匹配 → Partially Relevant;不相关 → Not Relevant。
    - 全量替换:search_tools(prompt、valid、统计与过滤)、search_registry(ProductItem.match_label 默认及注释、SearchResult 注释)、app.py(卡片 label_style、结果块头部与筛选逻辑)。
    
    ## Registry 与 UI
    - SearchResult 移除 quality_verdict 字段;quality_summary 由 _assess_search_quality 的 LLM 返回写入。
    - 结果块头部不再展示 verdict 图标/文案,改为展示 query + Highly/Partially Relevant 件数 + quality_summary(若有)。
    
    ## Agent
    - 系统提示词调整:角色与原则、价值提供与信息收集、search_products 与 [SEARCH_REF:xxx] 使用说明。
    
    Co-authored-by: Cursor <cursoragent@cursor.com>
    tangwang
     
  • - Search image_url: parse results[].image_url, add _normalize_image_url() to
      convert protocol-less URLs (////host/path) to https://host/path; fix double
      slash (use https:// + url.lstrip("/") so normalized URL has single //).
    - Logging: log full LLM request/response (LLM_REQUEST, LLM_RESPONSE), full
      tool call results (TOOL_CALL_RESULT); for search tool log SEARCH_RESULT
      summary and per-item SEARCH_RESULT_ITEM (image_url_raw) and
      SEARCH_RESULT_PRODUCT (image_url_normalized).
    - Streamlit: replace deprecated use_container_width=True with width="stretch"
      for st.image and st.button.
    
    Co-authored-by: Cursor <cursoragent@cursor.com>
    tangwang
     
  • ## 搜索结果管理与人机回复引用
    - 新增 app/search_registry.py:SearchResultRegistry + SearchResult/ProductItem 数据结构,按 session 存储每次搜索的 query、质量评估与商品列表。
    - 搜索工具改为工厂 make_search_products_tool(session_id, registry):每次搜索后由 LLM 对 top20 打标(完美匹配/部分匹配/不相关),产出整体 verdict(优质/一般/较差),仅将「完美+部分」写入 registry 并返回摘要 + [SEARCH_REF:ref_id];不再向 Agent 返回完整商品列表。
    - 废除 extract_products_from_response:最终回复中通过内联 [SEARCH_REF:xxx] 引用「搜索结果块」,UI 用 SEARCH_REF_PATTERN 解析后从 registry 取对应 SearchResult 渲染 query 标题 + 商品卡片,避免 LLM 复述商品列表,节省 token 并减少错误。
    
    ## 系统提示与行为约束
    - 系统提示词通用化(不绑定时尚品类),明确四步:理解意图 → 规划 2~4 个 query → 执行搜索并评估 → 撰写回复。
    - 要求同一条回复中并行发起 2~4 次 search_products(不同 query),利用 LangGraph ToolNode 的并行执行缩短等待;禁止串行「搜一个看一个再搜下一个」。
    - 轮次上限:最多两轮搜索(两轮 = 两次「Agent 发 tool_calls → Tools 执行 → 返回」);若已有优质/一般结果则直接写回复,仅当全部较差时允许第二轮(最多再 1~2 个 query)。图逻辑增加 n_tool_rounds 状态与 agent_final 节点,两轮后强制进入「仅回复、不调工具」的 agent_final,避免无限重搜。
    
    ## 前端与工具导出
    - app.py:render_message_with_refs(content, session_id) 按 [SEARCH_REF:xxx] 切分并渲染;render_search_result_block 展示 query + 质量 + 商品卡片;display_product_card_from_item 支持 image_url/本地图/占位;Clear Chat 时 clear_session(registry)。
    - app/tools/__init__.py:改为导出 make_search_products_tool、web_search,不再导出已移除的 search_products 顶层名。
    
    Co-authored-by: Cursor <cursoragent@cursor.com>
    tangwang
     
  • tangwang
     

18 Feb, 2026

1 commit


12 Feb, 2026

4 commits