# 语义相似度分析模块 ## 功能概述 提供基于 AI Agent 的语义相似度分析功能,支持缓存机制以提高性能和降低 API 调用成本。 ## 主要功能 ### 1. 核心函数 - `difference_between_phrases()` - 返回原始 AI 响应 - `difference_between_phrases_parsed()` - 返回解析后的 JSON 字典 - `compare_phrases()` - `difference_between_phrases_parsed()` 的别名 ### 2. 缓存系统设计 #### 缓存文件名设计 **方案:可读文件名 + 哈希后缀** ``` cache/semantic_similarity/ ├── 宿命感_vs_余华的小说_gpt-4.1-mini_t0.0_a7f3e2d9.json ├── 人工智能_vs_机器学习_claude-sonnet-4.5_t0.0_b8e4f3e0.json ├── 深度学习_vs_神经网络_gemini-2.5-pro_t0.2_c9f5g4h1.json └── 创意写作_vs_AI生成_gpt-4.1-mini_t0.7_d0a6h5i2.json ``` **文件名格式:** ``` {phrase_a}_vs_{phrase_b}_{model}_t{temp}_{hash[:8]}.json ``` - `phrase_a`: 第一个短语(最长20字符,特殊字符转为下划线) - `phrase_b`: 第二个短语(最长20字符,特殊字符转为下划线) - `model`: 模型简称(提取 `/` 后部分,最长20字符) - `t{temp}`: 温度参数(格式化为1位小数,如 t0.0, t0.2, t0.7) - `hash[:8]`: 完整哈希的前8位 **哈希生成逻辑:** - 基于所有影响结果的参数生成唯一 MD5 哈希: - `phrase_a` - 第一个短语 - `phrase_b` - 第二个短语 - `model_name` - 模型名称 - `temperature` - 温度参数 - `max_tokens` - 最大 token 数 - `prompt_template` - 提示词模板 **缓存文件格式(结构化 JSON):** ```json { "input": { "phrase_a": "宿命感", "phrase_b": "余华的小说", "model_name": "openai/gpt-4.1-mini", "temperature": 0.0, "max_tokens": 65536, "prompt_template": "从语意角度,判断【{phrase_a}】和【{phrase_b}】..." }, "output": { "result": "{\n \"说明\": \"...\",\n \"相似度\": 0.75\n}" }, "metadata": { "timestamp": "2025-11-19 14:30:45", "cache_key": "a7f3e2d9c1b4a5f8e6d7c9b2a1f3e5d7", "cache_file": "宿命感_vs_余华的小说_gpt-4.1-mini_t0.0_a7f3e2d9.json" } } ``` #### 缓存特性 1. **自动缓存**:默认启用,首次调用保存结果 2. **智能匹配**:相同参数自动从缓存读取 3. **可控性**:支持 `use_cache=False` 强制重新请求 4. **可追溯**:缓存文件包含完整元数据和时间戳 5. **自定义目录**:支持通过 `cache_dir` 参数自定义缓存位置 ## 使用示例 ### 基本使用(自动缓存) ```python from lib.semantic_similarity import compare_phrases # 第一次调用 - 请求 API 并缓存 result = await compare_phrases("宿命感", "余华的小说") # 输出: ✓ 已缓存: 宿命感_vs_余华的小说_gpt-4.1-mini_t0.0_a7f3e2d9.json # 第二次调用相同参数 - 从缓存读取 result = await compare_phrases("宿命感", "余华的小说") # 输出: ✓ 使用缓存: 宿命感_vs_余华的小说_t0.0_a7f3e2d9.json print(result['相似度']) # 0.3 print(result['说明']) # "两个概念..." ``` ### 禁用缓存 ```python # 强制重新请求 API result = await compare_phrases( "人工智能", "机器学习", use_cache=False ) ``` ### 自定义缓存目录 ```python # 使用自定义缓存目录 result = await compare_phrases( "深度学习", "神经网络", cache_dir="my_cache/similarity" ) ``` ### 自定义提示词模板 ```python custom_template = """ 请详细分析【{phrase_a}】和【{phrase_b}】的语义关系 输出格式: ```json {{ "说明": "详细分析", "相似度": 0.5, "关系类型": "相关/包含/对立/无关" }} ``` """ result = await compare_phrases( "机器学习", "深度学习", prompt_template=custom_template ) ``` ### 配置不同模型 ```python # 使用 Claude 模型 result = await compare_phrases( "人工智能", "深度学习", model_name='anthropic/claude-sonnet-4.5', temperature=0.2 ) ``` ## 缓存管理 ### 查看缓存 ```bash # 查看缓存目录 ls cache/semantic_similarity/ # 查看特定缓存文件 cat cache/semantic_similarity/a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6.json ``` ### 清理缓存 ```bash # 清理所有缓存 rm -rf cache/semantic_similarity/ # 清理特定缓存文件 rm cache/semantic_similarity/a1b2c3d4*.json ``` ### 缓存统计 ```python from pathlib import Path import json cache_dir = Path("cache/semantic_similarity") cache_files = list(cache_dir.glob("*.json")) print(f"缓存文件总数: {len(cache_files)}") # 统计各模型使用情况 model_stats = {} for file in cache_files: with open(file, 'r') as f: data = json.load(f) model = data.get('model_name', 'unknown') model_stats[model] = model_stats.get(model, 0) + 1 print("各模型缓存数量:") for model, count in model_stats.items(): print(f" {model}: {count}") ``` ## 参数说明 ### 所有函数共享参数 | 参数 | 类型 | 默认值 | 说明 | |------|------|--------|------| | `phrase_a` | str | 必填 | 第一个短语 | | `phrase_b` | str | 必填 | 第二个短语 | | `model_name` | str | `'openai/gpt-4.1-mini'` | 使用的 AI 模型 | | `temperature` | float | `0.0` | 温度参数(0.0-1.0) | | `max_tokens` | int | `65536` | 最大生成 token 数 | | `prompt_template` | str | `None` | 自定义提示词模板 | | `use_cache` | bool | `True` | 是否启用缓存 | | `cache_dir` | str | `'cache/semantic_similarity'` | 缓存目录路径 | ### 支持的模型 - `'google/gemini-2.5-pro'` - `'anthropic/claude-sonnet-4.5'` - `'google/gemini-2.0-flash-001'` - `'openai/gpt-5-mini'` - `'anthropic/claude-haiku-4.5'` - `'openai/gpt-4.1-mini'` (默认) ## 性能优化 ### 缓存命中率优化 1. **参数标准化**:确保相同语义使用相同参数 2. **批量处理**:对相同短语对只调用一次 3. **预热缓存**:提前为常用短语对生成缓存 ### 示例:批量处理 ```python phrase_pairs = [ ("宿命感", "余华的小说"), ("人工智能", "机器学习"), ("深度学习", "神经网络"), ] for phrase_a, phrase_b in phrase_pairs: result = await compare_phrases(phrase_a, phrase_b) print(f"{phrase_a} vs {phrase_b}: {result['相似度']}") ``` ## 注意事项 1. **参数敏感性**:任何参数变化都会导致新的缓存键 2. **存储空间**:长期使用可能积累大量缓存文件 3. **缓存一致性**:模型更新后建议清理旧缓存 4. **并发安全**:当前实现不支持并发写入同一缓存文件 ## 故障排查 ### 缓存未命中 **问题**:相同参数调用但未使用缓存 **可能原因**: - 参数细微差异(如空格、换行) - `prompt_template` 不一致 - 缓存文件损坏或被删除 **解决方案**: ```python # 检查缓存键 from lib.semantic_similarity import _generate_cache_key, DEFAULT_PROMPT_TEMPLATE key = _generate_cache_key( "宿命感", "余华的小说", "openai/gpt-4.1-mini", 0.0, 65536, DEFAULT_PROMPT_TEMPLATE ) print(f"缓存键: {key}") ``` ### 缓存损坏 **问题**:缓存文件存在但无法加载 **解决方案**: ```bash # 删除损坏的缓存文件 rm cache/semantic_similarity/{cache_key}.json ``` ## 版本历史 - **v1.0** - 初始版本,支持基本语义相似度分析 - **v1.1** - 添加缓存系统 - **v1.2** - 支持自定义提示词模板 - **v1.3** - 优化缓存文件格式,添加元数据