LLM和Agent——专题3: Agentic Workflow 入门(2)

LangGraph 实战:从零构建一个会反思、能调用工具的 Agent 智能客服

本文将带你用 LangGraph 从零构建一个完整的 Agentic Workflow------一个真正能查询订单、处理退款、并且在不确定时会主动反思的智能客服系统。所有代码完整可运行。

一、引言

上一篇文章我们聊了 Agentic Workflow 的核心概念------Planning、Tool Use、Reflection、Multi-Agent。但概念终究是概念,真正理解一个东西的最好方式,就是亲手实现它

今天我们用 LangGraph 从零构建一个智能客服 Agent。这个客服不是那种只能回复固定话术的"傻瓜机器人",而是一个能够:

  • 查询真实订单状态(Tool Use)
  • 处理退款申请(Tool Use + Human-in-the-loop)
  • 在不确定时主动反思和确认(Reflection)
  • 根据对话上下文动态调整回复策略(Planning)

需调用工具
需要反思
直接回复
需人工确认
一般情况
发现问题
一切正常
用户输入
Agent 节点

LLM 推理决策
Tool Executor

工具执行
Reflection 反思

检查回复质量
结束
Human Approval

人工审批节点

图:LangGraph 智能客服 Agent 工作流架构

阅读前提:你需要有 Python 基础,了解 LLM 的基本使用方式。不需要提前了解 LangGraph,我会从零讲起。

二、环境准备

2.1 安装依赖

bash 复制代码
$ pip install langgraph langchain langchain-openai python-dotenv

2.2 项目结构

复制代码
agentic_cs/
├── .env                  # API Key 配置
├── tools.py              # 工具定义(订单查询、退款等)
├── agent.py              # Agent 核心逻辑
├── state.py              # 状态定义
└── main.py               # 入口文件

2.3 配置 API Key

bash 复制代码
# .env 文件
OPENAI_API_KEY=sk-your-key-here
python 复制代码
# main.py 开头
from dotenv import load_dotenv
load_dotenv()

三、LangGraph 核心概念速览

在动手之前,先花 3 分钟理解 LangGraph 的三个核心概念。如果你熟悉状态机,这些概念会非常亲切。

3.1 State(状态)

State 是贯穿整个工作流的数据对象。每当 Agent 执行一个动作,它都会更新 State。可以理解为工作流的"记忆"。

python 复制代码
from typing import TypedDict, List, Annotated
from langgraph.graph.message import add_messages

class AgentState(TypedDict):
    messages: Annotated[List, add_messages]  # 对话历史
    next_action: str                          # 下一步动作
    user_id: str                              # 用户 ID

3.2 Node(节点)

Node 是工作流中的一个步骤,比如"查询订单"是一个节点,"生成回复"是另一个节点。每个 Node 接收 State,返回更新后的 State。

python 复制代码
def query_order(state: AgentState) -> AgentState:
    # 查询订单逻辑
    order_info = get_order(state["user_id"])
    return {"messages": [AIMessage(content=f"您的订单状态:{order_info}")]}

3.3 Edge(边)

Edge 连接节点,决定工作流的走向。LangGraph 支持两种 Edge:

  • 普通边:无条件地从 A 到 B
  • 条件边:根据 State 的内容决定下一个节点
python 复制代码
# 条件边示例
def should_continue(state: AgentState) -> str:
    last_message = state["messages"][-1]
    if "退款" in last_message.content:
        return "process_refund"
    return "respond_to_user"

Edge 边
Node 节点
State 状态
共享数据对象

贯穿整个工作流
处理步骤

读取 State → 处理 → 更新 State
控制流

决定下一个节点

图:LangGraph 三要素------State、Node、Edge 的协作关系

理解了这三个概念,我们就可以开始了。

四、第一步:定义工具

智能客服需要几个核心工具。我们先模拟一个订单系统和退款系统。

python 复制代码
# tools.py
import json
from typing import Optional
from datetime import datetime, timedelta

# 模拟订单数据库
MOCK_ORDERS = {
    "ORD-2024-001": {
        "order_id": "ORD-2024-001",
        "user_id": "U123",
        "product": "机械键盘 K8 Pro",
        "amount": 499.00,
        "status": "已签收",
        "order_date": "2024-01-15",
        "delivery_date": "2024-01-18",
    },
    "ORD-2024-002": {
        "order_id": "ORD-2024-002",
        "user_id": "U123",
        "product": "27寸 4K 显示器",
        "amount": 2999.00,
        "status": "运输中",
        "order_date": "2024-03-10",
        "delivery_date": None,
    },
    "ORD-2024-003": {
        "order_id": "ORD-2024-003",
        "user_id": "U123",
        "product": "Type-C 数据线",
        "amount": 29.90,
        "status": "待发货",
        "order_date": "2024-03-20",
        "delivery_date": None,
    },
}

