AI智能代理实战——驾驭大语言模型的力量

103 阅读26分钟

本章内容包括:

  • 理解大语言模型(LLM)的基础知识
  • 连接并调用 OpenAI API
  • 使用 LM Studio 探索和应用开源大语言模型
  • 通过提示工程(prompt engineering)引导 LLM
  • 根据具体需求选择最优的 LLM

“大语言模型”(LLM)这一术语现已成为一种人工智能形式的普遍称谓。这些LLM是基于生成式预训练变换器(GPT)开发的。虽然其他架构也支撑着LLM,但目前GPT架构是最为成功的一种。

LLM和GPT属于生成模型,这意味着它们的训练目标是生成内容,而非仅仅预测或分类内容。为进一步说明这一点,请参考图 2.1,该图展示了生成模型与预测/分类模型之间的区别。生成模型基于输入创造新的内容,而预测和分类模型则是对输入进行分类。

image.png

我们可以通过其组成部分进一步定义大语言模型(LLM),如图 2.2 所示。在该图中,数据表示用于训练模型的内容,架构则是模型自身的属性,例如参数数量或模型规模。模型还会针对特定的使用场景进行进一步训练,包括聊天、文本补全或指令执行。最后,微调是一项附加功能,通过优化输入数据和模型训练,使模型更好地匹配特定的使用场景或领域。

image.png

GPT所采用的变换器架构(transformer architecture),作为大语言模型(LLM)中特定的一种架构,使得模型规模能够扩展到数十亿参数。这些大型模型需要在海量文档(以TB计)上进行训练以打下基础。随后,模型会针对特定的使用场景,通过多种方法进行持续训练。

例如,ChatGPT 最初在公开的互联网数据上进行有效训练,随后通过多种训练策略进行微调。最终的微调训练采用了一种高级方法——基于人类反馈的强化学习(Reinforcement Learning with Human Feedback,RLHF),从而形成了一个专注于“聊天补全”的模型应用场景。

聊天补全类大语言模型设计上注重通过不断迭代和精炼进行提升——换句话说,就是通过聊天不断进步。这类模型在任务完成、推理和规划方面的表现也被评测为最佳,因此非常适合构建智能代理和助手。而文本补全类模型仅用于基于输入文本生成内容,不支持迭代优化。

在本书构建强大代理的旅程中,我们重点关注被称为“聊天补全”模型的这一类LLM。当然,这并不排除你尝试其他模型类型来构建代理,但可能需要对所提供的代码示例进行较大改动,以支持不同的模型形式。

在本章后续内容中,我们还将深入探讨LLM和GPT的更多细节,特别是在本地运行开源LLM时的相关内容。下一节,我们将介绍如何使用OpenAI日益成熟的标准来连接LLM。

2.1 掌握 OpenAI API

众多 AI 代理和助手项目使用 OpenAI API SDK 来连接大语言模型(LLM)。虽然这不是统一标准,但当前描述连接的基本概念普遍遵循 OpenAI 的模式。因此,我们必须理解使用 OpenAI SDK 连接 LLM 的核心概念。

本章将介绍如何使用 OpenAI Python SDK/包连接 LLM 模型。我们将讨论连接 GPT-4 模型、模型响应、token 计数以及如何定义一致的消息。从下一小节开始,我们将详细讲解如何使用 OpenAI。

2.1.1 连接聊天补全模型

要完成本节及后续练习,你需要搭建 Python 开发环境并获取访问 LLM 的权限。附录 A 会指导你如何注册 OpenAI 账户以及访问 GPT-4 或其他模型;附录 B 展示如何使用 Visual Studio Code (VS Code) 设置 Python 开发环境及安装所需扩展。如果你想跟着练习,建议先阅读这些附录内容。

首先,用 VS Code 打开 chapter_2 源代码文件夹,并创建新的 Python 虚拟环境。若需要帮助,参考附录 B。

然后,使用如下命令安装 OpenAI 和 python-dotenv 包,将所需依赖安装到虚拟环境中。

pip install openai python-dotenv

接下来,打开 VS Code 中的 connecting.py 文件,查看代码示例(见示例 2.2)。确保将模型名称设置为合适名称,例如 gpt-4。目前编写时,gpt-4-1106-preview 代表 GPT-4 Turbo。

示例 2.2 connecting.py

import os
from openai import OpenAI
from dotenv import load_dotenv

