基于知识库(RAG)系统打造由大模型(LLM)驱动NPC游戏的技术设想

基于知识库(RAG)系统打造由大模型(LLM)驱动NPC游戏的技术设想

核心玩法设想

最近一段时间有了一个想法------让大模型来驱动游戏里的NPC,让NPC活过来。这个点子并不是我首创,但是目前真正应用到实际游戏的,好像还真不多。我本以为不复杂,没想到随着研究的深入,复杂度已经超出了我的预期,这也解释了为什么,目前该技术没有大量应用到实际游戏了。

有个斯坦福小镇的开源项目,非常有借鉴意义,但他并不能让玩家参与其中,只能通过上帝视角观察AI小人的心路历程,挺有意思,但我觉得他并不是真正意义上的游戏,这个我在后面会详细分析。

这段时间利用业务时间,进行了大量的研究。不得不说,大模型是真的好,你只要有点子,他就能帮你干很多大量的工作,而且他还会给你建议,帮你避坑。写到这里,我就很想吐槽一下:国内的几个大模型,如果说在玩个梗、写个作文、讲个笑话、常规聊天方面,我觉得都非常优秀,主打一个亲情陪伴,但是你要是让他整个数学推导,写个代码,搞个算法,除了DeepSeek在及格线上挣扎以外,真的是没一个能打的。有条件还是得试试gemini和claude,grok也不错。当然,最关键的还是通过大模型来实现自己的学习,以前学个东西,得泡论坛,去找大牛问,论坛里呢,简单的问题大家抢着回答,个个显得很牛*,复杂的问题又都装死,所以,一个靠谱的大模型,真的能给你的学习带来很大的效率提升。

言归正传,我的想法核心是使用大模型驱动游戏中的NPC,不仅仅是对话,还要做出行动决策,这其实非常复杂。

斯坦福小镇项目分析

源码分析

斯坦福大学和谷歌合作的项目,他的基本原理是,基于RAG系统构建NPC的记忆体系,描述NPC周边的环境,让NPC做出决策,然后产生记忆,存入NPC的记忆系统,从而影响下一步的行动,如此产生闭环。比如发给大模型一个请求:"你是张三,你刚刚起床,精力充沛,但感觉有点饿,你现在身边有床、有电话、有炉灶,请选择选择一个地点,并且简要说明你要做什么",然后大模型会根据常理,做出选择,比如:"炉灶:去做点吃的"、"电话:打给李四告诉他xxx事"。当然,这只是一个粗略的原理描述,真实情况远比这些要复杂。当游戏端收到大模型的决策后,根据那个物品/地点,检索坐标,并让角色移动过去,然后脑袋上出现一个气泡,显示现在要做的事或者想法。之所以我说他不是真正意义上的游戏,原因就在于他并没有发生真正的交互,大模型的想法在游戏端仅仅是显示了一个气泡文字而已,并没有真正的实施。比如大模型让他打电话,在游戏端NPC并没有真正"拿起电话"。但是在大模型的脑子里,张三的记忆里多了一条"刚刚给李四打了电话"这条信息,而李四的脑子里,也凭空多了一条"刚刚张三给我打电话,告诉了我xxx这件事"。也就是说,所有的游戏中的"意义",都在大模型的脑子里,而游戏本身,除了显示了个气泡,别的什么也没发生。这也是这个项目的聪明之处,这样就可以让大模型产生很多想法,比如开个派对,而不用关心游戏端能不能实施它,游戏端只是让人类看的。

延伸思考

如果要做真正在游戏端能够实施的,怎么办,比如,NPC有了一个"开派对"的想法,你得让你的游戏有所表现,而不是简单的显示个"文字描述的气泡"。你得在张三家里真的布置上鲜花、气球,让他的其他NPC朋友都过来...这样,当玩家参与到游戏中进行游玩时,才会通过视觉直观的感受到张三正在开派对,而不是像斯坦福小镇那样,去查看NPC的记忆文字才知道,他开过派对。想要实现这个,其实也不是很难,那就是,比如让大模型返回确定的想法,或者指令,而不能凭空臆想,这需要更严格的格式化输出,让大模型输出的操作都能在游戏端真正得到实施。但是这样,就让大模型的决策有了"有限性",就无法真正发挥大模型的创意,这才是最难的部分,在这两者之间找到平衡。

