DeepSeek实战--手搓实现Agent

1.背景

要学习AI agent,只会用agent 框架,还不够,一旦框架出现问题,没法快速的排查出问题。 学习就应该“知其然,更应该知其所以然” ,今天我们就用编码的方式实现一个简单的agent 。我们模拟一套AI学生评价系统,通过自然语言查询数据、分析数据。

2.环境

python 版本:3.11
LLM: deepseek-chat(有 api key)
SDK:openai 1.63.2

若不知道,怎么获取“deepseek api key”,辛苦爬楼看一下,我前面的文章

3.步骤

1)定义prompt

REACT_PROMPT = """
--你在思考、行动、行动输入、暂停、观察的循环中运行。 
--在循环结束时,输出一个答案 
--用Thought来描述你对被问到的问题的想法。 
--使用Action运行一个可用的操作 
--使用动作输入来指示动作的输入-然后返回"等待,处理中"。 
--观察将是运行这些操作的结果。

你可用的工具有:
{tools}

Rules:
1-如果输入是问候或再见,直接以友好的方式回复,不要使用思考-行动循环。 
2-否则,按照思考-行动-输入循环去寻找最佳答案。 
3-如果你已经有了问题的一部分或整个的答案,不要依赖于外部行为,使用你的知识。 
4-如果你需要执行多个Action,在单独的调用中执行。 
5-最后,给出一个最终的答案。

Some examples:

###
Question: 今天北京天气怎么样?
Thought: 我需要调用 get_weather 工具获取天气
Action: get_weather
Action Input: {"city": "BeiJing"}

等待,处理中

You will be called again with this:

Observation: 北京的气温是0度.

You then output: 
Final Answer: 北京的气温是0度.

Begin!

New input: {input}"""

注意prompt 规则说清楚,让模型逐步处理, 可以减少幻觉

2)定义工具


tools = [
    {
        "name": "get_score_by_name",
        "description": "使用该工具获取指定员工的绩效评分",
        "parameters": {
            "type": "object",
            "properties": {
                "name": {
                    "type": "string",
                    "description": "员工名字",
                }
            },
            "required": ["name"]
        },
    }
]

def get_score_by_name(name):
    if name == "张三":
        return "name: 张三 绩效评分: 85.9"
    elif name == "李四":
        return "name: 李四 绩效评分: 92.7"
    else:
        return "未搜到该员工的绩效"

4)写LLM 对接client

client = OpenAI(
    api_key="sk-xx自己申请",
    base_url="https://api.deepseek.com/v1"
)

def send_messages(messages):
    response = client.chat.completions.create(
        model="deepseek-chat",
        messages=messages
    )
    return response

5)写agent 逻辑


if __name__ == "__main__":
    query = "张三和李四的绩效谁好?"
    prompt = REACT_PROMPT.replace("{tools}", json.dumps(tools)).replace("{input}", query)
    messages = [{"role": "user", "content": prompt}]

    #进入无限循环,直到满足某个结束条件
    while True:
        response = send_messages(messages)
        response_text = response.choices[0].message.content

        print("大模型的回复:")
        print(response_text)

        final_answer_match = re.search(r'Final Answer:\s*(.*)', response_text)
        # 有“Final Answer:” 退出循环
        if final_answer_match:
            final_answer = final_answer_match.group(1)
            print("最终答案:", final_answer)
            break

        messages.append(response.choices[0].message)

        # 使用正则表达式从response_text中提取Action字段的值
        # 该值用于标识所需的操作
        action_match = re.search(r'Action:\s*(\w+)', response_text)

        # 使用正则表达式从response_text中提取Action Input字段的值
        # 该值用于提供操作所需的输入参数,可以是JSON对象或字符串
        action_input_match = re.search(r'Action Input:\s*({.*?}|".*?")', response_text, re.DOTALL)

        if action_match and action_input_match:
            tool_name = action_match.group(1)
            params = json.loads(action_input_match.group(1))

            observation = ""
            if tool_name == "get_score_by_name":
                observation = get_score_by_name(params['name'])
                print("接口查询结果:Observation:", observation)
            elif tool_name =="无法识别":
                print("接口查询结果:Observation:", "无法识别")

            # 将观察结果作为用户角色的内容添加到消息中
            messages.append({"role": "user", "content": f"Observation: {observation}"})

4.成果

在这里插入图片描述

5.总结

1)注意prompt 逻辑、demo要写清楚,同时让模型按规则逐步处理, 可以减少幻觉
2)核心逻辑是用代码,在合适的时间调度大模型、工具,然后组装获取到最终结果
3)本case就涉及多次调用大模型,而且追加了上下文(message),让大模型不断地通过追加内容,生成最终结果,在程序中要判断,已经生产最终成果,然后输出结果,退出循环。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值