DLAI-Mistral-入门笔记-全-

DLAI Mistral 入门笔记(全)

001:引言 🚀

在本节课中,我们将要学习Mistral AI模型的基本概念,特别是其独特的“专家混合”架构,并了解如何开始使用其开源与商业模型。

欢迎与课程介绍

欢迎来到这个与Mistral AI合作打造的简短课程《Mistral入门》。

许多流行且高效的大型语言模型都基于标准的Transformer架构。但Mistral AI近期发布的一个名为Mixtral 8x7B的开源模型,使用了一种称为“专家混合”的技术来修改标准Transformer架构。

专家混合架构解析

这意味着模型内部有八个独立的前馈神经网络,被称为“专家”。在推理时,一个不同的门控神经网络首先会选择激活这八个专家中的两个来运行,以预测下一个词元。然后,模型会取这两个专家输出的加权平均值,以实际生成那个混合词元。

这种专家混合设计使得Mixtral模型既能获得更大模型的性能提升,同时又能保持与较小模型相当的推理成本。具体来说,尽管Mixtral模型拥有467亿个参数,但在推理每个词元时,它只使用其中的129亿个参数。

讲师与课程内容预告

我们很高兴本课程的讲师是Sophia Yang,她是Mistral AI的开发者关系负责人。在本课程中,你将通过API调用,获得使用各种Mistral开源和商业模型的实践经验,包括Andrew刚刚描述的开源Mixtral模型。

你还将学习到Mistral模型一些独特且有用的功能。

以下是本课程将涵盖的核心功能:

  • 函数调用:你将学习使用Mistral的API实现函数调用。这使你能够指示模型调用用户定义的Python函数,例如执行网络搜索或从数据库读取文本,以帮助其收集相关信息来回答用户请求。函数调用使大语言模型能够更可靠、更高效地执行代码擅长的任务,例如从大型数据库访问信息或执行复杂数学计算。
  • JSON模式:另一个非常有用的功能是JSON模式。当你将大语言模型集成到更大的软件应用程序中时,通过让输出以结构化的JSON格式作为响应,通常能非常方便地将大语言模型的输出馈送到下游软件系统中。对于某些大语言模型,用户可能依赖巧妙的提示或使用像LangChain或LlamaIndex这样的框架来保证响应的JSON格式可靠。Mistral的JSON功能可以设置为依赖项,以生成你请求的JSON格式的响应。

Sophia将通过Mistral API演示这些示例。你也可以轻松地通过我们的API试用开源模型(Mistral 7B和Mixtral 8x7B)以及商业模型(Mistral Small, Medium, Large),以便根据你的具体用例,更好地决定何时使用哪种模型。

下节预告

在下一课中,我们将更深入地了解8x7B专家混合架构,并概述开源和商业模型。让我们进入下一个视频开始学习。


本节课中,我们一起学习了Mistral AI及其核心模型Mixtral的“专家混合”架构优势,了解了课程将涵盖的实践内容,特别是函数调用和JSON模式这两个强大功能,为后续动手操作奠定了基础。

002:模型概览 🧠

在本节课中,我们将对Mistral提供的各类模型进行概览,了解其特点与适用场景。

概述

Mistral致力于构建最好的基础模型。目前,我们为所有用例和商业需求提供了六种模型。

开源模型

我们提供两种开源模型,你可以下载模型权重并无限制地在任何地方使用。

以下是两种开源模型的介绍:

  • Mistral 7B:这是我们于去年九月发布的第一个模型。它在多项标准评估基准测试中,性能优于参数规模相似甚至更大的Llama模型。例如,在知识、推理、代码等综合基准测试中,其表现(图表中的橙色柱)超越了其他颜色的Llama模型。该模型可单GPU运行,非常适合初学者开始实验。
  • Mistral 8x7B:这是一个稀疏专家混合模型,于去年十二月发布。简单来说,该模型有八个“专家”来处理文本,但并非每次调用所有专家,而是通过一个路由器为每个输入标记选择最相关的少数几个专家。其基础是Transformer块,包含前馈层和多头注意力层。虽然模型总参数量为467亿,但每个标记实际仅使用约129亿参数,从而在实现高性能的同时保证了快速的推理速度。它在大多数基准测试中超越了Llama 2 70B,且推理速度快八倍;在多数标准基准测试中,其表现与GPT-3.5相当或更优。

这两种模型均在开源Apache 2许可证下发布,这意味着你可以下载模型权重,针对自己的用例进行微调和定制,且无任何使用限制。例如,你可以创建用于商业用途的AI应用。我们致力于开源模型,未来将发布更多开源模型。

企业级模型

除了开源模型,我们还提供四种优化的企业级模型,以满足不同需求。

