
前阵子接了一个POI数据处理的项目核心目标是把散落在一堆报表和接口里的POI兴趣点数据清洗、补全、统一成一套能直接喂给下游业务的干净数据。做了之后发现传统规则清洗在复杂真实数据面前根本不够看后来把方案改成了“POI-Enhancer LLM4POI集成分析”的组合才真正把数据质量和整体效率提了上来。这篇文章就把这套方案的核心思路、关键实现和踩过的坑完整记录一下适合正在做POI数据治理、基础数据标准化、或者想用大模型做地址/兴趣点增强的朋友参考。1. 项目整体设计与思路拆解1.1 POI数据到底难在哪里POI数据表面看就是“名称地址经纬度类别”但真实场景下远没有这么简单。我拿到的原始数据来源极杂有老系统的导出表有运营手工填的Excel有地图SDK回传的日志还有爬虫抓的商户信息。这些数据混在一起之后几个老问题就特别扎眼名称不规范同一家店可以叫“老王牛肉面”、“老王牛肉面馆”、“老王牛肉面(人民路店)”甚至还有人写成“老王牛内面”这种错别字版本。地址残缺有的只有“人民路88号”有的写“某某大厦B座3楼”有的甚至连市辖区都没有只有一句“在火车站附近”。类别混乱不同来源对“餐饮”的分类粒度完全不同有的只有一级大类有的能细分到“川菜-火锅-重庆火锅”。坐标漂移一部分数据没有经纬度一部分经纬度明显偏移还有一部分是平面坐标没有做投影转换。属性缺失营业时间、联系电话、人均消费、评分这些业务属性大量缺失。如果用传统ETL里的正则匹配、字典映射、规则判断去做清洗每一条规则都要针对具体脏数据编写写一版跑上去过两天又来一种新脏格式规则库无限膨胀维护成本直线上升。这是我最初用规则清洗吃到的最大教训。1.2 LLM4POI能解决什么、不能解决什么LLM4POI这个方向本质是把大语言模型当成一个“懂地理常识的知识处理器”引入到POI处理链路中。大模型在名称纠错、地址理解、语义分类、属性抽取这些环节上有天然优势因为它不是靠固定规则去匹配而是靠语义理解去推断。比如把“老王牛内面 人民路88号 张记隔壁”交给LLM它能推断出这是“餐饮-面馆”能纠正“牛内面”为“牛肉面”能尝试解析出地址主体是“人民路88号”还能顺带把“张记隔壁”识别为位置参照信息而不是正式地址。但LLM4POI不是万能的。它的坐标计算能力几乎为零不能指望它输出准确的经纬度它的幻觉问题在地址补全场景里很危险尤其当原始信息太模糊时它会一本正经地编一个不存在的地址它的成本也不是零十万条POI全部走大模型接口是一笔不小的开销。所以方案定位是LLM负责“理解”和“推断”规则和外部数据负责“校验”和“修正”也就是标题里那句“集成分析”的意思。1.3 POI-Enhancer的定位与模块划分POI-Enhancer在我的设计里不是一个单点脚本而是一个可编排的处理框架。它的核心职责是把脏POI作为输入输出一条结构化、标准化的增强POI记录。整体分四层输入适配层兼容多种来源数据自动识别字段映射做初步去重。LLM推理层对每条POI进行名称标准化、地址解析、类别映射、属性抽取。外部校验层接入行政区划库、坐标反查、业务知识库对LLM结果做约束和修正。输出标准化层统一数据模型输出JSON格式的增强结果附带质量评分和置信度。这样设计的好处是每一层可以独立替换。比如LLM推理层今天用的是通用模型明天某个场景需要换成领域微调模型只要输出格式不变其它层完全不用动。外部校验层也一样接入新的行政区划库就像换一张表那么简单。2. 技术选型与核心原理2.1 为什么采用“规则LLM知识库”三层架构第一版我试过纯LLM端到端直接把原始POI文本塞给模型让它输出一个完整的JSON。效果在单个样本上看非常惊艳但批量跑下来问题就露出来了。一是相同输入不同输出带有温度参数时同一家店两次跑出来的类别可能不一样二是无法约束边界模型偶尔会输出根本没有依据的营业时间三是成本浪费很多已经规则能处理的简单结构化数据没必要每次都走LLM。后来调整为三层架构后问题基本都解决了第一层用规则处理所有“确定性”的工作去重、字段映射、非法字符清理、基础格式校验。第二层用LLM处理“需要理解”的工作语义纠错、地址结构识别、类别推断、属性补全。第三层用知识库做“最终裁决”行政区域合法性检查、坐标反查验证、业务属性字典匹配。这样做最大的收益是确定性。规则能兜底的绝不让模型自由发挥模型只做规则做不了的事情模型输出的东西又被知识库约束着防止它编造出离谱的结果。2.2 直接调用通用大模型还是微调专用模型这个纠结了很久也对比过两版效果。通用大模型优势明显开箱即用、推理灵活、对中文地址的理解能力强但劣势是单条成本偏高、大批量调用时延迟不稳定、偶尔输出格式不符合预期。微调专用模型呢成本和延迟可控、输出格式能约束得很稳定但需要准备高质量训练语料且POI这类数据更新迭代快模型一旧又得重新训。我最终的结论是分场景标准化清洗类任务名称纠错、地址解析、类别映射走通用大模型即可因为不需要业务私有知识通用大模型的知识覆盖已经足够。业务持久属性类任务比如从POI名称推断是否连锁、是否品牌直营建议用小模型微调或规则映射这类任务一旦理解错代价很高。高质量标注语料充足且有持续迭代需求时才考虑微调专用模型。我的项目里LLM4POI集成的基座选了调用通用大模型接口但在链路里加了一层输出Schema约束和知识库验证让模型自由发挥的空间被限制在可控范围内。2.3 统一数据模型与输出Schema设计LLM输出混乱是集成时最容易翻车的点解决办法是在Prompt里给出强约束的JSON Schema并且解析失败时自动重试。我的输出Schema大致长这样{ poi_id: 原始编号或内部生成ID, name_standard: 标准化后名称, name_original: 原始名称, name_confidence: 0.95, address: { province: 省, city: 市, district: 区县, street: 道路信息, house_number: 门牌号, landmark: 地标/参照物, full_text: 完整标准化地址, confidence: 0.9 }, category: { l1: 一级大类, l2: 二级类别, l3: 三级细分类别, confidence: 0.88 }, attributes: { open_time: , phone: , per_capita: null }, coordinate: { lat: null, lng: null, source: none }, quality_score: 0.85, flags: [address_incomplete, phone_missing] }这个Schema设计时有几个细节要说明confidence不是给业务看的而是给自己的质量评估系统看的低于某个阈值的记录进入人工审核队列。source字段标记坐标来源区分是原始数据带的、还是反查得到的、还是没有。flags是异常标记列表方便下游直接过滤处理而不需要重新解析整条JSON。最关键的一点我不知道你会不会踩这个坑Schema必须要求模型只输出JSON不要输出任何解释性文本否则解析时一半的时间都花在清洗Markdown代码块上了。3. 核心实现与实操环节3.1 原始数据预处理输入干净才能输出干净很多人一上来就把原始数据直接丢给LLM这其实是浪费。我发现先做一轮“物理清洗”再进LLM效果提升非常明显。具体做了这几件事字段映射与类型强制原始表里“地址”列可能有空值有“不详”有“待定”这些字符串统一转成空值避免LLM被干扰。名称与地址截断异常超长文本比如有人把备注都填进名称里了截断或拆分因为超长输入既增加Token成本又稀释注意力。基础维度拆分如果原始数据有经纬度列提前校验经纬度范围。非法经纬度不能直接删要标记后让后续流程决定是否反查。简单规则预清洗全角半角转换、乱码清理、重复标点压缩、emoji过滤对地址字段里真有带emoji的商户。预处理阶段我用一个基于Pandas的流水线脚本处理十万条数据跑完大约不到一分钟性价比极高为后续LLM调用省下了大量Token。3.2 LLM结构化输出实现Prompt构建与后处理Prompt构建是这个项目里最值得琢磨的部分。我实际试过几版Prompt发现单靠一句“请帮我清洗POI数据”是不够的输出质量会很不稳定。最终使用的Prompt框架包含四个部分角色设定明确模型是“POI数据增强专家”要求输出符合行业标准的结果。输出约束只能是JSON且严格按照给定Schema不允许添加任何额外字段。具体分析指令名称纠错要结合语义和地域习惯地址解析要区分出正式地址和参照描述类别映射要到三级属性补全宁可留空也不能编造。少量示例给两三个典型输入输出对帮助模型对齐格式。举个例子Prompt里我固定的指令是你是一个POI数据增强专家。请根据输入的兴趣点信息完成以下任务 1. 标准化名称纠正错别字统一简称与全称去除无意义的品牌后缀词。 2. 解析地址区分省/市/区/街道/门牌号/地标对于不能确认的字段留空不要推断。 3. 推断类别输出三级的品类层次。 4. 补全属性营业时间、电话等信息仅从原文中抽取原文没有就留空。 5. 对结果给出置信度评分和异常标记列表。 只输出JSON对象不要输出任何解释或Markdown标记。后处理部分我写了解析函数优先尝试json.loads直接解析失败则提取最早出现的{到最后一个}之间的子串再解析还失败就把模型原始输出写入异常队列不会硬撑。这个队列在联调阶段每天能抓到几十条模型抽风的记录对排查Prompt缺陷非常有帮助。3.3 外部知识库校验给LLM结果“上把锁”只靠LLM输出就落库还是不放心尤其地址这块。我接了三类外部知识数据做校验行政区划库省市区三级标准名称和编码表。LLM输出的地址解析结果如果区县名称不在库里直接置为null并打上district_mismatch标记。坐标反查服务如果原始数据带坐标但地址解析后区县与坐标反查的区县不一致触发警告。宁可保留原始坐标并标记异常也不要盲信LLM的输出坐标。业务知识字典特定类别要求特定属性比如餐饮必须有经营品类酒店必须有星级档位。如果类别推断出来但关键属性缺失则标记为质量不合格。知识库校验有个妙用用规则修正LLM的小错误而不是全盘推翻。比如模型把“武昌区”和“洪山区”搞混了如果坐标反查在洪山区就把区县字段改成洪山区同时把置信度下调。这比让LLM重新生成一遍既省成本又稳定。3.4 特征对齐与记录合并解决“同一实体多条记录”的难题数据源合并后同一家店存在多条记录是常态。传统做法是按名称地址精确匹配但错别字问题会让匹配失效。我设计了一个分层匹配策略第一层标准化名称完全一致且区县一致直接合并。第二层标准化名称相似度超过85%且地址要素中街道门牌号一致合并并触发冲突检测。第三层无名称匹配但坐标距离小于50米且类别一致合并但降低合并置信度。相似度用的是字符编辑距离加一个简单的语义判断因为中文地址词序变化会影响编辑距离所以我在比较前先把地址字符串按“省市区街牌号参照”拆成要素再逐要素比较实测效果比全文相似度稳定得多。合并时还处理了一个细节属性冲突。比如一条记录营业时间是“10:00-22:00”另一条是“09:30-23:00”不能随便覆盖。我的策略是按数据源可靠度排序高可靠度覆盖低可靠度可靠度相同时取更宽泛的时间范围。3.5 质量评估与人工审核闭环每条输出都带quality_score这个分数综合了置信度、字段完整度、异常标记数量。算法很简单quality_score 0 起步 名称标准化且有高置信度0.2 地址完整到街道/门牌0.3 类别三级齐全0.2 坐标存在且通过反查0.2 - 每一个异常标记-0.1 - 置信度低于阈值再减0.1跑完下来分数低于0.5的数据进入人工审核池0.5到0.7之间抽样审核0.7以上自动通过。刚开始人工审核池占将近四成后来Prompt优化和知识库补全后压到了不到一成这个指标是检验整个链路效果的硬标尺。4. 实践中的典型问题与排查实录4.1 模型幻觉地址补全变成了地址编造最头疼的问题就是模型编地址。比如输入“某市人民路附近”模型可能直接补全出一个不存在的“人民路88号”而且看起来很合理。我排查后总结出规律模型在低信息量输入下特别容易产生幻觉因为它在努力“填满”Schema输出。解决办法有几层在Prompt里明确写“地址缺省字段一律留空不要推断”。在知识库校验层增加“地址要素合法化校验”门牌号超过范围直接标记。在输出后处理时统计地址完整度凡是关键字段连续多个由模型推断且无原始数据佐证的直接降置信度并进人工审核池。平静之后观察模型确实更“老实”了不敢乱编了。4.2 类别体系漂移不同批次跑出的分类粒度不一致同样的“牛肉面馆”有时候模型输出“餐饮-快餐-面馆”有时候输出“餐饮-小吃-面条”甚至还有一次输出“食品-餐饮服务-正餐”。这就是大模型输出不稳定的直接体现。我用了两个手段约束预先给一份类目体系树的关键节点放到Prompt里让模型只能在树里选。输出后再做一层类目映射表把模型输出结果统一映射到业务侧标准三级类目上。有个有趣的现象加了类目体系树之后模型的分类一致性肉眼可见地提高因为候选空间被收窄了。这个细节很值得留意。4.3 规则预清洗把有效信息误删了有一版清洗规则里我加了“过滤括号内容”的逻辑本意是去掉名称里的无意义注释。结果一批连锁品牌的数据大量中招比如“瑞幸咖啡(某某广场店)”被清成了“瑞幸咖啡”反而丢了门店识别信息合并时大量误合并。这个教训让我明白预清洗规则必须可审计、可回滚。后来规则全部记录处理动作每条清洗数据都能查到“谁改了什么、为什么改”并且针对名称清洗和白名单保护了品牌主体后面的括号内门店词。4.4 成本监控十万条POI的Token消耗如何降下来跑批量那几天Token账单涨得比较快不得不认真做一次成本复盘。优化方式主要有三个缓存历史结果相同MD5内容的原始记录直接复用上一次结果不做重复LLM调用这条省下的成本最直观。优先规则处理能通过字典映射和坐标校验完成的记录跳过LLM步骤这类数据节省了大约三成Token。动态选择输入字段某些来源只有名称没有地址Prompt里就不放地址任务只做名称标准化和类别推断省略地址部分的输出Token。优化后单条成本下降了一半以上但质量分没有掉说明之前的成本确实有不少花在了无意义的地方。5. 集成过程中的关键经验与可复用建议5.1 链路可观测性日志字段要提前设计不管是POI-Enhancer还是LLM4POI集成过程中一定要做好链路日志。我在每个处理阶段都输出一条日志记录输入原始值、规则处理结果、LLM返回结果、知识库校验结果、最终输出结果的差异对比。联调时这些日志是定位问题最快的依据。比如我遇到过一个问题“某市某区某路某大厦”在知识库校验时区县匹配失败日志显示规则清洗阶段把这个地址的区县字段给覆盖成别的值了如果没有日志很难排查到这种跨模块的数据污染。5.2 接口容错超时、限流、重试策略LLM接口调用不是百分百可靠项目里出现过高延迟、限流、偶尔5xx错误。我设置了分级重试策略超时类错误指数退避重试两次限流类错误等待后重试一次参数类错误直接终止并告警。同时把并发数调低让调用速率稳定在服务方容忍范围内。这个策略跑下来整体成功率稳定在99.5%以上其余进入异常队列第二天重放。5.3 从单机脚本升级到任务化调度项目初期就是单机脚本跑全量后来数据量变大且需要每日增量更新加调度框架后好处明显断点续跑、失败告警、依赖编排、并行分区处理都顺了。我把整个处理流程拆成“原始同步、预清洗、LLM增强、知识库校验、输出落库、质量报告”六个阶段每个阶段独立可跑、可跳过、可重试。这个改造虽然初期花了些时间但后续每一次调参都收益明显。5.4 快速上线建议先跑通一条链路再横向扩展如果你也要做类似的POI增强系统我的建议是别一上来就铺全量。先拿出一个区级的数据几百条把所有模块跑通手工检验质量分阈值和Prompt效果稳定后再扩展到全市数据每一次batch处理完都要看质量报告而不是只关心有没有跑挂。调Prompt是个玄学过程观察几十条典型case再修改比盲目加规则和示例更高效。6. 后续扩展方向当前方案解决了POI标准化和增强的主链路但还有几个方向值得继续深入。多模态信息接入POI对应的门头照片、街景图如果能作为辅助信号配合LLM做名称和类别的交叉验证准确率应该还能再上一个台阶。增强检索与自助问答能力增强后的POI数据接上向量检索能支撑更灵活的上游服务比如用户发一句“这附近有没有适合带娃吃面的店”能直接定位到对应POI集合。构建POI数据回流闭环业务使用过程中用户反馈的修正信息收集起来定期更新知识库字典让系统越跑越准。我个人在实际操作中的体会是这套方案真正的壁垒不是模型本身而是围绕模型搭建的校验、纠错、反馈体系。通用大模型的能力还在快速升级但POI数据治理里的确定性问题——格式、规则、字典、行政区划——始终需要工程化手段去兜底。LLM负责“创造性理解”规则和知识库负责“确定性约束”两相结合才能把一个看起来简单的数据清洗需求真正做出生产级质量。最后再分享一个小技巧在写Prompt时把“不能做什么”比“要做什么”写得更醒目一些尤其在地址补全和属性推断这两类高风险环节。这套系统上线到现在质量报告里新增的高风险异常基本都来源于当时我没有在Prompt中约束清楚的场景。