ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

基于 CrewAI 与 CopilotKit AG-UI 协议的实时股票组合分析 Agent 实战指南

基于 CrewAI 与 CopilotKit AG-UI 协议的实时股票组合分析 Agent 实战指南 基于 CrewAI 与 CopilotKit AG-UI 协议的实时股票组合分析 Agent 实战指南【免费下载链接】ai-engineering-hubIn-depth tutorials on LLMs, RAGs and real-world AI agent applications.项目地址: https://gitcode.com/GitHub_Trending/ai/ai-engineering-hub导读本文围绕 ai-engineering-hub 仓库中的stock-portfolio-analysis-agent项目完整讲解如何构建一个实时流式输出分析流程的 AI 股票组合分析 Agent后端使用 CrewAI 编排多阶段分析工作流意图解析 → 行情拉取 → 组合分配 → 牛熊洞察前端使用 React/Next.js 搭建可交互图表界面并通过 CopilotKit 的AG-UI Protocol将工具调用、进度日志与中间结果以事件流SSE方式实时推送到浏览器。读完本文你将掌握 AG-UI 事件驱动的 Agent 流式架构、CrewAI Flow 编排方法、基于 yfinance 的投资回测/分配模拟实现以及一套可直接复制运行的前后端联调方案。项目总览与技术栈该项目演示了一条完整的AI Agent 实时可视化链路用户在前端输入一句自然语言投资请求例如 Analyze AAPL and MSFT with $10k eachAgent 立即开始工作——拉取历史行情、计算组合分配、生成牛熊分析——而这一切都以事件流的形式实时呈现在 UI 上用户无需等待最终结果可以看着 Agent 干活。核心技术栈依据 README.md 与 pyproject.toml层级技术职责前端 UIReact Next.js 15交互式投资仪表盘与聊天面板后端 APIFastAPI Uvicorn提供/crewai-agent流式接口流式协议CopilotKit AG-UI Protocol实时传输 Agent 事件SSEAgent 编排CrewAI Flow多阶段工作流调度市场数据yfinance pandas/numpy行情下载与收益计算后端依赖在 pyproject.toml 中锁定crewai0.140.0、copilotkit0.1.52、ag-ui-protocol0.1.7、fastapi0.115.14、yfinance0.2.64、pandas2.3.0Python 版本要求3.12,3.13。环境搭建与运行1. 安装依赖项目使用uv管理 Python 依赖前端使用 npm 管理 Node 依赖# 在仓库根目录安装后端依赖 uv sync # 安装前端依赖 cd frontend npm install cd ..提示stock-portfolio-analysis-agent目录下同时存在uv.lock与pnpm-lock.yamlREADME 推荐使用npm install安装前端依赖若你偏好 pnpm也可使用pnpm install并基于 frontend/package.json 中的脚本运行。2. 配置环境变量需要两个.env文件分别供后端与前端使用后端agent/.envOPENAI_API_KEYyour-key前端frontend/.envOPENAI_API_KEYyour-openai-key NEXT_PUBLIC_CREWAI_URLhttp://127.0.0.1:8000/crewai-agent其中NEXT_PUBLIC_CREWAI_URL告诉前端代理层后端流式接口的位置。在 frontend/src/app/api/copilotkit/route.ts 中HttpAgent会读取该变量并回退到默认值http://0.0.0.0:8000/crewai-agentconst crewaiAgent new HttpAgent({ url: process.env.NEXT_PUBLIC_CREWAI_URL || http://0.0.0.0:8000/crewai-agent, });3. 启动应用# 终端一启动后端默认端口 8000 uv run python agent/main.py # 终端二启动前端默认端口 3000 cd frontend npm run dev后端入口 agent/main.py 中main()读取环境变量PORT默认8000并以host0.0.0.0、开发热重载reloadTrue启动 Uvicorn。4. 调整后端地址可选README 明确提示前端默认假定后端运行在本机。若你修改了后端 host/port需要同步更新前端 API 调用配置即上面的NEXT_PUBLIC_CREWAI_URL否则前端无法建立到后端的代理连接。后端架构FastAPI AG-UI 事件流5. 状态管理继承 CopilotKitState后端用自定义的AgentState贯穿整个分析流程它继承自CopilotKitState后者进一步继承 LangGraph 的MessagesState见 agent/main.pyclass AgentState(CopilotKitState): tools: list messages: list be_stock_data: Any # 拉取到的行情 DataFrame be_arguments: dict # 从用户输入中解析出的投资参数 available_cash: int # 可用现金 investment_summary: dict # 分配/收益/基准对比结果 tool_logs: list # 供 UI 展示的进度日志这份状态在/crewai-agent接口中初始化并在工作流各阶段被持续读写最终回流到前端用于渲染。6. 流式接口事件生成器与 SSE核心接口POST /crewai-agent接收前端传来的RunAgentInput含用户消息、工具、thread_id/run_id、当前 state并返回media_typetext/event-stream的StreamingResponse见 agent/main.py。整个事件流由异步生成器event_generator()驱动其关键机制如下事件编码EventEncoder将 AG-UI 事件编码为 SSE 格式事件队列asyncio.Queue作为工作流与流式循环之间的桥梁工作流通过emit_event回调把StateDeltaEvent等事件put_nowait入队异步编排asyncio.create_task(StockAnalysisFlow().kickoff_async(...))在后台运行 CrewAI 工作流主循环以asyncio.wait_for(event_queue.get(), timeout0.1)轮询队列并逐条转发。事件流生命周期包含以下 AG-UI 事件类型见 agent/main.pyRunStartedEvent通知客户端一次运行开始携带 thread_id/run_idStateSnapshotEvent推送初始快照available_cash、investment_summary、investment_portfolio并清空 tool_logsStateDeltaEvent工作流推进时增量更新/tool_logs、/investment_portfolio等路径ToolCallStartEvent/ToolCallArgsEvent/ToolCallEndEvent渲染图表工具render_standard_charts_and_table的调用与参数内含完整的investment_summaryTextMessageStartEvent/TextMessageContentEvent/TextMessageEndEvent普通文本回复内容被切成最多 100 个分片、每片间隔 50ms 推送形成打字机效果RunFinishedEvent标记运行结束。7. 智能节流先出图表、后出洞察值得注意的一个工程细节主循环中实现了事件节流逻辑agent/main.py目的是先让图表数据完整送达再放行后续洞察内容避免 UI 渲染抖动当检测到/tool_logs某条日志被替换为completed或检测到TOOL_CALL_ARGS中包含render_standard_charts_and_table时标记chart_data_sent True此后/investment_portfolio的更新继续放行而包含insights/processing/extracting的增量事件被拦截若图表已发送而工作流仍在生成洞察则短暂 sleep 后提前结束流让图表先进入可交互状态。这个设计说明流式 Agent 不仅要能推送事件还要能按用户感知的优先级编排事件顺序这是该示例区别于普通聊天流的关键点。Agent 工作流CrewAI Flow 的六个阶段工作流主体是 agent/stock_analysis.py 中的StockAnalysisFlow使用 CrewAI Flow 的start、listen、or_装饰器串联start → chat → simulation → allocation → insights → end └──────────── chat未解析出投资参数时直通 end各阶段职责与关键实现如下。阶段一start——注入组合上下文start()方法stock_analysis.py将当前投资组合 JSON 替换进系统提示词模板中的{PORTFOLIO_DATA_PLACEHOLDER}占位符提示词见 agent/prompts.py使 LLM 从一开始就知道用户已经持有哪些股票从而正确处理追加买入而非替换持仓。阶段二chat——意图解析与结构化提取chat()stock_analysis.py负责把自然语言翻译成结构化投资参数在tool_logs中追加 Analyzing user query 日志并通过StateDeltaEventop: add,path: /tool_logs/-推送给 UI调用 OpenAIgpt-4o-mini并挂载函数调用工具extract_relevant_data_from_user_prompt若finish_reason tool_calls将工具调用转换为内部格式convert_tool_call追加AssistantMessage与ToolMessage返回simulation进入下一阶段若没有触发工具调用说明用户只是在闲聊追加普通助手消息并返回end直接收尾。extract_relevant_data_from_user_prompt工具stock_analysis.py的参数 schema 是理解整个系统的关键参数类型说明ticker_symbolsstring[]股票代码列表如[AAPL, GOOGL]必填investment_datestring (date)投资起始日期如2023-01-01必填amount_of_dollars_to_be_investednumber[]每只股票的投入金额与 ticker 列表一一对应必填interval_of_investmentenum1d/5d/7d/1mo/3mo/6mo/1y/2y/3y/4y/5y/single_shot未指定时默认single_shotto_be_added_in_portfolioboolean是否加入真实组合false 表示进入沙盒组合必填同时agent/prompts.py 中的系统提示词对工具调用行为做了强约束一次调用传入多个 ticker而不是每个 ticker 调用一次对于组合修改增/删/替换分别规定返回完整最新列表 / 剔除后的列表 / 仅新股票列表。阶段三simulation——行情拉取simulation()stock_analysis.py负责真实市场数据的获取与预处理解析上一阶段遗留的be_arguments将新投资与既有组合做加性合并existing_portfolio new_investments并通过StateDeltaEventop: replace,path: /investment_portfolio实时更新前端日期校验投资日期距今超过 4 年则自动修正为当前年-4-01-01yfinance 数据可得性限制并据此推导history_period如1y、2y……用yf.download(all_tickers, start..., end..., interval3mo)拉取全部 ticker含既有持仓的季度收盘价存储到self.be_stock_datadata[Close]DataFrame若数据为空则直接return end兜底否则继续到 allocation。注意一个产品约束README 与前端初始话术prompt-panel.tsx都明确提示AI agent 只能访问过去 4 年的行情数据——这与源码中的 4 年截断逻辑一致。阶段四allocation——组合分配与收益模拟allocation()stock_analysis.py是整个系统最核心的算钱环节包含以下要点两种投资策略由interval_of_investment决定single_shot一次性买入仅取行情第一个日期为每个 ticker 用allocated // price整数除法买入整股现金不足时记录add_funds_datesDCA定投遍历行情所有日期只要有可用现金就按total_cash // price尽可能买入逐笔写入investment_log若用户只给了一个金额但包含多个 ticker代码会自动等额拆分amount_per_ticker amounts[0] / len(tickers)。收益与分配指标对每个 ticker 计算已投入金额、持仓市值、绝对收益、百分比分配invested / total_invested * 100与百分比收益(holding_value - invested) / invested * 100汇总成investment_summary包含holdings、final_prices、cash、returns、total_value、investment_log、add_funds_needed、add_funds_dates、total_invested_per_stock、percent_allocation_per_stock、percent_return_per_stock等字段。SPY 基准对比下载同期 SPY标普 500 ETF日线数据用与组合相同的策略single-shot 一次买入或 DCA 等额分批模拟投入同等资金逐日期计算组合净值与 SPY 净值生成performanceData: [{date, portfolio, spy}, ...]为前端折线图提供对比数据。源码对日期对齐做了处理SPY 起始日早于组合数据时将 stock_data 截断到 SPY 首个可用日期并用reindex(..., methodffill)前向填充取数失败时回退为占位 Series。图表触发本阶段末尾工作流在messages中追加一条携带render_standard_charts_and_table工具调用的AssistantMessage参数为完整investment_summary这一工具调用随后被后端流式循环转换为ToolCallStart/Args/End事件推给前端从而触发 UI 渲染图表。阶段五insights——牛熊洞察生成insights()stock_analysis.py调用gpt-4o-mini并挂载generate_insights工具为当前 ticker 列表生成平衡的多空观点generate_insights工具stock_analysis.py要求输出bullInsights与bearInsights两组结构化数据每组项包含title、description、emoji三个必填字段拿到洞察后将其合并进图表工具调用的参数args_dict[insights] ...这样图表渲染和洞察可以在同一次工具调用参数中一起到达前端失败兜底洞察生成异常时置空self.state[state][insights] {}。阶段六end——收尾end()监听or_(chat, insights)stock_analysis.py无论是chat 阶段未解析出投资参数还是insights 阶段完成都会进入此步返回完整 state随后由主循环清空 tool_logs 并发送RunFinishedEvent。前端架构CopilotKit 驱动的实时画布8. 前端数据流前端入口 frontend/src/app/page.tsx 通过 CopilotKit React 核心 Hook 与后端 Agent 建立双向连接useCoAgent声明 Agent 名称crewaiAgent并注入初始状态available_cash: 1000000、空investment_summary、空investment_portfolio见 page.tsxuseCoAgentStateRender订阅后端流式推送的状态渲染ToolLogs组件将 Analyzing user query / Gathering Stock Data / Allocating cash / Extracting Key insights 等实时进度以动态卡片呈现见 tool-logs.tsxprocessing 态为黄色脉冲动画、completed 态为绿色对勾useCopilotAction声明render_standard_charts_and_table与render_custom_charts两个前端动作前者渲染折线图 柱状图 分配表并提供 Accept/Reject 交互按钮page.tsx后者用于沙盒组合的自定义图表对比useCopilotReadable把当前investment_portfolio暴露给 Copilot 上下文让对话模型看得到组合状态page.tsxuseCopilotChatSuggestions基于 frontend/src/utils/prompts.ts 中的INVESTMENT_SUGGESTION_PROMPT生成 35 条可点击的投资建议增持/减持/替换格式金额范围 5,00050,000 美元建议日期不早于 2020 年且距今至少 6 个月。9. 界面布局与可视化组件页面采用三栏布局page.tsx左栏 PromptPanelCopilotChat 聊天面板展示可用现金与初始化引导语prompt-panel.tsx中栏 GenerativeCanvas渲染 Performance折线图、Allocation分配表、Returns柱状图、Market Insights牛/熊洞察卡片与 Custom Charts 区块generative-canvas.tsx顶栏 CashPanel展示并支持编辑 Total Cash、Invested、Portfolio Value、4-Year Return 与 Portfolio Allocation 进度条cash-panel.tsx。图表组件基于Rechartsrecharts^3.0.2见 frontend/package.json位于frontend/src/app/components/chart-components/line-chart.tsx组合 vs SPY 净值曲线、bar-chart.tsx各 ticker 收益、allocation-table.tsxTicker/% /Value/Return 表格、insight-card.tsx牛熊卡片。10. Next.js 代理路由frontend/src/app/api/copilotkit/route.ts 中前端通过CopilotRuntime注册crewaiAgent的HttpAgent并借助copilotRuntimeNextJSAppRouterEndpoint把/api/copilotkit端点与OpenAIAdapter组合起来实现浏览器 → Next.js 路由 → FastAPI 后端的请求转发与 SSE 回流。端到端使用流程打开 UI浏览器访问http://localhost:3000左侧聊天面板会显示 Agent 的自我介绍与示例引导Invest in Apple with 10k dollars since Jan 2023并注明仅支持过去 4 年数据发起分析在输入框提交类似Analyze AAPL and MSFT with $10k each的投资请求。可观察以下实时事件流ToolLogs 依次出现并点亮 Analyzing user query → Gathering Stock Data → Allocating cash → Extracting Key insights组合面板的 investment_portfolio 被增量更新新 ticker 追加图表工具调用到达后Performance 折线图组合 vs SPY、Returns 柱状图、Allocation 表格渲染完成并出现 Accept/Reject 按钮供用户确认page.tsx接受后牛/熊洞察卡片显示在 Market Insights 区块CashPanel 更新总现金、已投入与 4 年回报查看结果若投资参数未被解析例如纯闲聊消息Agent 会以打字机效果输出普通文本回复不触发任何图表。开发注意事项与扩展方向解释器环境若编辑器报缺失导入请确保其指向安装了依赖的同一 Python 环境uv、venv、conda均可README 推荐在仓库根目录执行uv sync。FastAPI 应用位于agent/main.py核心工作流逻辑位于agent/stock_analysis.py。模型配置意图解析与洞察生成硬编码使用gpt-4o-mini见 stock_analysis.py 与 #L978-L986依赖OPENAI_API_KEY如需更换模型修改这两处model参数即可但需确认目标模型兼容 OpenAI 函数调用格式。数据边界行情仅覆盖最近 4 年、粒度为季度interval3moSPY 基准使用日线如需更精细回测可调整 simulation 阶段 的 interval 参数。可扩展方向从源码结构看前端已预留render_custom_charts动作与sandBoxPortfolio状态可以在此基础上扩展沙盒组合 vs 真实组合的对比分析也可以将extract_relevant_data_from_user_prompt的 enum 值扩展更多投资频率。总结stock-portfolio-analysis-agent是一个值得完整研读的端到端示例它把AG-UI 事件协议事件类型、SSE 编码、增量状态、CrewAI Flow 多阶段编排、yfinance 行情模拟与 SPY 基准对比、CopilotKit React 前端渲染四层技术无缝串联并额外展示了事件节流优先渲染图表这类贴近真实产品体验的工程技巧。无论你是要构建实时可观测的 Agent 应用还是需要一套可复用的金融分析 Agent 参考实现都可以从 agent/main.py、agent/stock_analysis.py 与 frontend/src/app/page.tsx 这三处源码入手逐步拆解其设计并迁移到自己的项目中。【免费下载链接】ai-engineering-hubIn-depth tutorials on LLMs, RAGs and real-world AI agent applications.项目地址: https://gitcode.com/GitHub_Trending/ai/ai-engineering-hub创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进