以下是四种企业级模型的介绍:

  • Mistral Small:最适合低延迟用例。
  • Mistral Medium:适用于仅需中等推理能力的语言任务,例如数据提取、摘要和邮件撰写。
  • Mistral Large:这是我们功能最强大的模型,具备高级推理能力,适用于最复杂的任务。其性能接近GPT-4,拥有原生多语言能力,在常识和推理基准测试中显著优于Llama 2 70B。它擅长遵循指令,并原生支持函数调用功能。
  • Embedding模型:提供最先进的文本嵌入,可用于聚类、分类等多种用例。

所有我们提供的服务模型均支持32K令牌的上下文窗口。函数调用功能在Mistral Small和Mistral Large模型中均可使用。

如何开始使用

许多客户已在银行、电信、媒体、法律科技等行业广泛应用我们的模型,用于文本检索增强生成、内容生成、内容合成、代码生成、洞察生成等。

通过本课程,你将学习如何在类似用例中使用我们的模型。要立即开始使用我们的模型,你可以通过以下方式:

  • Le Chat(聊天界面):你可以使用我们的聊天界面直接与模型交互。访问 chat.mistral.ai,在聊天框中输入请求即可,例如“编写一个Python函数来对给定字符串进行排序”。目前Le Chat可免费使用,只需注册即可。
  • 本地运行开源模型:如果你有兴趣在本地运行我们的开源模型,可以使用 Transformers、Llama.cpp 或 Ollama。请注意,许多人使用模型的量化版本以将其加载到内存中,但量化可能会影响模型性能,因此量化模型的表现若不如预期,无需惊讶。
  • 使用托管服务:虽然在自己机器上运行模型很有趣,但为了获得更快的推理速度、更可靠的性能并节省精力,我们推荐使用托管服务,例如Mistral AI平台。通过该平台,你不仅可以访问开源模型,还能通过简单的API调用使用企业级模型。平台定价比一些其他托管平台更便宜。

设置API密钥

要通过平台访问我们的模型,你需要创建自己的API密钥。

设置API密钥的步骤如下:

  1. 访问 console.mistral.ai。
  2. 创建账户。
  3. 设置账单信息。
  4. 点击“API keys”创建新的API密钥。

本课程将重点讲解如何使用我们的API端点,并在后续课程中深入探讨许多使用API的用例。为了方便学习,在后续课程中你实际上无需创建账户,我们将提供一个预置的API密钥供课堂使用。

总结

本节课我们一起学习了Mistral提供的两大类模型:开源模型(Mistral 7B, Mistral 8x7B)和企业级模型(Small, Medium, Large, Embedding),了解了它们的特点、性能和应用场景。我们还介绍了三种开始使用模型的方式:通过聊天界面、本地运行以及使用托管API服务。

在下一节课中,你将学习如何使用Mistral API以及一些提示词技巧。让我们开始下一课的学习。

003:提示工程基础 🚀

在本节课中,你将学习如何通过API调用访问并提示Mistral模型,以执行分类、信息提取、个性化回复和摘要总结等多种任务。

概述

我们将从编写代码开始。在课程环境中,所需的库已经预先安装。但如果你在自己的机器上运行,需要安装以下库:

pip install mistralai

由于本次课程无需执行此命令,我们将其注释掉。这里提供了一个辅助函数,用于帮助你加载Mistral API密钥和模型,以便轻松开始运行Mistral API。

我们可以向模型提问:“你好,你能做什么?”。你可以随时暂停视频,按喜好修改提示词。在本节课结束时,我将带你了解辅助函数中的代码,以便你理解API调用原理,并能在课堂环境之外使用API。

分类任务示例

首先,我们来看看如何使用模型对银行客户咨询进行分类。在这个提示词中,我们设定了角色和任务:

你是一名银行客服机器人。你的任务是评估客户意图,并将客户咨询分类。

我们有一个预定义的类别列表。如果文本不符合任何类别,则将其归类为“客户服务”。你可以看到,这里我们提供了一些示例,让模型确切了解我们的期望。

提示词优化

如果我们想确保提示词没有拼写或语法错误,可以请模型先进行校正。运行以下代码:

# 示例:请求模型校正提示词
corrected_prompt = model.correct_spelling_and_grammar(original_prompt)
print(corrected_prompt)

然后打印响应。我们可以看到一些语法修正,例如,“customer inquiry”被修正为“the customer inquiry”。现在,我们可以使用这个校正后的提示词,并将“inquiry”替换为实际的咨询内容:“我正在询问贵行卡片在欧盟地区的可用性”。

运行后,我们得到分类结果“国家支持”,这符合预期。现在,运行另一个咨询:“今天天气如何?”,因为它不属于任何预定义类别,模型正确地将其归类为“客户服务”。

提示词技术分析

现在,让我们回头仔细分析这个提示词,看看我们使用了哪些提示技术。

首先,我们使用了角色扮演,为模型提供了一个“银行客服机器人”的角色。这为模型提供了个性化的上下文。

其次,我们使用了少样本学习,在提示词中提供了几个示例。少样本学习通常能提高模型性能,尤其是在任务较复杂或我们希望模型以特定方式响应时。

