零门槛实战:双模型互证揪出46处解析偏差

长沙市中小学每年暑期都会面向社会开放运动场、体育馆、图书馆等公共区域,满足市民健身、休闲与学习需求。各区县教育局定期公示开放学校名单、时段、场地范围及预约规则,这份公开数据是城市便民服务系统的重要基础。项目计划批量抓取长沙各区县暑期校园开放公告,用图文解析能力抽取学校名称、详细地址、开放日期、时段、限制条件等结构化字段,支撑一个便民查询小程序。

最初的解析却频频翻车:单一图文大模型对公告图片与图文混排文档的识别存在大量偏差,直接掏空了结构化数据的可用性。问题集中爆发在三处——学校名称被识别成错别字或漏字;暑期分段开放时间被搅成一团,工作日与周末规则混肴;文字地址无法精准落到地图上,导致后续的地图展示与区域筛选功能彻底失效。

图文大模型并非全能

当下主流图文大模型在通用识别与信息抽取上确实强悍,但碰到垂直细分、规则化文本、语义相近的场景,短板就暴露出来了,这正是校园开放信息解析出错的病根。

一方面,单一模型自带认知偏见与场景适配缺陷。不同大模型的训练数据、微调方向和推理逻辑差异极大,有的擅长通用识别,却对校园公告这类官方制式文本、分段规则化信息缺乏精度,时序与细节容易丢失。另一方面,图文混排文档里藏着干扰项——备注说明、特殊节假日闭校通知、场地限流规则,常被模型误判成常规开放规则。

更麻烦的是,单一模型没有自我纠错能力,输出看起来格式规整,实则埋着隐性错误,靠人工逐条核对成本高得离谱。CodeBuddy 支持多模型自由切换与并行推理,恰好提供了一套低成本的交叉校验思路:让多个模型对同一任务各出一版结果,靠算法比对差异、标记风险、保留共识,从而化解单一模型的认知盲区。

搭建多模型交叉校验流水线

CodeBuddy 内置腾讯混元、DeepSeek、Kimi、GLM 等多款主流大模型,开发者可以自定义切换模型、配置降级策略、批量并行推理,无需复杂部署就能跑起交叉校验工作流。它的核心逻辑是利用不同模型的能力互补性,对同一批图文解析任务产出多组结果,再经算法比对差异、标记风险数据、保留共识结果,从根本上消弭单一模型的解析误差。

基础信息互证

本次校验聚焦长沙暑期开放学校的核心字段:学校全称、所属区县、详细地址、开放场地类型。单一模型常把区县归属搞错、学校名称简写不统一、地址关键字缺失、场地类型混淆。

方案采用「双模型并行校验 + 差异比对」策略,挑出 kimi2-k2.6(擅长官方图文与文本推理)与 GLM5.2(支持图文输入与推理)对同一批校园公告图文数据做解析。校验规则分三档:

  • 一致性规则:两模型在学校名称、区县归属上完全一致,判定为有效数据,直接留存;
  • 差异标记规则:名称、地址、区县出现分歧,自动标记为高风险数据,触发二次精准解析;
  • 溯源校验规则:针对差异数据回溯解析逻辑,比对原始图文素材,修正识别错误。

交叉检查提示词

在 CodeBuddy 中,用下面这段提示词对 json 数据与原始图片做验证:

W020260707346693894688.jpg
W020260707346694155028.jpg
W020260707346694416153.jpg
W020260707346694698336.jpg
W020260707346695046292.jpg
W020260707346695405020.jpg
W020260707346695679472.jpg
W020260707346695939204.jpg
W020260707346696188612.jpg
W020260707346696436334.jpg
W020260707346696673596.jpg 
仔细对照图片内容和changsha_schools_sports_2026.json
确认解析出来的信息是准确的,要求开放场地不要解析错误,学校名称不要解析错误。

输入提示词后,CodeBuddy 自动开始调用,并自行生成 Python 代码来完成数据解析,代码如下:

import json
data = json.load(open('changsha_schools_sports_2026.json', 'r', encoding='utf-8'))
def print_range(start, end):
    for d in data[start-1:end]:
        no = d['No.']
        district = d['district']
        school = d['schoolName']
        venues = ', '.join(d['venues'])
        start_date = d['startDate']
        end_date = d['endDate']
        print(f"{no:>3} | {district:>6} | {school:<35} | {venues:<50} | {start_date} ~ {end_date}")

