当前位置:首页>python>科大讯飞AstronClaw发布后:Python实战从零构建AI Agent系统

科大讯飞AstronClaw发布后:Python实战从零构建AI Agent系统

  • 2026-09-08 22:08:51
科大讯飞AstronClaw发布后:Python实战从零构建AI Agent系统

 科大讯飞AstronClaw发布后:Python实战从零构建AI Agent系统

 文 | 程飞  |  2026年4月16日


 科大讯飞4月15日发布了AstronClaw智能体矩阵,整个科技圈都在讨论"AI Agent时代真的来了"这件事。我没打算凑这个热闹,我想做的是一件事:把它拆成代码,然后看看能不能自己动手复现一个简化版的框架。

 这篇文章分两部分:第一部分,我会拆解一个最小化的AI Agent系统应该包含哪些核心模块;第二部分,我会用Python写出这些模块的代码,可以直接跑。不会写大模型底层,不会搞黑科技,就是工程化地解决实际问题。

 一、最小化AI Agent系统 = 四个模块的循环

 先说清楚一个核心概念:什么是AI Agent?拆到最底层,它就是四件事的循环:感知(Perceive)、规划(Plan)、行动(Act)、记忆(Memory)。科大讯飞的AstronClaw也好,OpenAI的Operator也好,本质上都是这四个模块的不同实现。

 感知模块负责接收输入——用户的语音、文本、传感器数据,诸如此类。规划模块负责拆解任务——用户说"帮我分析这家公司值不值得投资",规划模块要把它拆解成"查财报、读新闻、跑量化模型、出结论"这几个步骤。行动模块负责调用工具——调用搜索API、运行Python脚本、查数据库,诸如此类。记忆模块负责存储上下文——历史对话、用户偏好、任务进度,都存在这里。

 科大讯飞的Claw框架,本质上就是把这四个模块标准化了,然后开放API让开发者接入自己的工具和场景。理解了这个,你就理解了为什么SkillHub开源是这次发布最有战略价值的部分。

 二、实战:从零构建一个股票分析Agent

 理论说完了,上代码。这个场景我选的是"股票分析Agent"——用户给一个股票代码,Agent自动调用多个工具收集信息,然后综合分析给出一个结论。完全用Python实现,不依赖任何商业Agent框架。

 2.1 基础框架结构

import json
import time
from typing import List, Dict, Any, Optional
from dataclasses import dataclass, field
from enum import Enum

class TaskStatus(Enum):
    PENDING = "pending"
    RUNNING = "running"
    COMPLETED = "completed"
    FAILED = "failed"

@dataclass
class Message:
    role: str  # "user" / "assistant" / "system"
    content: str
    timestamp: float = field(default_factory=time.time)

@dataclass
class Tool:
    name: str
    description: str
    input_schema: Dict[str, Any]
    function: callable  # 实际执行函数

 这几行代码定义了整个Agent系统的核心数据结构。Message是消息单元,Tool是工具定义,TaskStatus是任务状态枚举。没有任何花哨的东西,就是为了类型安全和代码可读性。

 2.2 记忆模块实现

class Memory:
    """记忆模块:管理对话历史和任务上下文"""

    def __init__(self, max_history: int = 100):
        self.messages: List[Message] = []
        self.max_history = max_history
        self.context: Dict[str, Any] = {}  # 跨对话的持久上下文
        self.task_history: List[Dict] = []  # 历史任务记录

    def add_message(self, role: str, content: str):
        self.messages.append(Message(role=role, content=content))
        # 防止内存溢出,只保留最近N条
        if len(self.messages) > self.max_history:
            self.messages = self.messages[-self.max_history:]

    def get_context_window(self, window_size: int = 20) -> List[Message]:
        """获取最近N条消息,用于送入大模型"""
        return self.messages[-window_size:]

    def store_fact(self, key: str, value: Any):
        self.context[key] = value

    def get_fact(self, key: str, default: Any = None) -> Any:
        return self.context.get(key, default)

 记忆模块是整个系统里被很多人低估的组件。实际上,Agent的"智能"程度,很大程度上取决于记忆模块的设计——上下文窗口多大、历史信息怎么压缩、哪些信息值得长期存储。这些选择直接影响Agent的表现。我这里用的是一个简化版本,但思路是通用的。

 2.3 工具注册与调用

