AI代理的简单方法:查询当前时间

2024年11月13日 由 alex 发表 103 0

大型语言模型(LLM)无处不在。现在很少有人还没用过像ChatGPT这样的工具。LLM的基本工作原理是根据其训练数据提供响应。但是,有些特定任务无法仅通过这种方式得到答案。一个简单的例子就是问题:“现在几点了?”无论你拥有多少训练数据,这个问题都无法仅通过LLM来回答,而需要执行额外的任务。这就是代理程序(Agents)的用武之地。像詹姆斯·邦德这样的代理程序有使命,并通过执行任务来完成它。这基本上就是AI代理程序的工作原理。它们通过执行代码来完成任务。市面上有很多花哨的AI代理框架,例如CrewAI、AutoGen、LangChain和Vertex。它们的发展速度之快以及在现实世界应用中的高效程度令人惊叹。


在这篇文章中,我以“现在几点了?”这个简单问题作为引言,来介绍AI代理程序的基本工作原理。一旦我们对代理程序有了基本了解,我们将回答另一个问题:“我所在位置的天气如何?”这个问题更复杂,因为它不仅仅需要执行一个任务,而是需要执行多个任务,其中一个任务建立在前一个任务结果的基础上。要执行代码,你需要访问一个LLM,在我的情况下是Azure OpenAI,但你也可以选择任何其他LLM。如果你没有通过API访问LLM的权限,你也可以将生成的提示复制到ChatGPT(或任何其他LLM)中,在那里执行,然后将答案粘贴回代码中。让我们从总体方法的概念开始。


方法

像“现在几点了?”这样的问题需要执行任务。如果你让LLM提供获取当前时间的Python代码,它最终会给出类似这样的内容


datetime.now().strftime("%H:%M:%S")"%H:%M:%S")


你可以执行这段自动生成的代码,然后就能得到答案。这样做确实能解决问题,但我们希望采用另一种方式来解决,即从已有的函数样本中选择函数。采用这种方法时,每个函数都应该有良好的文档说明,以便我们——或者更准确地说,是LLM——能够确切地知道函数的功能。为了获取当前时间,我们可以使用这个函数:


def get_current_time():
    """
    Returns the current time as a formatted string.
    This function uses the datetime module to fetch the current time 
    in the format 'HH:MM:SS'.
    Returns:
        str: The current time in 'HH:MM:SS' format.
    
    Example:
        >>> get_current_time()
        '14:23:56'
    """
    # Get the current time using datetime.now() and format it to 'HH:MM:SS'
    current_time = datetime.now().strftime("%H:%M:%S")
    return current_time


所有这些文档可能看起来有些过度,但在这个例子中,我们想强调的是,良好的函数文档对于找到这些函数非常重要。在链接函数时,特别重要的是还要定义输入和输出(以及数据类型!!!)。在这个文件中,我提供了一些带有适当文档的函数。现在让我们来看看如何获取时间。


现在几点了?

首先,让我们导入相关的库,加载环境变量,并设置我们的提示。


import pydoc, utils_generation, os, requests, json, io
from contextlib import redirect_stdout
from utils_generation import *
from dotenv import load_dotenv
load_dotenv(override=True)
prompt = "What time is it?"


utils_generation库是包含我们为代理程序准备的函数的那个库(不仅包含获取时间的函数,还包含许多其他函数,以便我们看到代理程序确实能够为任务找到正确的函数)。现在,我们想使用我们的LLM来回答提示。LLM应该为我们提供完成此任务所需的函数。我们可以传递utils_generation的全部内容,但这会消耗大量的令牌(即计算资源或费用)。我们只需要提供关于这些函数的元信息。这就是contextlib库派上用场的地方。它允许我们将库作为输入传递,并创建一个包含文档说明的txt文件。运行下面的代码,


with open(fn_docs, "w") as file: file.write(pydoc.plain(pydoc.render_doc(utils_generation)))


会生成一个包含如下内容的文件:


Python Library Documentation: module utils_generationmodule utils_generation
NAME
    utils_generation
FUNCTIONS
    add_numbers(a: float, b: float) -> float
        Adds two numbers and returns the result.
        
        This function takes two numeric inputs (int or float) and returns their sum.
        It can handle integers or floating-point numbers.
        
        Args:
            a (float): The first number to add.
            b (float): The second number to add.
        
        Returns:
            float: The sum of the two numbers.
        
        Example:
            >>> add_numbers(5, 3)
            8
            >>> add_numbers(5.5, 3.2)
            8.7


该文件包含了关于函数的全部信息,但没有包含(在实际场景中)庞大的代码。好的,现在我们来创建提示以找到所需的函数。提示的一个选项是:


prompt = "What time is it?""What time is it?"
prompt_adapted = f"""Initial prompt is
'{prompt}'
To answer this prompt, generate a function based on available functions:
'{available_functions}'
Whenever possible, use one of the provided functions. Do not create functions on your own.
Format your response as JSON in this format:
{{"code": "xxx"}}
Do not make any imports in the code. I will handle this.
Do not put anything else in the response except the JSON.
Do not show api keys. Use os.getenv.
Print the result at the end!"""