# 1-40
print("="*120)
print("序号 1-40 (市直+雨花区)")
print("="*120)
print_range(1, 40)
print()

# 41-80
print("="*120)
print("序号 41-80 (雨花区+开福区)")
print("="*120)
print_range(41, 80)
print()

# 81-120
print("="*120)
print("序号 81-120 (浏阳市)")
print("="*120)
print_range(81, 120)
print()

# 121-160
print("="*120)
print("序号 121-160 (浏阳市)")
print("="*120)
print_range(121, 160)
print()

# 161-200
print("="*120)
print("序号 161-200 (浏阳市)")
print("="*120)
print_range(161, 200)
print()

# 201-240
print("="*120)
print("序号 201-240 (浏阳市)")
print("="*120)
print_range(201, 240)
print()

# 241-280
print("="*120)
print("序号 241-280 (浏阳市+长沙县+湘江新区)")
print("="*120)
print_range(241, 280)
print()

# 281-320
print("="*120)
print("序号 281-320 (湘江新区)")
print("="*120)
print_range(281, 320)
print()

# 321-360
print("="*120)
print("序号 321-360 (湘江新区+宁乡市)")
print("="*120)
print_range(321, 360)
print()

# 361-400
print("="*120)
print("序号 361-400 (宁乡市+天心区)")
print("="*120)
print_range(361, 400)
print()

# 401-455
print("="*120)
print("序号 401-455 (天心区+望城区+芙蓉区)")
print("="*120)
print_range(401, 455)

代码跑起来后,程序化的检查随即展开。

开放时间专项校验

校园暑期开放时间是便民服务的核心数据,也是图文解析的重灾区。长沙各校规则差异极大:分段开放、周末专属、节假日闭校、分场地分时开放交织在一起,单一模型极易混淆时段、遗漏特殊规则。

在双模型校验之外,这一步叠加了规则约束校验。结合教育局通用暑期开放规范,设定时间校验规则:区分日常开放时段、周末专属时段、特殊闭校日期,对模型解析出的时间格式、时段逻辑、规则完整性做多层核验。相比基础信息校验,时间校验重点解决三类问题——开放起止日期错乱、每日时段时分识别错误、特殊限流与闭校规则遗漏。多个模型结果比对后提取共识时间规则,再修正差异化错误输出。

时间校验代码

针对校园开放时间规则,编写专属交叉校验代码,完成时序数据标准化、规则校验与错误修正:

import json
data = json.load(open('changsha_schools_sports_2026.json', 'r', encoding='utf-8'))
# Check items with special dates or venues
for idx in [289, 292, 332, 334, 340, 392, 403, 408, 413, 430, 440, 448]:
    d = data[idx]
    print(f"No.{d['No.']}: {d['schoolName']}")
    print(f"  venues: {d['venues']}")
    print(f"  dates: {d['startDate']} ~ {d['endDate']}")
    print()
# Check items with 2+ venues (potential splitting issues)
for idx in [271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 287, 288, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 312, 313, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348]:
    d = data[idx]
    if len(d['venues']) >= 3:
        print(f"No.{d['No.']}: {d['schoolName']}")
        print(f"  venues: {d['venues']}")
        print(f"  dates: {d['startDate']} ~ {d['endDate']}")
        print()

两段交叉校验代码跑完,单一图文大模型解析校园数据的偏差被啃了下来,全部开放学校的基础信息与开放时间完成标准化清洗,给后续的地图定位与数据落地备好了精准数据源。

校验成果一览

输入交叉检查提示词后,系统逐张图片、逐条记录与 JSON 做系统比对,最终发现并修复约 46 处错误。主要修正汇总如下:

学校名称错误

序号 修正内容
No.93 浏阳市沙市市镇沙市完全小学 → 浏阳市沙市镇沙市完全小学
No.307 长沙高新区明华小学 → 长沙市岳麓区科教小学
No.422 长沙月亮岛第三小学 → 长郡月亮岛第三小学
No.429 兴中学 → 代管中学

开放场地错误