class ToolRegistry:
    """工具注册中心:管理所有可用工具"""

    def __init__(self):
        self.tools: Dict[str, Tool] = {}

    def register(self, name: str, description: str,
                input_schema: Dict[str, Any],
                function: callable):
        self.tools[name] = Tool(
            name=name,
            description=description,
            input_schema=input_schema,
            function=function
        )

    def execute(self, tool_name: str, **kwargs) -> Any:
        if tool_name not in self.tools:
            raise ValueError(f"Tool {tool_name} not found")
        tool = self.tools[tool_name]
        try:
            result = tool.function(**kwargs)
            return result
        except Exception as e:
            return {"error": str(e)}

    def list_tools(self) -> List[Dict]:
        return [
            {"name": t.name, "description": t.description,
              "input_schema": t.input_schema}
            for t in self.tools.values()
        ]

 ToolRegistry是工具层的核心抽象。任何外部能力——搜索API、数据库查询、Python脚本执行——只要包装成Tool注册进来,Agent就能调用。这就是为什么科大讯飞的SkillHub能接入那么多第三方技能——本质上是统一了工具的注册和调用协议。

 2.4 股票分析工具集:接入akshare获取实时数据

# 工具1:获取股票实时行情
def get_stock_quote(stock_code: str) -> Dict:
    """获取股票实时报价(示例用akshare)"""
    import akshare as ak
    try:
        # 获取单只股票实时数据
        df = ak.stock_zh_a_spot_em()
        row = df[df['代码'] == stock_code]
        if row.empty:
            return {"error": f"Stock {stock_code} not found"}
        data = row.iloc[0].to_dict()
        return {
            "code": stock_code,
            "name": data.get("名称", ""),
            "price": data.get("最新价", 0),
            "change_pct": data.get("涨跌幅", 0),
            "volume": data.get("成交量", 0),
            "turnover": data.get("成交额", 0)
        }
    except Exception as e:
        return {"error": str(e)}

# 工具2:获取股票历史K线数据
def get_stock_history(stock_code: str, period: str = "daily",
                           adjust: str = "qfq") -> Dict:
    """获取股票历史K线数据"""
    import akshare as ak
    try:
        df = ak.stock_zh_a_hist(
            symbol=stock_code,
            period=period,
            adjust=adjust,
            start_date="20260101",
            end_date="20260416",
            limit=30  # 最近30个交易日
        )
        # 计算简单技术指标
        df["MA5"] = df["收盘"].rolling(5).mean()
        df["MA20"] = df["收盘"].rolling(20).mean()
        return {
            "code": stock_code,
            "latest_price": df["收盘"].iloc[-1],
            "MA5": round(df["MA5"].iloc[-1], 2),
            "MA20": round(df["MA20"].iloc[-1], 2),
            "volume_ratio": round(
                df["成交量"].iloc[-1] / df["成交量"].rolling(20).mean().iloc[-1], 2
            )
        }
    except Exception as e:
        return {"error": str(e)}

 这两个工具是股票分析Agent的数据来源。get_stock_quote获取实时行情,get_stock_history获取历史数据并计算均线和量比。接入akshare,不需要任何收费数据接口,直接能跑。这是做量化最基础的技能,我强烈建议每个人都熟悉一下akshare的文档。

 2.5 Agent主循环:规划+执行+反思

class StockAnalysisAgent:
    """股票分析Agent:整合感知、规划、行动、记忆"""

    def __init__(self, llm_client, tools: ToolRegistry):
        self.llm = llm_client  # 接入任意LLM API
        self.tools = tools
        self.memory = Memory()

    def think(self, user_input: str) -> str:
        """Agent核心:思考-规划-执行循环"""
        # Step 1: 将用户输入存入记忆
        self.memory.add_message("user", user_input)

        # Step 2: 构建系统提示词(含工具描述)
        tool_descs = "\n".join([
            f"- {t['name']}: {t['description']}"
            for t in self.tools.list_tools()
        ])
        system_prompt = f"""
    你是一个股票分析助手。
    用户提出股票相关问题,你可以调用以下工具:
    {tool_descs}
    每次只调用一个工具。如果需要多个工具,按顺序逐一调用。
    """

        # Step 3: 与LLM对话直到任务完成
        MAX_ITERATIONS = 5
        for _ in range(MAX_ITERATIONS):
            # 构建消息历史
            messages = [
                {"role": "system", "content": system_prompt},
                *[{"role": m.role, "content": m.content}
                  for m in self.memory.get_context_window()]
            ]
            response = self.llm.chat(messages)

            # 解析LLM响应:判断是最终回答还是调用工具
            if response.is_final_answer:
                self.memory.add_message("assistant", response.content)
                return response.content
            else:
                # 执行工具调用
                tool_name = response.tool_to_call
                tool_result = self.tools.execute(**response.tool_args)
                self.memory.add_message("assistant",
                     f"[调用工具: {tool_name}]\n结果: {tool_result}")

        return "任务超时,未能在规定步数内完成。"

 这个Agent主循环的核心逻辑,是一个"思考-执行-反思"的循环:LLM决定是否调用工具,如果调用就执行并把结果放回上下文,然后继续问LLM要不要继续调用,直到LLM认为任务完成。这个循环就是AstronClaw、Operator、Claude的Computer Use等所有Agent框架的共同本质——差异只在细节。

 三、实际运行:分析一只股票

 框架搭好了,怎么用?简单演示一下完整流程。