load_dotenv()                           #1
api_key = os.getenv('OPENAI_API_KEY')
if not api_key:                             #2
    raise ValueError("No API key found. Please check your .env file.")
client = OpenAI(api_key=api_key)                        #3

def ask_chatgpt(user_message):
    response = client.chat.completions.create(      #4
        model="gpt-4-1106-preview",
        messages=[{"role": "system", "content": "You are a helpful assistant."},
                  {"role": "user", "content": user_message}],
        temperature=0.7,
    )
    return response.choices[0].message.content     #5

user = "What is the capital of France?"
response = ask_chatgpt(user)                #6
print(response)

注释说明:

  • #1 加载存储在 .env 文件中的密钥
  • #2 检查 API 密钥是否存在
  • #3 使用密钥创建客户端
  • #4 调用 create 方法生成响应
  • #5 返回响应中的文本内容
  • #6 执行请求并打印响应

代码功能较多,下面逐步拆解。chapter_2 文件夹中有一个 .env 文件,存放环境变量,调用 load_dotenv 函数时自动加载。

你必须在 .env 文件中设置你的 OpenAI API 密钥,如示例 2.3 所示。附录 A 介绍如何获取密钥和查找模型名称。

示例 2.3 .env 文件

OPENAI_API_KEY='your-openai-api-key'

设置好密钥后,可按 F5 键或在 VS Code 菜单选择“Run > Start Debugging”调试运行代码。运行后你应该看到类似“The capital of France is Paris.”的输出。

请记住,生成模型的响应依赖概率,通常会给出正确且一致的答案。

你可以通过调整请求的 temperature 参数来控制响应的随机性。如果想让模型更稳定,一般将 temperature 降至 0;如果希望模型产生更多变化,则调高 temperature。下一节我们将详细探讨 temperature 的设置。

2.1.2 理解请求与响应

深入了解聊天补全请求和响应的特性非常有帮助。我们先关注请求部分,如下所示。请求中包含了指定的模型、消息内容和 temperature。

示例 2.4 聊天补全请求

response = client.chat.completions.create(
    model="gpt-4-1106-preview",                 #1
    messages=[{"role": "system", "content": "You are a helpful assistant."},  #2
              {"role": "user", "content": user_message}],      #3
    temperature=0.7,     #4
)

注释说明:

  • #1 响应请求所使用的模型或部署
  • #2 系统角色消息,描述请求的规则与指南
  • #3 用户角色消息,包含用户输入内容
  • #4 temperature,控制生成内容的随机性或多样性

请求中的 messages 字段定义了一组消息和对应的角色。聊天补全模型支持三种角色类型:

  • System 角色:描述请求规则和指导方针,通常定义 LLM 在对话中的角色身份
  • User 角色:代表并包含用户的输入消息
  • Assistant 角色:用于记录之前 LLM 的响应历史,也可用于注入历史消息

单次请求发送的消息可以封装整个对话历史,如示例 2.5 所示。

示例 2.5 带有历史消息的消息列表(JSON 格式)

[    {        "role": "system",        "content": "You are a helpful assistant."    },    {        "role": "user",        "content": "What is the capital of France?"    },    {        "role": "assistant",        "content": "The capital of France is Paris."    },    {        "role": "user",        "content": "What is an interesting fact of Paris."    }]

你可以打开 VS Code 中的 message_history.py 文件,按 F5 调试运行,查看输出结果。多运行几次,观察结果变化。

由于 temperature 设为 0.7,结果会在多次运行中有所差异。你可以将 temperature 调为 0,再次运行 message_history.py 多次,观察结果会保持一致或高度相似。

请求的 temperature 设置通常取决于具体使用场景。有时你可能希望限制回答的随机性,降低 temperature 至 0 可获得稳定结果;相反,temperature 设为 1.0 则能产生最大变异。

接下来,我们关注响应返回的信息格式。示例 2.6 展示了聊天补全响应的输出结构。你可以通过运行 message_history.py 文件查看实际输出。

示例 2.6 聊天补全响应示例

{
    "id": "chatcmpl-8WWL23up3IRfK1nrDFQ3EHQfhx0U6",
    "choices": [                                      #1
        {
            "finish_reason": "stop",
            "index": 0,
            "message": {
                "content": "… omitted",
                "role": "assistant",       #2
                "function_call": null,
                "tool_calls": null
            },
            "logprobs": null
        }
    ],
    "created": 1702761496,
    "model": "gpt-4-1106-preview",     #3
    "object": "chat.completion",
    "system_fingerprint": "fp_3905aa4f79",
    "usage": {
        "completion_tokens": 78,     #4
        "prompt_tokens": 48,         #4
        "total_tokens": 126          #4
    }
}