RAG系统介绍

什么是RAG

前面说用RAG系统构建NPC的记忆体系,这是让大模型驱动NPC的基石。如果没有RAG,那么一切将无从谈起。

简单的说,RAG就是知识库,如果你搜索一下,就会有很多资料。他本质上是这样:将一段文字,转化为一个多维向量,这个向量表述了这段文字的"语义"。比如,"桔子"和"香蕉"这两个东西都是水果,他们的向量表述在那个多维空间里就会很相似(余弦相似度,或者你可以理解为两个坐标距离很近),而"桔子"和"导弹"他们的向量相似度就会很低。通过这个,我们就可以检索两段文字在语义上是否相近。具体应用就是,我们提前建立好一些文字库(知识库),其实就是一段一段的文字,每一段文字都计算好这个向量(embedding),当玩家问一个问题时,把玩家的问题也计算一下向量,然后去库中检索,找到那些语义相关的文字段,一起发给大模型,让大模型根据知识库的内容更有针对性的回答问题。

RAG在游戏里能干什么

在我们的游戏里,就可以用RAG来构建NPC的记忆体系,比如玩家之前帮助NPC获得了"御用菜刀",当下次你又提及"御用菜刀"时,NPC就会一下想起来,玩家曾经帮助他获得过这东西这件事。

父子切片的RAG实现

在传统的RAG基础上,我们还要更进一步。传统的RAG的弊端,当知识库条目文本太长时,由于计算向量是针对整块文本的,那么其中包含的最关键的语义可能会被稀释,这就会导致你检索(召回)这段文字时其相关性排名可能会降低。但是当你把文字分块太短时,虽然检索更加精准了,但是可能会丢失上下文信息,因为一个语义可能需要在整个语义环境中才能表达完整意思。因此,我们需要使用典型工业级做法:父子语义分块。就是说,把一大段文字作为父块,然后这个父块低下包含了若干子块,通过对子块的语义检索,召回整段父块。这样不仅语义精准,而且还能保证上下文完整。

对称检索与非对称检索

仅仅处理了父子切片还是不够的。考虑下面的情况:假设有这样一条知识:"铁匠铺位于小镇的中央"。当玩家问:"铁匠铺怎么走?"或者"铁匠铺在哪里?",这是非常正常的询问,我们信心满满的期待系统能召回上面那条知识点,遗憾的时,不行。为什么呢?因为Embedding模型在训练时,目标是让语义相似的句子在空间中靠近。"铁匠铺在哪",这是一个疑问句,而"铁匠铺位于小镇的中央",这是一个陈述句,他俩在语义上完全不同,因此,"铁匠铺在小镇的中央"反而跟"铁匠铺在铁匠们住地方"这句废话在语义上靠的更近。解决这个问题的主要途径是:

  • 假设性文档嵌入(HyDE)。就是把玩家的问题,像让大模型整一个伪答案,提示词如:"请简要回答这个问题,不要在意准确性仅提从陈述句格式"。大模型会将"铁匠铺在哪"转换为一个伪答案,比如:"铁匠铺在湖边"。用这个假的回答,去匹配知识库中的条目,就很容易匹配到那条"铁匠铺在小镇中央"这条真答案。
  • 逆向搜索。为知识库预先生成问题(Question-to-Question)。在知识库预处理阶段,每导入一个子块,让大模型根据语义,预先生成几个玩家可能问道的问题。比如,提示词如下:"请针对这个子块知识点,结合 父块的上下文,生成 3 个玩家可能会问的短句。",将"铁匠铺在小镇的中央",转化为3个问题,比如"铁匠铺在哪?"、"铁匠铺怎么走?"、"小镇中央有什么?"。将这三个问题作为子块一起存入到知识库中。在检索时,就可以根据用户疑问句,匹配到这条知识了。
更大的坑------查询侧语义漂移