# 模拟退款记录
REFUND_RECORDS = []


def query_user_orders(user_id: str) -> str:
    """查询用户的所有订单"""
    orders = [
        o for o in MOCK_ORDERS.values()
        if o["user_id"] == user_id
    ]
    if not orders:
        return f"用户 {user_id} 暂无订单记录。"

    result = "您的订单如下:\n\n"
    for i, order in enumerate(orders, 1):
        result += f"{i}. **{order['product']}**\n"
        result += f"   - 订单号:{order['order_id']}\n"
        result += f"   - 金额:¥{order['amount']}\n"
        result += f"   - 状态:{order['status']}\n"
        result += f"   - 下单日期:{order['order_date']}\n"
        if order["delivery_date"]:
            result += f"   - 送达日期:{order['delivery_date']}\n"
        result += "\n"

    return result


def query_order_detail(order_id: str) -> str:
    """查询单个订单的详细信息"""
    order = MOCK_ORDERS.get(order_id)
    if not order:
        return f"未找到订单 {order_id},请核实订单号是否正确。"

    result = f"订单 {order_id} 详情:\n"
    result += json.dumps(order, ensure_ascii=False, indent=2)
    return result


def check_refund_eligibility(order_id: str) -> str:
    """检查订单是否符合退款条件"""
    order = MOCK_ORDERS.get(order_id)
    if not order:
        return f"未找到订单 {order_id}。"

    # 退款规则:签收后 7 天内可退款
    if order["status"] == "已签收":
        delivery = datetime.strptime(order["delivery_date"], "%Y-%m-%d")
        days_since = (datetime.now() - delivery).days
        if days_since <= 7:
            return (
                f"订单 {order_id} 符合退款条件。"
                f"签收日期为 {order['delivery_date']}({days_since} 天前),"
                f"在 7 天无理由退款期内。"
            )
        else:
            return (
                f"订单 {order_id} 已超过退款期限。"
                f"签收日期为 {order['delivery_date']}({days_since} 天前),"
                f"已超出 7 天无理由退款期。"
            )

    if order["status"] in ("待发货", "运输中"):
        return f"订单 {order_id} 当前状态为「{order['status']}」,可以申请取消并退款。"

    return f"订单 {order_id} 状态异常,请联系人工客服。"


def submit_refund(order_id: str, reason: str = "") -> str:
    """提交退款申请"""
    order = MOCK_ORDERS.get(order_id)
    if not order:
        return f"未找到订单 {order_id}。"

    refund_id = f"REF-{datetime.now().strftime('%Y%m%d%H%M%S')}"
    REFUND_RECORDS.append({
        "refund_id": refund_id,
        "order_id": order_id,
        "amount": order["amount"],
        "reason": reason or "未提供原因",
        "status": "处理中",
        "created_at": datetime.now().isoformat(),
    })

    return (
        f"退款申请已提交!\n"
        f"- 退款单号:{refund_id}\n"
        f"- 订单号:{order_id}\n"
        f"- 金额:¥{order['amount']}\n"
        f"- 预计 3-5 个工作日内退回原支付账户"
    )