第三,我们使用了分隔符,如井号或尖括号,来指定文本不同部分之间的边界。在我们的例子中,使用三个井号表示示例,使用尖括号表示客户咨询。

最后,如果模型回答过于冗长,我们可以添加“请勿提供解释或备注”的指令,以确保输出简洁。如果你想知道使用哪种分隔符,这并不重要,选择你喜欢的即可。

信息提取示例

接下来,我想展示一个信息提取的例子。信息提取在很多场景下都非常有用。在这个例子中,假设你有一些医疗笔记,并希望从中提取特定信息。

在提示词中,我们提供了医疗笔记,并要求模型按照以下JSON模式返回JSON格式的数据:

{
  "diagnosis": "string",
  "medication": "array",
  "follow_up": "boolean"
}

我们定义了要提取的变量、其类型以及输入选项列表。例如,对于“诊断”,模型应从四个选项中选择一个输出。

运行此提示词,我们得到了与定义完全一致的JSON格式输出。在Mistral函数中,我们通过设置 json=True 来启用JSON模式。我们将在课程末尾详细讲解Python API调用。

信息提取策略

让我们再次审视这个提示词。我们使用的一个策略是,在提示词中明确要求返回JSON格式。当启用JSON模式时,要求JSON格式非常重要。

我们使用的另一个策略是定义了JSON模式。我们在提示词中使用这个JSON模式,以确保JSON输入的一致性和结构。请注意,即使我们没有设置 json=True,输出可能仍然是JSON格式,但我们建议启用JSON模式以获得可靠的JSON格式输出。

个性化回复示例

现在,让我们看看我们的模型如何创建个性化的电子邮件回复来解答客户问题,因为大语言模型非常擅长个性化任务。

这里有一封客户Anna询问抵押贷款利率的电子邮件,以及我们的提示词:

你是一名抵押贷款机构的客服机器人。你的任务是创建个性化的电子邮件回复来解答客户问题。
请使用下面提供的事实来回答客户咨询。

然后,我们在提示词中提供了一些关于利率的数据。与之前类似,我们使用字符串格式将实际的电子邮件内容添加到这里的“email”变量中。

运行代码后,我们得到了一封针对Anna的个性化邮件,根据提供的事实回答了她的问题。通过这种提示词,你可以轻松创建自己的客服机器人,回答关于你产品的问题。

在呈现这些事实或产品信息时,使用清晰简洁的语言非常重要。这有助于模型为客户查询提供准确、快速的响应。

摘要总结示例

最后,我们来看摘要总结。摘要是大语言模型的常见任务,我们的模型在这方面可以做得很好。

假设你想总结这份来自Batch的新闻简报。以下是我尝试的提示词:

你是一名科技评论员。你的任务是在阅读新闻简报后撰写一份报告。
当呈现一份新闻简报时,请提出有趣的问题并逐一回答。
之后,整合所有信息,以Markdown格式撰写一份报告。

然后,我有一个部分用于插入新闻简报内容,以及一个指令部分:第一,总结关键点;第二,生成三个独特且发人深省的问题;第三,撰写分析报告。

运行我们的Mistral模型后,我们得到了我们要求的一切:一份摘要、一些有趣的问题以及分析报告。当然,你也可以直接要求模型总结新闻简报,而无需这些详细指令。

如果你有一个复杂任务,提供分步指令通常有助于模型使用一系列中间推理步骤来解决复杂问题。在我们的例子中,使用这些步骤可能有助于模型在每一步进行思考,从而生成更全面的报告。

这里一个有趣的策略是,我们要求模型通过生成带有解释和步骤的示例,来自动引导推理和理解过程。另一个常用策略是,你可以要求模型以特定格式输出,例如使用Markdown格式。

API调用详解

以上就是本节课我想展示的所有提示词示例。本节课我们使用了辅助函数来加载Mistral模型,以下是API调用的工作原理。

我们首先需要定义Mistral客户端。如果你在课堂环境之外运行Mistral模型,需要将这里的API密钥变量替换为你自己的API密钥。

我们还需要定义聊天消息。聊天消息可以以用户消息、系统消息或助手消息开始。系统消息通常为AI助手设置行为和上下文,但它是可选的。你可以同时拥有系统消息和用户消息,或者只使用用户消息,并通过实验看看哪种消息能产生更好的结果。本节课我们将所有内容都放在用户消息中。

然后,我们定义如何获取模型响应,需要指定模型和消息。如果我们启用了JSON模式,需要添加一行代码:response_format={"type": "json_object"},以指定我们希望响应格式为JSON。

这里还有其他几个非必需的参数可以更改,你可以查看API规范以了解所有细节。

总结

本节课,我们一起学习了如何提示Mistral模型执行各种任务。在下一节课中,我们将探讨如何针对不同的使用场景选择合适的Mistral模型。下节课见!

004:模型选择 🧠

在本节课中,你将学习如何根据你的具体使用场景,选择合适的Mistral模型。