注释说明:

  • #1 模型可能返回多个响应选项
  • #2 以 assistant 角色返回的响应内容
  • #3 标明所使用的模型
  • #4 统计输入(prompt)和输出(completion)token 的数量

跟踪输入 token(提示中使用的)和输出 token(响应返回的)数量是很有意义的。有时减少 token 数量非常关键,因为较少的 token 意味着与 LLM 交互成本更低、响应更快且结果更好更稳定。

以上涵盖了连接 LLM 并获取响应的基础知识。在本书后续章节,我们将继续复盘和拓展如何与 LLM 交互。接下来,我们将探索如何加载和使用开源 LLM。

2.2 使用 LM Studio 探索开源大语言模型(LLM)

商业化的 LLM,如 OpenAI 的 GPT-4,是学习现代 AI 使用和构建代理的绝佳起点。然而,商业代理是外部资源,通常需要付费,降低了数据隐私和安全性,并且引入了外部依赖。此外,其他外部因素可能进一步加剧这些问题。

因此,构建可比肩的开源 LLM 的竞赛日益激烈也不足为奇。如今已有许多开源 LLM 能够满足众多任务和代理系统的需求。仅在一年时间里,相关工具的进步就非常显著,使得本地部署 LLM 变得十分简便,正如我们将在下一节看到的那样。

2.2.1 安装与运行 LM Studio

LM Studio 是一款免费下载的软件,支持在 Windows、Mac 和 Linux 平台本地下载和托管 LLM 及其他模型。该软件易于使用,提供多项便捷功能,帮助用户快速上手。以下是下载和设置 LM Studio 的简要步骤:

  • lmstudio.ai/ 下载 LM Studio。
  • 根据你的操作系统完成软件安装。请注意,部分版本可能处于测试阶段,需要额外安装工具或库。
  • 启动软件。

图 2.3 展示了正在运行的 LM Studio 窗口界面。在这里,你可以查看当前热门模型列表,搜索其他模型,甚至进行下载。主页内容对于了解顶级模型的详细信息和规格非常有帮助。

image.png

LM Studio 一个非常吸引人的功能是它能够分析你的硬件配置,并与所选模型的需求进行匹配。软件会告诉你当前硬件能否顺畅运行某个模型,这大大节省了你选择和试验模型的时间。

你只需输入关键词搜索模型,然后点击“Go”按钮,就会进入搜索页面界面,如图 2.4 所示。在该页面,你可以看到所有模型的变体及其他规格信息,比如上下文 token 大小。点击“Compatibility Guess”(兼容性预测)按钮后,软件甚至会告诉你该模型是否适合在你的系统上运行。

image.png

点击即可下载任何适合你系统运行的模型。你可能更倾向于选择专为聊天补全设计的模型,但如果系统性能有限,也可以先使用现有资源。此外,如果不确定选用哪个模型,完全可以下载多个试用。LM Studio 是探索和尝试多种模型的极佳工具。

模型下载完成后,你可以在聊天页面加载并运行该模型,也可以在服务器页面将其作为服务器运行。图 2.5 展示了在聊天页面加载和运行模型的界面,同时还显示了启用和使用 GPU 的选项(如果你拥有 GPU 的话)。

image.png

要加载并运行模型,打开页面顶部中间的下拉菜单,选择已下载的模型。随后会出现进度条,显示模型加载状态,加载完成后即可开始在界面中输入内容。

如果检测到 GPU,软件还允许你使用部分或全部 GPU 资源进行模型推理。GPU 通常能在一定程度上加快模型响应速度。你可以通过查看页面底部的性能状态(如图 2.5 所示)来了解添加 GPU 后对模型性能的影响。

通过与模型聊天并尝试各种提示词,可以帮助你判断模型是否适合你的具体应用场景。更系统的方法是使用“提示流(prompt flow)”工具来评估提示词和大语言模型。我们将在第 9 章介绍如何使用提示流。

LM Studio 还支持在服务器上运行模型,并通过 OpenAI 包进行访问。下一节我们将介绍如何使用服务器功能并部署模型。

2.2.2 使用 LM Studio 本地部署 LLM 服务器

