AI创想

标题: 搭建智能体(代码版) [打印本页]

作者: admin    时间: 2025-9-7 23:15
标题: 搭建智能体(代码版)
文章目录


一、什么是智能体?

智能体就像一个独立的小家伙,它能感知周围的环境,自己做决定,然后采取行动来实现特定的目标。**即智能体(Agent)是指能够感知环境并自主采取行动以实现特定目标的实体。**简单的就像那种只会对刺激做出反应的“反应型智能体”,复杂的就像那种能不断学习和适应的“智能智能体”。
核心概念
常见的智能体类型包括:
像聊天机器人、推荐系统、自动驾驶汽车,它们都用了不同类型的智能体来高效、智能地完成任务。
典型应用场景

二、实现构建智能体

好啦,让我们挽起袖子开始干活吧!


我们这个智能体的核心组成部分是:

2.1、准备工作

在运行代码之前,请确保你的电脑满足以下条件:

  1. # 验证安装:   
  2. python --version
复制代码
  1. conda create --name agents python=3.8-y
  2. conda activate agents
复制代码

  1. ollama --version
复制代码
  1. ollama pull mistral  # 将 'mistral' 替换为你需要的模型
复制代码
2.2、实现步骤

实现案例:
1)对两个数字执行数值运算
2)反转给定的字符串
3)回答问题


第一步:设置环境
除了 Python,我们还需要安装一些必要的库。在这个教程中,我们将使用 requests、json 和 termcolor。此外,我们将使用 dotenv 来管理环境变量。
  1. pip install requests termcolor python-dotenv
复制代码
第二步:定义模型类
我们首先需要一个模型来处理用户的输入。我们将创建一个 OllamaModel 类,它与本地 API 交互以生成响应。
这是一个基本的实现:
  1. from termcolor import colored
  2. import os
  3. from dotenv import load_dotenv
  4. load_dotenv()import requests
  5. import json
  6. import operator
  7. classOllamaModel:def__init__(self, model, system_prompt, temperature=0, stop=None):"""
  8.         用给定的参数初始化 OllamaModel。
  9.         参数:
  10.         model (str): 要使用的模型的名称。
  11.         system_prompt (str): 要使用的系统提示。
  12.         temperature (float): 模型的温度设置。
  13.         stop (str): 模型的停止标记。
  14.         """
  15.         self.model_endpoint ="http://localhost:11434/api/generate"
  16.         self.temperature = temperature
  17.         self.model = model
  18.         self.system_prompt = system_prompt
  19.         self.headers ={"Content-Type":"application/json"}
  20.         self.stop = stop
  21.     defgenerate_text(self, prompt):"""
  22.         根据提供的提示从 Ollama 模型生成响应。
  23.         参数:
  24.         prompt (str): 用于生成响应的用户查询。
  25.         返回:
  26.         dict: 模型的响应,以字典形式返回。
  27.         """
  28.         payload ={"model": self.model,"format":"json","prompt": prompt,"system": self.system_prompt,"stream":False,"temperature": self.temperature,"stop": self.stop
  29.         }try:
  30.             request_response = requests.post(
  31.                 self.model_endpoint,
  32.                 headers=self.headers,
  33.                 data=json.dumps(payload))print("请求响应", request_response)
  34.             request_response_json = request_response.json()
  35.             response = request_response_json['response']
  36.             response_dict = json.loads(response)print(f"\n\n来自 Ollama 模型的响应: {response_dict}")return response_dict
  37.         except requests.RequestException as e:
  38.             response ={"error":f"调用模型时出错!{str(e)}"}return response
