EN

用 RAG 搭一个世界杯赛事知识库问答(2026 实战)

把赛程、球队、历史战绩喂给大模型,做一个能用大白话问的赛事助手——顺便讲清楚 RAG 在「实时数据」场景的真实边界

返回教程列表🌐 Read in English
进阶12 分钟

用 RAG 搭一个世界杯赛事知识库问答(2026 实战)

把赛程、球队、历史战绩喂给大模型,做一个能用大白话问的赛事助手——顺便讲清楚 RAG 在「实时数据」场景的真实边界

世界杯期间想随口问「上届冠军是谁」「这两队历史交锋如何」,让 LLM 直接答又怕它瞎编。这篇用 RAG 把权威赛事数据接进来,搭一个不胡说的问答助手,并讲清楚 RAG 处理实时比分的坑该怎么绕。

用 RAG 搭一个世界杯赛事问答助手

世界杯期间,你大概率想随口问点东西:「上届冠军是谁」「这两支队历史交锋几胜几负」「C 组现在积分什么情况」。直接丢给 ChatGPT?它会自信地编——尤其是日期、比分这种具体数字,幻觉率极高。

正确做法是 RAG(检索增强生成):把权威赛事数据存进向量库,提问时先检索相关资料,再让大模型基于检索到的真实内容回答。这篇带你搭一个不胡说的世界杯问答助手,同时——这点更重要——讲清楚 RAG 在实时数据场景下的真实边界。

如果你对 RAG 框架选型还没概念,可以先扫一眼LlamaIndex vs LangChain 怎么选,这篇直接进入实操。

先分清两类数据:静态的 vs 实时的

这是搭这个系统最关键的认知,想清楚能省掉一半的坑:

  • 静态/慢变数据:球队历史、往届冠军、球员资料、赛程表。这类适合 RAG,存进向量库即可。
  • 实时数据:当前比分、实时积分榜、最新伤停。这类不该塞进向量库——向量检索是为语义相似度设计的,不是为「取最新一条」设计的。实时数据应该走工具调用(function calling)实时查 API。
  • 很多人一上来把比分也 embedding 进去,结果问「现在几比几」答的是三小时前的——因为向量库里那条没更新。记住:RAG 管知识,工具调用管实时。 本文聚焦前者,实时那半见用 LLM Agent 做实时赛事解说

    第一步:准备并切分数据

    把赛事资料整理成结构化文本。关键是切分(chunking)要带上下文——每个 chunk 自己得能读懂。

    python
    

    每支球队、每届赛事整理成一段自包含的文本

    docs = [ { "id": "team-brazil", "text": "巴西国家队:五次夺得世界杯冠军(1958、1962、1970、1994、2002)," "是夺冠次数最多的球队。绰号桑巴军团,传统打法以技术和进攻著称。" }, { "id": "h2h-bra-arg", "text": "巴西对阵阿根廷历史交锋:两队是南美双雄,交锋逾百场," "整体战绩接近,巴西略占优。经典战役包括……" }, ]

    切分原则:一个 chunk 一个完整主题,别把「巴西队简介」和「阿根廷队简介」混在一块,否则检索精度会塌。

    第二步:向量化并入库

    用 embedding 模型把文本转成向量,存进向量库。本地小项目我推荐 Qdrant 或 Chroma,省心(两者区别见Qdrant vs Chroma)。

    python
    from qdrant_client import QdrantClient
    from qdrant_client.models import VectorParams, Distance, PointStruct
    from openai import OpenAI

    client = QdrantClient(":memory:") # 生产换成持久化地址 oai = OpenAI()

    def embed(text): return oai.embeddings.create( model="text-embedding-3-small", input=text ).data[0].embedding

    client.create_collection( "worldcup", vectors_config=VectorParams(size=1536, distance=Distance.COSINE), ) client.upsert("worldcup", points=[ PointStruct(id=i, vector=embed(d["text"]), payload=d) for i, d in enumerate(docs) ])

    第三步:检索 + 生成

    提问时,先检索 top-k 相关 chunk,拼进 prompt,再让模型基于它回答。关键是 prompt 里要明确约束「只能用提供的资料,没有就说不知道」——这是压住幻觉的核心。

    python
    def ask(question, k=3):
        q_vec = embed(question)
        hits = client.search("worldcup", query_vector=q_vec, limit=k)
        context = "\n\n".join(h.payload["text"] for h in hits)

    prompt = f"""你是世界杯资料助手。只能依据下面提供的资料回答, 资料里没有的,直接说「资料中没有相关信息」,绝对不要编造。

    资料: {context}

    问题:{question}"""

    resp = oai.chat.completions.create( model="gpt-4o-mini", messages=[{"role": "user", "content": prompt}], temperature=0, # 事实问答,温度调到 0 ) return resp.choices[0].message.content

    print(ask("巴西一共拿过几次世界杯冠军?"))

    temperature=0 很重要:事实问答不需要创造力,调高只会增加跑偏风险。

    把幻觉压到最低的几个实战要点

    搭起来容易,搭得可信才是难点。几条经验:

  • 强约束 prompt:明确「资料没有就说不知道」。这一条能消掉大半幻觉。
  • 检索不到就别硬答:如果 top-k 的相似度分数都很低(比如低于 0.7),说明知识库里压根没相关内容,直接回退「我不掌握这个信息」,别让模型硬编。
  • 给出处:把命中的 chunk id 一起返回,让用户能核对。这是判别一个 RAG 系统是否专业的标志。
  • 静态数据定期重建索引:赛程变了、出局了,要重新 embedding,否则答的是过期信息。
  • 它能做什么、不能做什么

    搭完这套,它能很好地回答:历史战绩、球队资料、赛制规则、往届数据——这些是静态知识,RAG 的主场。

    答不好:当前比分、实时积分、刚刚的红牌——这些得靠工具调用实时查,是另一篇的内容。把两者拼起来,才是一个完整的赛事助手:RAG 管「知识」,Agent 工具调用管「实时」。

    想看实时那半怎么做,继续读用 LLM Agent 做实时赛事解说与数据播报;想要全景视角,看AI 与 2026 世界杯应用盘点

    相关工具

    QdrantChromaOpenAILlamaIndex