从零实现股票分析智能体:FDE与Agent开发实战指南
发布时间:2026/9/2 19:17:23 作者:尧图编辑部 阅读量:1,286

1. FDE是做什么的Agent开发为什么需要FDE最近聊Agent开发的同学明显变多了但很多人学完LangChain、看完几篇Prompt教程后依然卡在同一个问题平时调API、跑Demo都很顺一旦面对真实业务需求需求拆不清楚、文档写不明白、代码改三版还是跑不通、Agent效果好不好也说不清。如果你是这种状态那这篇文章值得看完。FDEForward Deployment Engineer前沿部署工程师不是传统意义上的运维工程师而是负责把大模型能力真正落到业务场景中的角色。它最早由豆包等大模型团队在对外服务客户的过程中开始配备核心任务是理解客户业务、设计Agent与人协作的流程、进行项目落地实施并持续评估和优化效果。简单来说大模型算法工程师负责“把模型训好”而后端开发工程师负责“把系统做好”FDE负责的是“把场景跑通”。FDE和普通后端开发者的主要区别体现在几个方面对比维度传统后端开发FDE/Agent开发核心产出接口、系统、功能模块Agent、工作流、业务闭环需求来源产品文档、交互稿业务痛点 大模型能力 用户反馈效果验证功能测试、性能测试评测集、人工评估、真实场景回归主要风险报错、崩溃、数据不一致模型幻觉、工具调用失败、需求理解偏差迭代方式版本发布评测驱动、快速试错如果你正在准备Agent开发或者想转FDE方向建议先建立一套完整的项目实践认知。本文就以一个股票分析智能体为例完整走一遍FDE的干活流程需求拆解、文档设计、Vibe-Coding开发、评测驱动验证。无论你是零基础入门还是已有后端经验想转Agent方向都可以跟着做一遍。2. Agent开发的核心概念与技术栈在进入股票分析智能体项目之前先对齐几个基础概念。Agent不是简单“调用大模型接口然后返回结果”而是一个具备目标理解、任务规划、工具调用、记忆管理等能力的智能体系统。2.1 Agent的典型架构目前业界比较通用的Agent架构可以拆成四层模型层大语言模型负责理解用户意图、生成回复、决定调用哪个工具。常见选择有OpenAI的GPT系列、豆包大模型、通义千问、DeepSeek等。规划层负责把复杂任务拆解成子步骤。比如用户问“看一下最近一个月某股票的走势并给出分析”Agent需要先拆成“获取行情数据→计算技术指标→判断趋势→生成报告”这几步。工具层为Agent提供调用外部数据或系统的能力。股票分析智能体至少需要“获取股票行情”“计算技术指标”“获取公司基本面信息”等工具。记忆层保存对话上下文、历史分析记录、用户偏好等。项目初期可以先用列表保存短期记忆进阶再引入向量数据库做长期记忆。2.2 Agent开发需要哪些技术栈作为新手不需要一上来就堆很多框架。核心技术栈和说明如下技术/工具作用重要程度Python主流AI生态语言写Agent最顺手必须掌握大模型APIAgent的“大脑”通过API调用即可必须掌握工具函数用普通Python函数实现数据获取、计算必须掌握一个Agent框架LangChain、LlamaIndex或自研简化框架按需选择关系型数据库保存历史记录、评测结果进阶使用Docker部署Agent服务进阶使用向量数据库管理长期记忆、知识库进阶使用坦白说现阶段做Agent开发并不需要一上来就精通LangChain所有模块。更重要的是理解“LLM 工具 评测”这个闭环。你完全可以先用原生Python写一个最简Agent主控循环跑通之后再决定要不要用框架。3. 股票分析智能体需求拆解Agent开发最怕需求模糊。传统后端开发时产品经理会把需求写清楚但Agent项目的难点在于业务方往往不知道自己想要什么或者说出来的需求和真正能落地的形态之间差距很大。3.1 业务目标我们先给股票分析智能体定义一个清晰的目标用户输入股票代码如 600519.SH 或 AAPL智能体自动获取历史行情数据计算常用技术指标输出趋势判断和风险提示并生成一份结构化分析报告。需要特别说明的是本文项目只做“技术分析和报告生成”不接真实交易下单不构成投资建议。这一点在需求阶段就应该明确写进文档否则Agent一旦输出“建议买入”之类的内容会带来合规风险。3.2 功能模块拆分把业务目标拆成功能模块如下数据获取模块根据股票代码获取最近N日历史行情数据包括开、高、低、收、成交量。指标计算模块计算移动平均线MA、相对强弱指数RSI、MACD等常用技术指标。趋势判断模块根据指标数值生成趋势信号例如多头排列、空头排列、超买、超卖。报告生成模块将数据、指标、信号整理成中英文均可的结构化报告输出Markdown格式方便直接展示。3.3 数据源选择股票行情数据建议通过第三方开源库获取。最常用的是 Python 的yfinance它封装了获取 Yahoo Finance 数据的接口用法简单适合做技术分析。但使用外部数据源时要注意遵守数据源的服务条款和频率限制。部分数据源在某些网络环境下可能不可用需要额外的网络配置本文不做展开。演示场景建议使用模拟数据兜底避免因网络问题导致Agent运行中断。3.4 需求边界明确边界是FDE的重要工作之一。本项目“不做”的事情包括不接真实证券账户不做自动交易。不做长文本金融知识问答只做行情数据指标分析。不保证预测准确性输出结果仅供参考不构成投资建议。把这些边界写在需求文档里开发时就不会被各种“顺手加个功能”的诉求带偏。4. 从需求到文档PRD与Agent设计需求拆解清楚后下一步是写文档。很多开发者不爱写文档觉得浪费时间但Agent项目不写文档的后果非常严重AI生成的代码没有依据、功能边界模糊、评测标准无法制定。FDE的文档不一定很长但必须覆盖目标和验收标准。4.1 最小PRD模板一个适合Agent项目的PRD建议包含以下内容模块内容示例项目目标实现一个股票分析智能体支持行情获取、指标计算、趋势分析、报告生成用户画像个人投资者、技术分析爱好者核心流程输入股票代码 → 获取数据 → 计算指标 → 分析信号 → 输出报告功能清单数据获取、指标计算、趋势判断、报告生成异常处理股票代码不存在、网络超时、数据为空评测标准工具调用正确、报告格式合规、指标计算准确安全边界不提供投资建议、不接真实交易4.2 Agent系统提示词设计文档写好之后进入Agent设计阶段。首先需要设计系统提示词。在Agent开发中系统提示词相当于“岗位说明书”它决定了Agent的角色、能力范围和输出风格。你是一名专业的股票数据分析助手。 你擅长获取股票历史行情数据计算技术指标并输出结构化分析报告。 工作流程 1. 用户提供股票代码后先调用 get_stock_data 工具获取数据。 2. 数据获取成功后调用 calculate_indicators 工具计算技术指标。 3. 根据指标结果在分析报告中给出趋势判断和风险提示。 4. 输出报告必须包含股票代码、时间范围、核心指标数据、趋势判断、风险提示。 5. 如果用户输入的不是合法股票代码请礼貌说明并提供示例格式。 重要规则 - 报告仅基于历史数据和技术指标生成不构成投资建议。 - 如果数据获取失败请明确提示原因不要编造数据。注意几个细节系统提示词明确写了调用工具的顺序明确写了“不要编造数据”。这些都是实际Agent开发中非常重要的点因为大模型在没有数据时很容易“一本正经地胡说八道”。4.3 工具Schema设计在Agent开发中工具的定义方式很影响调用成功率。如果使用OpenAI兼容接口工具需要按照JSON Schema格式定义。下面是一个简化示例{ type: function, function: { name: get_stock_data, description: 获取股票历史行情数据, parameters: { type: object, properties: { symbol: { type: string, description: 股票代码例如 600519.SH 或 AAPL }, period: { type: string, description: 时间范围例如 1mo 表示最近一个月 } }, required: [symbol] } } }工具描述写得越清晰大模型正确调用工具的概率越高。这里有一个容易被忽略的点description字段里要写明股票代码格式示例否则大模型可能把“贵州茅台”直接传给接口而不是传“600519.SH”。5. Vibe-Coding实战自然语言驱动开发Vibe-Coding是最近很火的开发方式核心思想是用自然语言描述需求让AI生成代码开发者负责审查和串联。它特别适合Agent项目的前期原型搭建因为Agent代码往往涉及大量胶水逻辑和模板代码用自然语言驱动可以大幅提高效率。但要注意Vibe-Coding不等于“把代码全部丢给AI然后不管”。在实际项目中更推荐的做法是把PRD拆成多个小模块每个模块单独交给AI实现然后人工审查、测试、集成。5.1 如何向AI描述需求还是以数据获取模块为例。假设我们要让AI写一个Python函数可以这样描述请帮我实现一个Python函数 get_stock_data(symbol, period)用于获取股票历史行情数据。 要求使用 yfinance 库。返回一个字典包含日期列表、收盘价列表、成交量列表。如果网络请求失败抛出带有明确错误信息的异常。写上完整的类型注解。用中文注释解释关键步骤。这个描述包含了函数签名、依赖库、返回值结构、异常处理、类型注解AI生成的结果质量会明显高于“帮我写个股票数据函数”。5.2 数据获取模块代码示例下面是一个可以直接保存的示例文件# 文件路径stock_agent/tools/data_loader.py 股票行情数据获取模块。 from typing import Dict, List, Optional from datetime import datetime, timedelta try: import yfinance as yf except ImportError: yf None def get_stock_data(symbol: str, period: str 1mo) - Dict[str, List]: 获取股票历史行情数据。 Args: symbol: 股票代码例如 600519.SH 或 AAPL period: 时间范围例如 1mo、3mo、1y Returns: 包含日期、收盘价、成交量的字典。 Raises: RuntimeError: 当数据获取失败或yfinance未安装时。 if yf is None: raise RuntimeError(yfinance 未安装请先执行 pip install yfinance) try: ticker yf.Ticker(symbol) hist ticker.history(periodperiod) if hist is None or hist.empty: raise RuntimeError(f股票代码 {symbol} 未获取到行情数据请检查代码是否正确) dates [str(d.date()) for d in hist.index] closes [round(float(v), 2) for v in hist[Close]] volumes [int(v) for v in hist[Volume]] return { symbol: symbol, dates: dates, closes: closes, volumes: volumes, } except Exception as e: raise RuntimeError(f获取股票数据失败: {str(e)}) from e def get_mock_stock_data(symbol: str, days: int 30) - Dict[str, List]: 生成模拟行情数据用于网络不可用时的演示兜底。 Args: symbol: 股票代码 days: 模拟数据天数 Returns: 与 get_stock_data 返回结构一致的字典。 import random random.seed(hash(symbol) % 10000) base_price 50.0 random.random() * 200 dates, closes, volumes [], [], [] for i in range(days): date datetime.now() - timedelta(daysdays - i) dates.append(str(date.date())) base_price * (1 (random.random() - 0.48) * 0.05) closes.append(round(base_price, 2)) volumes.append(random.randint(500000, 5000000)) return { symbol: symbol, dates: dates, closes: closes, volumes: volumes, }核心要点是数据获取函数只做数据获取这一件事返回值结构固定方便后续指标计算模块直接消费。同时提供了模拟数据兜底函数避免因网络问题中断演示。6. 评测驱动开发EDD让Agent质量可度量Agent开发和传统软件开发最大的不同在于传统代码对错基本确定而Agent的行为有很强的随机性。同一套Prompt这次输出可以下次可能就跑偏。因此Agent开发必须用“评测驱动”的方式来管理质量。评测驱动开发Evaluation-Driven DevelopmentEDD的核心思想是先定义好“什么是好的答案”再开发Agent每次改动都跑一遍评测用数据判断改动是变好还是变差。6.1 构建评测集股票分析智能体的评测集至少应包含三类用例正常用例输入合法的股票代码期望Agent正确调用工具并输出完整报告。边界用例输入不存在的股票代码期望Agent提示错误信息而不是编造数据。指令遵从用例要求Agent只输出指定格式的报告期望输出严格遵守格式要求。下面是一个评测集示例[ { case_id: normal_001, input: 请分析一下AAPL最近一个月的走势, expected_tools: [get_stock_data, calculate_indicators], expected_fields: [symbol, trend, risk, indicators] }, { case_id: edge_001, input: 请分析一下ZZZZZ这只股票的走势, expected_behavior: should_error, expected_message: 股票代码无效或未获取到数据 }, { case_id: format_001, input: 请用markdown表格格式输出AAPL的技术指标, expected_fields: [indicators], expected_format: markdown } ]6.2 评测指标在Agent开发中常用的评测指标包括指标含义说明工具调用成功率Agent正确调用所需工具的比例直接反映Agent的“动手能力”字段完整率输出报告中必填字段是否齐全反映报告质量格式合规率输出是否符合指定格式反映指令遵从能力幻觉率是否编造了数据或不存在的结论安全底线指标平均响应时长从输入到输出的耗时影响用户体验6.3 自动化评测脚本下面是一个简化评测脚本示例用于检查Agent输出是否包含预期字段# 文件路径stock_agent/evaluation/evaluate.py 基于评测集的自动化评测脚本。 import json import time from typing import Dict, List def load_test_cases(file_path: str) - List[Dict]: 加载评测集。 with open(file_path, r, encodingutf-8) as f: return json.load(f) def evaluate_case(test_case: Dict, agent_predict) - Dict: 评测单个用例。 Args: test_case: 评测用例 agent_predict: 调用Agent的函数输入用户消息输出Agent回复 Returns: 包含是否通过、耗时、错误信息的字典。 start time.time() result { case_id: test_case[case_id], passed: False, message: , elapsed: 0.0, } try: if test_case.get(expected_behavior) should_error: # 期望Agent报错这里可以补充错误检测逻辑 result[passed] True else: output agent_predict(test_case[input]) text output[text] if isinstance(output, dict) else str(output) missing_fields [] for field in test_case.get(expected_fields, []): if field not in text: missing_fields.append(field) result[passed] len(missing_fields) 0 result[message] f缺失字段: {missing_fields} if missing_fields else OK except Exception as e: result[message] f执行异常: {str(e)} result[elapsed] round(time.time() - start, 2) return result def run_evaluation(test_cases: List[Dict], agent_predict) - Dict: 运行全部评测用例并输出汇总结果。 results [evaluate_case(case, agent_predict) for case in test_cases] passed_count sum(1 for r in results if r[passed]) return { total: len(results), passed: passed_count, pass_rate: round(passed_count / len(results), 2), details: results, }这个脚本的价值在于有了它每次修改Prompt或工具定义后只要跑一次就能看到通过率是升还是降。这是评测驱动开发落地的基础设施没有这套机制Agent优化就全靠“感觉”。7. 完整实战跑通一个最小闭环上面几节分别介绍了需求、文档、Vibe-Coding和评测。本节把整个项目串起来从创建项目到运行验证完整过一遍。7.1 项目结构推荐按职责划分目录stock_agent/ ├── agent.py # Agent主控循环 ├── requirements.txt # 依赖清单 ├── app.py # 入口接收命令行输入 ├── tools/ │ ├── __init__.py │ ├── data_loader.py # 数据获取模块 │ └── indicators.py # 技术指标计算模块 ├── evaluation/ │ ├── __init__.py │ ├── evaluate.py # 自动化评测脚本 │ └── test_cases.json # 评测集 └── README.md7.2 添加依赖在requirements.txt中写入yfinance0.2.40注意版本号可以根据实际环境调整。如果担心网络环境无法安装yfinance可以先不安装在代码中使用get_mock_stock_data函数兜底。安装命令如下pip install -r requirements.txt7.3 技术指标计算模块# 文件路径stock_agent/tools/indicators.py 技术指标计算模块。 from typing import Dict, List from .data_loader import get_mock_stock_data, get_stock_data def calculate_indicators(data: Dict[str, List]) - Dict[str, Dict]: 计算常用技术指标。 当前实现 MA5、MA20、RSI14。MACD 可根据需要补充。 Args: data: 行情数据字典包含 dates、closes、volumes。 Returns: 指标结果字典。 closes data[closes] n len(closes) def calc_ma(window: int) - List[float]: result [None] * n for i in range(window - 1, n): avg sum(closes[i - window 1 : i 1]) / window result[i] round(avg, 2) return result def calc_rsi(period: int 14) - List[float]: result [None] * n gains, losses [], [] for i in range(1, n): change closes[i] - closes[i - 1] gains.append(max(change, 0)) losses.append(abs(min(change, 0))) if len(gains) period: return result avg_gain sum(gains[:period]) / period avg_loss sum(losses[:period]) / period for i in range(period, n): if avg_loss 0: result[i] 100.0 else: rs avg_gain / avg_loss result[i] round(100 - 100 / (1 rs), 2) avg_gain (avg_gain * (period - 1) gains[i - 1]) / period avg_loss (avg_loss * (period - 1) losses[i - 1]) / period return result return { ma5: calc_ma(5), ma20: calc_ma(20), rsi14: calc_rsi(14), } def generate_trend_signal(indicators: Dict[str, List]) - str: 根据技术指标生成趋势判断。 Args: indicators: 指标字典。 Returns: 趋势信号字符串。 ma5 indicators[ma5] ma20 indicators[ma20] closes ma5 # 简化处理实际应传入收盘价 latest_ma5 next((v for v in reversed(ma5) if v is not None), None) latest_ma20 next((v for v in reversed(ma20) if v is not None), None) if latest_ma5 is None or latest_ma20 is None: return 数据不足无法判断趋势 if latest_ma5 latest_ma20: return 短期均线位于长期均线上方短期趋势偏多 elif latest_ma5 latest_ma20: return 短期均线位于长期均线下方短期趋势偏空 else: return 短期均线与长期均线接近趋势不明朗这个模块把指标计算和趋势判断分开便于后续单元测试。7.4 Agent主控循环# 文件路径stock_agent/agent.py 股票分析智能体主控循环。 import json from typing import Dict, List from tools.data_loader import get_mock_stock_data, get_stock_data from tools.indicators import calculate_indicators, generate_trend_signal class StockAnalysisAgent: 股票分析智能体当前为简化实现不依赖大模型API。 def __init__(self, use_mock: bool False): self.use_mock use_mock def run(self, user_input: str) - Dict: 执行分析任务。 Args: user_input: 用户输入例如 分析 AAPL 最近一个月走势 Returns: 结构化分析结果字典。 symbol self._parse_symbol(user_input) if symbol is None: return { success: False, message: 未识别到股票代码请输入合法股票代码例如 AAPL 或 600519.SH, } # Step 1: 获取数据 try: if self.use_mock: data get_mock_stock_data(symbol) else: data get_stock_data(symbol, period1mo) except Exception as e: return { success: False, message: f数据获取失败: {str(e)}, } # Step 2: 计算指标 indicators calculate_indicators(data) # Step 3: 趋势判断 trend generate_trend_signal(indicators) # Step 4: 组装报告 report self._format_report(data, indicators, trend) return { success: True, symbol: symbol, trend: trend, report: report, } def _parse_symbol(self, user_input: str) - str | None: 从用户输入中提取股票代码。 支持格式 - 纯英文代码如 AAPL - 带交易所后缀如 600519.SH stripped user_input.strip() upper stripped.upper() if upper.endswith(.SH) or upper.endswith(.SZ) or upper.endswith(.HK): return upper if upper.isalpha() and 1 len(upper) 6: return upper return None def _format_report(self, data: Dict, indicators: Dict, trend: str) - str: 转成 Markdown 报告。 symbol data[symbol] dates data[dates] closes data[closes] latest_close closes[-1] if closes else N/A latest_date dates[-1] if dates else N/A latest_rsi next((v for v in reversed(indicators[rsi14]) if v is not None), N/A) report f## 股票分析报告{symbol} **报告日期**{latest_date} **最新收盘价**{latest_close} ### 趋势判断 {trend} ### 核心指标 - RSI14{latest_rsi} ### 数据概览 | 日期 | 收盘价 | | --- | --- | for i in range(max(0, len(dates) - 10), len(dates)): report f| {dates[i]} | {closes[i]} |\n report \n 免责声明本报告仅基于历史数据和技术指标生成不构成投资建议。 return report当前版本为了便于直接运行没有接入大模型API而是用规则解析股票代码后直接走工具函数。这种方式能快速验证工具和数据流程后续可以再接入LLM让模型决定调用哪个工具。7.5 运行入口# 文件路径stock_agent/app.py 命令行入口。 import sys from agent import StockAnalysisAgent def main(): agent StockAnalysisAgent(use_mockTrue) # 网络不可用时先使用模拟数据 if len(sys.argv) 2: print(用法: python app.py 分析 AAPL 最近一个月走势) return user_input sys.argv[1] result agent.run(user_input) if result[success]: print(result[report]) else: print(f分析失败: {result[message]}) if __name__ __main__: main()运行命令cd stock_agent python app.py 分析 AAPL 最近一个月走势预期输出是一份Markdown格式的股票分析报告包含股票代码、最新收盘价、趋势判断、指标数据和免责声明。7.6 验证完整流程刚才的代码虽然简化了但已经形成“用户输入→数据获取→指标计算→趋势判断→报告输出”的完整闭环。在此基础上你要做两件事接入真实数据源把use_mock设为False验证yfinance能正常工作。接入大模型API让LLM动态决定工具调用顺序替换掉当前规则解析的写法。8. 常见问题与排查思路Agent开发过程中以下几个问题出现频率很高结合实际经验整理成表格问题现象常见原因解决思路Agent输出格式不稳定系统提示词不够具体未明确输出格式在Prompt中给出示例输出模板并用评测集格式约束工具参数传错比如把“AAPL”传成“苹果”工具Schema描述不清晰在工具description中注明股票代码示例格式数据获取失败Agent却编造了一组数字缺少异常处理逻辑模型幻觉兜底强制要求“数据获取失败时必须提示错误不得编造数据”评测通过率不稳定评测集太小或提示词未固定扩充评测集固定系统提示词版本多次采样取平均值同一份Prompt不同模型效果差异大模型能力差异参数化模型配置记录每次实验使用的模型和评测结果工具函数报错导致Agent直接崩溃工具层未做异常捕获所有工具函数统一抛出带提示的异常主控模块统一捕获排查Agent问题时建议按“输入→规划→工具→输出”的顺序逐步定位。先看用户输入是否被正确解析再看Agent是否选择了正确工具然后检查工具返回的数据格式最后检查输出报告是否符合预期。9. FDE工程师的工程化建议与学习路线写到这里你应该已经完成了一个最小可运行的股票分析智能体。接下来给它加评测、加模型、加记忆才能真正达到工程可用标准。9.1 项目落地建议文档先行先把业务目标和边界写清楚再动手Agent项目尤其需要。最少必要工具优先只做3到4个最核心的工具不要一上来就接一堆API。工具越多Agent的调用错误率越高。评测集倒推需求如果你不知道某个功能要不要做先写评测用例。写不出来评测用例的功能大概率不需要做。先跑通死流程再上Agent先用代码写死工具调用顺序确认数据和报告没问题再让LLM接管决策。日志和观测每一步记录使用了哪个模型、调用了哪个工具、耗时多少、输出是什么。没有日志Agent出问题时无从排查。灰度发布新Prompt或新工具可以先让10%的用户试用观察评测通过率后再全量切换。9.2 Agent开发学习路线如果你刚开始转Agent开发可以按下面的路径循序渐进Python基础重点掌握函数、异常处理、类型注解、文件读写。大模型API调用熟悉System/User/Assistant消息结构掌握流式输出。工具函数设计学会定义清晰的输入输出结构让LLM容易调用。Prompt工程学习System Prompt设计、Few-shot示例、约束性表达。Agent开发框架理解LangChain等框架的Workflow和Tool调用机制。评测与部署掌握评测集构建、自动化评测、Docker部署。很多同学卡在第4步到第5步原因是没有实际项目驱动。建议就用本文的股票分析智能体动手一遍把规则解析改成LLM决策再给Agent加上几个新工具比如获取公司基本面信息、获取行业新闻这样你对Agent开发的理解会深很多。10. 最后说两句FDE这个角色本质上不是“提示词工程师”也不是“API调用师”而是能把大模型能力变成业务价值的落地者。它的核心工作方式是需求拆解、文档设计、Vibe-Coding快速开发、评测驱动保障质量。这四个环节缺一不可。本文从零实现了一个股票分析智能体但它支撑的最重要能力不是技术指标计算而是帮你建立了一个可复用、可评测、可扩展的Agent样板。接下来可以做的方向有很多把技术指标拓展到MACD、布林带把报告输出接到飞书或钉钉机器人定时推送加入历史分析结果的长期记忆把评测机制迁移到其他场景比如客服助手、数据分析助手等。如果你正准备面试Agent开发或FDE方向建议把评测驱动开发的实践作为自己的亮点项目来准备。动手做一遍比读十篇教程都有用。