大型语言模型
spacy-llm 包 将大型语言模型 (LLM) 集成到 spaCy 流程中,具有用于快速原型设计和提示词生成的模块化系统,并将非结构化响应转换为用于各种 NLP 任务的可靠输出,无需训练数据。
- 可序列化的
llm组件,用于将提示词集成到您的流程中 - 模块化函数,用于定义 任务(提示词生成和解析)和 模型(使用的模型)
- 支持托管 API 和自托管开源模型
- 与
LangChain集成 - 访问 OpenAI API,包括 GPT-4 和各种 GPT-3 模型
- 内置支持托管在 Hugging Face 上的各种开源模型
- 使用示例,适用于标准 NLP 任务,例如命名实体识别和文本分类
- 通过 注册表 实现您自己的函数,用于自定义提示词生成、解析和模型集成
动机
大型语言模型 (LLM) 具有强大的自然语言理解能力。只需少量(有时甚至不需要)示例,就可以提示 LLM 执行自定义 NLP 任务,例如文本分类、命名实体识别、指代消解、信息提取等。
监督学习在原型设计方面远不如 LLM 提示词生成,但在许多任务中,对于生产而言则更好。在单个 GPU 上舒适运行的 Transformer 模型非常强大,并且对于任何具有明确定义的输出的任务而言,它可能是一个更好的选择。您可以使用从几百到几千个标记示例训练模型,它将学习执行该任务。效率、可靠性和控制性都优于监督学习,并且准确性通常也高于 LLM 提示词生成。
spacy-llm 让你拥有两全其美。您可以快速初始化一个流程,其中包含由 LLM 提示词驱动的组件,并自由地混合由其他方法驱动的组件。随着项目进展,您可以根据需要替换一些或全部由 LLM 驱动的组件。
当然,您的系统中可能存在一些完全证明使用 LLM 力量的组件。如果您想要一个能够以微妙的方式从多个文档中综合信息并为您生成细致摘要的系统,那么规模越大越好。但是,即使您的生产系统需要 LLM 来完成某些任务,也不意味着您需要 LLM 来完成所有任务。也许您想使用廉价的文本分类模型来帮助您找到要总结的文本,或者您想添加一个基于规则的系统来检查摘要的输出。这些前置和后置任务使用成熟且经过深思熟虑的库更容易实现,而这正是 spaCy 提供的。
安装
spacy-llm 将在未来的 spaCy 版本中自动安装。现在,您可以在已经安装了 spacy 的同一个虚拟环境中运行以下命令 安装。
用法
任务和模型必须使用 配置系统 提供给 llm 流程组件。此包提供了各种内置功能,如 API 文档中所述。
示例 1:使用来自 OpenAI 的 GPT-3 模型添加文本分类器
从 openai.com 创建一个新的 API 密钥或获取现有的密钥,并确保将密钥设置为环境变量。有关更多背景信息,请参阅 OpenAI 部分。
创建一个名为 config.cfg 的配置文件,其中至少包含以下内容(或参阅完整的示例 此处)
现在运行
示例 2:使用通过 Hugging Face 的开源模型添加 NER
要运行此示例,请确保您已启用 GPU,并且已安装 transformers、torch 和 CUDA。有关更多背景信息,请参阅 DollyHF 部分。
创建一个名为 config.cfg 的配置文件,其中至少包含以下内容(或参阅完整的示例 此处)
现在运行
请注意,Hugging Face 会在您第一次使用它时下载 "databricks/dolly-v2-3b" 模型。您可以 定义缓存目录,方法是设置环境变量 HF_HOME。此外,您可以将模型升级到 "databricks/dolly-v2-12b" 以获得更好的性能。
示例 3:直接在 Python 中创建组件
llm 组件的行为与其他组件相同,并且有 特定于任务的组件 定义,可以帮助您快速启动并获得合理的内置任务实现。
请注意,为了有效利用资源,通常您应该使用 nlp.pipe(docs) 和一个批处理,而不是使用单个文档调用 nlp(doc)。
示例 4:实现您自己的自定义任务
要编写 task,您需要实现两个函数:generate_prompts,它接受 Doc 对象列表并将其转换为提示词列表,以及 parse_responses,它将 LLM 输出转换为 Doc 上的注释,例如实体跨度、文本类别等。
要注册您的自定义任务,请使用 spacy_llm.registry.llm_tasks 装饰器装饰一个工厂函数,并使用您可以在配置中引用的自定义名称。
日志记录
spacy-llm 具有内置的记录器,可以记录发送到 LLM 的提示词以及其原始响应。此记录器使用调试级别,并且默认情况下配置了 logging.NullHandler()。
为了使用此记录器,您可以设置一个简单的处理程序,如下所示
然后在使用流程时,您将能够查看提示词和响应。
例如,使用 示例 1 上面的配置和代码
您将看到类似于以下内容的 logging 输出
print(doc.cats) 输出到标准输出应如下所示
API
spacy-llm 暴露了一个具有 可配置设置 的 llm 工厂。
一个 llm 组件由两个主要设置定义
- 一个 任务,定义发送到 LLM 的提示词以及将结果响应解析回 Doc 对象上的结构化字段的功能。
- 一个 模型,定义使用的模型以及如何连接到它。请注意,
spacy-llm支持访问外部 API(例如 OpenAI)以及访问自托管开源 LLM(例如通过 Hugging Face 使用 Dolly)。
此外,spacy-llm 暴露了一个可定制的 缓存 功能,以避免将同一文档多次传递给 LLM 服务(无论是本地服务还是通过 REST API)。
最后,你可以选择将 LLM 提示/响应的字符串化版本保存在 Doc.user_data["llm_io"] 属性中,方法是将 save_io 设置为 True。 Doc.user_data["llm_io"] 是一个字典,其中包含 nlp 管道中的每个 LLM 组件的一个条目。每个条目本身也是一个字典,包含两个键:prompt 和 response。
关于 validate_types 的说明:默认情况下,spacy-llm 会检查 model 和 task 可调用对象的签名是否一致,如果不一致则发出警告。可以将 validate_types 设置为 False 以禁用此行为。
任务
一个 task(任务)定义了一个 NLP 问题或问题,它将通过提示发送到 LLM。此外,任务定义了如何将 LLM 的响应解析回结构化信息。所有任务都在 llm_tasks 注册表中注册。
实际上,一个任务应该遵循在 ty.py 中定义的名为 LLMTask 的 Protocol 协议。它需要定义一个 generate_prompts 函数和一个 parse_responses 函数。
任务可能支持提示分片(有关更多信息,请参阅 API 文档中关于 分片 和 非分片 任务的内容)。generate_prompts 和 parse_responses 函数的签名取决于它们是否支持分片。
对于不支持分片的任务
| 任务 | 描述 | |
|---|---|---|
task.generate_prompts | 接收一组文档,并返回一组提示,提示的类型可以是 Any。 | |
task.parse_responses | 接收一组 LLM 响应和原始文档,将响应解析为结构化信息,并在文档上设置注释。 |
对于支持分片的任务
| 任务 | 描述 | |
|---|---|---|
task.generate_prompts | 接收一组文档,并返回一组提示分片集合,提示分片的类型可以是 Any。 | |
task.parse_responses | 接收一组 LLM 响应集合(每个提示分片一个)和原始文档,将响应解析为结构化信息,将注释设置在文档分片上,并将这些文档分片合并回单个文档实例。 |
此外,任务可以定义一个可选的 scorer 方法。它应该接受一个 Example 对象的迭代器作为输入,并返回一个分数字典。如果定义了 scorer 方法,spacy-llm 将调用它来评估组件。
| 组件 | 描述 |
|---|---|
spacy.EntityLinker.v1 | 实体链接任务提示模型将给定文本中的所有实体链接到知识库中的条目。 |
spacy.Summarization.v1 | 摘要任务提示模型提供所提供文本的简洁摘要。 |
spacy.NER.v3 | 为 NER 提取实现链式思考推理 - 比 v1 或 v2 获得更高的准确性。 |
spacy.NER.v2 | 在 v1 的基础上,还支持使用明确的描述定义提供的标签。 |
spacy.NER.v1 | 内置 NER 任务的原始版本支持零样本和少样本提示。 |
spacy.SpanCat.v3 | 将 v3 NER 任务调整为支持重叠实体并将注释存储在 doc.spans 中。 |
spacy.SpanCat.v2 | 将 v2 NER 任务调整为支持重叠实体并将注释存储在 doc.spans 中。 |
spacy.SpanCat.v1 | 将 v1 NER 任务调整为支持重叠实体并将注释存储在 doc.spans 中。 |
spacy.REL.v1 | 关系提取任务支持零样本和少样本提示。 |
spacy.TextCat.v3 | 版本 3 在 v2 的基础上构建,并允许设置标签的定义。 |
spacy.TextCat.v2 | 版本 2 在 v1 的基础上构建,并包含改进的提示模板。 |
spacy.TextCat.v1 | 内置 TextCat 任务的版本 1 支持零样本和少样本提示。 |
spacy.Lemma.v1 | 对提供的文本进行词形还原,并相应地更新标记的 lemma_ 属性。 |
spacy.Raw.v1 | 将原始文档内容作为提示传递给 LLM。 |
spacy.Sentiment.v1 | 对提供的文本执行情感分析。 |
spacy.Translation.v1 | 将文档内容翻译成指定的目标语言。 |
spacy.NoOp.v1 | 此任务仅用于测试 - 它指示 LLM 什么也不做,并且不会在 docs 上设置任何字段。 |
提供用于少样本提示的示例
所有内置任务都支持少样本提示,即在提示中包含示例。示例可以通过两种方式提供:(1)作为仅包含示例的单独文件,或(2)通过使用类似于任何其他管道组件的 get_examples() 回调来初始化 llm。
(1) 少样本示例文件
包含少样本提示示例的文件可以这样配置
提供的文件必须符合所需任务的格式(请参阅下文的任务文档)。
(2) 使用 get_examples() 回调初始化 llm 组件
或者,你可以通过为 nlp.initialize 提供 get_examples 回调并设置 n_prompt_examples 为正数来初始化你的 nlp 管道,以自动获取用于少样本学习的几个示例。将 n_prompt_examples 设置为 -1 以将所有示例用作少样本学习提示的一部分。
模型
一个 model(模型)定义了要查询哪个 LLM 模型,以及如何查询它。它可以是一个简单的函数,接收一组提示(与 task.generate_prompts() 的输出类型一致)并返回一组响应(与 parse_responses 的预期输入一致)。通常来说,它是一个类型为 Callable[[Iterable[Any]], Iterable[Any]] 的函数,但特定的实现可以具有其他签名,例如 Callable[[Iterable[str]], Iterable[str]]。
所有内置模型都注册在 llm_models 中。如果未指定模型,则仓库当前默认使用 REST 连接到 OpenAI API,并访问 "gpt-3.5-turbo" 模型。
目前支持三种不同的使用 LLM 的方法
spacy-llm的原生 REST 接口。这是所有托管模型(例如 OpenAI、Cohere、Anthropic 等)的默认设置。- 一个 HuggingFace 集成,允许在本地运行有限数量的 HF 模型。
- 一个 LangChain 集成,允许运行 LangChain 支持的任何模型(托管或本地)。
方法 1 和 2 分别是托管模型和本地模型的默认设置。或者,你可以使用 LangChain 访问托管或本地模型,方法是指定使用 langchain. 前缀注册的模型之一。
| 模型 | 描述 |
|---|---|
spacy.GPT-4.v2 | OpenAI 的 gpt-4 模型系列。 |
spacy.GPT-3-5.v2 | OpenAI 的 gpt-3-5 模型系列。 |
spacy.Text-Davinci.v2 | OpenAI 的 text-davinci 模型系列。 |
spacy.Code-Davinci.v2 | OpenAI 的 code-davinci 模型系列。 |
spacy.Text-Curie.v2 | OpenAI 的 text-curie 模型系列。 |
spacy.Text-Babbage.v2 | OpenAI 的 text-babbage 模型系列。 |
spacy.Text-Ada.v2 | OpenAI 的 text-ada 模型系列。 |
spacy.Davinci.v2 | OpenAI 的 davinci 模型系列。 |
spacy.Curie.v2 | OpenAI 的 curie 模型系列。 |
spacy.Babbage.v2 | OpenAI 的 babbage 模型系列。 |
spacy.Ada.v2 | OpenAI 的 ada 模型系列。 |
spacy.Azure.v1 | Azure 的 OpenAI 模型。 |
spacy.Command.v1 | Cohere 的 command 模型系列。 |
spacy.Claude-2.v1 | Anthropic 的 claude-2 模型系列。 |
spacy.Claude-1.v1 | Anthropic 的 claude-1 模型系列。 |
spacy.Claude-instant-1.v1 | Anthropic 的 claude-instant-1 模型系列。 |
spacy.Claude-instant-1-1.v1 | Anthropic 的 claude-instant-1.1 模型系列。 |
spacy.Claude-1-0.v1 | Anthropic 的 claude-1.0 模型系列。 |
spacy.Claude-1-2.v1 | Anthropic 的 claude-1.2 模型系列。 |
spacy.Claude-1-3.v1 | Anthropic 的 claude-1.3 模型系列。 |
spacy.PaLM.v1 | Google 的 PaLM 模型系列。 |
spacy.Dolly.v1 | 通过 HuggingFace 提供的 Dolly 模型。 |
spacy.Falcon.v1 | 通过 HuggingFace 提供的 Falcon 模型。 |
spacy.Mistral.v1 | 通过 HuggingFace 提供的 Mistral 模型。 |
spacy.Llama2.v1 | 通过 HuggingFace 提供的 Llama2 模型。 |
spacy.StableLM.v1 | 通过 HuggingFace 提供的 StableLM 模型。 |
spacy.OpenLLaMA.v1 | 通过 HuggingFace 提供的 OpenLLaMA 模型。 |
| LangChain 模型 | 用于 API 检索的 LangChain 模型。 |
请注意,Llama 2 的聊天模型变体目前不受支持。这是因为它们需要特定的提示设置,并且与 spacy-llm 的使用场景(即,非交互式聊天)相比,在完成模型变体中没有增加任何可辨识的优势。
缓存
通过外部 API 或本地实例与 LLM 交互成本较高。由于开发 NLP 管道通常意味着大量的探索和原型设计,spacy-llm 实现了一个内置的 缓存,以避免每次运行时重复处理相同的文件,该缓存将一批文档存储在磁盘上。
各种函数
| 函数 | 描述 |
|---|---|
spacy.FewShotReader.v1 | 此函数在 spaCy 的 misc 注册表中注册,并从 .yml、.yaml、.json 或 .jsonl 文件中读取示例。它使用 srsly 读取这些文件,并根据文件扩展名解析它们。 |
spacy.FileReader.v1 | 此函数在 spaCy 的 misc 注册表中注册,并读取提供给 path 的文件,以返回其内容的 str 表示形式。此函数通常用于读取包含提示模板的 Jinja 文件。 |
| 归一化函数 | 这些函数为字符串比较提供简单的归一化,例如,在 LLM 响应的原始文本中给定的标签与指定标签列表之间。 |