复制代码
这个类用模型的名称、系统提示、温度和停止标记进行初始化。generate_text 方法向模型 API 发送请求并返回响应。
第三步:为智能体创建工具
下一步是创建我们的智能体可以使用的工具。这些工具是执行特定任务的简单 Python 函数。这是一个基本计算器和字符串反转器的示例:
  1. defbasic_calculator(input_str):"""
  2.     根据输入的字符串或字典对两个数字执行数值运算。
  3.     参数:
  4.     input_str (str 或 dict): 表示字典的 JSON 字符串,包含键 'num1'、'num2' 和 'operation',
  5.                             或者直接是一个字典。例如:'{"num1": 5, "num2": 3, "operation": "add"}'
  6.                             或 {"num1": 67869, "num2": 9030393, "operation": "divide"}
  7.     返回:
  8.     str: 运算结果的格式化字符串。
  9.     抛出:
  10.     Exception: 如果在运算过程中发生错误(例如,除以零)。
  11.     ValueError: 如果请求了不支持的运算或输入无效。
  12.     """try:# 同时处理字典和字符串输入ifisinstance(input_str,dict):
  13.             input_dict = input_str
  14.         else:# 清理并解析输入字符串
  15.             input_str_clean = input_str.replace("'",""")
  16.             input_str_clean = input_str_clean.strip().strip(""")
  17.             input_dict = json.loads(input_str_clean)# 验证必需的字段ifnotall(key in input_dict for key in['num1','num2','operation']):return"错误:输入必须包含 'num1'、'num2' 和 'operation'"
  18.         num1 =float(input_dict['num1'])# 转换为浮点数以处理小数
  19.         num2 =float(input_dict['num2'])
  20.         operation = input_dict['operation'].lower()# 不区分大小写except(json.JSONDecodeError, KeyError)as e:return"无效的输入格式。请提供有效的数字和运算。"except ValueError as e:return"错误:请提供有效的数值。"# 定义支持的运算并进行错误处理
  21.     operations ={'add': operator.add,'plus': operator.add,# add 的替代词'subtract': operator.sub,'minus': operator.sub,# subtract 的替代词'multiply': operator.mul,'times': operator.mul,# multiply 的替代词'divide': operator.truediv,'floor_divide': operator.floordiv,'modulus': operator.mod,'power': operator.pow,'lt': operator.lt,'le': operator.le,'eq': operator.eq,'ne': operator.ne,'ge': operator.ge,'gt': operator.gt
  22.     }# 检查运算是否受支持if operation notin operations:returnf"不支持的运算:'{operation}'。支持的运算有:{', '.join(operations.keys())}"try:# 特殊处理除以零的情况if(operation in['divide','floor_divide','modulus'])and num2 ==0:return"错误:不允许除以零"# 执行运算
  23.         result = operations[operation](num1, num2)# 根据类型格式化结果ifisinstance(result,bool):
  24.             result_str ="True"if result else"False"elifisinstance(result,float):# 处理浮点数精度
  25.             result_str =f"{result:.6f}".rstrip('0').rstrip('.')else:
  26.             result_str =str(result)returnf"答案是:{result_str}"except Exception as e:returnf"计算过程中出错:{str(e)}"defreverse_string(input_string):"""
  27.     反转给定的字符串。
  28.     参数:
  29.     input_string (str): 要反转的字符串。
  30.     返回:
  31.     str: 反转后的字符串。
  32.     """# 检查输入是否为字符串ifnotisinstance(input_string,str):return"错误:输入必须是字符串"# 使用切片反转字符串
  33.     reversed_string = input_string[::-1]# 格式化输出
  34.     result =f"反转后的字符串是:{reversed_string}"return result
复制代码
这些函数被设计为根据提供的输入执行特定任务。basic_calculator 处理算术运算,而 reverse_string 反转给定的字符串。
第四步:构建工具箱
ToolBox 类存储智能体可以使用的所有工具,并提供每个工具的描述:
  1. classToolBox:def__init__(self):
  2.         self.tools_dict ={}defstore(self, functions_list):"""
  3.         存储列表中每个函数的字面名称和文档字符串。
  4.         参数:
  5.         functions_list (list): 要存储的函数对象列表。
  6.         返回:
  7.         dict: 以函数名称为键,其文档字符串为值的字典。
  8.         """for func in functions_list:
  9.             self.tools_dict[func.__name__]= func.__doc__
  10.         return self.tools_dict
  11.     deftools(self):"""
  12.         将 store 中创建的字典作为文本字符串返回。
  13.         返回:
  14.         str: 存储的函数及其文档字符串的字典,以文本字符串形式返回。
  15.         """
  16.         tools_str =""for name, doc in self.tools_dict.items():
  17.             tools_str +=f"{name}: "{doc}"\n"return tools_str.strip()
