
开篇先聊一个现象当我们在中文互联网上问“从北京到上海走陆路和走水路哪个更绕”大部分大模型都能答对可如果换成一门资源稀少的小语种再配合“跨海输油管道走向”“时区与经度换算”这类需要地图协作的问题模型的推理能力会迅速崩盘。原因很简单主流评估集几乎被英文和西方地理覆盖模型的地理常识与多语言推理能力没有得到公平、系统的检验。这也正是 MultiGlobeQA 这类基准要解决的问题。本文将围绕 MultiGlobeQA 展开先拆解它作为多语言、全球多样性地理空间推理基准的设计思路再给出可直接落地的评估框架、数据构建方法和结果统计代码。适合正在做大模型评测、多语言 NLP、地理知识增强的开发者阅读。读完你可以独立搭建一套小型的多语言地理空间推理评测管道也能把 MultiGlobeQA 的评测思想迁移到自己的业务场景中。1. 背景为什么需要 MultiGlobeQA 这样的基准1.1 现有基准的“地理偏见”与“语言偏见”过去几年大模型评测基准层出不穷从常识问答到数学推理、代码生成、Agent 任务都有覆盖。但仔细看会发现两个明显短板。第一个短板是地理覆盖不均。许多基准题目默认以北美和欧洲为背景比如地名、时区、气候、货币、交通网络都围绕少数国家展开。模型只要记住“华盛顿是首都”“伦敦在泰晤士河畔”这类高频知识就能在评测中拿到不错分数但对非洲、东南亚、南美、大洋洲等地区的地理结构了解很少。第二个短板是语言覆盖不足。即便某些基准声称支持多语言实际题目也经常是英文题目的机器翻译版本而不是基于本地地理语境重新设计的题目。翻译题目会引入词汇泄漏、文化偏差和事实不一致问题。举个例子把“Which state is Lagos located in?”直接翻译成中文或日语并不会让模型真正理解奈及利亚的地理层级反而可能因训练数据中该语言的语料稀少而测出虚假的“语言能力差”。1.2 地理空间推理到底是什么地理空间推理不等于地名问答。它至少包含以下能力地理事实记忆知道国家、首都、河流、山脉、岛屿的位置与关系。空间关系判断能判断“A 在 B 的哪个方向”“C 是否与 D 接壤”。距离与路径估算结合经纬度、交通方式、地形条件推断距离或路线。环境与气候推断根据地理位置推断气候带、植被、时区、自然灾害风险。多源信息综合把地图、文本、常识和个人经验结合起来回答开放问题。MultiGlobeQA 这类基准的价值就是把这些能力拆成可量化、可对比的题目同时要求模型在多种语言下拥有稳定的表现而不是依赖语言模板或地名联想。1.3 为什么大模型评测会长期依赖 Benchmark不管是 Meta 的 Nemotron 系列评测、Harvey AI Agent Benchmark还是各种 USB Flash Benchmark本质上都做同一件事把不可直接观测的模型能力压缩成一组可重复、可计分的任务。评测基准的意义在于提供横向对比基准不同模型能在同一组题目上比出差距。暴露模型短板为训练数据筛选和模型对齐提供方向。驱动迭代每次榜单更新都是对“最强模型”定义的重写。但基准也有局限。如果题目本身存在语言偏见、地理偏见、信息泄漏榜单分数就会失真。MultiGlobeQA 的定位就是针对这些局限做一次系统性修正。2. MultiGlobeQA 的核心设计思路2.1 多语言不只是翻译而是“语言本地化”MultiGlobeQA 在题目构建上强调语言本地化而不是简单翻译。简单翻译的问题是题目会残留源语言的语序、命名习惯和背景知识导致模型通过模式匹配而不是真正推理来作答。语言本地化要求题目在目标语言中自然成立地名、行政区划、文化常识都要符合该语言使用者的认知方式。例如同样考察“判断一个非洲国家是否跨赤道”英文题可能写“Which country in Africa is crossed by the Equator?”本地化后的斯瓦希里语或豪萨语版本会使用更贴近当地表述习惯的说法而不是把英文逐词翻译。这种设计带来的直接效果是评估更公平。模型是否答对取决于它是否真正理解目标语言里的地理知识而不是能否从英文翻译痕迹中猜到答案。2.2 全球多样性从“西方中心”到“全球分布”所谓全球多样性指的是题目覆盖的国家、地区、地貌类型、语系都应当尽量均衡。一个理想的多语言地理空间推理基准至少包含不同大洲的主要国家与次区域。多种地理特征河流、山脉、沙漠、岛屿、海峡、湖泊、城市群。不同类型的地理问题定位、关系、路径、时区、气候、行政区划。多语言来源的原生题目而不是同一批英文题目的多语言影子。这种多样性提升了评测的难度也让模型无法依靠“背地图册上最常见条目”来得分。2.3 题型的层次划分从推理深度来看地理空间推理题目可以分成三个层次。第一层是事实检索例如“巴西的首都是什么”。这种题只需要记忆。第二层是关系推理例如“智利与阿根廷的国界线主要由什么山脉构成”。这种题需要把多个地理事实关联起来。第三层是复合推理例如“如果一个从开罗出发的航班向东飞行跨越 5 个时区后抵达某城市那么到达时当地时间可能是几点”。这种题需要组合距离、方向、时区、政治边界等多种知识。MultiGlobeQA 这类基准通常覆盖以上多个层次。评测模型时不能只统计总体正确率还要按题型和语言分别分析。3. 如何理解和使用 MultiGlobeQA 数据集3.1 数据集的典型结构虽然没有官方固定 API但一个多语言地理空间推理数据集通常以 JSON 或 JSONL 形式组织。每条样本一般包含以下字段。{ id: mgqa_swa_0012, language: sw, question: Je! ni mji gani ulio mashariki mwa Ziwa Victoria?, options: [Kisumu, Kampala, Mwanza, Entebbe], answer: Kisumu, answer_index: 0, question_type: spatial_relation, region: East Africa, source: localized_original }字段含义id样本唯一标识。languageISO 639-1 语言代码。question题目文本。options候选选项。answer标准答案。answer_index正确选项下标方便评分。question_type题目类型如fact_retrieval、spatial_relation、path_distance。region题目所属地理区域。source题目来源区分原创题目与翻译题目便于分析标记。3.2 读取数据的 Python 示例实际使用时用 Python 读取 JSONL 文件是最常见的做法。import json from pathlib import Path from typing import Dict, List def load_multiglobeqa(file_path: str) - List[Dict]: 读取 JSONL 格式的 MultiGlobeQA 数据。 samples [] with Path(file_path).open(r, encodingutf-8) as f: for line in f: line line.strip() if not line: continue samples.append(json.loads(line)) return samples def filter_by_language(samples: List[Dict], language: str) - List[Dict]: 按语言过滤样本。 return [s for s in samples if s.get(language) language] def filter_by_type(samples: List[Dict], question_type: str) - List[Dict]: 按题型过滤样本。 return [s for s in samples if s.get(question_type) question_type] if __name__ __main__: data load_multiglobeqa(multiglobeqa_dev.jsonl) swahili_samples filter_by_language(data, sw) spatial_samples filter_by_type(data, spatial_relation) print(f总样本数: {len(data)}) print(f斯瓦希里语样本数: {len(swahili_samples)}) print(f空间关系题型样本数: {len(spatial_samples)})这里需要注意不同版本的基准字段可能有差异实际使用时先打印一条样本确认字段名再写加载逻辑。4. 搭建一套多语言地理空间推理评测管道4.1 评测流程总览一次完整的评测包含五个步骤加载数据集。根据语言和题型构建 Prompt。调用模型接口获取回答。解析模型输出并判分。按语言、题型、地区维度汇总结果。下面我们用 Python 写一套可运行的迷你评测框架。示例使用 OpenAI 兼容接口但核心逻辑对任何模型都通用。4.2 构建 Prompt多语言地理空间推理题目需要使用模型能理解的语言指令。常见做法是如果模型是英文为主可以把系统提示词写成英文题目保留原始语言并允许模型输出英文答案。如果模型是多语言模型系统提示词和题目都可以使用目标语言。SYSTEM_PROMPT You are a geospatial reasoning assistant. Answer the multiple-choice question based on your knowledge. Output only the option letter and the answer text, separated by a dot. Example: A. Nairobi def build_prompt(sample: Dict) - str: options sample[options] option_text \n.join(f{chr(65 i)}. {opt} for i, opt in enumerate(options)) prompt fQuestion: {sample[question]}\n{option_text}\nAnswer: return prompt这里通过chr(65 i)把选项下标转为 A、B、C、D便于模型输出稳定的格式也方便后续解析。4.3 调用模型接口示例使用openai库的 OpenAI 兼容模式其他模型服务只要兼容/chat/completions接口都可以替换。from openai import OpenAI class GeoSpatialEvaluator: def __init__(self, base_url: str, api_key: str, model: str): self.client OpenAI(base_urlbase_url, api_keyapi_key) self.model model def predict(self, prompt: str, language: str) - str: response self.client.chat.completions.create( modelself.model, messages[ {role: system, content: SYSTEM_PROMPT}, {role: user, content: prompt}, ], temperature0.0, max_tokens128, ) return response.choices[0].message.content.strip()温度设为 0.0 是为了提高可复现性。地理空间推理评测希望答案稳定不需要创造性和随机性。4.4 答案解析与判分模型输出可能是A. Kisumu、A、Kisumu或混合格式。解析时要尽量兼容多种写法。保守做法是优先匹配选项文本再匹配选项字母。import re from typing import Optional def normalize_answer_text(text: str) - str: return re.sub(r[\s.,!?;:]$, , text.strip()).lower() def parse_prediction(raw_output: str, options: List[str]) - Optional[int]: 从模型输出中解析出选项下标。 raw_output raw_output.strip() # 匹配 A. Kisumu / A: Kisumu / A 等格式 letter_match re.match(r^([A-D])[.:、]?\s*(.*)$, raw_output, re.IGNORECASE) if letter_match: letter letter_match.group(1).upper() option_index ord(letter) - ord(A) if 0 option_index len(options): return option_index return None # 匹配直接输出答案文本 normalized normalize_answer_text(raw_output) for idx, opt in enumerate(options): if normalize_answer_text(opt) normalized: return idx return None def score_sample(sample: Dict, raw_output: str) - bool: pred_idx parse_prediction(raw_output, sample[options]) if pred_idx is None: return False return pred_idx sample[answer_index]解析逻辑不追求覆盖所有输出格式而是用稳定格式A. 答案做默认遇到非标格式则尝试文本匹配。这样在大多数模型上都能获得较高的解析成功率。4.5 批量评测与结果汇总批量评测时建议加入失败重试和错误日志避免网络抖动导致整体任务中断。import json import logging import time from collections import defaultdict from typing import Dict, List logging.basicConfig(levellogging.INFO) def run_evaluation( evaluator: GeoSpatialEvaluator, samples: List[Dict], max_retries: int 3, sleep_seconds: float 1.0, ) - Dict[str, object]: results defaultdict(lambda: {correct: 0, total: 0, failures: 0}) detail [] for sample in samples: prompt build_prompt(sample) lang sample[language] qtype sample[question_type] region sample.get(region, unknown) keys [(all,), (lang, lang), (type, qtype), (region, region)] try: raw_output evaluator.predict(prompt, lang) is_correct score_sample(sample, raw_output) except Exception as e: logging.warning(fSample {sample[id]} failed: {e}) raw_output is_correct False for key_tuple in keys: results[key_tuple][failures] 1 for key_tuple in keys: results[key_tuple][total] 1 if is_correct: results[key_tuple][correct] 1 detail.append({ id: sample[id], language: lang, question_type: qtype, region: region, prediction: raw_output, correct: is_correct, }) time.sleep(sleep_seconds) summary {} for key_tuple, value in results.items(): acc value[correct] / value[total] if value[total] else 0.0 summary[ / .join(key_tuple)] { accuracy: round(acc, 4), correct: value[correct], total: value[total], failures: value[failures], } return {summary: summary, detail: detail}sleep_seconds参数用于控制请求频率避免触发 API 限流。实际生产环境可改为指数退避重试。4.6 主程序入口把上面几个模块串起来主程序只需要加载数据、创建评测器、执行评测、保存结果。def main(): data_path multiglobeqa_dev.jsonl output_path eval_result.json model your-model-name base_url https://api.openai.com/v1 api_key your-api-key samples load_multiglobeqa(data_path) logging.info(fLoaded {len(samples)} samples) evaluator GeoSpatialEvaluator(base_urlbase_url, api_keyapi_key, modelmodel) result run_evaluation(evaluator, samples, max_retries3, sleep_seconds0.5) with open(output_path, w, encodingutf-8) as f: json.dump(result, f, ensure_asciiFalse, indent2) for group, metric in result[summary].items(): print(f{group}: accuracy{metric[accuracy]}, correct{metric[correct]}/{metric[total]}) if __name__ __main__: main()4.7 预期运行效果运行完成后控制台会输出如下格式的结果。all: accuracy0.6234, correct6234/10000 lang / en: accuracy0.7211, correct723/1002 lang / sw: accuracy0.3894, correct375/963 type / spatial_relation: accuracy0.5421, correct1801/3322 region / East Africa: accuracy0.4310, correct441/1023这些数字说明什么如果某个模型在英文题上准确率明显高于其他语言说明它的多语言地理泛化能力不足如果空间关系题得分低而事实检索题得分高说明模型记住了知识但推理能力弱。5. 多语言地理空间推理评测的常见问题与排查5.1 模型输出格式不稳定导致解析失败问题现象常见原因解决思路大量样本被判错但人眼检查模型输出正确模型输出格式不符合预期增加解析规则先匹配答案文本再匹配选项字母输出附带解释文字导致文本匹配失败模型没有严格按指令输出在解析前截取首个选项字母所在行或只取第一段小语种输出包含特殊字符编码或分词问题统一使用 UTF-8并做字符归一化改进解析的示例def parse_prediction_v2(raw_output: str, options: List[str]) - Optional[int]: # 取第一行作为候选答案 first_line raw_output.strip().split(\n)[0] return parse_prediction(first_line, options)5.2 多语言题目下模型“答非所问”模型把题目理解成翻译任务或者输出“我不确定”等回避性回答。这种情况在低资源语言上尤其明显。解决思路包括将系统提示词改为目标语言降低模型对“必须翻译”的误解。在 Prompt 中明确说明“这是地理知识题不是翻译题”。在解析阶段把回避性回答标记为错误同时统计“拒答率”辅助分析模型能力边界。def is_refusal(raw_output: str) - bool: refusal_words [sorry, cannot, i dont know, 不确定, わかりません] return any(word in raw_output.lower() for word in refusal_words)5.3 同一模型在不同机器上评测结果不一致主要原因是模型接口的非确定性、批量并发和浮点数计算差异。建议固定temperature0.0。固定随机种子。每次评测后保存原始输出方便复盘。对大样本进行分组并行时保证每个样本独立评估。5.4 数据集中答案与选项存在重复个别低质量数据可能存在两个选项都正确的歧义题。遇到这种情况不要强行判错应该在数据分析阶段筛掉或者标记为争议样本。可以在加载数据时做一次简单去重和校验。def validate_samples(samples: List[Dict]) - List[Dict]: valid [] seen_ids set() for sample in samples: if sample[id] in seen_ids: continue if sample[answer_index] len(sample[options]): continue seen_ids.add(sample[id]) valid.append(sample) return valid6. 自建多语言地理空间推理评测集的工程建议6.1 题目设计要控制变量在设计新题目时尽量控制变量。比如想测“空间方位推理”就不要在题干里加入需要专业地理知识才能看懂的词汇。一道题只测一种核心能力这样结果归因才清晰。可以用下面的模板来设计题目核心能力空间关系判断 目标语言Swahili 题目Ni mji gani uko kaskazini mwa Nairobi? 选项Kisumu, Mombasa, Nakuru, Arusha 正确答案Nakuru如果题目同时涉及“北方向”和“国家边界”那么错题后不清楚模型到底错在哪一环。6.2 构建双语对照验证集为了让结果更可解释建议为每道题保留一个英文参考版本但英文版本只作为对照不计入多语言排名。这样做有三个好处能区分“语言理解缺陷”和“地理知识缺陷”。能用于检查翻译类题目是否存在信息泄漏。能统一用英文做答案校验降低答案歧义。基础数据结构可以扩展为{ id: mgqa_swa_0012, language: sw, question: Ni mji gani uko mashariki mwa Ziwa Victoria?, question_en: Which city is located east of Lake Victoria?, options: [Kisumu, Kampala, Mwanza, Entebbe], answer: Kisumu, answer_index: 0 }6.3 评测报告必须包含分层指标一个合格的多语言地理评测报告至少要输出以下指标总体准确率。各语言准确率。各题型准确率。各区域准确率。拒答率与解析失败率。模型置信度分布如果接口提供 logprobs。分层指标能帮助你找到模型的薄弱区域。比如模型在南亚语言上准确率低可能不是推理能力差而是训练语料中该语言的地理文本太少。6.4 注意评测集污染问题大模型训练数据通常会抓取网页公开内容如果你的自定义评测集被发布到 GitHub 或公开网络模型可能在预训练阶段看到过答案导致评测结果虚高。降低污染风险的方式对私有评测集进行脱敏不在公开仓库上传完整数据。定期更换题目或选项顺序。使用动态生成题目代替静态题库。6.5 用日志方式记录评测过程生产级评测管道应该记录每一次请求的完整上下文而不是只保存最终分数。import logging logger logging.getLogger(eval) def log_sample(sample: Dict, raw_output: str, is_correct: bool): logger.info( json.dumps( { id: sample[id], question: sample[question], options: sample[options], answer_index: sample[answer_index], raw_output: raw_output, is_correct: is_correct, }, ensure_asciiFalse, ) )有了这些日志后续分析模型错误时就不用重新跑一遍整个评测。7. 最佳实践与评估边界7.1 不要把 Benchmark 分数当成完整能力画像MultiGlobeQA 这类基准擅长暴露模型在多语言地理空间推理上的差异但它不是衡量模型“是否聪明”的唯一标尺。一个模型可能在 MultiGlobeQA 上表现一般但在代码生成、数学推理上很强。评测报告应该注明测试范围避免读者错误泛化。7.2 控制评测成本与时间调大模型接口评测 1 万条样本时成本和时间都不可忽略。工程上可以做三步优化先跑 200 条小样本确认 Prompt 和解析逻辑没有问题再全量评测。对存在缓存机制的模型服务先做一轮确定性输出测试。对失败样本进行有限次重试而不是无限重试。def truncate_samples(samples: List[Dict], max_size: int 200) - List[Dict]: if len(samples) max_size: return samples return samples[:max_size]7.3 评估结果要区分“语言能力”和“地理知识”这是多语言地理空间评测最容易被误解的地方。如果一个模型在斯瓦希里语题目上准确率很低不能直接说它“斯瓦希里语能力差”。可能是因为模型很少见斯瓦希里语地理文本。题目涉及非洲地理知识模型本来就不掌握。选项中有多个城市名模型产生词汇混淆。要区分这两者可以额外设计一组“地理常识无关的语言理解题”比如把地理题改成简单的日常问答用同样的语言测试模型的基础语言能力。这样多语言地理基准和基础语言能力基准就能互相补充。7.4 注意模型输出中的“虚假自信”在大模型评测中模型可能用非常肯定的语气说出错误答案而且错误答案往往符合“看起来合理但实际错误”的规律。例如模型可能把“坦桑尼亚首都”答成“达累斯萨拉姆”而正确答案是多多马。达累斯萨拉姆确实是最大城市这类错误在人类评测中也有一定迷惑性。评测脚本不会判断语气但人工复盘时要特别关注这类“合理错误”它往往指向训练数据中的陈旧信息。7.5 把评测结果反馈到数据与训练环节评测的终点不是出榜单而是指导改进。拿到 MultiGlobeQA 的分层结果后可以按优先级执行对低准确率的语言追加该语言的地理语料。对低准确率的题型设计专项训练数据。对模型频繁出错的区域补充地理关系三元组。这种“评测—分析—补数据—再评测”的闭环才是 benchmark 的真正价值。如果你打算在业务里复刻这套评估思路可以从 200 条题目的微型数据集起步先跑通加载、预测、解析、汇总整条链路再逐步扩展到全量数据。相比一开始就追求庞大题库先把评测管道的稳定性和日志体系搭好后续迭代会轻松很多。