Mistral AI提供了五个API端点,对应五个领先的语言模型:Mistral 7B、Mixtral 8x7B、Mistral Small、Mistral Medium和Mistral Large。从模型性能来看,例如在MMLU(多任务语言理解)任务上,Mistral Large表现最佳。事实上,在包括推理、多语言任务、数学和编码在内的各种基准测试中,Mistral Large的表现都优于其他所有模型。

然而,性能可能不是唯一的考量因素。对于你的应用,你可能还需要考虑定价。我们的模型提供有竞争力的价格,值得权衡性能与成本。Mistral模型是许多大型语言模型应用背后的技能支撑。

以下是不同类型用例及其对应推荐Mistral模型的简要概述。

用例与模型匹配 📊

以下是常见的任务类型及其推荐的Mistral模型。

  • 简单任务:可以批量处理的任务,例如分类、客户支持或文本生成,由 Mistral Small 驱动。
  • 中等任务:需要适度推理的任务,例如数据提取、摘要、撰写邮件等,由 Mistral Medium 驱动。
  • 复杂任务:需要高级推理能力或高度专业化的任务,例如合成文本生成、代码生成、RAG或智能体,由 Mistral Large 驱动。

实践示例 💻

上一节我们介绍了不同模型的定位,本节中我们来看看具体的代码示例。首先,我们使用辅助函数加载API密钥。如果你在课堂环境外运行,可以替换为你自己的API密钥。

# 加载API密钥的辅助函数
def load_api_key():
    # ... 你的代码 ...

接着,我们定义一个Mistral函数,以便轻松调用Mistral Python API。这段代码在之前的课程中已经见过。

# 定义调用Mistral API的函数
def call_mistral_model(model, prompt):
    # ... 你的代码 ...

示例1:简单分类任务

对于像分类这样的简单任务,我们可以使用较小尺寸的模型,例如Mistral Small。比如,让我们将一封电子邮件分类为垃圾邮件或非垃圾邮件。

prompt = "Classify this email as spam or not spam: 'Congratulations! You've won a free cruise!'"
response = call_mistral_model("mistral-small", prompt)
print(response)

Mistral Small能够正确地将电子邮件分类为垃圾邮件。实际上,我们所有的模型在这里都能给出好结果。使用Mistral Small更具成本效益且速度更快,因此我们推荐使用Mistral Small来处理简单任务。

示例2:中等语言转换任务

Mistral Medium非常适合需要语言转换的中等任务。例如,我们可以要求模型为刚完成首次购买的新客户撰写一封邮件。确保在提示中包含订单详情。

prompt = "Compose a welcome email for a new customer named Anna who just made her first purchase. Order details: Product: 'Learning Kit', Order ID: 12345."
response = call_mistral_model("mistral-medium", prompt)
print(response)

现在我们得到了一封格式美观的邮件,收件人是客户Anna,并包含了她的订单详情。

示例3:复杂推理任务

Mistral Large非常适合需要高级推理能力或高度专业化的复杂任务。在这个例子中,我们要求Mistral Large计算给定数据集中,支付金额接近的两位客户之间的付款日期差异。

我们先试试Mistral Small。

prompt = "Given this dataset: [{'customer': 'A', 'amount': 100, 'date': '2023-01-01'}, {'customer': 'B', 'amount': 105, 'date': '2023-01-05'}], calculate the difference in payment dates between the two customers whose payment amounts are close to each other."
response = call_mistral_model("mistral-small", prompt)
print(response)

你可以看到Mistral Small给出了错误的最终答案。但由于我们的模型结果是概率性的,如果你多次运行,有时可能会得到正确结果。

现在让我们运行Mistral Large。

response = call_mistral_model("mistral-large", prompt)
print(response)

正如你所见,Mistral Large能够将这个问题分解为多个步骤,并给出正确答案。

让我们尝试另一个有趣的例子:根据购买详情,计算我在每个类别(餐厅、杂货、毛绒玩具和道具)上花了多少钱。交易详情如下。

transactions = "Paid $30 at 'World Food Wraps', $15 at 'Grocery Mart', $25 for 'Teddy Bear', $10 for 'Magic Wand'"
prompt = f"Given these purchases: {transactions}. How much did I spend on each category: restaurants, groceries, stuffed animals, and props?"

首先运行Mistral Small。

response = call_mistral_model("mistral-small", prompt)
print(response)

你可以看到这里有一些错误,例如,“World Food Wraps”应该属于餐厅类别。

现在试试Mistral Large。

response = call_mistral_model("mistral-large", prompt)
print(response)

它恰好将“World Food Wraps”正确归类为餐厅,并给出了每个类别的正确答案。

示例4:编码任务

在下一个例子中,假设你即将见到一位非常重要的人物Andrew。你希望给他留下好印象,但你只有20分钟准备。他问你:“顺便问一下,我如何找到两个相加等于第三个数的数字?” Mistral如何帮助你留下好印象?让我们看看这个编码任务。Mistral Large在编码任务中表现最佳,所以让我们试一试。