复制代码
这个类将帮助智能体了解哪些工具可用以及每个工具的作用。
第五步:创建智能体类
智能体需要思考,决定使用哪个工具,并执行它。这是 Agent 类:
  1. """agent_system_prompt_template =
  2. 你是一个可以访问特定工具的智能 AI 助手。你的响应必须始终采用以下 JSON 格式:
  3. {{
  4.     "tool_choice": "工具名称",
  5.     "tool_input": "工具的输入"
  6. }}
  7. 工具及其使用时机:
  8. 1. basic_calculator: 用于任何数学计算
  9.    - 输入格式:{{"num1": 数字, "num2": 数字, "operation": "add/subtract/multiply/divide"}}
  10.    - 支持的运算:add/plus, subtract/minus, multiply/times, divide
  11.    - 示例输入和输出:
  12.      输入:"计算 15 加 7"
  13.      输出:{{"tool_choice": "basic_calculator", "tool_input": {{"num1": 15, "num2": 7, "operation": "add"}}}}
  14.      输入:"100 除以 5 是多少?"
  15.      输出:{{"tool_choice": "basic_calculator", "tool_input": {{"num1": 100, "num2": 5, "operation": "divide"}}}}
  16. 2. reverse_string: 用于任何涉及反转文本的请求
  17.    - 输入格式:只需将要反转的文本作为字符串
  18.    - 当用户提到“反转”、“倒过来”或要求反转文本时,始终使用此工具
  19.    - 示例输入和输出:
  20.      输入:"Howwwww 的反转?"
  21.      输出:{{"tool_choice": "reverse_string", "tool_input": "Howwwww"}}
  22.      输入:"Python 的反转是什么?"
  23.      输出:{{"tool_choice": "reverse_string", "tool_input": "Python"}}
  24. 3. no tool: 用于一般对话和问题
  25.    - 示例输入和输出:
  26.      输入:"你是谁?"
  27.      输出:{{"tool_choice": "no tool", "tool_input": "我是一个 AI 助手,可以帮助你进行计算、反转文本和回答问题。我可以执行数学运算和反转字符串。今天我能帮你做什么?"}}
  28.      输入:"你好吗?"
  29.      输出:{{"tool_choice": "no tool", "tool_input": "我运行良好,谢谢你的关心!我可以帮你进行计算、文本反转或回答你可能有的任何问题。"}}
  30. 规则:
  31. 1. 对于关于身份、能力或感受的问题:
  32.    - 始终使用 "no tool"
  33.    - 提供完整、友好的回应
  34.    - 提及你的能力
  35. 2. 对于任何文本反转请求:
  36.    - 始终使用 "reverse_string"
  37.    - 仅提取要反转的文本
  38.    - 删除引号、“的反转”和其他多余的文本
  39. 3. 对于任何数学运算:
  40.    - 始终使用 "basic_calculator"
  41.    - 提取数字和运算
  42.    - 将文本数字转换为数字
  43. 这是你的工具及其描述的列表:
  44. {tool_descriptions}
  45. 记住:你的响应必须始终是包含 "tool_choice" 和 "tool_input" 字段的有效 JSON。
  46. """classAgent:def__init__(self, tools, model_service, model_name, stop=None):"""
  47.         用工具列表和模型初始化智能体。
  48.         参数:
  49.         tools (list): 工具函数列表。
  50.         model_service (class): 具有 generate_text 方法的模型服务类。
  51.         model_name (str): 要使用的模型的名称。
  52.         """
  53.         self.tools = tools
  54.         self.model_service = model_service
  55.         self.model_name = model_name
  56.         self.stop = stop
  57.     defprepare_tools(self):"""
  58.         将工具存储在工具箱中并返回它们的描述。
  59.         返回:
  60.         str: 存储在工具箱中的工具的描述。
  61.         """
  62.         toolbox = ToolBox()
  63.         toolbox.store(self.tools)
  64.         tool_descriptions = toolbox.tools()return tool_descriptions
  65.     defthink(self, prompt):"""
  66.         使用系统提示模板和工具描述对模型运行 generate_text 方法。
  67.         参数:
  68.         prompt (str): 用于生成响应的用户查询。
  69.         返回:
  70.         dict: 模型的响应,以字典形式返回。
  71.         """
  72.         tool_descriptions = self.prepare_tools()
  73.         agent_system_prompt = agent_system_prompt_template.format(tool_descriptions=tool_descriptions)# 使用系统提示创建模型服务实例if self.model_service == OllamaModel:
  74.             model_instance = self.model_service(
  75.                 model=self.model_name,
  76.                 system_prompt=agent_system_prompt,
  77.                 temperature=0,
  78.                 stop=self.stop
  79.             )else:
  80.             model_instance = self.model_service(
  81.                 model=self.model_name,
  82.                 system_prompt=agent_system_prompt,
  83.                 temperature=0)# 生成并返回响应字典
  84.         agent_response_dict = model_instance.generate_text(prompt)return agent_response_dict
  85.     defwork(self, prompt):"""
  86.         解析 think 返回的字典并执行适当的工具。
  87.         参数:
  88.         prompt (str): 用于生成响应的用户查询。
  89.         返回:
  90.         执行适当工具的响应,如果找不到匹配的工具,则返回 tool_input。
  91.         """
  92.         agent_response_dict = self.think(prompt)
  93.         tool_choice = agent_response_dict.get("tool_choice")
  94.         tool_input = agent_response_dict.get("tool_input")for tool in self.tools:if tool.__name__ == tool_choice:
  95.                 response = tool(tool_input)print(colored(response,'cyan'))returnprint(colored(tool_input,'cyan'))return
