人工智能, 生活

使用Python原生代码搭建一个智能体(不依赖框架)

这是之前的几篇:

本篇不使用 LangChain、AutoGen 等智能体框架,通过 Python 直接手搓一个智能体,学习会更直观些。首先,在文件夹中新建 .env 文件,输入以下内容(可使用第三方 API 或者本地模型 API):

OPENAI_API_KEY=xxx
DASHSCOPE_BASE_URL=xxx

智能体代码如下:

import json
import os
from datetime import datetime
from openai import OpenAI

# --- 1. 配置 ---
import dotenv
dotenv.load_dotenv(".env")
client = OpenAI(
    api_key=os.getenv("OPENAI_API_KEY"),
    base_url=os.getenv("DASHSCOPE_BASE_URL"),
)
MODEL = "ark-code-latest"

# --- 2. 工具定义 ---
def get_current_time():
    return datetime.now().strftime("%Y-%m-%d %H:%M:%S")

def calculate(expression: str):
    try:
        return str(eval(expression))
    except Exception as e:
        return f"Error: {e}"

TOOLS = {
    "get_current_time": get_current_time,
    "calculate": calculate
}

# --- 3. 动态构建 Prompt ---
def build_system_prompt():
    # 自动从 TOOLS 字典生成描述
    tool_desc = "\n".join([f"- {name}: {func.__doc__ or '无描述'}" for name, func in TOOLS.items()]) 
    system_prompt = f"""你是一个智能助手。可用工具:
{tool_desc}

请直接返回纯 JSON 格式,不要使用 Markdown 代码块。
注意:input 字段必须是一个 JSON 对象,而不是字符串。
格式:
{{
    "thought": "思考过程 或 最终回复给用户的话"
    "action": "工具名 或 final",
    "input": "参数字典 或 null",
}}"""
    return system_prompt

# --- 4. 核心逻辑 ---
def run_agent(user_input):
    messages = [
        {"role": "system", "content": build_system_prompt()},
        {"role": "user", "content": user_input}
    ]

    print(f"\n🚀 任务: {user_input}\n" + "-"*50)

    for step in range(5):
        print(f"\n[步骤 {step+1}] 调用大模型...\n")

        try:
            print(f'📄 模型原始输入(Raw Prompt):\n{json.dumps(messages, indent=4, ensure_ascii=False)}')
        except:
            print(f'📄 模型原始输入(Raw Prompt):\n{messages}')
        
        # 调用模型
        response = client.chat.completions.create(model=MODEL, messages=messages, temperature=0)
        raw_response = response.choices[0].message.content.strip()

        # --- 打印原始回复 ---
        print(f"\n📄 模型原始回复 (Raw Response):\n{raw_response}")

        # 解析与执行
        try:
            data = json.loads(raw_response)
            action = data.get("action")
            thought = data.get("thought")
            input_params = data.get("input")

            print('\n解析得到:')
            print(f"(1)思考: {thought}")
            print(f"(2)动作: {action}")
            print(f"(3)参数: {input_params}")

            if action == "final":
                print()
                print("-" * 50)
                print(f"\n✅ 最终结果: {thought}\n")
                print("-" * 50)
                print()
                return

            # 执行工具
            if action in TOOLS:
                # 自动解包参数,如果没有参数则直接调用
                result = TOOLS[action](**input_params) if input_params else TOOLS[action]()
                print(f"\n工具输出: {result}")

                # 记录历史
                messages.append({"role": "assistant", "content": raw_response})
                messages.append({"role": "user", "content": f"工具执行结果: {result}"})
            else:
                print("❌ 未知工具")
                
        except Exception as e:
            print(f"❌ 执行错误: {e}")
            return

if __name__ == "__main__":
    run_agent("现在几点了?帮我算算 5*20 等于多少?")

运行结果:

🚀 任务: 现在几点了?帮我算算 5*20 等于多少?
--------------------------------------------------

[步骤 1] 调用大模型...

📄 模型原始输入(Raw Prompt):
[
    {
        "role": "system",
        "content": "你是一个智能助手。可用工具:\n- get_current_time: 无描述\n- calculate: 无描述\n\n请直接返回纯 JSON 格式,不要使用 Markdown 代码 块。\n注意:input 字段必须是一个 JSON 对象,而不是字符串。\n格式:\n{\n    \"thought\": \"思考过程 或 最终回复给用户的话\"\n    \"action\": \"工具名 或 final\",\n    \"input\": \"参数字典 或 null\",\n}"
    },
    {
        "role": "user",
        "content": "现在几点了?帮我算算 5*20 等于多少?"
    }
]

