前言
想象你问计算机:“谁在 2023 年 NBA 总决赛中得分最多?”然后它能直接、流畅地给出有数据支撑的答案。这就是 Retrieval-Augmented Generation(RAG)的魔力:结合检索与 AI 文本生成,让 AI 能够依据知识库回答自然语言问题。
本文将教你如何用 RAG 加上 PostgreSQL 数据库,搭建你自己的 NBA 问答系统,并在本地运行。我们会用到:
bge-m3
用于文本嵌入(embedding)- PostgreSQL +
pgvector
用于语义相似搜索 gemma3:12b
用于自然语言生成- Ollama 本地运行环境,支持 OpenAI 风格 API
无论你是篮球迷、开发者,还是想学习 AI 的入门者,这篇文章都将是你构建智能体育助手的第一步。
什么是 RAG?
RAG 是 Retrieval-Augmented Generation(检索增强生成)的缩写,它结合了两个核心组件:
- Retriever(检索器):从知识库中查找相关文档或信息;
- Generator(生成器):使用大型语言模型(LLM)基于检索结果生成回答。
这种组合方式将数据库的准确性与语言模型的表达能力结合起来,使 AI 回答更可靠、更自然。
你可以提出哪些 NBA 问题?
NBA 数据丰富,适合做语义搜索与问答系统。以下是一些常见问题类型:
- 数据查询类:Curry 在 2022 年投进了多少个三分球?
- 对比类:2023 季后赛中 Luka 和 Trae 谁的助攻更多?
- 趋势类:2024 年 3 月 Lakers 哪位球员得分最多?
- 历史类:勇士队上一次夺冠是哪一年?
一步步搭建你的 NBA 问答系统
第一步:使用 bge-m3
生成嵌入向量
bge-m3
是一款多语言、多任务的向量模型,用于语义搜索。它可以将一句话转换为 1024 维的向量,例如:
“2023 年总决赛得分王是谁?”
转化为:
[0.021, -0.033, ..., 0.008]
本地运行:
ollama pull bge-m3
ollama serve
使用 OpenAI API 格式调用:
import requests
res = requests.post("http://localhost:11434/v1/embeddings", json={
"model": "bge-m3",
"input": "2023 年 NBA 总决赛谁得分最多?"
})
embedding = res.json()["data"][0]["embedding"]
第二步:将向量存入 PostgreSQL
启用向量扩展:
CREATE EXTENSION IF NOT EXISTS vector;
创建表:
CREATE TABLE nba_texts (
id SERIAL PRIMARY KEY,
text TEXT,
embedding VECTOR(1024)
);
插入数据:
INSERT INTO nba_texts (text, embedding)
VALUES ('Curry 在总决赛第五场拿下 32 分', '[0.012, -0.024, ..., 0.031]');
第三步:通过相似度搜索检索内容
将用户问题转为向量,与数据库中的嵌入向量进行比较。
SELECT text
FROM nba_texts
ORDER BY embedding <-> '[0.018, -0.030, ..., 0.101]'
LIMIT 3;
这将返回语义上最相近的文本。
向量距离越小,表示语义越接近。例如,“得分最多” 和 “得分王” 表达不同但语义相近。
第四步:使用 gemma3:12b
生成回答
gemma3:12b
是 Google 推出的大型语言模型,可以本地运行并生成自然语言回答。
下载并运行模型:
ollama pull gemma3:12b
构造 prompt 并生成回答:
context = "\n".join(top_3_texts)
prompt = f"""上下文:\n{context}\n\n问题:2023 年总决赛得分最多的是谁?\n\n回答:"""
res = requests.post("http://localhost:11434/v1/chat/completions", json={
"model": "gemma3:12b",
"messages": [
{"role": "system", "content": "你是一位篮球数据分析师。"},
{"role": "user", "content": prompt}
]
})
answer = res.json()["choices"][0]["message"]["content"]
如何从新闻和数据生成文本
从球员数据生成描述文字
def generate_game_summary(player_name, stats):
return f"{player_name} 拿下 {stats['points']} 分,{stats['rebounds']} 篮板,{stats['assists']} 助攻,对阵 {stats['opponent']},比赛日期 {stats['date']}。"
抓取 NBA 新闻段落
from bs4 import BeautifulSoup
import requests
url = "https://www.espn.com/nba/story/_/id/abc..."
html = requests.get(url).text
soup = BeautifulSoup(html, "html.parser")
paragraphs = [p.text for p in soup.select("article p")]
添加标签信息,便于后续检索
{
"text": "LeBron 在揭幕战拿下 28 分。",
"source": "game_log",
"team": "Lakers",
"date": "2023-10-24"
}
示例用法
球员对比
问: Luka 和 Trae 谁在 2023 季后赛助攻更多?
- 检索季后赛数据
- 使用
gemma3:12b
生成对比回答
历史查询
问: 勇士队上一次夺冠是哪一年?
- 检索历史信息
- 生成简洁答案
队内得分王
问: Lakers 在 2024 年 3 月的得分王是谁?
- 检索比赛记录
- 提供球员名与得分数据
小贴士与注意事项
- 数据更新时应重算嵌入向量
- 保证嵌入维度一致(bge-m3 为 1024)
- 查询前可预处理(去除停用词等)
- 大数据量时可使用向量索引(如 ivfflat)加速查询
总结
RAG 技术结合了向量检索与语言生成,构建本地化、个性化的智能问答系统变得轻松可行。只需 PostgreSQL、pgvector、Ollama 和两个开源模型,你就能实现一个真正懂 NBA 的 AI 助手。
🏀 想进一步尝试?你可以:
- 接入实时比赛数据
- 添加重新排序模块提升回答质量
- 用 Streamlit/Gradio 打造可视化前端
欢迎进入 AI 篮球分析新时代!