复制代码
这个类有三个主要方法:
第六步:运行智能体
最后,让我们把所有东西放在一起并运行我们的智能体。在脚本的主要部分,初始化智能体并开始接受用户输入:
  1. # 示例用法if __name__ =="__main__":"""
  2.     使用此智能体的说明:
  3.     你可以尝试的示例查询:
  4.     1. 计算器运算:
  5.        - "计算 15 加 7"
  6.        - "100 除以 5 是多少?"
  7.        - "23 乘以 4"
  8.     2. 字符串反转:
  9.        - "反转单词 'hello world'"
  10.        - "你能反转 'Python Programming' 吗?"
  11.     3. 一般问题(将获得直接响应):
  12.        - "你是谁?"
  13.        - "你能帮我做什么?"
  14.     Ollama 命令(在终端中运行):
  15.     - 检查可用模型:    'ollama list'
  16.     - 检查正在运行的模型:      'ps aux | grep ollama'
  17.     - 列出模型标签:          'curl http://localhost:11434/api/tags'
  18.     - 拉取新模型:         'ollama pull mistral'
  19.     - 运行模型服务器:         'ollama serve'
  20.     """
  21.     tools =[basic_calculator, reverse_string]# 使用 Ollama 和 llama2 模型
  22.     model_service = OllamaModel
  23.     model_name ="llama2"# 可以更改为其他模型,如 'mistral'、'codellama' 等。
  24.     stop ="<|eot_id|>"
  25.     agent = Agent(tools=tools, model_service=model_service, model_name=model_name, stop=stop)print("\n欢迎使用 AI 智能体!输入 'exit' 退出。")print("你可以让我:")print("1. 执行计算(例如,'计算 15 加 7')")print("2. 反转字符串(例如,'反转 hello world')")print("3. 回答一般问题\n")whileTrue:
  26.         prompt =input("问我任何问题:")if prompt.lower()=="exit":break
  27.         agent.work(prompt)
复制代码
三、总结

在这篇文章里,我们从理解什么是智能体到一步步实现一个智能体。我们设置了环境,定义了模型,创建了必要的工具,并构建了一个结构化的工具箱来支持我们智能体的功能。最后,我们通过运行智能体将所有内容整合在一起。
这种结构化的方法为构建能够自动执行任务和做出明智决策的智能、交互式智能体奠定了坚实的基础。随着 AI 智能体的不断发展,它们的应用将在各个行业中扩展,推动效率和创新。




欢迎光临 AI创想 (http://llms-ai.com/) Powered by Discuz! X3.4