# 💡 Summary # 🧩 Cues # 🪞Notes 各方案的风险分析 ## 1. 标签方案的Bad Cases 输入:"早上去西湖,下午去灵隐寺" 期望:"早上去<poi>西湖</poi>,下午去<poi>灵隐寺</poi>" 可能的错误: ```Java ❌ "早上去<poi>西湖,下午去灵隐寺</poi>" # 标签未闭合/错位 ❌ "早上去<poi>西湖<poi>,下午去</poi>灵隐寺" # 嵌套混乱 ❌ "早上去<poi西湖</poi>" # 标签格式错误 ``` 问题:LLM生成的标签容易出错,解析复杂,一旦出错整个文本可能无法解析。 ## 2. Offset方案的Bad Cases 文本:"Day 1:早上去西湖散步" 错误offset:`{"text": "西湖", "start": 8, "end": 10}` 实际正确:start=9, end=11 结果:`text[8:10]= "去西" ❌ # 划词错位!` 问题:offset一旦错误,用户看到的高亮/点击会错位,体验很差。 ## 推荐的容错方案 🎯 采用"Offset + 自动验证 + 降级匹配"三层防护: ```Java @dataclass class EntityMention: text: str # 原词(必需) type: str # city/poi start: int # 主定位方式 end: int context: str # 备用定位方式(包含原词+前后文) ``` ## 前端使用时的容错逻辑 ```Java def safe_highlight(full_text, entity): # 1️⃣ 优先使用offset(快速精确) extracted = full_text[entity.start:entity.end] if extracted == entity.text: return {"start": entity.start, "end": entity.end, "valid": True} # 2️⃣ Offset不匹配,使用context验证 if entity.context in full_text: # 在context中找到原词的相对位置 ctx_pos = full_text.find(entity.context) word_pos_in_ctx = entity.context.find(entity.text) corrected_start = ctx_pos + word_pos_in_ctx return { "start": corrected_start, "end": corrected_start + len(entity.text), "valid": True, "corrected": True # 标记为修正过的 } # 3️⃣ 降级到全文搜索(contains) pos = full_text.find(entity.text) if pos >= 0: return {"start": pos, "end": pos + len(entity.text), "valid": True, "fallback": True} return {"valid": False} # 无法定位,放弃该实体 ``` 为什么这个方案最优? 方案 优点 缺点 容错性 纯标签 简单直观 LLM易出错,解析脆弱 ⭐ 纯Offset 精确高效 无容错,一错就错位 ⭐⭐ 纯Contains 最简单 多次出现时无法区分 ⭐⭐ Offset+验证+降级 精确+容错 数据结构稍复杂 ⭐⭐⭐⭐⭐ ```