prompt = "Write a Python function called `find_two_sum` that takes a list of integers `nums` and an integer `target`, and returns the indices of the two numbers such that they add up to `target`. Assume exactly one solution exists."
response = call_mistral_model("mistral-large", prompt)
print(response)

很好,现在让我们运行这个函数,并看看代码是否能通过这些测试。

# 假设从响应中提取了函数代码
def find_two_sum(nums, target):
    # ... Mistral生成的代码 ...
    pass

![](https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-mistral-intro/img/ecb1e1ca5e52af6482f7df777b04f3e1_9.png)

# 测试用例
print(find_two_sum([2, 7, 11, 15], 9))  # 应返回 [0, 1]
print(find_two_sum([3, 2, 4], 6))       # 应返回 [1, 2]

看起来我们的函数运行正常。现在,Andrew会因为你给出了正确答案而感到非常高兴。

示例5:多语言能力

此外,Mistral Large经过专门训练,能够理解和生成多种语言的文本,尤其是法语、德语、西班牙语和意大利语。这是一个用法语提问的例子:“哪个更重?一磅铁还是一公斤羽毛?” 😊

prompt = "Lequel est plus lourd ? Une livre de fer ou un kilogramme de plumes ?"
response = call_mistral_model("mistral-large", prompt)
print(response)

我不懂法语,但我希望它正确回答一公斤羽毛更重。

总结与展望 🎯

本节课中,我们一起学习了如何根据任务复杂度(简单、中等、复杂)来选择Mistral模型(Small、Medium、Large)。我们通过分类、邮件撰写、复杂计算、分类汇总和编码等具体示例,实践了不同模型的应用场景和效果差异。

到目前为止,我们已经看到了许多使用我们模型的用例,但还没有讨论外部工具。将我们的模型连接到外部工具可以帮助我们构建更强大的应用程序。在下一课中,你将学习如何使用函数调用来将Mistral模型连接到各种工具。

下节课见。

005:函数调用 🛠️

在本节课中,我们将学习如何为Mistral模型实现函数调用功能。函数调用允许Mistral模型连接到外部工具,使你能够轻松构建针对特定用例和实际问题的应用程序。

概述

函数调用使大型语言模型能够与外部函数或API交互,从而获取模型自身无法直接访问的信息或执行特定操作。整个过程分为四个核心步骤。

函数调用的四个步骤

上一节我们介绍了函数调用的概念,本节中我们来看看其具体实现的四个步骤。

步骤一:用户定义工具

用户需要为特定用例定义所有必要的工具。一个工具可以是一个用户定义的函数,也可以是一个外部API。

以下是定义两个函数的示例,一个用于提取支付状态,另一个用于提取支付日期。

import pandas as pd

# 假设我们有以下交易数据
data = {
    'transaction_id': ['T1001', 'T1002', 'T1003'],
    'status': ['paid', 'pending', 'failed'],
    'date': ['2024-01-15', '2024-01-16', '2024-01-17']
}
df = pd.DataFrame(data)

def retrieve_payment_status(transaction_id):
    """根据交易ID检索支付状态"""
    result = df[df['transaction_id'] == transaction_id]['status'].values
    return result[0] if len(result) > 0 else "Transaction ID not found"

def retrieve_payment_date(transaction_id):
    """根据交易ID检索支付日期"""
    result = df[df['transaction_id'] == transaction_id]['date'].values
    return result[0] if len(result) > 0 else "Transaction ID not found"

为了让Mistral模型理解这些函数,我们需要使用JSON模式来定义函数规范。

以下是定义函数规范的代码:

# 定义 retrieve_payment_status 函数的JSON规范
status_tool_spec = {
    "type": "function",
    "function": {
        "name": "retrieve_payment_status",
        "description": "根据交易ID获取支付状态",
        "parameters": {
            "type": "object",
            "properties": {
                "transaction_id": {
                    "type": "string",
                    "description": "交易的唯一标识符"
                }
            },
            "required": ["transaction_id"]
        }
    }
}

# 定义 retrieve_payment_date 函数的JSON规范
date_tool_spec = {
    "type": "function",
    "function": {
        "name": "retrieve_payment_date",
        "description": "根据交易ID获取支付日期",
        "parameters": {
            "type": "object",
            "properties": {
                "transaction_id": {
                    "type": "string",
                    "description": "交易的唯一标识符"
                }
            },
            "required": ["transaction_id"]
        }
    }
}

# 将工具规范组合成一个列表
tools = [status_tool_spec, date_tool_spec]

# 创建一个函数名到实际函数的映射字典
available_functions = {
    "retrieve_payment_status": retrieve_payment_status,
    "retrieve_payment_date": retrieve_payment_date
}

步骤二:模型生成函数参数

在定义了工具之后,我们需要让模型根据用户查询和工具规范来决定是否以及如何调用函数。

