距离上一篇发文,又过了大半年了。
这段时间学的挺杂的,虽然也花费不少功夫在学习上,但是对于现在很火的AI是一点也没涉及。
按道理来说我也是做技术的,不知道为什么就能一直拖,一直拖,一直拖,一直拖......直到有一天,灵魂突然觉醒!不能再拖下去了!!
然后,我就用python简单写了个ai agent,做了个demo,大概理解了一下整体的流程。
现在要给它记录一下。
搭建环境:
1.安装python:参考www.python.org/downloads/r…
python --version 即验证成功
2.安装vscode和Python插件:参考code.visualstudio.com/
3.安装Ollama,参考ollama.com/
介绍:Ollama可以将模型拉取到本地,然后代码里调用ollama,配置对应模型,就可以跑了,但是有电脑配置要求。
有条件的装个antigravity tools,可以薅到Google、Anthropic等平台提供的免费AI模型额度。
这里就先用Ollama做例子,如果有有对antigravity tools使用遇到问题,可以私我。
python语法
基础的语法还是要了解一下,比如def定义函数,and or not,if条件等等基本语法。
还有个虚拟环境,是为了隔离项目依赖,避免版本冲突的,可以看到文件夹下多了个.env。
开发流程
1.新建一个ai-demo文件夹(mkdir ai-demo),并在文件夹上新建一个m_agent.py(touch m_agent.py)文件。
2.openai的SDK是全球最流行的LLM调用方式。连接到antigravity tools也可以用它。
pip install openai
- ollama拉取一个模型,我用的是
ollama pull qwen2.5:3b(根据电脑自行配置)
- 调用本地模型的代码。
from openai import OpenAI
client = OpenAI(
base_url="http://localhost:11434/v1", // ollama的服务
api_key="no-key" // 不需要key,全部在本地运行 )
response = client.chat.completions.create(
model="qwen2.5:3b", // 刚才下到本地的模型
messages=[{"role": "user", "content": user_question}], // role是角色,有user、system、tool、assistant tools=tools
)
还有user_question和tools,接下去会解释。
5.获取AI回复。
response_content = response.choices[0].message
6.获取用户输入,即prompt,在这里,我们用python获取用户输入内容。
user_input = input('你:') // 可以获取用户输入、
if user_input.lower() in ["exit", "quit", "q"]: // 用户输入exit等,直接退出
print("👋 再见!")
break
7.到这里,已经能做到,用户输入内容 -> 本地模型处理 -> 输出内容。 但是如果需要去访问本地文件或者读写文件等操作,就没办法实现,这时候引入了tools的概念。
大模型通过去调用工具,来增强它的能力,这是一个循环过程,为了代码简单,下面是一个读取文件内容的例子。
8.我们先来定义一个工具函数,读文件。
def run_read(path: str, limit: int = None) -> str:
try:
with open(path, 'r', encoding='utf-8') as f:
lines = f.readlines()
if limit:
lines = lines[:limit]
return ''.join(lines)
except Exception as e:
return f'无法读取文件: {path}'
9.然后定义一下工具。这是传给模型的,即上面的tools,让模型知道它有了哪些工具可以调用。
tools = [
{
'type': 'function',
'function': {
'name': 'read_file',
'description': '读取文件内容',
'parameters': {
'type': 'object',
'properties': {
'path': {
'type': 'string',
'description': '文件路径'
},
'limit': {
'type': 'integer',
'description': '读取行数限制'
}
},
'required': ['path']
}
}
}
]
10.定义一个工具注册表。每一次调用工具手动输入容易造成混乱,在这里统一注册。
TOOL_HANDLERS = {
'read_file': run_read
}
11.这个时候,我们需要调用2次大模型,第一次传入tools(见4),并传入用户输入内容,模型会返回需要调用的工具。我们根据注册表找到对应的函数,执行,获取结果。
results = []
if hasattr(response_content, 'tool_calls') and response_content.tool_calls: // 判断ai返回的结果是否有tool_calls
for tool_call in response_content.tool_calls: // 循环工具
tool_name = tool_call.function.name // 获取工具名
func_args = json.loads(tool_call.function.arguments) // json.loads转字典,括号里是AI给的参数
print(f"AI请求调用工具: {tool_name},参数: {func_args}") handler = TOOL_HANDLERS.get(tool_name) // 获取需要执行的函数
output = handler(**func_args) if handler else f"未找到工具: {tool_name}" // **相当于把参数展开
results.append({ // 把工具执行完的结果,打包成模型能看懂的格式,存起来,等下一起发给AI
'role': 'tool', // 工具返回结果
'tool_call_id': tool_call.id,
'content': output
})
12.把结果发给ai,相当于把结果拼接成ai看的懂的格式重新发给ai,让它生成最终的自然语言。
final_response = client.chat.completions.create(
model="qwen2.5:3b",
messages=results
)
13.最终输出。
print("===AI最终回答===")
print(final_response.choices[0].message.content)
14.拓展
看到这里,是不是对ai agent有了个大致的了解。 但是目前还有几个问题,(1)如果ai返回的不是工具,相当于循环结束,要如何处理? (2)还有现在没有做到上下文理解,要如何给它加上记忆? 可以拓展试试~
最近claude code ‘被开源’了,我把代码拉下来跑了一下,还是要紧跟大家步伐,不能偷懒啊。
对于ai,我也是在起步阶段,只懂得皮中的毛毛,可能有很多错误之处,欢迎指点~ 祝大家都能心想事成~