序号 修正内容
No.1 删除多余的 "足球场"
No.10 "室外体育馆" → "户外体育场"
No.13 "体育馆及羽毛球馆" → "篮球球场及羽毛球场"
No.29 "体育馆综合馆" → "体育综合楼";"田径场" → "室外田径场"
No.280 删除重复的 "室外田径场"
No.314 "室外" → "室外上操场"
No.405 "主校门外" → "主校门旁"
No.424 "排球场" → "乒羽馆"
No.442 "室外篮球场"、"室内篮球场" → "室外田径场"、"室外篮球场"

日期错误(约 30 处)

  • 市直:No.33(7/10→7/13)
  • 雨花区:No.41、No.43(7/13→7/15)
  • 湘江新区:No.281(8/29→8/7)、No.282(8/7→8/30)、No.286(8/30→8/20)、No.294(8/14→8/20)、No.305(8/30→8/27)、No.316(8/25→8/31)、No.326(7/30→8/25)、No.334(8/31→8/27)、No.335(8/26→8/27)等
  • 宁乡市:No.359(8/30→7/30)
  • 天心区:No.407(8/10→8/18)、No.414(7/5→7/15, 8/25→8/30)、No.415(8/30→8/16)、No.416(7/7→7/11, 8/8→8/28)
  • 望城区:No.418(8/29→8/25)
  • 芙蓉区:No.441(8/29→8/25)、No.442(8/14→8/20)、No.443-446(7/8→7/11)、No.447(7/8→7/5)、No.448(7/6→7/5, 8/6→8/4)、No.449(7/7→7/1)、No.450(7/1→7/12)、No.451(7/10→7/12)、No.453(7/6→7/4)

全部 455 条记录的 startDate/endDate 已按图片中的实际日期范围重新核对;venues 数组按图片中顿号/逗号分隔,保留了"(室外)"、"(室内)"等括号备注。原图中带有分段备注的日期(如"逢周日闭馆"、"工作日"等)因已拆分为 startDate/endDate,备注信息未保留在 JSON 中,但整体时间跨度已取最早/最晚日期。本轮校正消耗积分 304 个,耗时约 28 分钟。

集成腾讯地图 Skill 落地经纬度

数据纠错清洗完成后,所有校园数据仍只停留在文本地址层面,无法直接用于地图展示、区域检索、距离测算。为此,基于 CodeBuddy 集成腾讯地图 Skill,把文本地址自动转换成精准经纬度,完成校园位置信息的地理数字化。

需求拆解

集成目标很明确:基于清洗后的长沙开放学校标准化地址,批量、精准地获取每所学校经纬度坐标。它要同时满足三件实事:

  • 高精度定位:规避普通地址解析的模糊定位,精准匹配校园正门坐标;
  • 批量处理:支持数十所学校地址批量转换,适配批量数据场景;
  • 无缝集成:依托 CodeBuddy 原生 Skill 能力,无需额外部署第三方 SDK,压低开发成本。

传统地址转经纬度依赖第三方 API 手动调用、参数拼接,开发繁琐且容错率低。CodeBuddy 官方适配的腾讯地图 Skill 基于 MCP 协议封装,原生支持地址解析、经纬度获取、地图点位渲染,开箱即用,正好契合本项目。

接入步骤

CodeBuddy 全面支持腾讯位置服务 Skill 扩展,通过技能导入与 Key 配置即可快速启用,具体步骤如下:

步骤 1:获取腾讯地图开发 Key

登录腾讯位置服务控制台,创建 Web 端应用,拿到专属 Key 与密钥用于接口权限校验,这是 Skill 调用的核心凭证。

步骤 2:下载并导入腾讯地图 Skill

前往腾讯位置服务 Skill 官方仓库,下载 tencentmap-jsapi-gl-skill 技能包,解压后在 CodeBuddy IDE 中点击「技能-导入 Skill 文件夹」,选中解压目录完成导入;也可通过软链接把技能包放进 CodeBuddy 全局技能目录实现全局生效。

步骤 3:配置 MCP 服务与 Key

在 CodeBuddy MCP 配置界面编辑 mcp.json,添加腾讯地图服务配置并绑定个人开发 Key,重启技能服务后即可启用经纬度定位能力:

{
  "mcpServers": {
    "tencent-map": {
      "url": ""
    }
  }
}

步骤 4:验证 Skill 可用性

在 CodeBuddy 对话窗口输入指令:

@skill:tencentmap-lbs-skill 请调用腾讯地图的服务,
将changsha_schools_sports_2026.json 中的schoolName进行位置检索,
返回对应的经纬度值,并添加到对应的json中。