以下是让模型处理用户查询并生成函数调用的代码:

# 假设我们有一个用户查询
user_query = "我的交易状态是什么?"
chat_history = [{"role": "user", "content": user_query}]

# 调用模型,传入工具定义和用户查询
# 注意:以下为伪代码,实际调用需使用Mistral API客户端
response = mistral_model.chat(
    messages=chat_history,
    tools=tools,
    tool_choice="auto"  # 让模型自动决定是否使用工具
)

# 检查模型的响应
print(response.choices[0].message)

模型可能会识别出缺少必要信息(例如交易ID),并请求用户提供。

步骤三:用户执行函数并获取结果

模型返回函数调用建议后,需要由用户端来实际执行这些函数。

以下是执行函数并获取结果的代码:

# 从模型响应中提取函数调用信息
tool_calls = response.choices[0].message.tool_calls

# 遍历所有工具调用(支持并行调用)
for tool_call in tool_calls:
    function_name = tool_call.function.name
    function_args = json.loads(tool_call.function.arguments)  # 解析参数字符串为字典

    # 根据函数名找到对应的函数并执行
    function_to_call = available_functions[function_name]
    function_result = function_to_call(**function_args)

    # 将函数执行结果构建成一条“工具”角色的消息
    tool_message = {
        "role": "tool",
        "content": str(function_result),
        "tool_call_id": tool_call.id  # 关联到对应的函数调用
    }
    chat_history.append(tool_message)

步骤四:模型生成最终答案

最后,我们将包含函数执行结果的完整对话历史再次提供给模型,让它生成面向用户的最终答案。

以下是让模型生成最终答案的代码:

# 将包含工具执行结果的对话历史再次发送给模型
final_response = mistral_model.chat(messages=chat_history)

# 输出模型的最终回答
print(final_response.choices[0].message.content)
# 示例输出:“您的交易 T1001 状态为‘已支付’。还有什么可以帮您的吗?”

并行函数调用

Mistral模型支持并行函数调用。如果用户在一个查询中请求多个信息,模型可以同时建议调用多个函数。

例如,用户查询:“我的交易T1001的状态和日期是什么?”,模型可能会同时返回 retrieve_payment_statusretrieve_payment_date 两个函数调用。

总结

本节课中我们一起学习了Mistral模型函数调用的完整流程。我们了解到,通过四个步骤——定义工具、模型生成参数、执行函数、模型生成答案——可以让大型语言模型安全、可靠地接入外部数据和功能,从而解决更复杂的实际问题。在下一课中,我们将学习RAG(检索增强生成),并了解如何将RAG作为函数调用的一个工具来使用。

006:检索增强生成(RAG) 🧠

在本节课中,我们将学习并实践如何为Mistral模型实现检索增强生成。这是一种结合了大型语言模型和信息检索系统能力的AI框架,能有效利用外部知识来回答问题或生成内容。

概述

检索增强生成是一个AI框架,它结合了大型语言模型和信息检索系统的能力。该框架对于利用外部知识来回答问题或生成内容非常有用。

为什么需要RAG?

大型语言模型可能面临许多挑战。例如,它无法访问你的内部文档,不具备最新的信息,并且可能产生幻觉。针对这些问题,一个潜在的解决方案就是RAG。

RAG的工作原理

从高层次来看,以下是RAG的工作流程。

当用户询问关于内部文档或知识库的问题时,我们从知识库中检索相关信息,其中所有文本片段都存储在向量数据库中。这一步称为检索

接着,在提示词中,我们同时包含用户查询和相关检索到的信息。这样,我们的模型就可以基于相关上下文生成输出。这第二步称为生成

从零开始实现RAG

在本节中,我们来看看如何从零开始实现RAG。

获取并解析文档

首先,我们从Hugging Face获取一篇文章。这是我们感兴趣的文章链接。我们使用一个名为BeautifulSoup的HTML解析器来查找文章的主要文本。

分割文档

接下来,我们将这个文档分割成块。在RAG系统中,这样做至关重要,以便能更有效地识别和检索最相关的信息片段。

在这个例子中,我们简单地按字符分割文本,将每512个字符组合成一个块。我们得到了8个块。根据你的具体用例,可能需要定制或尝试不同的块大小。

此外,在如何分割文本方面有多种选择,你可以按标记、句子、HTML标题等进行分割,具体取决于你的应用。

创建嵌入向量

现在,有了这8个文本块,让我们为每个块创建嵌入向量。我们再次使用一个辅助函数来加载API密钥,你可以在课程环境外用你自己的API密钥替换它。

我们定义这个get_text_embedding函数,使用Mistral嵌入API端点来获取单个文本块的嵌入向量。然后,我们使用这个列表推导式来获取所有文本块的文本嵌入向量。

让我们看看它是什么样子。

这些生成的文本嵌入向量是表示向量空间中文本的数值向量。如果我们查看第一个嵌入向量的长度,它返回1024,这意味着我们的嵌入维度是1024。