它清晰地定义了我们想要的内容。为了执行这个提示,我通常会使用像这样的函数。


def execute_text_prompt(prompt, API_KEY = os.getenv("AZURE_OPENAI_API_KEY"), ENDPOINT = os.getenv("AZURE_OPENAI_ENDPOINT"), is_json_response = None, pdf_binary = None):
    headers = {"Content-Type": "application/json","api-key": API_KEY}
    payload = {"messages" : [{ "role": "user","content": [{"type": "text","text": prompt}]}]}
    response = "DUMMY"
    try:
        response = requests.post(ENDPOINT, headers=headers, json=payload)
        response_short = response.json()["choices"][0]["message"]["content"]
        if is_json_response:
            if response_short.startswith("```"):
                response_short = "\n".join(response_short.splitlines()[1:-1])
            response_short = json.loads(response_short, strict=False)
    except requests.RequestException as e:
        print(f"ERROR: {e}")
        return response
    return response_short


我可以设置参数,使其立即返回一个JSON对象。如果你无法访问LLM(大型语言模型),只需打印出提示,在ChatGPT中执行它,然后将响应粘贴回代码中。响应是要执行的代码,以获得所需的结果。虽然我们在这篇文章的开头说过要避免使用自动生成的代码,但这里我们还是使用了它。不过,重要的是要指出,生成的代码只是调用我们的函数,并不包含任何逻辑。逻辑是包含在我们的函数中的。这比运行自动生成的代码要安全得多。我们的提示还明确要求打印出结果。为了将响应写入变量以供后续使用,我们采用了一个简单的技巧:


output = io.StringIO()
with redirect_stdout(output): exec(code)
captured_output = output.getvalue()


这里发生了两件事:

  • 我们的代码通过exec(code)被执行。
  • 输出被重定向,所有打印的内容都会被放入captured_output变量中。


运行这段代码后,我们就在captured_output变量中得到了输出。如果我们想在某处重用输出,这将非常有用。所以,基本上就是这样。代码被生成、执行,并且结果已经可用。生成的代码每次都会有所不同,但在我的情况下,它看起来像这样:


time = get_current_time()
print(time)


就是这样,最后我们终于得到了时间。但是如何获取天气情况呢?


现在天气怎么样?

我们可以使用与之前相同的代码。我把所有东西都整理到了一个漂亮的函数里,我们只需要简单地询问天气情况即可。


prompt = "What weather is it at my location?""What weather is it at my location?"
r = let_the_agent_work(prompt)
for k in r:
    print(f"{k}:\n{r[k]}")


生成的代码如下所示:


from utils_generation import *
import os
def main():
    location = get_location_by_ip()
    city = location.get('city')
    country = location.get('country')
    if city and country:
        api_key = os.getenv('WEATHER_API_KEY')
        weather = get_weather(city, country, api_key)
        print(weather)
    else:
        print('Could not determine location')
if __name__ == '__main__':
    main()


通过观察代码,我们可以很清楚地看到这里发生了什么:

  • 首先,它调用我的IP地址,
  • 然后,它根据IP地址获取位置,
  • 最后,它基于位置查询天气API。


对我来说,它的工作原理如此出色,真是令人着迷。我没有告诉它要使用哪些特定的函数,也没有告诉它获取天气的具体方法。它检查函数的文档,并能找到解决方案。(注意:你可以尝试从文档中移除一个函数。在这种情况下,它会自行生成这个函数。)基于函数输出格式的信息,它甚至知道如何获取正确的值,例如,


country = location.get('country')


最终的回应是我当前所在地的天气情况。


{'city': 'Koblenz', 'temperature_celsius': 8.3, 'humidity': 92, 'description': 'Overcast', 'wind_kph': 4.0}'city': 'Koblenz', 'temperature_celsius': 8.3, 'humidity': 92, 'description': 'Overcast', 'wind_kph': 4.0}


就是这样。这就是如何通过执行任务来解决问题的过程。这也是代理程序所做的工作。


总结


在这篇文章中,我试图对代理程序进行一个简单的介绍。代理程序通过执行任务来解决问题。在我们的情况下,执行任务意味着执行代码。在第一个示例中,检测到了一个简单的获取时间的函数。在第二个更复杂的示例中,多个函数被串联起来以找到解决方案。我们通过提供代理程序可以选择的函数来确保安全性。在我们的简单示例中,这并不是必需的,所有函数也可以通过大型语言模型(LLM)自动生成。但在许多情况下,为任务提供特定的函数是有益的。并且,当你提供良好的文档时,代理程序就知道该选择哪些函数。


文章来源:https://medium.com/python-in-plain-english/what-time-is-it-a-simple-approach-to-ai-agents-5a688c55ad96
欢迎关注ATYUN官方公众号
商务合作及内容投稿请联系邮箱:bd@atyun.com
评论 登录
热门职位
Maluuba
20000~40000/月
Cisco
25000~30000/月 深圳市
PilotAILabs
30000~60000/年 深圳市
写评论取消
回复取消