批量位置转换

Skill 配置妥当后,基于清洗后的标准化学校地址,编写批量经纬度转换代码,调用腾讯地图 Skill 能力实现地址一键转坐标:

import urllib.request
import urllib.parse
import json
import time
import os

KEY = '你的腾讯地图Web端Key'
INPUT_FILE = 'changsha_schools_sports_2026.json'
OUTPUT_FILE = 'changsha_schools_sports_2026.json'

def geocode(address):
    """调用腾讯地图地理编码API,返回(lng, lat)或(None, None)"""
    url = f')}&key={KEY}'
    try:
        req = urllib.request.Request(url, headers={'User-Agent': 'Mozilla/5.0'})
        resp = urllib.request.urlopen(req, timeout=15).read().decode('utf-8')
        data = json.loads(resp)
        if data.get('status') == 0:
            loc = data.get('result', {}).get('location')
            if loc and 'lng' in loc and 'lat' in loc:
                return float(loc['lng']), float(loc['lat'])
        return None, None
    except Exception as e:
        return None, None

def clean_name(name):
    """去掉括号及其中内容,用于备选查询"""
    import re
    return re.sub(r'[((].*?[))]', '', name).strip()

def main():
    with open(INPUT_FILE, 'r', encoding='utf-8') as f:
        data = json.load(f)

    success = 0
    fail = 0
    failed_items = []

    total = len(data)
    for idx, item in enumerate(data):
        no = item.get('No.', idx + 1)
        name = item.get('schoolName', '')
        if not name:
            continue

        # 优先用原始名称查询
        lng, lat = geocode(name)

        # 如果失败,尝试去掉括号内容
        if lng is None:
            clean = clean_name(name)
            if clean and clean != name:
                lng, lat = geocode(clean)

        # 如果还失败,尝试加"长沙市"前缀(针对区县级学校)
        if lng is None and not name.startswith('长沙市'):
            lng, lat = geocode('长沙市' + name)

        if lng is not None:
            item['longitude'] = lng
            item['latitude'] = lat
            success += 1
        else:
            fail += 1
            failed_items.append((no, name))

        # 每10条打印一次进度
        if (idx + 1) % 10 == 0 or idx == total - 1:
            print(f'进度: {idx + 1}/{total}, 成功: {success}, 失败: {fail}')

        # 控制请求频率,避免限流
        time.sleep(0.15)

    # 写回JSON
    with open(OUTPUT_FILE, 'w', encoding='utf-8') as f:
        json.dump(data, f, ensure_ascii=False, indent=2)

    print(f'\n处理完成!总计: {total}, 成功: {success}, 失败: {fail}')
    if failed_items:
        print('\n失败的条目:')
        for no, name in failed_items:
            print(f'  No.{no}: {name}')

if __name__ == '__main__':
    main()

代码执行后,每所开放学校都匹配到了精准经纬度坐标,同时返回定位精度参数,能够区分精准定位与模糊定位数据,为后续地图展示、区域筛选、便民查询功能提供可靠的 LBS 数据支撑。最终在 json 结果中,位置信息已成功获取并写回原始文件。

小结

面向暑期学校开放信息图文解析的偏差问题,这套 CodeBuddy 多模型交叉校验 + 腾讯地图 Skill 精准定位的方案,切中了单一图文大模型解析不准、垂直场景容错率低、文本地址无法地理数字化的三个核心痛点。

在数据纠错层面,依托 CodeBuddy 多模型并行推理,通过 GLM 与 Kimi 双模型交叉比对,实现学校基础信息与开放时间的自动化校验纠错,大幅压低人工核验成本,守住校园开放数据的准确性与规范性。在位置数字化层面,轻量化集成腾讯地图原生 Skill,无需复杂开发即可批量完成地址转经纬度,为便民查询系统、校园开放地图展示、区域公共服务分析提供可靠数据底座。

整套方案轻量、可复用、易拓展,既能服务校园开放数据处理,也可迁移到政务公示信息解析、公共服务点位校准、图文结构化数据纠错等垂直场景,为开发者化解模型输出偏差、快速落地 LBS 位置服务提供了可借鉴的实操路径。后续还可叠加多轮迭代校验、异常数据自动复盘、地图点位可视化渲染等能力,把数据处理的自动化与智能化再推一步。

0

评论0

请先
显示验证码
没有账号?注册  忘记密码?