借助 LM Studio,本地运行 LLM 服务器非常简单。只需打开服务器页面,加载模型,然后点击“启动服务器(Start Server)”按钮,如图 2.6 所示。之后,你可以复制粘贴示例代码,连接并调用你的模型。

image.png

你可以在 VS Code 中打开 chapter_2/lmstudio_server.py 文件,查看 Python 代码示例。代码内容也在下面的示例 2.7 中展示。然后,在 VS Code 调试器中运行该代码(按 F5)。

示例 2.7 lmstudio_server.py

from openai import OpenAI

client = OpenAI(base_url="http://localhost:1234/v1", api_key="not-needed")

completion = client.chat.completions.create(
  model="local-model",                           #1
  messages=[
    {"role": "system", "content": "Always answer in rhymes."},
    {"role": "user", "content": "Introduce yourself."}       #2
  ],
  temperature=0.7,
)

print(completion.choices[0].message)      #3

注释说明:

  • #1 目前未使用该参数,值可任意
  • #2 你可以根据需要修改消息内容
  • #3 默认代码输出完整消息

如果你遇到连接服务器或其他问题,请务必检查服务器模型设置(Server Model Settings)与你加载的模型类型是否匹配。例如,之前图 2.6 中展示的加载模型与服务器设置不一致,图 2.7 展示了正确的设置。

image.png

现在,你可以使用本地托管的 LLM 或商业模型来构建、测试,甚至运行你的代理。接下来的章节将探讨如何更有效地利用提示工程构建提示词。

2.3 通过提示工程引导大语言模型(LLM)

在 LLM 中,提示(prompt)指的是用于请求的消息内容,目的是获得更优质的响应输出。提示工程是一个新兴领域,试图构建一套系统化的方法论来设计提示词。然而,提示构建尚未成为成熟科学,目前有越来越多且多样化的方法被归纳为提示工程。

幸运的是,像 OpenAI 这样的机构已经开始整理并发布一套通用策略,如图 2.8 所示。这些策略涵盖了多种战术,其中一些需要额外的基础设施和考量。因此,涉及更高级概念的提示工程策略将在相关章节中详细讲解。

image.png

图 2.8 中的每种策略都进一步细化为具体的战术,用以精炼提示工程的具体方法。本章将重点探讨基本的“撰写清晰指令”(Write Clear Instructions)策略。图 2.9 详细展示了该策略下的各项战术及对应示例。我们将在接下来的章节通过代码演示运行这些示例。

image.png

“撰写清晰指令”策略强调在提出请求时要谨慎且具体。让大语言模型(LLM)执行任务,和让人完成相同任务没有本质区别。通常,你在请求中能提供越多与任务相关的信息和上下文,得到的响应就越准确。

这一策略被细化为多项具体战术,供你应用于提示设计。为了理解如何使用这些战术,chapter_2 源代码文件夹中提供了一个包含多种提示示例的代码演示文件 prompt_engineering.py。

打开 VS Code 中的 prompt_engineering.py 文件,如示例 2.8 所示。代码首先加载 prompts 文件夹中的所有 JSON Lines 文件,然后列出文件供用户选择提示选项。选择后,程序将提示提交给 LLM 并打印响应。

示例 2.8 prompt_engineering.py (main函数)

def main():
    directory = "prompts"
    text_files = list_text_files_in_directory(directory)    #1

    if not text_files:
        print("No text files found in the directory.")
        return

    def print_available():                                     #2
        print("Available prompt tactics:")
        for i, filename in enumerate(text_files, start=1):
            print(f"{i}. {filename}")

    while True:
        try:
            print_available()                   #2              
            choice = int(input("Enter … 0 to exit): "))           #3
            if choice == 0:
                break
            elif 1 <= choice <= len(text_files):
                selected_file = text_files[choice - 1]
                file_path = os.path.join(directory, selected_file)
                prompts = load_and_parse_json_file(file_path)                          #4
                print(f"Running prompts for {selected_file}")
                for i, prompt in enumerate(prompts):
                    print(f"PROMPT {i+1} --------------------")
                    print(prompt)
                    print(f"REPLY ---------------------------")
                    print(prompt_llm(prompt))                       #5
            else:
                print("Invalid choice. Please enter a valid number.")
        except ValueError:
            print("Invalid input. Please enter a number.")

注释说明:

  • #1 收集指定文件夹中的所有文件
  • #2 打印可选文件列表
  • #3 用户输入选择
  • #4 加载并解析选中提示文件中的提示内容
  • #5 将提示提交给 OpenAI LLM 并打印响应