存储与检索

一旦我们获得了嵌入向量,常见的做法是将它们存储在向量数据库中,以便高效处理和检索。有几种向量数据库可供选择。在我们的简单示例中,我们使用开源向量数据库Faiss。

我们定义IndexFlatL2类的一个实例,以嵌入维度作为参数。然后,我们将文本嵌入向量添加到这个索引结构中。

当用户提问时,我们也需要使用与之前相同的嵌入模型为这个问题创建嵌入向量。这里我们获取问题嵌入向量。

现在,我们可以从向量数据库中检索与所提问题相似的文本块。我们可以在向量数据库上使用index.search执行搜索,该函数返回向量数据库中与问题向量最相似的K个向量的距离和索引。

然后,基于返回的索引,我们可以检索与这些索引对应的实际相关文本块。如你所见,我们得到了两个文本块,因为我们定义了K=2来检索向量数据库中最相似的两个向量。

请注意,有许多不同的检索策略。在我们的示例中,我们在嵌入向量内部使用了简单的相似性搜索。根据你的用例,有时你可能希望先执行元数据过滤,或者为检索到的文档提供权重,甚至检索原始检索块所属的更大的父块。

生成最终答案

最后,我们可以将检索到的文本块作为上下文信息包含在提示词中。这是一个提示词模板,它可以在提示词中同时包含检索到的文本块和用户问题。

让我们再次使用之前见过的min函数。通过这个提示词,我们得到了一个响应。

以上就是从零开始实现RAG的工作原理。你可以自由使用另一篇Hugging Face文章,或结合多篇文章,并就这些文章提问。

高级RAG与函数调用

我们刚刚经历了一个非常基础的RAG工作流程。如果你对更高级的RAG策略感兴趣,有几门其他课程可以学习。

如果你正在开发一个复杂应用,其中RAG是你可调用的工具之一,或者如果你有多个RAG作为多个可调用的工具,那么你可以考虑在函数调用内部使用RAG。

让我们看一个简单的例子。

封装RAG逻辑

我们将上面定义的RAG逻辑封装在一个名为qa_with_context的函数中。

现在,我们将这个函数组织成一个名为name_to_function的字典中。正如我们在上一课中看到的,如果只有一个函数,这可能看起来不那么有用,但如果你有多个工具或函数,将它们组织到一个字典中是非常有用的。

定义函数规范

现在,我们可以使用JSON模式来定义函数规范,以告诉我们的模型这个函数是关于什么的。其中函数名是qa_with_context,必需的参数是用户问题。

调用模型与工具

通过将用户问题和工具传递给模型,我们得到了工具调用结果,其中函数名为qa_with_context,参数是我们的用户问题。

让我们从模型响应中提取函数信息,我们得到函数名和函数参数。

然后,我们执行该函数以获取函数结果。

作为练习,请自由编写另一个RAG函数,询问关于另一篇Hugging Face文章的问题,并将它们都作为工具提供给我们的Mistral模型。

工具选择策略

作为练习,如果我们将用户查询改为“编写一个Python函数来对字符串中的字母进行排序”,会发生什么?它不应该使用我们的工具qa_with_context,因为这个问题与这个工具无关。

那么为什么会发生这种情况?这是因为我们将tool_choice设置为any,这会强制使用工具。现在我们将它改为auto,这意味着模型决定是否使用工具,但现在它仍然使用qa_with_context工具。

这可能是因为我们对工具的描述太笼统了。我们需要指定工具更具体。让我们在描述中添加一些细节:“你通过检索相关上下文来回答用户关于AI的问题。”

让我们运行这个。现在,让我们将描述更改为:“通过检索文章的相关上下文,回答用户关于一篇AI文章的问题。”这样描述就更具体了。

当我们再次运行它时,我们可以看到它返回了我们所要求的Python函数内容,并且现在没有返回工具调用,这正是我们需要的。

当然,如果你知道这个问题不应该使用工具,我们可以在这里将tool_choice设置为none。这将保证我们不会调用任何工具或函数。

现在让我们再试试any。记住,any会强制进行函数调用,现在我们可以看到,即使我们更改了函数描述,它仍然使用函数调用,因为我们的tool_choiceany,这会强制进行函数调用。

所以,默认行为是auto,我建议你将tool_choice设置为auto

总结

在本节课中,我们一起学习了检索增强生成的基本概念和从零开始的实现步骤。我们了解了RAG如何结合检索和生成来利用外部知识,并实践了文档获取、分割、嵌入、存储、检索以及最终生成答案的完整流程。我们还探讨了如何将RAG逻辑封装为函数,并在函数调用框架中管理它,同时学习了tool_choice参数的不同设置(autoanynone)如何影响模型是否以及如何使用工具。

请注意,你可以使用Mistral与其他工具(如LangChain、LlamaIndex和Haystack)一起进行RAG,请查看我们的文档以了解其工作原理。