这就完了吗??不!!前面利用父块切块、预先生成问题等,仅仅是把知识库的质量提高了。如果玩家输入的文字比较多,就是废话比较多的时候,他问的问题的语义就会被稀释,就算你的知识库再完美,也没有毛用。另外,如果玩家一次问了两个问题,怎么办?传统的Embedding会将这两个问题的语义进行平均,那么就将导致两头都找不到。

解决方案:多路子查询(Mult-Querying)

LLM 拆解:在检索前,先将用户输入发给大模型,让其识别并拆解意图。提示词比如 :"你是一个搜索助手。请分析用户的输入,如果包含多个独立的问题或意图,请将其拆分为多个简短、独立的查询语句。以列表格式返回。",然后,并行检索 :针对拆解出的每一个 Sub-Query 分别执行向量检索。最后,结果合并 (RRF):根据每个子查询返回的结果,计算一个综合得分,选出最终最相关的知识块。

如果用户的废话较多,则需要让大模型提炼,精简,总结为一个简短的问题。

使用精排模型(Reranking)

扩大第一步检索到的结果,比如取TOP50,引入一个极小的精排模型。它不计算向量距离,而是将 用户原始问题 和检索到的文本块同时输入,直接计算两者的"相关性分数"。精排模型对长文本和复杂意图的理解能力远超Embedding向量。用这个精排模型的结果重新进行排序,取TOP5-10。

这一套流程下来,RAG阶段,大概要消耗500-800ms。

构建游戏里的数据

游戏背景知识、世界观、常识。

这一部分是整个游戏的背景知识,试想一下,你开发一个古代武侠题材的游戏,但是玩家问NPC怎么坐着宇宙飞船去火星,那大模型很容易就穿帮了。所以背景知识是要提前喂给大模型的。当然,如果你构建的是一个非常复杂的世界观,就需要前面说的父子块结构的知识库体系,通过检索知识,来实现和大模型对话时,避免一次发送太多的文本,而只将当前最相关的信息发过去。这部分几乎没什么可说的。

NPC个人档案

这一部分,严格来讲不需要知识库。因为NPC档案就是描述了NPC的性格、爱好等固有信息,每次对话请求发给大模型,大模型根据档案描述来模拟他说话的语气、做出符合他人设的决定等。这部分也没什么可说的。

传说

比如,据说火焰宝剑藏在幽暗森林。可以让20%的NPC知道这件事,其他NPC不知晓。这样在玩家探索的时候,有概率获知这个信息,让游戏有更多的不确定性,当然,可以让知道这个传说的NPC告诉另一个NPC。。。本质上,"传说"并不是一种独立的数据体,他只是NPC的记忆,所以在实现方式上,不需要额外处理,参加下面的"记忆"部分。

NPC记忆体系

这一部分这就大了去了。

  • 记忆产生

    游戏里发生的事件,大到玩家摧毁了王国的城堡,小到NPC刚刚吃下一个苹果,这些都可以形成NPC的记忆,然后存储在RAG中。然后在请求大模型时,这些记忆被检索、召回,发给大模型,让大模型根据这些记忆,决策行动或者回复问答。

  • NPC记忆产生,还可以是由玩家或其他NPC告诉了他某件事。比如玩家告诉铁匠,他的儿子其实一直暗恋裁缝店的小美。

  • 记忆的重要性

    玩家杀死了国王,和NPC肚子饿了吃了一个苹果,这两件事显示重要程度不同。所以要评估一下每一条记忆的重要度,这个也可以用大模型来实现,把将要存储的记忆发给大模型,让大模型来打分,比如1分是最不重要的,10分是非常重要的事。

  • 记忆衰减

    让NPC像人一样,能够忘记一些事。但是要根据重要程度进行差异化,这里,我引入了艾宾浩斯曲线,来模拟衰减速度:用一个值来表示衰减度,最不重要的事,5分钟内就可以衰减到接近0,对于最重要的事,10年才能衰减接近0(几乎是永久记忆了)。对于已经衰减到低于阈值的条目,在进行记忆整理时,予以删除。

  • 记忆压缩和反思

    本质上是对记忆的总结,或者说反思。比如,玩家总是给NPC送花,那么在这个NPC的记忆里,可能有很多条关于送花的记忆,只是描述略有不同,比如"今天早上玩家送了一直郁金香"、"中午玩家送了一支玫瑰"...那么,可以在游戏时间深夜的时候,比如NPC睡觉了,或者NPC空闲的时候,把NPC的记忆发给大模型,让大模型对记忆进行总结,就可以把很多条送花的信息,总结为"玩家每天都送你一枝花",顺还可以让大模型评估NPC之间或者跟玩家之间的好感度什么的,甚至还可以推断出"玩家喜欢这个NPC"之类的结论。