# 初始化Agent
tools = ToolRegistry()
tools.register(
    "get_quote",
    "获取股票实时报价数据,包括最新价、涨跌幅、成交量",
    {"stock_code": "str"},
    get_stock_quote
)
tools.register(
    "get_history",
    "获取股票历史K线数据,计算均线和量比指标",
    {"stock_code": "str", "period": "str"},
    get_stock_history
)

# 假设有一个LLM客户端(支持OpenAI兼容API)
llm = OpenAICompatibleClient(api_key="your-key", base_url="...")
agent = StockAnalysisAgent(llm, tools)

# 运行分析
user_question = "帮我分析一下科大讯飞的股票,值得关注吗?"
answer = agent.think(user_question)
print(answer)

 运行这个脚本,Agent会自动完成以下步骤:先用get_quote获取科大讯飞的实时行情,再用get_history获取历史K线数据,然后综合这些数据给出分析结论。整个过程不需要人工干预,用户只需要问问题,Agent自动完成剩余的工作。

 四、Agent系统工程化的几个关键坑

 写了这么多,我踩过的坑还是要说两句,不然你们照着我的代码抄过去会遇到一堆莫名其妙的问题。

 第一个坑:工具描述的清晰度直接决定Agent表现。大模型调用工具的能力,取决于工具描述是否准确和完整。我见过太多人的工具描述写得像产品文档,LLM根本看不懂要传什么参数。工具描述要写成"输入什么,得到什么",越具体越好。

 第二个坑:循环终止条件要设好。我上面写的MAX_ITERATIONS=5是一个保守值,但实际项目里要根据任务复杂度调整。无限制的循环会让Agent一直调用工具不返回,如果你的场景涉及付费API调用,烧钱速度会超出你的预期。

 第三个坑:记忆模块的上下文窗口管理。上下文窗口不是越大越好,太大的上下文会增加推理成本和延迟,而且大模型对中间信息的注意力会稀释。我通常会根据任务类型预设窗口大小——简单查询用5-10条,复杂分析用20-30条,再大就需要做信息摘要压缩了。

 第四个坑:错误处理要健壮。工具执行失败是常态——API超时、网络波动、数据源异常——Agent不能因为一个工具失败就崩溃退出。我上面的execute方法用try-except包装了所有工具调用,工具失败时会返回错误对象而不是抛异常,这是基本的工程素养。

 五、这个框架与AstronClaw的差距在哪里

 写完这个最小化版本,我知道你们想问的问题:这个玩具能跟科大讯飞的AstronClaw比吗?差距在哪里?

 差距很大,但方向是对的。科大讯飞的AstronClaw至少在以下三个方面比我的玩具版本强得多:多模态感知能力(语音+视觉+文本融合)、场景化微调的大模型(不是通用GPT,而是专门优化过的场景模型)、以及大规模用户数据反馈的迭代优化。这些东西需要大量研发投入,不是一两个人的代码能解决的。

 但我的玩具版本有一个AstronClaw没有的优势:完全可控、可定制、可审计。整个代码都在你手里,数据流向完全透明,你不需要依赖任何第三方平台。对于机构投资者和量化团队来说,这种可控性是商业产品替代不了的。


 说实话

 我自己现在每天的量化研究工作流,已经大量引入了这类自建的Agent系统。数据清洗、因子挖掘、回测结果分析、研报摘要——这些过去需要我手工做的重复性工作,现在大部分都交给Agent处理了。我的感受是:不要等商业产品成熟,现在就开始用Python搭建自己的Agent系统,一边用一边迭代,一边踩坑一边优化。这个过程本身,就是最好的学习。


 免责声明:本文代码仅供学习研究使用,不构成任何投资建议。量化策略存在风险,历史表现不代表未来收益。股市有风险,投资需谨慎。

最新文章

随机文章