NBA Agent 实战:基于 FastAPI、BallDontLie 与 OpenAI 的 AI 篮球比赛预测与投注洞察机器人
【免费下载链接】ottomator-agentsAll the open source AI Agents hosted on the oTTomator Live Agent Studio platform!项目地址: https://gitcode.com/GitHub_Trending/ot/ottomator-agents
本篇技术指南以 oTTomator 仓库中的 nba-agent 项目 为主体,完整拆解一个"AI 驱动 NBA 比赛预测与投注洞察机器人"的设计与实现。该 Agent 通过自然语言接收用户提问(如"预测今天凯尔特人的比赛"),自动解析比赛日期、识别球队、抓取实时赛程/战绩/伤病/赔率数据,并调用大语言模型生成带胜率与置信度的比赛分析和投注参考。读完本文,你将掌握该机器人的整体架构、FastAPI 接口设计、5 个核心环境变量的配置、数据管道调用链,以及从源码 nba_agent.py 延伸出的完整部署与二次开发路径。
项目概览:一个端到端的体育预测 Agent
NBA Agent 是一个 AI 驱动的 NBA 比赛预测与投注洞察机器人,其定位是帮助用户在赛前获得数据驱动的决策参考。它不只是简单返回赛程,而是把实时数据抓取与大模型推理结合起来:既评估即将到来的对阵、潜在赛果与相关统计数据,也输出投注赔率视角的分析,为体育竞猜爱好者提供结构化参考。
原文档 README.md 明确列出的功能特性包括:
- 实时 NBA 比赛预测:基于当日或指定日期的赛程生成逐场预测;
- 投注赔率与分析:抓取实时盘口数据(让分盘、大小分)并整合进预测结果;
- 球队专属洞察:支持按球队维度过滤与聚焦分析;
- 历史比赛数据分析:通过历史统计与战绩数据支撑分析结论;
- 交互式 Web 界面:内置聊天式前端,零门槛使用。
在技术栈上,项目由四个层次构成:
| 层次 | 技术选型 | 仓库证据 |
|---|---|---|
| 后端框架 | FastAPI + Python | nba_agent.py |
| 前端界面 | HTML + CSS + JavaScript | templates/index.html |
| 数据存储 | Supabase(会话消息持久化) | nba_agent.py |
| 外部 API | BallDontLie API(篮球数据)+ OpenAI API(推理生成) | nba_agent.py |
从仓库结构看,项目还保留了早期原型 agent_trial/nba_agent_1.py(共 954 行,面向 2023-24 赛季),而主程序 nba_agent.py(共 722 行)则是面向 2024-25 赛季的生产版本,二者在赛季号、OpenAI 客户端初始化方式(同步OpenAIvs 异步AsyncOpenAI)和 CORS 配置上有所差异,适合对照阅读以理解演进过程。
系统架构与一次预测请求的完整链路
整个机器人以 FastAPI 应用为中枢,核心执行逻辑集中在NBAPredictor类中。一次典型请求"What are the predictions for the Celtics game today?"的完整调用链如下:
- 鉴权:
verify_token校验请求头中的 Bearer Token 与API_BEARER_TOKEN环境变量是否一致(nba_agent.py); - 会话持久化:先把用户提问写入 Supabase
messages表(store_message,nba_agent.py); - 日期解析:
NBAPredictor.parse_game_date将自然语言中的时间(today / tomorrow / Jan 27 等)转换为YYYY-MM-DD(nba_agent.py); - 赛程抓取:
get_games(date)调用 BallDontLie/games接口获取当日比赛列表(nba_agent.py); - 球队意图识别:在内置的 30 支球队别名映射表中匹配提问中出现的球队名,若命中则过滤赛程(nba_agent.py);
- 逐场分析:对每场比赛执行
analyze_matchup,并行获取双方伤病(get_team_injuries)、联盟战绩(get_standings)与盘口数据(get_betting_odds)(nba_agent.py); - AI 生成:
_generate_prediction把战绩、伤病等结构化上下文注入 Prompt,调用gpt-4-turbo-preview生成格式化的胜者、分析与置信度(nba_agent.py); - 结果回写与返回:将 AI 回复连同结构化数据(日期、场次数、逐场预测)写回 Supabase,最后返回
AgentResponse(success=True)(nba_agent.py)。
从源码结构看,第 4~6 步的多个数据获取调用大量使用httpx.AsyncClient与asyncio.to_thread,体现了"数据管道并行化 + 大模型调用异步化"的设计思路。
快速开始:依赖安装与环境变量配置
原文档给出的三步启动流程(克隆仓库 → 安装依赖 → 配置环境变量 → 运行)在此展开说明,每一步都有仓库中的具体文件与之对应。
1. 安装依赖
项目依赖集中在 requirements.txt,核心依赖及其用途如下:
| 依赖 | 版本约束 | 用途 |
|---|---|---|
| fastapi | >=0.68.0,<0.69.0 | Web 框架与自动文档 |
| uvicorn | >=0.15.0,<0.16.0 | ASGI 服务器 |
| supabase | >=1.0.3 | Supabase 客户端(消息持久化) |
| openai | >=1.3.0 | OpenAI 大模型调用 |
| httpx | >=0.24.0 | 异步 HTTP 客户端(抓取篮球数据) |
| requests | >=2.31.0 | 同步 HTTP 客户端(赛程/伤病接口) |
| dateparser | >=1.1.8 | 自然语言日期解析 |
| python-dotenv | >=0.19.0 | 加载.env环境变量 |
| pydantic | >=1.10.0,<2.0.0 | 请求/响应模型校验 |
| python-multipart | >=0.0.6 | 表单解析支持 |
| python-telegram-bot | >=20.0 | Telegram 集成预留依赖 |
安装命令与原文档一致:pip install -r requirements.txt。
2. 配置五个必需环境变量
在项目根目录创建.env文件,配置以下变量。需要特别说明的是,这 5 个变量并非"可选配置"——主程序在启动阶段就做了强制校验:
required_vars = [ "BALLDONTLIE_API_KEY", "OPENAI_API_KEY", "API_BEARER_TOKEN", "SUPABASE_URL", "SUPABASE_SERVICE_KEY" ] missing_vars = [var for var in required_vars if not os.getenv(var)] if missing_vars: raise ValueError(f"Missing required environment variables: {', '.join(missing_vars)}")以上代码来自 nba_agent.py:任一变量缺失,进程会直接抛出ValueError并拒绝启动。各变量职责如下:
BALLDONTLIE_API_KEY:BallDontLie API 的鉴权 Key,用于访问赛程、战绩、伤病、赔率、球员场均等篮球数据接口(默认基址https://api.balldontlie.io/v1,见 nba_agent.py);OPENAI_API_KEY:OpenAI 平台 API Key,用于初始化OpenAI客户端并调用gpt-4-turbo-preview生成预测文本;API_BEARER_TOKEN:自定义的接口访问令牌,调用方必须以Authorization: Bearer <token>形式传入,否则返回 401(见 verify_token);SUPABASE_URL与SUPABASE_SERVICE_KEY:Supabase 项目地址与服务端密钥,用于初始化create_client并操作messages表做会话持久化(见 nba_agent.py)。
BALLDONTLIE_API_KEY=your_balldontlie_key OPENAI_API_KEY=your_openai_key API_BEARER_TOKEN=your_custom_bearer_token SUPABASE_URL=https://your-project.supabase.co SUPABASE_SERVICE_KEY=your_service_role_key3. 启动服务
原文档给出的启动命令为:
uvicorn nba_agent:app --reload主程序内置的入口也支持直接以脚本方式运行:python nba_agent.py,此时 uvicorn 会监听0.0.0.0:8001(nba_agent.py),代码注释明确提示"如需可自行修改端口"。启动成功后访问http://localhost:8001即可看到聊天界面。
API 设计:请求/响应模型与端点鉴权
请求与响应模型
Agent 的输入输出由两个 Pydantic 模型约束(nba_agent.py):
class AgentRequest(BaseModel): query: str # 用户提问,如 "What are the predictions for today's NBA games?" user_id: str # 用户标识 request_id: str # 请求唯一标识,用于追踪 session_id: str # 会话标识,用于关联历史消息 class AgentResponse(BaseModel): success: bool # 是否处理成功该请求模型遵循 oTTomator Live Agent Studio 平台 Agent 的通用契约,session_id与request_id同时用于 Supabase 会话记录与日志追踪。
端点与鉴权
- POST
/api/nba_agent:唯一的主预测端点(nba_agent.py),依赖verify_token完成 Bearer 鉴权,未携带或携带错误 Token 时分别返回 500(服务端未配置 Token)与 401(Token 不匹配); - GET /:返回聊天界面 HTML(nba_agent.py),直接读取
templates/index.html渲染。
前端 JavaScript 以Authorization: Bearer test123调用接口(templates/index.html),即默认演示环境中的API_BEARER_TOKEN为test123,生产环境务必替换。注意主版本 nba_agent.py 的 CORS 配置为allow_origins=["*"](全放行),而早期原型 agent_trial/nba_agent_1.py 则限定为https://nbaagent-production.up.railway.app与http://localhost:8001,后者更适合作为生产环境的收紧参考。
核心引擎 NBAPredictor:多源数据管道深度解析
NBAPredictor类(nba_agent.py)是所有预测能力的载体,初始化时配置 BallDontLie 基址、API Key 与 OpenAI 客户端。它对外暴露的核心数据方法可归纳为四类:
赛程与战绩
get_games(date):同步requests.get请求/games接口,以dates[]参数传入YYYY-MM-DD格式日期,返回当日比赛列表(nba_agent.py);get_standings(season=2024):异步请求/standings,把返回列表按team.id转成字典,字段覆盖胜场/负场、分区、分区排名、主场战绩、客场战绩、近 10 场与连胜/连败(如W3、L2)等(nba_agent.py)。
伤病与球队信息
get_team_injuries(team_id):同步请求/player_injuries,按team_ids[]过滤,返回球队当前伤病名单(nba_agent.py);_is_notable_player与_get_season_averages:通过/season_averages接口判断球员是否"关键球员",阈值包括场均得分 ≥ 10、篮板 ≥ 5、助攻 ≥ 4 或出场时间 ≥ 20 分钟,用于衡量伤停对球队实力的影响(nba_agent.py);_get_advanced_stats与_get_team_leaders:请求/stats/advanced与/leaders接口,可获取进阶数据与球队各项统计领跑者(得分/篮板/助攻/抢断/盖帽),是扩展分析深度的预留能力(nba_agent.py)。
投注赔率
get_betting_odds(game_id, game_date):异步请求/odds接口,支持按game_id或date过滤,非 200 状态码时返回空列表而非抛异常,保证单场赔率缺失不阻塞整体流程(nba_agent.py);_parse_odds_data:解析原始赔率数据,提取type == 'spread'的away_spread(让分盘)与type == 'over/under'的over_under(大小分盘),且要求live字段为真(nba_agent.py);_analyze_over_under:基于双方场均得分之和与盘口总分对比,给出 OVER / UNDER 的简单规则判断(nba_agent.py)。
这些方法的调用关系在 analyze_matchup 中被串联:先取赛季 → 并行拉取双方伤病 → 拉取联盟战绩 → 拉取本场赔率 → 汇总传入_generate_prediction,最终返回matchup、prediction与完整data三个字段。
自然语言日期解析:从"Jan 27"到 YYYY-MM-DD
parse_game_date(nba_agent.py)是 Agent 理解用户语义的关键一环,其设计要点包括:
- 时区基准:以
US/Eastern(NBA 官方时间区)作为基准时区获取当前时间,避免跨时区用户提问导致"今天"错位; - 相对日期:命中
tomorrow/yesterday/today/tonight关键字时,基于美东时间做 ±1 天或取当天计算; - 绝对日期抽取:用正则
(?i)(jan|january|...|dec|december)\s+\d{1,2}从查询中抽取"月份+日"片段; - 兜底解析:抽不到日期片段时,把整句查询交给
dateparser.parse,配置项包括时区US/Eastern、返回时区感知对象RETURN_AS_TIMEZONE_AWARE: True、倾向未来日期PREFER_DATES_FROM: future; - 失败反馈:解析失败时抛出带引导性的错误信息,提示用户"请指定日期,例如 Jan 29 或 January 29",该提示会作为 AI 回复直接返回给用户(nba_agent.py)。
最终统一以strftime('%Y-%m-%d')输出,作为/games接口的dates[]参数。
球队识别与意图路由:30 支球队的别名映射
为了支持"预测凯尔特人今天的比赛"这类球队维度的提问,源码内置了一张覆盖全部 30 支球队的别名映射表(nba_agent.py),每条记录包含球队规范名与常见变体,例如:
| 规范名 | 匹配变体 |
|---|---|
| celtics | boston, celtics |
| sixers | philadelphia, philly, 76ers, sixers |
| lakers | la lakers, lal, lakers |
| warriors | golden state, gsw, warriors |
| mavericks | dallas, mavs, mavericks |
| thunder | oklahoma, okc, thunder |
匹配逻辑为:遍历映射表,只要提问中出现任一变体(小写化后做子串匹配)即命中球队;命中后用同一组变体去过滤当日比赛列表(nba_agent.py)。路由结果决定回复前缀:
- 命中球队且有比赛 → "Here's my prediction for the {Team} game on {date}:";
- 命中球队但当日无赛 → 明确告知"没有找到该球队在指定日期的比赛";
- 未命中球队 → 返回当日全部场次预测("I found N games scheduled for {date}...")。
该逻辑位于主端点 nba_agent 中,是整个预测流程的意图路由层。
AI 预测生成:Prompt 工程与输出格式约束
_generate_prediction(nba_agent.py)是整个 Agent 的"大脑",其设计核心是严格约束大模型输出格式,便于程序化解析:
- 分析型 Prompt:把对阵双方、当前战绩(如
凯尔特人: 32-15)、伤病人数等结构化数据拼入 Prompt,要求模型按固定三段式输出:
Winner: [Team Name] ([Win Probability]%) Analysis: 3-4 sentences analyzing key factors including records, matchup advantages, and injury impact Confidence: High/Medium/Low- 系统角色与生成参数:系统提示词设定为"You are an expert NBA analyst",使用
gpt-4-turbo-preview模型,temperature=0.7、max_tokens=200,并通过asyncio.to_thread把同步的 OpenAI 调用放到线程池执行,避免阻塞事件循环(nba_agent.py); - 结果格式化:逐行提取
Winner:/Analysis:/Confidence:前缀行,组装成🏀 客队 (Away) @ 主队 (Home)+ 预测正文的展示格式; - 盘口附加:在预测末尾追加
Betting Lines:区块,从最新更新的赔率数据中提取客队让分(如Team -3.5)与大小分(如O 224.5),用last_update字段比较选取最新盘口(nba_agent.py)。
需要注意,_parse_odds_data要求赔率记录的live字段为真才参与解析,而_generate_prediction内部遍历时不再要求live——两处逻辑存在差异,二次开发时若发现盘口缺失,可优先排查 BallDontLie/odds返回数据中live与type字段的实际取值。
Supabase 会话记忆:让 Agent 记住上下文
Agent 通过 Supabase 的messages表实现会话级记忆(nba_agent.py):
store_message(session_id, message_type, content, data):把消息对象(type、content、可选data)插入表内,type取值为human(用户提问)或ai(模型回复),data中附带request_id及预测的日期、场次数等结构化信息;fetch_conversation_history(session_id, limit=10):按created_at倒序取最近 N 条记录后反转成时间正序,供上下文注入使用。
在主端点中,用户提问会先于处理被持久化,AI 回复连同响应数据在流程末尾统一写入(nba_agent.py 与 nba_agent.py),实现"有问必录、有答必存"。这一设计使 Agent 天然兼容 Live Agent Studio 平台的会话管理机制。
交互式 Web 界面
前端为单文件聊天界面 templates/index.html(382 行),内嵌样式与脚本:
- 欢迎与引导:顶部 NBA 主题色(深蓝
#1d428a+ 红#c9082a)的欢迎横幅,内置 4 条示例提问,帮助用户快速上手(index.html):- "What are the predictions for today's NBA games?"
- "What are the predictions for tomorrow's games?"
- "What are the predictions for the Celtics game today?"
- "What are the predictions for the NBA games on Jan 27?"
- 预测卡片渲染:
formatPrediction函数按🏀拆分多条预测,识别Winner:行生成卡片式布局,让分盘与大小分盘以不同颜色的 pill 样式区分(index.html); - 交互体验:含打字指示器(typing indicator)、加载动画与回车发送,请求地址为
window.location.origin + '/api/nba_agent',演示 Token 为test123。
部署:Dockerfile 与 Procfile 双通道
项目同时提供了容器化与平台化两种部署方式:
- Dockerfile:基于
ottomator/base-python:latest基础镜像,通过ARG PORT=8001支持构建期指定端口(ENV PORT与EXPOSE ${PORT}),先复制requirements.txt安装依赖以利用 Docker 缓存,再复制应用代码,最终以uvicorn nba_agent:app --host 0.0.0.0 --port ${PORT}启动; - Procfile:声明
web: uvicorn nba_agent:app --host 0.0.0.0 --port $PORT,兼容 Railway、Heroku 等读取$PORT环境的 PaaS 平台(项目作者线上部署地址即 Railway 域名,见 README.md)。
本地调试推荐uvicorn nba_agent:app --reload(自动重载便于迭代);生产部署推荐 Dockerfile 或 Procfile 通道,并务必把API_BEARER_TOKEN与两个 Supabase 密钥作为部署平台的环境变量注入,切忌写死在代码或前端中。
已知限制与二次开发建议
基于源码可以确认以下限制,二次开发时需特别注意:
- 赛季号硬编码:
_get_current_nba_season直接返回2024(面向 2024-25 赛季,nba_agent.py),get_standings、_get_season_averages等接口同样硬编码赛季值。跨赛季使用需同步更新这些常量,未来可改为根据比赛日期动态推导; - CORS 全放开:主版本
allow_origins=["*"]适用于公开演示,生产环境建议参考 agent_trial/nba_agent_1.py 收紧为白名单; - 前端 Token 硬编码:演示界面内置
test123,仅限本地联调,上线必须改为服务端安全注入; - 语义能力边界:日期解析依赖英文月份关键字与
dateparser,对中文或非常规表述支持有限;球队匹配为子串匹配,可能对"凯尔特人 vs 湖人"这类含两队名提问仅命中先出现的球队; - 可扩展方向:源码中已预留球员场均、进阶统计、球队领跑者等接口(
_get_season_averages、_get_advanced_stats、_get_team_leaders)与fetch_conversation_history会话上下文,可进一步把历史对话与更细粒度的球员/进阶数据注入 Prompt,提升分析深度。
小结
NBA Agent 是一个结构清晰、可完整落地运行的"实时数据 + 大模型推理"型体育预测 Agent:FastAPI 提供标准化的 Bearer 鉴权接口,NBAPredictor聚合赛程、战绩、伤病、赔率四类实时数据,parse_game_date与球队别名映射完成自然语言意图理解,gpt-4-turbo-preview以严格格式输出胜者/分析/置信度,Supabase 负责全量会话持久化,前端聊天界面与 Docker/Procfile 双部署通道则覆盖了从演示到上线的完整链路。无论你想复刻一个体育预测机器人,还是借鉴"多源数据管道 + 大模型格式化输出"的 Agent 设计范式,nba_agent.py 与 README.md 都是值得通读的参考实现。
【免费下载链接】ottomator-agentsAll the open source AI Agents hosted on the oTTomator Live Agent Studio platform!项目地址: https://gitcode.com/GitHub_Trending/ot/ottomator-agents
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考