手搓RAG系统

为啥不用向量数据库

市面上有很多向量数据库。但是我权衡之后,决定不使用这些专业数据库。原因是,数据库解决问题仅仅是一个量的问题,在搜索速度上,性能跟我手搓的内存版没有本质差异,甚至规模较小时还不如内存版。关键是,因为NPC遇到事情要请求大模型,行为决策要请求大模型,记忆反思要请求大模型,所以综合起来,整个系统的瓶颈并不是RAG,而是大模型的并发性,如果对接外部大模型,那么成本堪忧,如果考虑使用本地大模型,并发性就成了最大的瓶颈,这就决定了NPC数量不可能太大,也就决定了数据量不会太大,故此,就没必须要使用数据库系统。

当然,这里有很多值得优化的点,比如,视野外的NPC,可以降低大模型请求频率,甚至不请求,决策通过传统的策略树实现,在玩家附近的NPC,才用大模型来决策。

手搓RAG系统设计思想,用到的技术点
  • 核心是使用读写分离的快照模式,避免读锁竞争。
  • 利用SIMD加速向量的点积计算
  • 合理使用线程静态变量:
csharp 复制代码
[ThreadStatic] private static HashSet<string> ....

[ThreadStatic]对每个线程是独立的,可以避免堆分配(GC)。

  • 检索数据时使用动态阈值,更具性价比的取到TopK。

目前值得优化的地方:

记忆条目数据中,存储embedding的flaot[]目前没有池化。可能会产生内存碎片。优化点是考虑使用一个巨大的池,每条记忆里存储的不再是float[],而是池子中的索引偏移。这是gemini给我的建议,但是是否真的需要优化值得商榷,毕竟NPC规模不大。

大模型选型

我是用ollama本地部署的,我的显卡是RTX 4090D 48G显存版。最先尝试的是70B的DeepSeek,Q4_M_K量化版,可以勉强100%GPU运行。但是占据的显存几乎没有剩余了,模型上下文空间也少很多,而且还要跑游戏本身,所以PASS掉了。尝试了下Qwen3.5-35B-A3B-Q4-M-K亮化版,但是无发在API测关掉模型思考模式,明明按照API手册设置了关闭思考,仍然会思考,连自定义的Modelfile都尝试了,还是关闭不掉思考模式。折腾了一晚上放弃了。然后尝试了Qwen2-32B-Q4_M_K,占用显存大约20来G。

后记

项目目前还在开发中。。手搓RAG很复杂,很复杂。

相关推荐
wanhengidc2 小时前
裸金属服务器与普通服务器的区别
运维·服务器·网络·游戏·智能手机
Lw中3 小时前
从PDF到RAG知识库
pdf·rag·大模型应用基础·多源文档处理
Lw中3 小时前
RAG如何统一多源文档格式?
rag·多源文档处理
想摆烂的不会研究的研究生3 小时前
RAG入门指南:检索增强生成全解析
人工智能·agent·rag
CoderJia程序员甲4 小时前
GitHub 热榜项目 - 日榜(2026-03-13)
ai·大模型·llm·github·ai教程
WWZZ20255 小时前
具身智能入门Isaac Sim——机器人设置-初级设计轮式机器人3
机器人·大模型·具身智能·isaac
智海观潮5 小时前
只用一周时间通过AI工具重写Next.js,Cloudflare推出vinext重建前端开发边界
开发语言·javascript·人工智能·大模型·web
wanhengidc6 小时前
云手机有哪些辅助功能?
运维·服务器·网络·游戏·智能手机·生活
翔云1234566 小时前
OpenClaw与大模型通信过程:详细图文教程(2026最新)
ai·大模型·openclaw