data_analysis_agent.py 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. """
  2. 智能股票分析助手 — 数据分析Agent
  3. 基于 HelloAgents ReActAgent,使用 mx_data 工具查询行情和财务数据,
  4. 执行基本面和技术面的深度分析。
  5. 使用方式:
  6. from agents.data_analysis_agent import create_data_analysis_agent
  7. agent = create_data_analysis_agent(api_key="...", llm=llm)
  8. result = agent.run("分析贵州茅台的财务指标和估值水平")
  9. """
  10. import sys
  11. from pathlib import Path
  12. _PROJECT_ROOT = Path(__file__).parent.parent
  13. _HELLO_PATH = _PROJECT_ROOT / "HelloAgents Optimized"
  14. _AGENTS_DIR = _PROJECT_ROOT / "agents"
  15. _BACKEND_DIR = _PROJECT_ROOT / "backend"
  16. _SKILLS_DATA = _PROJECT_ROOT / "skills" / "金融数据" / "mx-data"
  17. for p in [_HELLO_PATH, _AGENTS_DIR, _BACKEND_DIR, _SKILLS_DATA]:
  18. if str(p) not in sys.path:
  19. sys.path.insert(0, str(p))
  20. from typing import Iterator
  21. from hello_agents.tools import ToolRegistry
  22. from hello_agents.agents.react_agent import ReActAgent
  23. from hello_agents.core.llm import HelloAgentsLLM
  24. from hello_agents.core.config import Config
  25. from hello_agents.core.stream import StreamEvent
  26. from agents.tools.mx_data_tool import MXDataTool
  27. # 数据分析Agent系统提示词
  28. DATA_ANALYSIS_PROMPT = """你是一位专业的A股数据分析师,精通基本面分析和技术面分析。
  29. ## 你的职责
  30. 1. 查询目标股票的实时行情数据(价格、涨跌幅、成交量、换手率等)
  31. 2. 分析核心财务指标(ROE、净利润、营收增长率、毛利率等)
  32. 3. 评估估值水平(市盈率、市净率、股息率等)
  33. 4. 查看公司基本概况(主营业务、行业地位、高管等)
  34. 5. 结合多维数据给出基本面和技术面的综合评估
  35. ## 分析框架
  36. - **盈利能力**: ROE、净利润率、毛利率、营收增长率
  37. - **估值水平**: PE、PB、PS、PEG
  38. - **成长性**: 近3年营收/利润复合增长率
  39. - **现金流**: 经营现金流/净利润比率
  40. - **分红**: 股息率、分红率、分红稳定性
  41. ## 输出格式
  42. 分析结果应包含:
  43. 1. **行情快照**:最新价格、涨跌幅、成交情况
  44. 2. **财务健康度**:核心指标雷达图式评估
  45. 3. **估值分位**:当前估值在历史区间的位置
  46. 4. **亮点与风险**:2-3个关键发现
  47. ## 重要提醒
  48. - 数据优先,所有结论需有查询数据支撑
  49. - 历史对比时标明时间区间
  50. - 末尾标注免责声明
  51. ## ReAct 回合输出(与框架对接,必须遵守)
  52. 每一轮模型回复都必须同时包含下面两行(缺一不可),禁止只输出 Markdown 报告正文而不写 Action:
  53. - `Thought:` 一行简明推理(可与中文「思考:」择一,但推荐英文标签)
  54. - `Action:` 要么是 `mx_data[查询指令]`,要么是 **最终结论** `Finish[完整分析报告正文]`
  55. 准备输出最终报告时,也必须使用 `Action: Finish[...]` 包裹全文;`[` 与结尾 `]` 必须成对,报告内如需括号请避免单独的 `]` 破坏配对,或把长报告压缩为不含裸 `]` 的表述。
  56. """
  57. def create_data_analysis_agent(
  58. api_key: str = None,
  59. llm: HelloAgentsLLM = None,
  60. system_prompt: str = None,
  61. max_steps: int = 8,
  62. ) -> ReActAgent:
  63. """创建数据分析Agent
  64. Args:
  65. api_key: 东方财富MX_APIKEY
  66. llm: HelloAgentsLLM实例(必需)
  67. system_prompt: 自定义系统提示词(可选)
  68. max_steps: 最大推理步数,默认8(数据分析需要多步查询)
  69. Returns:
  70. 配置好的ReActAgent实例
  71. """
  72. if llm is None:
  73. llm = _create_default_llm()
  74. registry = ToolRegistry()
  75. data_tool = MXDataTool(api_key=api_key)
  76. registry.register_tool(data_tool)
  77. prompt = system_prompt or DATA_ANALYSIS_PROMPT
  78. agent = ReActAgent(
  79. name="数据分析Agent",
  80. llm=llm,
  81. tool_registry=registry,
  82. system_prompt=prompt,
  83. config=Config(temperature=0.2, max_tokens=4096),
  84. max_steps=max_steps,
  85. )
  86. return agent
  87. def _create_default_llm() -> HelloAgentsLLM:
  88. """从环境变量创建默认LLM实例"""
  89. import os
  90. model = os.getenv("LLM_MODEL_ID")
  91. api_key = os.getenv("LLM_API_KEY")
  92. base_url = os.getenv("LLM_BASE_URL")
  93. provider = os.getenv("LLM_PROVIDER", "auto")
  94. if not api_key:
  95. raise RuntimeError(
  96. "LLM_API_KEY 环境变量未设置,请先设置环境变量:\n"
  97. "export LLM_API_KEY=your_llm_api_key_here\n"
  98. "或在创建Agent时传入 llm 参数"
  99. )
  100. return HelloAgentsLLM(
  101. model=model,
  102. api_key=api_key,
  103. base_url=base_url,
  104. provider=provider,
  105. temperature=0.2,
  106. )
  107. def analyze_data_stream(
  108. agent: ReActAgent,
  109. stock_code: str = "",
  110. stock_name: str = "",
  111. ) -> Iterator[dict]:
  112. """流式数据分析 - 通过ReActAgent查询行情和财务数据并分析
  113. Args:
  114. agent: 已配置的数据分析Agent
  115. stock_code: 股票代码
  116. stock_name: 股票名称
  117. Yields:
  118. dict: {"type": "meta"|"status"|"delta"|"done"|"error", "content": str}
  119. """
  120. stock_label = f"{stock_name}({stock_code})" if stock_name else stock_code
  121. yield {"type": "meta", "stock_code": stock_code, "stock_name": stock_name}
  122. yield {"type": "status", "content": f"正在查询 {stock_label} 的行情和财务数据..."}
  123. task = f"""请查询股票 {stock_label} 的以下数据并进行综合分析:
  124. 1. 实时行情(价格、涨跌幅、成交量、换手率等)
  125. 2. 核心财务指标(ROE、净利润、营收增长率、毛利率等)
  126. 3. 估值水平(市盈率、市净率、股息率等)
  127. 4. 公司基本概况
  128. 请给出专业的数据分析报告。"""
  129. try:
  130. for event in agent.stream_run(task):
  131. if event.event_type == "status":
  132. yield {"type": "status", "content": event.content}
  133. elif event.event_type in ("text", "observation"):
  134. yield {"type": "delta", "content": event.content}
  135. elif event.event_type == "tool_call":
  136. yield {"type": "status", "content": f"正在查询: {event.metadata.get('tool_name', '')}"}
  137. elif event.event_type == "done":
  138. yield {"type": "done"}
  139. elif event.event_type == "error":
  140. yield {"type": "error", "content": event.content}
  141. except Exception as e:
  142. yield {"type": "error", "content": f"数据分析出错: {e}"}