这次我们来看一篇大语言模型评测方向的研究。标题有点长,先翻译过来:Cultural Awareness is Represented but Not Decoded,意思是“文化意识在模型里存在,但模型不一定能把它解码出来”。副标题是 Tracking Mythological Knowledge across 18 Open-Source LLMs,即在 18 个开源大语言模型里,追踪它们对神话知识的掌握程度。
为什么选神话知识?因为神话是文化底层的浓缩体,里面有人物、事件、因果关系、器物、禁忌和象征,比普通百科问答更能暴露模型训练语料的偏差。这篇论文的核心问题不是“模型知不知道某个国家的神话”,而是更深一层:知识明明已经在权重里了,为什么提问方式一变、语言一换、上下文一改,模型就答不出来。
这个问题的研究价值很高,尤其对三类人非常有用:做多语言产品的人、做本地化功能的人、负责模型选型和 RAG 方案设计的工程师。看完这篇文章,你会理解“知识表示”和“知识解码”之间的差距,也能拿到一套自建神话知识评测集的思路,以及用 OpenAI 兼容接口批量跑多个开源模型的方法。
1. 研究核心信息速览
先把这篇研究的规格信息放在前面,方便快速判断它讨论了什么、需要什么环境、能得出什么结论。
| 项目 | 内容 |
|---|---|
| 研究类型 | 大语言模型知识评测与文化意识分析 |
| 评测对象 | 18 个开源大语言模型 |
| 评测内容 | 跨文化神话知识 |
| 核心命题 | 文化知识在模型权重中已经存在,但不一定能被正确解码 |
| 评测方式 | 用统一提示模板跑全部模型,汇总答案并对比正确率 |
| 硬件要求 | 需要 GPU,支持 CPU 小规模测试,按实际评测规模决定 |
| 接口要求 | 更推荐使用 OpenAI 兼容接口,便于批量调用 |
| 是否支持批量 | 支持,同一测试集可跑多个模型 |
| 适用读者 | LLM 研究者、多语言产品开发者、模型选型工程师 |
需要说明的是,输入材料中没有给出 18 个模型的具体名单,所以本文不会猜测具体模型。常见的开源系列包括 Qwen、Llama、Mistral、DeepSeek 等,实际选型以论文原文为准。拿同一套测试集在本地跑这些模型,就能复现类似的评测流程。
2. 为什么要拿“神话知识”来评测模型
2.1 神话知识的评测难度高于普通常识
先看一个问题:模型 A 知道“希腊神话的主神是宙斯”,模型 B 也知道,这能说明什么?什么也说明不了。因为这类知识点在互联网语料里出现频率很高,模型相当于背过答案。
真正的难点在于神话知识的多层结构。以“大禹治水”为例,单问“大禹是谁”和“大禹为什么能治水”是两个难度。更进一步,如果问“大禹治水与诺亚方舟中‘洪水叙事’有什么异同”,模型不仅要回忆两个文明的神话事实,还要理解其中不同的自然环境、神人关系和伦理逻辑。这种问题无法靠关键词匹配解决。
所以,神话知识是一个很好的评测载体。它能测试出模型是否真的理解了文化内部的逻辑,而不只是记住了几个名字。
2.2 神话知识能区分“语言能力”和“文化能力”
很多开源模型在中文、英文等语言任务上分数很高,但这只能说明它们的语言能力强。语言能力强不代表文化能力强。一个模型可能能流利地用中文解释“龙”这个词,但当你问“中国的龙和西方的 dragon 在象征意义上有什么本质区别”时,它很容易输出一套混杂的、甚至自相矛盾的答案。
这正是“文化意识”需要被单独评测的原因。日常对话里,文化差异是隐藏的,模型就算搞混了也能用通用词掩盖过去。但神话知识是具体且强相关的,文化搞错了,答案就是错的。研究标题里强调“神话知识”,本质上是在用高密度的文化信息测试模型的文化边界。
3. “表示”与“解码”的差距在哪里
3.1 什么是“表示”
在神经网络模型中,知识并不是像数据库那样存储的,而是以参数和分布式向量的形式存在。模型读了很多关于神话的语料之后,与神话相关的实体、关系和语义特征会被压缩到一组高维向量里。
“表示”这个层面的意思是:如果你去探测模型的内部向量,或者用一种特殊的提示方式去引导它,它是能表现出知道某些神话知识的。例如,用靠近训练语料的提问方式,模型很可能给出正确答案。这个时候我们认为,知识存在于模型的表示空间里。
3.2 什么是“解码”
“解码”指的是模型在推理时,把存储在权重里的知识转换成自然语言输出的过程。模型通过注意力机制和生成头,一步步预测下一个 token,最终把你要的答案写出来。
解码并不是一个直接查表的过程。同样的知识,只要提问的语言变了、选项的顺序变了、上下文加了额外信息,模型可能就走不到正确的输出路径上。这就是“表示但解码失败”的直观表现。
3.3 为什么会出现“表示但解码失败”
主要原因可以拆成三层。
第一层是训练目标和解码目标的错位。语言模型训练的核心任务是预测下一个 token,它并不专门优化“从知识库中精确检索某个事实”这个目标。训练阶段形成了“下一词概率高”的路径,但推理阶段用户追问的是“某条知识的精确答案”,这两个目标经常不一致。
第二层是分布式存储导致的路径依赖。知识不是存在一个独立的单元里,而是分散在很多参数中。模型需要正确的上下文激活某些路径,才能把分散的信息拼接起来。如果用户给出的上下文结构偏离训练分布,模型就很难完成内部的路径激活,最后只能输出一个模糊的、通用的答案。
第三层是提示语言与知识语言的错配。如果知识来自中文语料,但用户用英文提问,模型需要先完成一次内部翻译,再检索知识,再翻译回来。这个过程中每多一次转换,就多一分信息损失。跨语言评测下,“表示但解码失败”会更普遍。
4. 评测方法设计建议
如果你想参考这篇论文的思路,自建一套神话知识评测方案,可以把评估拆成三步:测试集、提示模板、评分方式。
4.1 测试集结构设计
不要只做单一题型,建议用四类任务,覆盖不同层面的文化知识:
- 选择题:给定四个选项,判断人物、事件、物品归属,适合批量统计准确率。
- 开放题:只给问题,不提供选项,考察模型从表示空间里自由提取知识的能力。
- 连线题:给出两组神话元素,要求模型判断是否匹配,考察关系记忆。
- 对比题:要求模型比较两个不同文化神话中的同类概念,考察深层推理。
同时,测试集要有明确的类别划分。例如:神话人物类、事件因果类、神物与象征类、仪式与禁忌类、跨文化比较类。每一类最好单独统计得分,这样能看出模型是在哪类知识上存在解码失败。
4.2 提示模板设计
提示模板不要只用一种,建议至少测试三种:
模板A(直接提问): 请回答下面关于神话知识的题目,只输出答案,不要解释。 问题:XXX 答案: 模板B(带选项提问): 请回答下面关于神话知识的题目,从给出的选项中选择最合适的一项,只输出选项字母。 问题:XXX 选项:A. XXX B. XXX C. XXX D. XXX 答案: 模板C(限定角色提问): 你是一位比较文化学研究者,请根据你掌握的神话知识回答下面的问题。 问题:XXX 答案:不同模板的得分差异,本身就是一个很有价值的观察维度。如果模型在模板 A 下得 30 分,在模板 C 下得 60 分,说明知识表示是存在的,但解码路径对提示结构非常敏感。这就是“表示但未解码”的直接证据。
4.3 评分方式
评分不要只看最终答案是否精确匹配,建议使用三级评分:
| 分数 | 标准 |
|---|---|
| 2 分 | 答案准确,信息无遗漏 |
| 1 分 | 答案方向正确,但存在部分错误或遗漏 |
| 0 分 | 答案错误,或输出“我不知道”等无效内容 |
对于开放题和对比题,建议用语义相似度辅助评分,但一定要加入人工抽检。大模型输出的文本经常结构完整但内容虚假,纯自动评分很容易给“看似合理但实际错误”的答案打高分。
5. 在 18 个开源 LLM 上跑评测的脚本
下面给出一套完整示例,采用 OpenAI 兼容接口,大多数本地推理框架都支持,包括 vLLM、Ollama 等。如果你的推理服务不是 OpenAI 兼容协议,需要按实际接口调整。
5.1 准备测试集文件
建议使用 JSONL 格式,一行一个题目:
{"id": "greek_001", "question": "宙斯的兄弟波塞冬掌管哪个领域?", "options": ["天空", "海洋", "冥界", "大地"], "answer": "B", "category": "人物关系"} {"id": "chinese_001", "question": "在“大禹治水”的传说中,禹主要通过哪种方式治理洪水?", "options": ["筑堤堵水", "疏浚河道", "建塔镇水", "求神赐雨"], "answer": "B", "category": "事件因果"} {"id": "norse_001", "question": "北欧神话中,奥丁为了获取智慧付出了一只眼睛,他换取的是什么?", "options": ["命运之力", "智慧之泉的智慧", "雷神之锤", "世界树的果实"], "answer": "B", "category": "事件因果"}5.2 编写评测脚本
保存为eval_cultural_knowledge.py,核心逻辑是读取 JSONL,逐题请求模型,拿到答案后与正确答案对比。
import json import argparse from openai import OpenAI def run_question(client, model, q, temperature=0.1): options_text = " ".join( f"{chr(ord('A') + i)}. {opt}" for i, opt in enumerate(q["options"]) ) prompt = ( "请回答下面关于神话知识的题目,只输出选项字母,不要解释。\n" f"问题:{q['question']}\n" f"选项:{options_text}\n" "答案:" ) resp = client.chat.completions.create( model=model, messages=[{"role": "user", "content": prompt}], temperature=temperature, max_tokens=16, ) return resp.choices[0].message.content.strip() def evaluate(data, base_url, api_key, model, output_path): client = OpenAI(base_url=base_url, api_key=api_key) results = [] total = 0 correct = 0 for q in data: pred = run_question(client, model, q) answer_letter = pred[0].upper() if pred else "" exact = answer_letter == q["answer"] total += 1 correct += int(exact) results.append({ "id": q["id"], "category": q["category"], "pred": pred, "expected": q["answer"], "correct": exact, }) print(f"{q['id']} | pred={pred} | expected={q['answer']} | {'OK' if exact else 'FAIL'}") accuracy = correct / total if total else 0 print(f"\n模型 {model} 准确率: {accuracy:.2%} ({correct}/{total})") with open(output_path, "w", encoding="utf-8") as f: json.dump({ "model": model, "total": total, "correct": correct, "accuracy": accuracy, "details": results, }, f, ensure_ascii=False, indent=2) if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument("--model", required=True, help="模型名称") parser.add_argument("--base-url", default="http://127.0.0.1:8000/v1", help="推理服务地址") parser.add_argument("--api-key", default="EMPTY", help="API Key") parser.add_argument("--questions", default="questions.jsonl", help="测试集路径") parser.add_argument("--output", default="eval_result.json", help="结果输出路径") args = parser.parse_args() with open(args.questions, encoding="utf-8") as f: data = [json.loads(line) for line in f if line.strip()] evaluate(data, args.base_url, args.api_key, args.model, args.output)这个脚本会逐题输出预测结果,最后统计准确率,并把完整结果写入 JSON。这样不仅能看总分,还能按category字段分析每个知识类别的得分情况。
5.3 批量执行多个模型
有了单个模型的评测脚本,批量跑 18 个模型就很容易了。写一个 for 循环,把模型名换成你要测的列表:
for model_name in qwen2.5:7b llama3.1:8b mistral:7b deepseek-r1:7b; do echo "==============================" echo "Evaluating: $model_name" echo "==============================" python eval_cultural_knowledge.py \ --model "$model_name" \ --output "result_${model_name//:/_}.json" done注意:如果你的推理服务使用的是自定义模型名,请把$model_name替换成你在服务端配置的名称。另外,18 个模型并行跑会占用大量显存,建议根据 GPU 总量分批处理,一次跑 3 到 4 个模型,结果会更稳定。
6. 资源占用与性能观察
评测 18 个开源 LLM 不是一件轻松的事,资源占用量取决于模型尺寸、输入长度和并发数。理论上有两条路线:本地 GPU 推理和云端 API 推理。
如果是本地 GPU 推理,重点观察两个指标:显存占用和推理吞吐。显存直接决定单卡能跑多大的模型。7B 级别模型在 FP16 下大约需要 14GB 显存,如果量化到 4bit 能压到 6GB 左右。更简单的方式是直接看推理服务启动时的提示信息,不同负载框架会打印显存占用。
运行过程中,用下面的命令动态观察显存:
nvidia-smi --query-gpu=name,memory.total,memory.used,memory.free,utilization.gpu --format=csv -l 5每 5 秒刷新一次,重点关注memory.used和utilization.gpu。如果显存占用稳定在 95% 以上且利用率很高,说明模型正在满负荷推理;如果利用率低于 20%,可能是批处理逻辑有问题或者输入输出长度过短。
批量评测场景下,温度的设置也会影响性能测试的稳定性。建议把温度固定在 0.1,关闭随机性,这样同一个模型在相同题目上输出可复现,也更容易定位推理框架的问题。如果对生成长度没有特殊需求,max_tokens设置得越短越好,这样能有效降低单请求延迟。
如果本地 GPU 资源紧张,可以用 CPU 推理跑小型模型。但要注意,CPU 上跑 7B 模型的延迟可能是 GPU 的几十倍,评测集如果很大,耗时非常夸张。如果模型名以“8B”“14B”结尾,而显存不足,优先考虑量化版本或换云 GPU,不要直接硬撑。
7. 评测结果能指导什么
“表示但解码失败”这个现象如果被充分验证,对实际工程有四个直接启发。
第一个启发是提示词工程不是玄学。模型在模板 A 下答错,在模板 C 下答对,这种现象用同一个模型也能复现。这说明“提示词对结果影响巨大”不是偶然,而是模型知识检索路径对上下文结构的依赖。面向用户的产品里,设计提示词时不要只考虑“能不能答”,还要考虑“换一种问法之后是否依然稳定”。
第二个启发是模型选型要多看文化维度。很多企业选模型只看通用 benchmark,这会导致产品里出现奇怪的文化错位。用一套小规模的神话知识测试集,哪怕是 50 道题,就能快速筛选出哪些模型在你的目标文化场景里表现稳定。这个做法比看通用分数更有指导意义。
第三个启发是 RAG 系统不能完全替代模型的文化知识。RAG 能召回文档片段,但如果模型本身无法把召回内容与文化背景结合,答出来的内容依然可能是生硬的拼接。在做知识库问答时,不要假设“召回对了就万事大吉”,还需要对生成结果做文化校验。
第四个启发是做人机协同接口时要预留人工复核机制。如果模型被评测为“知识存在但解码不稳定”,那在实际产品里就必须加入兜底逻辑。当模型答案不确定时,不要强行给一个看似合理的答案,而是返回“建议人工确认”或触发二次检索。
8. 常见问题与排查方法
自己跑文化知识评测时,很容易遇到下面几个问题。
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| 所有模型全部得 0 分 | 测试集格式错误或提示模板无法触发模型回答 | 打印一条原始请求和响应,人工检查 | 调整提示模板,加入“请直接选择”等约束 |
| 模型答案总是无效文本 | max_tokens太小,答案被截断 | 查看完整输出,确认是否包含完整选项字母 | 调大max_tokens,或改用输出解析逻辑 |
| 同一模型不同时间结果不一致 | 温度设置过高 | 检查温度参数和随机种子 | 把温度降到 0.1,必要时设置 seed |
| 显存不足导致推理中断 | 并行模型过多或单模型过大 | 用nvidia-smi查看显存占用 | 减少并发模型数,使用量化版本 |
| 请求超时 | 模型推理速度慢或并发过高 | 查看服务端日志,观察平均延迟 | 增大超时时间,降低请求并发数 |
| 输出结果全是“A”或固定项 | 模型未真正解析题目,输出发生了坍缩 | 查看不同模板下的输出差异 | 更换模板,加入思考要求或拆分子问题 |
| 测试集本身包含错误答案 | 评测集未经过人工校验 | 随机抽 20 条人工复核 | 重新校对测试集,避免错误标签污染结论 |
| 不同模型之间分数差异极小 | 题目太难或太简单,没有区分度 | 统计每道题的正确率 | 筛选正确率在 30%-80% 之间的题目作为有效评测项 |
如果你在跑大规模评测时发现分数忽高忽低,优先检查提示模板和输出解析逻辑。这两个环节出问题的概率远高于模型本身。
9. 合规与安全边界
评测神话知识时,要注意几个边界问题。
第一,神话知识不等于宗教评价。很多神话体系与某些地区的历史文化、民间信仰强关联,评测中应保持学术中性和文化尊重,不要把神话人物或典故用于贬低、戏谑某个民族或宗教群体。
第二,测试集不能包含过度敏感的内容。本地部署评测时,如果测试集涉及特定民族、传统习俗、神话传说,不要使用带有诋毁性、歧视性表述的题目,也不要将虚构神话与现实政治建立映射。
第三,如果评测的是从网络收集的文本,需要注意数据来源的版权要求。神话故事本身很多属于公共领域,但现代改写版本、翻译文本可能受版权保护。自建评测集时建议优先使用公共领域的经典文本,不直接批量下载商业电子书或受限数据库中的全文。
第四,调用外部模型 API 进行评测时,不要把未脱敏的内部业务数据放进测试集。神话知识测试本身通常不涉及隐私,但如果你把用户生成内容混入测试集,就必须遵循数据最小化原则,提前做匿名化处理。
第五,标注“模型存在文化知识但解码失败”不等于“模型具备某种文化立场”。评测结果只能说明模型在特定提示下能否输出特定知识点,不适合据此下结论说某个模型“天然偏向某种文化”,更不能用这种结论去制造对特定模型或地区的刻板印象。
10. 最佳实践与后续方向
如果你打算把神话知识评测纳入模型评估体系,推荐按下面的顺序落地。
第一,先建一个 50 到 100 题的迷你测试集。覆盖人物、事件、物品、跨文化比较四个类别,每类不少于 10 题,先拿两三个模型试跑一遍,确认题目的区分度和提示模板的稳定性。第一轮不要追求 18 个模型,先把流程跑通。
第二,记录每个模型在不同提示模板下的表现差异。这个差异本身就是评估报告的重要部分。如果某个模型直接提问得分低、限定角色后得分高,说明它的解码路径比较窄,需要靠强提示词才能激活知识区域。
第三,把评测脚本接入 CI 或定期评估流程。每次升级模型版本、切换推理框架、调整量化参数时,都跑一遍同一套测试集。这样能及时发现“模型变强了,但文化知识反倒没法解出来了”的回归问题。
后面如果想继续深入,可以往三个方向扩展:跨语言评测,用同一道题的多种语言版本测试模型;文化纠偏训练,在模型输出后进行文化合规校验;以及解码策略优化,比如用多轮追问或思维链方式提升知识检索成功率。
这套方法论不只能用于神话知识,中医概念、地域民俗、历史典故都可以按同样思路做成评测集。评测的目的不是给模型排名,而是搞清楚模型的知识边界在哪里,哪些场景需要提示词强行拉回,哪些场景必须交给 RAG 或人工兜底。先把“表示但解码失败”这个问题测量出来,后续的优化才有依据。