代码中有一段被注释掉的示例,演示了如何连接本地 LLM。这样你就可以在本地运行的开源 LLM 上探索相同的提示工程战术。默认情况下,此示例使用了我们在 2.1.1 节中配置的 OpenAI 模型。如果之前未完成配置,请先回去完成,再运行此示例。

图 2.10 展示了在 VS Code 中运行 prompt_engineering.py 测试提示工程战术时的输出界面。运行测试器后,你可以输入想测试的战术编号并观察执行结果。

image.png

接下来的章节中,我们将更详细地探讨每种提示战术,并审视各种示例。

2.3.1 创建详细查询

该战术的基本原则是尽可能提供详尽的信息,同时注意避免包含无关细节。以下示例展示了用于探索该战术的 JSON Lines 文件内容。

示例 2.9 detailed_queries.jsonl

[    {        "role": "system",        "content": "You are a helpful assistant."    },    {        "role": "user",        "content": "What is an agent?"    }]
[    {        "role": "system",        "content": "You are a helpful assistant."    },    {        "role": "user",        "content": "What is a GPT Agent? \nPlease give me 3 examples of a GPT agent"    }]

注释说明:

  • #1 第一个示例未使用详细查询
  • #2 第一个示例提出了一个非常笼统的问题
  • #3 第二个示例提出了更具体的问题,并请求举例

该示例演示了使用详细查询和不使用详细查询的差别,同时进一步通过请求示例来强化问题与期望输出之间的关联。请记住,提示中提供越多相关信息和上下文,整体响应质量通常越高。请求示例是强化问题与答案关联的另一种方式。

2.3.2 采用人物设定(Persona)

采用人物设定可以为 LLM 定义一个宏观的上下文或规则集。LLM 随后会基于该上下文和/或规则来框定所有后续的输出响应。这是一种非常有效的策略,本书中也将广泛使用。

示例 2.10 adopting_personas.jsonl

[    {        "role": "system",        "content": "You are a 20 year old female who attends college in computer science. Answer all your replies as a junior programmer."    },    {        "role": "user",        "content": "What is the best subject to study."    }]
[    {        "role": "system",        "content": "You are a 38 year old male registered nurse. Answer all replies as a medical professional."    },    {        "role": "user",        "content": "What is the best subject to study."    }]

注释说明:

  • #1 第一种人物设定
  • #2 第二种人物设定

代理角色设定的核心元素之一即为人物设定。我们将采用多种人物设定来辅助代理完成任务。运行此战术时,请特别留意 LLM 输出响应的风格和内容。

GPT 橡皮鸭(Rubber Ducking)

橡皮鸭调试法是一种问题解决技巧,指的是将问题向一个无生命物体(如橡皮鸭)解释,以理清思路或找到解决方案。此方法在编程和调试中广泛使用,因为通过口头表达问题常常能理清思路并获得新见解。

GPT 橡皮鸭调试法采用同样技巧,但将对象替换为 LLM。该策略还可进一步扩展,为 LLM 赋予特定领域的人物设定,以针对特定解决方案场景进行辅助。

2.3.3 使用分隔符(Delimiters)

分隔符是一种有效的方法,用于隔离消息的某部分内容,使 LLM 专注于该部分信息。此战术常与其他战术结合使用,也能独立发挥良好效果。以下示例演示了两种用法,但实际上分隔符的描述方式多种多样,包括 XML 标签或 Markdown 语法。

示例 2.11 using_delimiters.jsonl

[    {        "role": "system",        "content": "Summarize the text delimited by triple quotes with a haiku."    },    {        "role": "user",        "content": "A gold chain is cool '''but a silver chain is better'''"    }]
[    {        "role": "system",        "content": "You will be provided with a pair of statements (delimited with XML tags) about the same topic. First summarize the arguments of each statement. Then indicate which of them makes a better statement and explain why."    },    {        "role": "user",        "content": "<statement>gold chains are cool</statement>\n<statement>silver chains are better</statement>"    }]

注释说明:

  • #1 分隔符由字符类型和重复次数定义(三重引号)
  • #2 分隔符遵循 XML 标准

运行此战术时,请关注 LLM 输出响应时关注的文本部分。该战术对于描述层级信息或其他关系模式非常有用。

2.3.4 指定步骤