在下一课中,我们将学习如何使用Mistral模型和Panel创建简单的UI界面。

007:创建聊天界面

概述

在本节课中,我们将学习如何创建两种简单的聊天界面,用于与Mistral模型交互以及与外部文档进行对话。


导入必要包

首先,我们需要导入必要的Python包。除了之前课程中见过的包,我们还需要引入一个新的包:panelpanel是一个开源的数据探索和Web应用框架。

import panel as pn

导入后,我们需要运行以下代码行来加载Panel应用的自定义JavaScript和CSS扩展。

pn.extension()

创建基础聊天界面

上一节我们导入了必要的工具,本节中我们来看看如何创建一个基础聊天界面。

我们定义一个之前见过的myal函数。请注意,这里我们添加了两个额外的参数userchat_interface。虽然函数本身不使用它们,但为了UI的兼容性,我们需要将其包含在参数列表中。

接下来,我们只需运行以下四行代码,就能获得一个可以与模型交互的聊天界面。

chat_interface = pn.chat.ChatInterface(callback=myal, callback_user="Mistral")
chat_interface.send("Write an email to schedule an appointment with my CS professor to discuss research opportunities.", user="User", respond=False)
chat_interface.servable()

效果相当不错。现在,让我们更仔细地看看代码。

我们使用pn.chat.ChatInterface定义了一个聊天界面小部件。这个小部件处理了聊天应用的所有用户界面和逻辑。然后,我们在回调函数中定义系统如何响应,这个回调函数就是我们上面定义的myal函数。我们可以将回调用户名定义为“Mistral”,以指示来自Mistral模型的响应。

由此可见,仅用几行代码,你就可以获得一个与我们的模型交互的简单聊天界面。


创建文档问答聊天界面

接下来,让我们看看如何创建一个能与外部文档对话的聊天界面。

我们之前见过这部分代码。我们从Batch获取一份新闻简报,并将其文本内容保存为batch.txt文件。

以下是相关代码的简要回顾:

首先,在提示词中,我们包含了基于用户查询检索到的文本块信息,然后是用户查询本身,我们试图据此获得答案。

我们有一个使用text-embedding模型获取文本嵌入向量的函数。
另一个函数用于运行Mistral模型。对于RAG任务,我们推荐使用Mistral-Large模型以获得最佳性能。

主要函数是answer_question函数。它的工作流程是:

  1. 从上传的文件中获取文本。
  2. 将文档分割成块。
  3. 将文本块加载到向量数据库中。
  4. 为问题创建嵌入向量。
  5. 从向量数据库中检索相似的文本块。
  6. 最后,基于检索到的相关文本块生成响应。

以下是该聊天界面的代码。在这个聊天界面中,我们首先需要定义一个文件输入小部件,用于上传文件。

让我们看看这个小部件:file_input,我们可以选择并上传一个文件。

然后,我们需要定义聊天界面小部件,在回调函数中定义系统如何响应,这个回调函数就是我们刚刚定义的answer_question函数。

我们可以将文件输入小部件安排在界面的顶部。如你所见,我们首先看到的是文件输入小部件和一些文本描述。我们还可以选择用一条系统消息来启动聊天界面,以便用户了解这个聊天应用的预期用途。

现在让我们再试一次。我们上传batch.txt文件。我们问一个关于这个文件的问题。然后我们从Mistral-Large模型得到一个答案。

这就是这个聊天用户界面的代码。作为练习,你可以尝试通过更改这里的URL来使用Batch的不同文章。然后尝试上传不同的文章并询问相关问题,看看Mistral-Large模型如何响应。


总结

本节课中,我们一起学习了如何创建两种聊天界面:一种是基础的、直接与Mistral模型对话的界面;另一种是更高级的、能够处理并回答关于上传文档问题的界面。我们使用了panel库来构建用户界面,并集成了文本嵌入和检索增强生成技术来实现文档问答功能。

008:总结 🎯

在本节课中,我们将对Mistral入门课程的核心内容进行回顾与总结,并为您提供进一步学习的路径。


非常感谢您加入本课程的学习。您已经了解了关于Mistral各种模型及其特性的丰富知识。

关于Mistral AI,还有更多值得学习和期待的内容。😊

以下是您可以采取的后续步骤:

  • 请访问我们的官方网站 Mitro Dl AI 以获取最新信息。
  • 请务必加入我们活跃的 Discord社区,与其他学习者和开发者交流。

我非常希望了解您接下来希望学习哪些主题,这将帮助我规划未来的教学内容。

再次衷心感谢,期待不久后与您再次相见。😊


本节课中,我们一起回顾了整个Mistral入门课程,并为您指明了继续探索Mistral AI世界、参与社区以及反馈学习需求的方向。希望本课程为您开启了使用大语言模型的精彩旅程。

posted @ 2026-03-26 08:12  绝不原创的飞龙  阅读(1)  评论(0)    收藏  举报