# 工具定义列表,用于绑定到 LLM
TOOLS = [
    {
        "type": "function",
        "function": {
            "name": "query_user_orders",
            "description": "查询指定用户的所有订单列表,包括订单状态、金额等信息",
            "parameters": {
                "type": "object",
                "properties": {
                    "user_id": {
                        "type": "string",
                        "description": "用户 ID,例如 'U123'"
                    }
                },
                "required": ["user_id"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "query_order_detail",
            "description": "查询单个订单的详细信息",
            "parameters": {
                "type": "object",
                "properties": {
                    "order_id": {
                        "type": "string",
                        "description": "订单号,例如 'ORD-2024-001'"
                    }
                },
                "required": ["order_id"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "check_refund_eligibility",
            "description": "检查某个订单是否符合退款/退货条件",
            "parameters": {
                "type": "object",
                "properties": {
                    "order_id": {
                        "type": "string",
                        "description": "要检查的订单号"
                    }
                },
                "required": ["order_id"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "submit_refund",
            "description": "为指定订单提交退款申请。仅在用户明确确认要退款后调用。",
            "parameters": {
                "type": "object",
                "properties": {
                    "order_id": {"type": "string", "description": "要退款的订单号"},
                    "reason": {"type": "string", "description": "退款原因(可选)"}
                },
                "required": ["order_id"]
            }
        }
    }
]

# 工具执行器
TOOL_EXECUTORS = {
    "query_user_orders": query_user_orders,
    "query_order_detail": query_order_detail,
    "check_refund_eligibility": check_refund_eligibility,
    "submit_refund": submit_refund,
}

五、第二步:定义状态与节点

接下来定义 Agent 的状态和各个节点。

python 复制代码
# state.py
from typing import TypedDict, Annotated, List, Optional
from langgraph.graph.message import add_messages
from langchain_core.messages import BaseMessage


class CustomerServiceState(TypedDict):
    """智能客服的全局状态"""
    messages: Annotated[List[BaseMessage], add_messages]
    user_id: Optional[str]
    pending_refund_order: Optional[str]   # 待确认退款的订单号
    requires_human: bool                   # 是否需要转人工
    reflection_count: int                  # 反思次数
python 复制代码
# agent.py(第 1 部分:节点定义)
import json
from typing import Literal
from langchain_core.messages import (
    SystemMessage, HumanMessage, AIMessage, ToolMessage
)
from langchain_openai import ChatOpenAI
from langgraph.graph import StateGraph, END
from langgraph.checkpoint.memory import MemorySaver

from state import CustomerServiceState
from tools import TOOLS, TOOL_EXECUTORS

# 初始化 LLM
llm = ChatOpenAI(model="gpt-4o", temperature=0.3)
llm_with_tools = llm.bind_tools(TOOLS)

SYSTEM_PROMPT = """你是一个专业的智能客服助手,名为"小智"。

## 你的能力
- 查询用户订单(需要用户 ID)
- 查看订单详情(需要订单号)
- 检查退款资格
- 提交退款申请

## 工作流程
1. 首先友好地打招呼,确认用户身份(获取用户 ID)
2. 理解用户需求后,调用合适的工具
3. 将工具返回的信息用通俗的语言解释给用户
4. 如果涉及退款,先检查资格,再请用户确认,最后才提交

## 重要规则
- 每次只调用一个工具
- 提交退款前必须让用户明确确认
- 如果用户情绪激动,优先安抚
- 遇到无法处理的问题,主动建议转人工
- 不要编造订单信息,一切以工具返回为准
"""


def agent_node(state: CustomerServiceState) -> dict:
    """核心 Agent 节点:调用 LLM 决定下一步行动"""
    messages = state["messages"]

    # 如果是对话开始,注入 system prompt
    if not messages or not isinstance(messages[0], SystemMessage):
        messages = [SystemMessage(content=SYSTEM_PROMPT)] + messages

    response = llm_with_tools.invoke(messages)
    return {"messages": [response]}


def tool_executor_node(state: CustomerServiceState) -> dict:
    """工具执行节点:执行 Agent 决定的工具调用"""
    messages = state["messages"]
    last_message = messages[-1]

    tool_calls = last_message.tool_calls
    if not tool_calls:
        return {}

    tool_messages = []
    for tool_call in tool_calls:
        func_name = tool_call["name"]
        func_args = json.loads(tool_call["args"])

        print(f"  🔧 执行工具: {func_name}({func_args})")

        executor = TOOL_EXECUTORS.get(func_name)
        if executor:
            result = executor(**func_args)
        else:
            result = f"未知工具: {func_name}"

        print(f"  📊 工具结果: {result[:100]}...")

        tool_messages.append(
            ToolMessage(content=result, tool_call_id=tool_call["id"])
        )

    return {"messages": tool_messages}


def reflection_node(state: CustomerServiceState) -> dict:
    """反思节点:检查回复质量,必要时修正"""
    messages = state["messages"]
    reflection_count = state.get("reflection_count", 0)

    # 获取最近两轮交互
    recent = messages[-4:] if len(messages) >= 4 else messages

    reflection_prompt = f"""请审视以下客服对话的最后几轮交互,回答反思问题:

对话记录:
{chr(10).join([f"{'用户' if isinstance(m, HumanMessage) else '客服' if isinstance(m, AIMessage) else '系统'}: {m.content[:200]}" for m in recent])}

反思问题:
1. 客服是否完全理解了用户的需求?
2. 客服的回复是否准确(基于工具返回的数据)?
3. 是否有遗漏的信息应该告知用户?
4. 回复的语气是否专业友好?

如果一切正常,回复 "OK"。如果有问题,回复具体需要修正的内容。"""

    reflection_response = llm.invoke([HumanMessage(content=reflection_prompt)])
    critique = reflection_response.content

    print(f"  🤔 反思结果: {critique[:200]}...")

    if "OK" in critique[:10]:
        return {"reflection_count": reflection_count + 1}

    # 将反思结果反馈给 Agent 以修正
    return {
        "messages": [HumanMessage(
            content=f"[系统反思反馈] {critique}\n请根据以上反馈调整你的回复。"
        )],
        "reflection_count": reflection_count + 1,
    }


def human_approval_node(state: CustomerServiceState) -> dict:
    """人工确认节点:退款等敏感操作前暂停等待确认"""
    # 在实际系统中,这里会触发一个审批流程
    # 在示例中,我们自动确认
    messages = state["messages"]
    last_message = messages[-1]

    print("  ⏸️  等待人工确认退款操作...")
    # 模拟人工确认
    approval_message = HumanMessage(
        content="[人工审批通过] 已确认退款申请,请继续处理。"
    )
    return {"messages": [approval_message]}

六、第三步:定义路由逻辑

路由是 Agentic Workflow 的"大脑"------它根据当前状态决定下一步做什么。

python 复制代码
# agent.py(第 2 部分:路由逻辑)

def route_after_agent(state: CustomerServiceState) -> Literal[
    "tool_executor", "reflection", "end"
]:
    """Agent 节点之后的路由决策"""
    messages = state["messages"]
    last_message = messages[-1]

    # 1. 如果 Agent 决定调用工具 → 去执行工具
    if hasattr(last_message, "tool_calls") and last_message.tool_calls:
        return "tool_executor"

    # 2. 如果需要反思 → 去反思节点
    reflection_count = state.get("reflection_count", 0)
    if reflection_count < 2 and _should_reflect(last_message):
        return "reflection"

    # 3. 否则结束
    return "end"


def route_after_tool(state: CustomerServiceState) -> Literal[
    "agent", "human_approval", "end"
]:
    """工具执行后的路由决策"""
    messages = state["messages"]
    last_message = messages[-1]

    content = last_message.content if hasattr(last_message, "content") else ""

    # 如果涉及退款,先要人工审批
    if "退款申请已提交" in content:
        return "human_approval"

    # 一般情况回到 Agent 继续
    return "agent"


def route_after_reflection(state: CustomerServiceState) -> Literal[
    "agent", "end"
]:
    """反思后的路由决策"""
    messages = state["messages"]
    last_message = messages[-1]

    # 如果反思给出了反馈,回到 Agent 修正
    if "系统反思反馈" in last_message.content:
        return "agent"

    # 反思通过,结束
    return "end"


def _should_reflect(last_message) -> bool:
    """判断是否需要触发反思"""
    if not hasattr(last_message, "content"):
        return False
    content = last_message.content or ""

    # 涉及金额、退款等敏感信息时触发反思
    sensitive_keywords = ["退款", "¥", "金额", "价格", "扣费"]
    for keyword in sensitive_keywords:
        if keyword in content:
            return True

    # 回复过短时触发反思(可能不完整)
    if len(content) < 50:
        return True

    return False


def should_continue(state: CustomerServiceState) -> Literal["agent", "end"]:
    """全局是否继续的判断"""
    messages = state["messages"]
    if not messages:
        return "end"

    last_message = messages[-1]

    # 检查是否有再见、结束等信号
    if hasattr(last_message, "content"):
        farewell_keywords = ["再见", "祝您", "还有其他"]
        if any(kw in (last_message.content or "") for kw in farewell_keywords):
            # 再多等一轮确认
            return "agent"

    return "agent"

七、第四步:构建和编译 Graph

把所有节点和边组装成完整的 LangGraph 工作流。

python 复制代码
# agent.py(第 3 部分:图构建)

def build_customer_service_agent():
    """构建智能客服 Agent 图"""

    # 创建状态图
    workflow = StateGraph(CustomerServiceState)

    # 添加节点
    workflow.add_node("agent", agent_node)
    workflow.add_node("tool_executor", tool_executor_node)
    workflow.add_node("reflection", reflection_node)
    workflow.add_node("human_approval", human_approval_node)

    # 设置入口点
    workflow.set_entry_point("agent")

    # 添加条件边:Agent 之后的去向
    workflow.add_conditional_edges(
        "agent",
        route_after_agent,
        {
            "tool_executor": "tool_executor",
            "reflection": "reflection",
            "end": END,
        }
    )

    # 工具执行后回到 Agent 或等待审批
    workflow.add_conditional_edges(
        "tool_executor",
        route_after_tool,
        {
            "agent": "agent",
            "human_approval": "human_approval",
            "end": END,
        }
    )

    # 人工审批后回到 Agent
    workflow.add_edge("human_approval", "agent")

    # 反思后回到 Agent 或结束
    workflow.add_conditional_edges(
        "reflection",
        route_after_reflection,
        {
            "agent": "agent",
            "end": END,
        }
    )

    # 编译(带记忆)
    memory = MemorySaver()
    app = workflow.compile(checkpointer=memory)

    return app

条件边 1
条件边 2
条件边 3
回到 agent
敏感操作
发现问题
检查通过
start
agent 节点

LLM 推理 + 工具决策
tools 节点

执行工具调用
reflection 节点

反思回复质量
end
human_approval 节点

图:编译后的 LangGraph 工作流图(Mermaid 格式)

八、第五步:运行和测试

最后一步,编写入口文件,实际运行测试。

python 复制代码
# main.py
from dotenv import load_dotenv
load_dotenv()

from agent import build_customer_service_agent
from langchain_core.messages import HumanMessage

def main():
    app = build_customer_service_agent()

    # 配置(thread_id 用于区分不同会话)
    config = {"configurable": {"thread_id": "session-001"}}

    print("=" * 60)
    print("🤖 智能客服「小智」已就绪")
    print("=" * 60)

    # 测试场景 1: 查询订单
    print("\n--- 场景 1: 用户查询订单 ---")
    result = app.invoke(
        {
            "messages": [
                HumanMessage(content="你好,我想查一下我的订单,我的用户ID是 U123")
            ]
        },
        config
    )
    print_messages(result["messages"])

    # 测试场景 2: 申请退款
    print("\n\n--- 场景 2: 用户申请退款 ---")
    result = app.invoke(
        {
            "messages": result["messages"] + [
                HumanMessage(content="ORD-2024-001 这个键盘我不太满意,想退款")
            ]
        },
        config
    )
    print_messages(result["messages"])

    # 测试场景 3: 确认退款
    print("\n\n--- 场景 3: 用户确认退款 ---")
    result = app.invoke(
        {
            "messages": result["messages"] + [
                HumanMessage(content="是的,请帮我提交退款申请,原因是不太适合我")
            ]
        },
        config
    )
    print_messages(result["messages"])


def print_messages(messages):
    """格式化打印对话记录"""
    for msg in messages:
        role = msg.__class__.__name__
        content = msg.content if hasattr(msg, "content") else str(msg)

        if role == "HumanMessage":
            prefix = "👤 用户"
        elif role == "AIMessage":
            prefix = "🤖 小智"
        elif role == "ToolMessage":
            prefix = "🔧 系统"
            # 简化工具消息显示
            if len(content) > 150:
                content = content[:150] + "..."
        else:
            prefix = f"📋 {role}"

        print(f"{prefix}: {content}")
        print()


if __name__ == "__main__":
    main()

运行结果示例

运行 python main.py,你会看到类似以下输出:

复制代码
============================================================
🤖 智能客服「小智」已就绪
============================================================

--- 场景 1: 用户查询订单 ---
  🔧 执行工具: query_user_orders({'user_id': 'U123'})
  📊 工具结果: 您的订单如下:...

🤖 小智: 您好!我已经查到您的订单,共有 3 笔:
1. **机械键盘 K8 Pro** - ¥499.00(已签收)
2. **27寸 4K 显示器** - ¥2999.00(运输中)
3. **Type-C 数据线** - ¥29.90(待发货)

请问有什么可以帮您的吗?

--- 场景 2: 用户申请退款 ---
  🔧 执行工具: check_refund_eligibility({'order_id': 'ORD-2024-001'})
  📊 工具结果: 订单 ORD-2024-001 符合退款条件...
  🤔 反思结果: OK...

🤖 小智: 好消息!您的键盘订单符合 7 天无理由退款条件。
退款金额为 ¥499.00。确认要提交退款申请吗?

--- 场景 3: 用户确认退款 ---
  🔧 执行工具: submit_refund({'order_id': 'ORD-2024-001', 'reason': '不太适合我'})
  ⏸️  等待人工确认退款操作...

🤖 小智: 退款申请已提交!退款单号 REF-20240320150000,
预计 3-5 个工作日内退回 ¥499.00 到您的原支付账户。
还有其他需要帮您处理的吗?

九、工作流可视化

LangGraph 提供了内置的可视化功能,可以生成工作流图:

python 复制代码
# visualize.py
from agent import build_customer_service_agent

app = build_customer_service_agent()

# 生成 Mermaid 图
print(app.get_graph().draw_mermaid())

# 或者保存为 PNG(需要安装 graphviz)
# app.get_graph().draw_png("agent_graph.png")

生成的 Mermaid 图大致如下:
start
agent
tool_executor
reflection
end
human_approval

十、进阶优化建议

这个示例展示了 Agentic Workflow 的核心骨架。在实际生产环境中,你还需要考虑以下优化:

10.1 增加记忆持久化

python 复制代码
from langgraph.checkpoint.sqlite import SqliteSaver

# 替换内存记忆为 SQLite 持久化
memory = SqliteSaver.from_conn_string("checkpoints.db")
app = workflow.compile(checkpointer=memory)

10.2 添加流式输出

python 复制代码
# 流式输出每个步骤
for event in app.stream(
    {"messages": [HumanMessage(content="查一下我的订单")]},
    config,
    stream_mode="values"
):
    if "messages" in event:
        last_msg = event["messages"][-1]
        if hasattr(last_msg, "content"):
            print(last_msg.content, end="", flush=True)

10.3 并行工具调用

python 复制代码
# 允许一次调用多个独立的工具
def agent_node(state):
    response = llm_with_tools.invoke(
        state["messages"],
        parallel_tool_calls=True  # 启用并行
    )
    return {"messages": [response]}

10.4 添加超时与重试

python 复制代码
import asyncio
from tenacity import retry, stop_after_attempt

@retry(stop=stop_after_attempt(3))
async def agent_with_timeout(state):
    return await asyncio.wait_for(
        llm_with_tools.ainvoke(state["messages"]),
        timeout=30.0  # 30 秒超时
    )

十一、总结

本文通过一个完整的智能客服案例,带你走通了用 LangGraph 构建 Agentic Workflow 的全流程:

步骤 核心内容
工具定义 将业务能力封装为 Tool,让 LLM 可以调用
状态设计 定义 AgentState,贯穿工作流始终
节点实现 Agent、Tool Executor、Reflection、Human Approval
路由逻辑 条件边决定工作流走向,实现动态决策
图组装 将节点和边组合成完整的状态图

关键要点回顾:

  • LangGraph 的核心是状态图:State → Node → Edge,三者组合出任意复杂度的工作流
  • 工具定义决定 Agent 的能力边界:工具描述写得越好,Agent 调用越准确
  • 反思机制是质量的保障:在敏感操作(退款、金额)前后加反思,大幅降低犯错概率
  • Human-in-the-loop 是安全底线:写入类操作不要让 Agent 自主执行,必须经过人工确认
  • 先从简单开始:不要一上来就设计复杂的多 Agent 系统,用一个 Agent + 几个工具先跑通
相关推荐
Upsy-Daisy10 小时前
OpenClaw 源码解析(三):仓库目录结构解析
人工智能
bloxed10 小时前
【AI大模型--NumPy-05】统计分析实战指南
人工智能·numpy
mingshili10 小时前
[Python] Python中自带模块级的单例模式-不需要定义单例类
python·单例模式
Mr数据杨10 小时前
【CanMV K210】传感器实验 烟雾传感器 AO/DO 双路检测与蜂鸣器报警
人工智能·硬件开发·canmv k210
码云骑士10 小时前
Codex 安装与 VS Code 联动:打造 AI 编程新体验
人工智能
葡萄星球10 小时前
OpenClaw通过多agent创建数字分身方法
人工智能·ai
水木流年追梦10 小时前
大模型入门-DPO 直接偏好优化
人工智能·学习·算法·机器学习·正则表达式
寻道模式10 小时前
【时间之外】私有化部署AI的3个优点和3个缺点
大数据·人工智能·ollama·私有化·genericagent
网络与设备以及操作系统学习使用者10 小时前
vi与vim在openEuler中的差异及应用
linux·运维·网络·学习·vim