指定步骤是另一种强有力的提示战术,具有广泛的应用场景,包括代理系统,如示例 2.12 所示。在为复杂的多步骤任务设计提示或代理角色时,这一战术尤为有效。你可以将复杂的提示拆解为逐步执行的流程,让 LLM 按步骤依次执行。这样,LLM 可以通过多轮交互和多次迭代,在较长对话中逐步完成任务。

示例 2.12 specifying_steps.jsonl

[
    {
        "role": "system",
        "content": "Use the following step-by-step instructions to respond to user inputs.\nStep 1 - The user will provide you with text in triple single quotes. Summarize this text in one sentence with a prefix that says 'Summary: '.\nStep 2 - Translate the summary from Step 1 into Spanish, with a prefix that says 'Translation: '."
    },
    {
        "role": "user",
        "content": "'''I am hungry and would like to order an appetizer.'''"
    }
]
[
    {
        "role": "system",
        "content": "Use the following step-by-step instructions to respond to user inputs.\nStep 1 - The user will provide you with text. Answer any questions in the text in one sentence with a prefix that says 'Answer: '.\nStep 2 - Translate the Answer from Step 1 into a dad joke, with a prefix that says 'Dad Joke: '."
    },
    {
        "role": "user",
        "content": "What is the tallest structure in Paris?"
    }
]

注释说明:

  • #1 注意使用了分隔符战术
  • #2 步骤可以执行完全不同的操作

2.3.5 提供示例

提供示例是引导 LLM 产生期望输出的绝佳方式。向 LLM 演示示例的方法多种多样,系统消息或提示可以有效强调输出的整体风格。下面示例中,示例作为最后一次助手回复添加,提示为“Teach me about Python”。

示例 2.13 providing_examples.jsonl

[
    {
        "role": "system",
        "content": "Answer all replies in a consistent style that follows the format, length and style of your previous responses.\nExample:\n  user:\n       Teach me about Python.\n  assistant:\n       Python is a programming language developed in 1989 by Guido van Rossum.\n\n  Future replies:\n       The response was only a sentence so limit all future replies to a single sentence."
    },
    {
        "role": "user",
        "content": "Teach me about Java."
    }
]

注释说明:

  • #1 以“之前”的助手回复注入示例输出
  • #2 添加限制输出的战术,限制回复长度并匹配示例风格

提供示例还可用于要求 LLM 以特定格式输出复杂任务的结果。例如,请求 LLM 生成与示例输出匹配的代码,是示例战术的理想应用。我们将在全书中多次使用此战术,但也存在其他引导输出的方法。

2.3.6 指定输出长度

指定输出长度战术不仅有助于限制 token 数量,还能引导输出呈现期望格式。示例 2.14 展示了两种不同的技巧。第一个示例将输出限制在不超过 10 个单词,有助于让回答更简洁、更有针对性,适合部分使用场景。第二个示例将输出限制为简洁的项目符号列表,有助于缩小输出范围并保持回答简短。更简洁的回答通常意味着内容更集中、冗余更少。

示例 2.14 specifying_output_length.jsonl

[    {        "role": "system",        "content": "Summarize all replies into 10 or fewer words."    },    {        "role": "user",        "content": "Please tell me an exciting fact about Paris?"    }]
[    {        "role": "system",        "content": "Summarize all replies into 3 bullet points."    },    {        "role": "user",        "content": "Please tell me an exciting fact about Paris?"    }]

注释说明:

  • #1 限制输出使回答更简洁
  • #2 限制回答为简短的项目符号

在开发多代理系统时,保持回答简短还有额外好处。任何与其他代理对话的系统都能从简洁且聚焦的回复中受益,这有助于让 LLM 保持专注,减少噪声通信。

务必运行本策略所有提示战术的示例。如前所述,我们将在后续章节介绍更多提示工程策略和战术。本章最后,我们将探讨如何为你的使用场景挑选最佳 LLM。

2.4 为你的具体需求选择最优的大语言模型(LLM)

虽然成为一名成功的 AI 代理设计师不一定需要深入理解大语言模型(LLM),但能够评估模型规格仍然非常有帮助。就像电脑用户不必了解处理器的制造过程,也能分辨不同处理器型号的差异一样,这个类比同样适用于 LLM。尽管评判标准可能不同,但仍然基于一些主要的考量因素。

结合我们之前的讨论和对 LM Studio 的了解,可以提炼出一些基本的评估标准,这些标准在选择适合构建 GPT 代理或执行任何 LLM 任务的模型时尤为重要。图 2.11 说明了定义一个值得考虑的 LLM 所需的关键标准。

