Agent_项目学习_day02

follow up datawhalechina/Agent-Learning-Hub: AI Agent 学习路线与资料库收集

Stage 1: Build A Minimal Agent Loop

一个简单的agent对话机器人

和agent建立连接

没用langchain因为电脑内存不够了

1
2
import dotenv
from dotenv import load_dotenv

然后在.env里面存一下apikey和base_url,方便管理同时不在功能代码里出现api扣钱

1
miniagent = OpenAI(api_key = os.getenv("OPENAI_API_KEY"),base_url = os.getenv("OPENAI_BASE_URL"),)

注册一下agent信息,然后写调用函数

1
2
3
4
5
6
7
def call_llm(message : List[Dict[str,Any]]) -> str:
response = miniagent.chat.completions.create(
model="deepseek-v4-flash",
messages=messages,
temperature=0.7,
)
return response.choices[0].message.content

定义并且注册工具

定义工具和函数一样,正常执行功能就可以,唯一比较不同的是多定义一个字典,存储工具名称、工具的功能描述、以及工具的参数列表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
TOOLS_REGISTER = {
"calculator": calculator,
"get_current_time": get_current_time,
"get_weather": get_weather,
}
#这里修改,先每个工具告诉一句简要的提示,等模型决定要使用哪个工具时,再告诉模型对应的参数列表
TOOLS_DESCRIPTIONS = {
"calculator": "计算表达式,支持 sin/cos/tan数学函数",
"get_current_time": "获取当前时间",
"get_weather": "获取指定城市的天气信息",
}
TOOLS_DETAILS = {
"calculator": {
"parameters": {
"expression": {"type": "string", "description": "数学表达式"}
},
"required": ["expression"]
},
"get_current_time": {
"parameters": {},
"required": []
},
"get_weather": {
"parameters": {
"city": {"type": "string", "description": "城市名"},
"days": {"type": "integer", "description": "天数(1-3)", "default": 1}
},
"required": ["city"]
}
}



最开始的时候没有单独把工具功能描述和工具的属性列表拆开,导致agent效果很差,调用工具的时候传入的参数名字是错的导致工具调用失败,很多次都这样,然后查了一下claude-code是会在确定使用这个工具的时候才传入这个工具的参数列表,虽然多了一次llm调用,但是在具体表现上稳定了很多。

Agent循环

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
def agent_loop(user_input:str, max_step: int = 3, timeout:int = 30) -> str:
start_time = time.time()
step1_prompt = f'''你是个.....,你需要完成用户的任务,你可以选择使用工具辅助你完成,如果能够直接完成任务,可以直接回复。注册的工具有:{TOOLS_DESCRIPTION}
- 如果用户问题可以直接回答,不需要工具,请直接回答。
- 如果需要工具,请只输出工具名称,格式:TOOL:工具名
- 每次只能调用一个工具.'''
messages = [
{
"role":"system", "content":step1_prompt
},
{
"role":"user", "content" : user_input
}
]
step = 0
while step < max_step :
if(time.time()-start_time > timeout)
return "超出应答时间"
response = call_llm(messages)
step += 1

if not response.startswith("TOOL:"):
return response

tool_name = response.replace("TOOL:","").strip()

step2_prompt = f"""{step1_prompt}
用户问题:{user_input}
你决定使用工具:{tool_name}
工具的参数有:{TOOLS_DETAILS[tool_name]}
请输出严格的 JSON 格式:
{{"tool": "{tool_name}", "arguments": {{"参数名": "参数值"}}}}
"""
tool_messages = [
{
"role" :"system", "content" :step2_prompt
},
{
"role" : "user", "content" : user_input
}
]
tool_response = call_llm(tool_messages)
step += 1

try:
tool_call = json.loads(tool_response)
tool_name = tool_call["tool"]
arguments = tool_call["arguments"]

result = execute_tool(tool_name, arguments)

messages.append({"role":"assistant","content":f"使用了工具{tool_name}"})
messages.append({"role":"user","content":f"工具执行结果{result}"})

逻辑就是先给模型,看模型选不选择调用工具,然后再把模型选择的工具需要的参数给模型,让模型给出如何调用工具,返回结果后调用工具把函数返回值再给模型。

具体示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
助手启动,输入 'exit' 退出
用户: 你好,请你告诉我长沙的天气好吗
[Step 0] 助手输出: TOOL:get_weather
[Step 1] 工具调用 JSON: {"tool": "get_weather", "arguments": {"city": "长沙"}}
从tool工具调用,获取未来1天的天气信息
[Step 2] 工具结果: {
"temp": 26,
"humidity": 62,
"wind": 3,
"cloud": 70,
"rain": 0.0,
"snow": 0.0,
"sunrise": "06:00",
"sunset": "18:00"
}
[Step 2] 助手输出: 长沙现在的天气很不错哦!🌤️

- **气温**:26°C,非常舒适,不冷不热。
- **湿度**:62%,比较适中,不会感觉闷。
- **风力**:3级,微风拂面。
- **云量**:70%,多云为主,但无降雨或降雪。
- **日出/日落**:06:00 / 18:00,白天时间充足。

总的来说,今天是个适合外出活动的好天气,不需要带伞,享受阳光和微风吧!😊
最终回答: 长沙现在的天气很不错哦!🌤️

- **气温**:26°C,非常舒适,不冷不热。
- **湿度**:62%,比较适中,不会感觉闷。
- **风力**:3级,微风拂面。
- **云量**:70%,多云为主,但无降雨或降雪。
- **日出/日落**:06:00 / 18:00,白天时间充足。

总的来说,今天是个适合外出活动的好天气,不需要带伞,享受阳光和微风吧!😊
用户: 闭麦是对小麦发言权的一种侵害这对吗
[Step 0] 助手输出: 这话是个谐音梗,带点幽默讽刺。“闭麦”通常指关闭麦克风,而“小麦” 是农作物,没有发言权一说。所以从字面逻辑上不对,从玩笑角度看,它是在调侃“闭麦”这个词的字面意思。答案是:不对,这是幽默的说法。
最终回答: 这话是个谐音梗,带点幽默讽刺。“闭麦”通常指关闭麦克风,而“小麦”是农作物,没有发言权一说。所以从字面逻辑上不对,从玩笑角度看,它是在调侃“闭麦”这个词的字面意思。答案是:不对,这是幽默的说法。
用户:

碎碎念

还不错完成了一整个流程,虽然很简单,原本上网课一直在概念阶段,动手觉得挺开心的?