📄 模型原始回复 (Raw Response):
{
    "thought": "用户需要先获取当前时间,再计算5*20,先调用get_current_time获取时间,之后再计算",
    "action": "get_current_time",
    "input": null
}

解析得到:
(1)思考: 用户需要先获取当前时间,再计算5*20,先调用get_current_time获取 时间,之后再计算
(2)动作: get_current_time
(3)参数: None

工具输出: 2026-04-01 20:03:57

[步骤 2] 调用大模型...

📄 模型原始输入(Raw Prompt):
[
    {
        "role": "system",
        "content": "你是一个智能助手。可用工具:\n- get_current_time: 无描述\n- calculate: 无描述\n\n请直接返回纯 JSON 格式,不要使用 Markdown 代码 块。\n注意:input 字段必须是一个 JSON 对象,而不是字符串。\n格式:\n{\n    \"thought\": \"思考过程 或 最终回复给用户的话\"\n    \"action\": \"工具名 或 final\",\n    \"input\": \"参数字典 或 null\",\n}"
    },
    {
        "role": "user",
        "content": "现在几点了?帮我算算 5*20 等于多少?"
    },
    {
        "role": "assistant",
        "content": "{\n    \"thought\": \"用户需要先获取当前时间,再计算5*20,先调用get_current_time获取时间,之后再计算\",\n    \"action\": \"get_current_time\",\n    \"input\": null\n}"
    },
    {
        "role": "user",
        "content": "工具执行结果: 2026-04-01 20:03:57"
    }
]

📄 模型原始回复 (Raw Response):
{
    "thought": "已经获取到当前时间,接下来需要计算5*20的结果,调用calculate工具",
    "action": "calculate",
    "input": {"expression": "5*20"}
}

解析得到:
(1)思考: 已经获取到当前时间,接下来需要计算5*20的结果,调用calculate工具
(2)动作: calculate
(3)参数: {'expression': '5*20'}

工具输出: 100

[步骤 3] 调用大模型...

📄 模型原始输入(Raw Prompt):
[
    {
        "role": "system",
        "content": "你是一个智能助手。可用工具:\n- get_current_time: 无描述\n- calculate: 无描述\n\n请直接返回纯 JSON 格式,不要使用 Markdown 代码 块。\n注意:input 字段必须是一个 JSON 对象,而不是字符串。\n格式:\n{\n    \"thought\": \"思考过程 或 最终回复给用户的话\"\n    \"action\": \"工具名 或 final\",\n    \"input\": \"参数字典 或 null\",\n}"
    },
    {
        "role": "user",
        "content": "现在几点了?帮我算算 5*20 等于多少?"
    },
    {
        "role": "assistant",
        "content": "{\n    \"thought\": \"用户需要先获取当前时间,再计算5*20,先调用get_current_time获取时间,之后再计算\",\n    \"action\": \"get_current_time\",\n    \"input\": null\n}"
    },
    {
        "role": "user",
        "content": "工具执行结果: 2026-04-01 20:03:57"
    },
    {
        "role": "assistant",
        "content": "{\n    \"thought\": \"已经获取到当前时间,接下来需要计算5*20的结果,调用calculate工具\",\n    \"action\": \"calculate\",\n    \"input\": {\"expression\": \"5*20\"}\n}"
    },
    {
        "role": "user",
        "content": "工具执行结果: 100"
    }
]

📄 模型原始回复 (Raw Response):
{
    "thought": "当前时间是2026-04-01 20:03:57,计算得出5*20等于100",      
    "action": "final",
    "input": null
}

解析得到:
(1)思考: 当前时间是2026-04-01 20:03:57,计算得出5*20等于100
(2)动作: final
(3)参数: None

--------------------------------------------------

✅ 最终结果: 当前时间是2026-04-01 20:03:57,计算得出5*20等于100

--------------------------------------------------
3 次浏览

【说明:本站主要是个人的一些笔记和代码分享,内容可能会不定期修改。为了使全网显示的始终是最新版本,这里的文章未经同意请勿转载。引用请注明出处:https://www.guanjihuan.com

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

Captcha Code