image.png

为了构建 AI 代理,我们需要从任务相关的角度来审视这些标准。模型的上下文大小和速度也可被视为第六、第七个标准,但它们通常被归类为模型部署架构和基础设施的变体。第八个需要考虑的标准是成本,但这受到许多其他因素的影响。以下是这些标准与构建 AI 代理的关系总结:

  • 模型性能 — 通常需要了解 LLM 在特定任务上的表现。例如,如果你正在构建专注于编码的代理,那么对代码表现优异的 LLM 至关重要。
  • 模型参数(规模) — 模型规模通常是推理性能和响应质量的良好指标。但模型规模也决定了你的硬件需求。如果计划使用本地托管模型,模型大小将直接影响你所需的计算机和 GPU。幸运的是,近年来不断涌现出小巧且功能强大的开源模型。
  • 使用场景(模型类型) — 模型类型有多种变化。聊天补全模型(如 ChatGPT)适合通过迭代和推理解决问题,而补全、问答和指令类模型更侧重于特定任务。聊天补全模型对代理应用尤其重要,尤其是需要迭代的代理。
  • 训练输入 — 了解模型训练所用的数据内容通常决定模型适用的领域。通用模型适用于多种任务,而更具体或经过微调的模型在特定领域可能更具相关性。对于特定领域的代理来说,较小且微调过的模型有时能表现得和大型模型(如 GPT-4)一样好甚至更好。
  • 训练方法 — 这可能不是最关键的考量,但了解模型的训练方法有助于判断其泛化、推理和规划能力。这对规划型代理尤为重要,而对更专注于具体任务的助手则相对次要。
  • 上下文 token 大小 — 上下文大小更依赖模型架构和类型,决定模型能保持的上下文或记忆容量。对于简单任务,少于 4000 个 token 的上下文窗口通常足够。但在多代理系统中(多个代理围绕同一任务对话),较大的上下文窗口非常关键。模型通常会根据上下文窗口大小进行不同配置。
  • 模型速度(部署) — 模型速度由推理速度决定,即模型响应请求的快慢,进而取决于其运行的基础设施。如果代理不直接与用户交互,实时速度可能不是必要条件;反之,实时交互的 LLM 代理则需要尽可能快。商业模型的速度由服务商保障,而自托管模型的速度则由你的硬件基础设施决定。
  • 模型成本(项目预算) — 成本通常受项目预算限制。无论是学习构建代理还是实施企业软件,成本始终是重要考量。在自托管 LLM 与使用商业 API 之间存在显著权衡。

选择构建生产级代理系统所用的模型时,需要考虑的因素很多。但对于研究和学习来说,选择并专注于单一模型通常更合适。如果你是 LLM 和代理领域的新手,建议选择商业模型如 GPT-4 Turbo。除非另有说明,本书的内容均基于 GPT-4 Turbo。

随着时间推移,更优秀的模型必将取代现有模型,因此你可能需要升级或更换模型。为此,你必须了解所用 LLM 和代理的性能指标。幸运的是,在第 9 章中,我们将探讨如何使用提示流(prompt flow)评估 LLM、提示词和代理角色设定。

总结

  • 大语言模型(LLM)采用一种称为生成式预训练变换器(GPT)的架构。
  • 生成模型(如 LLM 和 GPT)不同于预测/分类模型,它们通过学习如何表示数据而不仅仅是对数据进行分类。
  • LLM 是数据、架构及针对特定应用场景的训练(即微调)的集合。
  • OpenAI API SDK 可用于连接 GPT-4 等模型的大语言模型,也支持调用开源 LLM。
  • 你可以快速搭建 Python 环境并安装集成 LLM 所需的软件包。
  • LLM 能处理各种请求并生成独特响应,可用于提升与 LLM 集成相关的编程技能。
  • 开源 LLM 是商业模型的替代方案,可通过 LM Studio 等工具本地托管。
  • 提示工程是一套帮助设计更有效提示词以改善 LLM 响应的技术集合。
  • LLM 可用于驱动各类代理和助手,从简单聊天机器人到功能完善的自主工作者。
  • 为特定需求选择最合适的 LLM 需综合考虑性能、参数规模、应用场景、训练输入等标准。
  • 本地运行 LLM 需要多种技能,包括 GPU 配置和理解各种配置选项。