generative-ai-for-beginners 中的 Mistral 实战:Mistral Large、Small 与 NeMo 三大模型选型、RAG 与分词器对比
本篇基于课程第 20 课 20-mistral/README.md 展开,系统讲解如何在 generative-ai-for-beginners 课程体系中,通过 Microsoft Foundry Models(原 GitHub Models 的继任者)免费调用三款 Mistral 模型:企业级旗舰 Mistral Large 2、轻量低延迟的 Mistral Small,以及 Apache 2.0 开源许可的 Mistral NeMo。读完本篇,你将能够配置推理端点与凭据、用 Mistral Large 2 完整跑通一个基于 FAISS 的 RAG(检索增强生成)示例、用同一提示词量化对比 Small 与 Large 的延迟差异,并通过 mistral-common 库验证 NeMo 更高效的 Tekken 分词器。
课程定位:三款模型与 Microsoft Foundry Models
本课(20-mistral/README.md)覆盖三个目标:
- 探索不同的 Mistral 模型;
- 理解每款模型的用例与适用场景;
- 通过代码示例演示各模型的独特能力。
本课聚焦的三款模型及其定位如下:
| 模型 | 定位 | 核心特点 |
|---|---|---|
| Mistral Large 2 (2407) | 旗舰,面向企业 | 128k 上下文、原生函数调用、多语言 |
| Mistral Small | 轻量级(SLM) | 低成本(约 80% 降价)、低延迟、部署灵活 |
| Mistral NeMo | 开源(Apache 2.0) | Tekken 分词器、可微调、原生函数调用 |
这三个模型均可在 Microsoft Foundry Models 上免费使用,配套的可执行 Notebook 位于 20-mistral/python/githubmodels-assignment.ipynb。
注意(原文档明确说明):GitHub Models 将于 2026 年 7 月底停止服务,本课代码统一改用 Microsoft Foundry Models 进行 AI 模型原型验证。仓库的 00-course-setup/03-providers.md 也同步标注了这一点:Microsoft Foundry Models 是“多提供商模型目录,替代将于 2026 年 7 月底退役的 GitHub Models”。
环境准备:端点与凭据
本课所有示例代码统一从两个环境变量读取访问信息:
AZURE_INFERENCE_ENDPOINT:你的 Microsoft Foundry 项目端点;AZURE_INFERENCE_CREDENTIAL:Foundry Models 的 API 密钥。
两者的取值来自你 Foundry 项目的 “Overview” 页面。仓库根目录提供了 .env.copy 模板文件,其中已包含这两项的占位定义:
## Microsoft Foundry Models (multi-provider model catalog, replaces GitHub Models, which retires end of July 2026)
AZURE_INFERENCE_ENDPOINT='<add your Microsoft Foundry project endpoint here>'
AZURE_INFERENCE_CREDENTIAL='<add your Microsoft Foundry Models API key here>'
按 00-course-setup/03-providers.md 的说明操作:将 .env.copy 复制为 .env(cp .env.copy .env),再填入真实值。.env 已被 gitignore,密钥不会进入版本库。
客户端统一使用 azure-ai-inference SDK。以下初始化代码贯穿全课所有示例,只需配置一次:
import os
from azure.ai.inference import ChatCompletionsClient
from azure.ai.inference.models import SystemMessage, UserMessage
from azure.core.credentials import AzureKeyCredential
# 从你的 Microsoft Foundry 项目 "Overview" 页面获取
endpoint = os.environ["AZURE_INFERENCE_ENDPOINT"]
token = os.environ["AZURE_INFERENCE_CREDENTIAL"]
client = ChatCompletionsClient(
endpoint=endpoint,
credential=AzureKeyCredential(token),
)
Mistral Large 2 (2407):旗舰模型能力
Mistral Large 2 是 Mistral 当前的旗舰模型,面向企业场景设计。相较初代 Mistral Large,它的主要升级是:
- 更大的上下文窗口:128k(初代为 32k);
- 更强的数学与编码表现:平均准确率 76.9%(初代为 60.4%);
- 更强的多语言能力:覆盖英语、法语、德语、西班牙语、意大利语、葡萄牙语、荷兰语、俄语、中文、日语、韩语、阿拉伯语、印地语。
基于这些特性,Mistral Large 擅长三类任务:
- 检索增强生成(RAG)——得益于 128k 的更大上下文窗口;
- 函数调用(Function Calling)——模型原生支持,可对接外部工具与 API,且既支持并行调用,也支持顺序调用;仓库中 11-integrating-with-function-calling/README.md 一课专门讲解函数调用的通用原理,可与本课互参;
- 代码生成——在 Python、Java、TypeScript、C++ 生成上表现突出。
RAG 实战:Mistral Large 2 回答韩语问题
本课给出了一个完整的 RAG 示例,演示流程为:下载一篇 Paul Graham 的英文随笔 → 按 2048 字符切块 → 用 Cohere 多语言 Embedding 模型向量化 → 存入 FAISS 的 IndexFlatL2 索引 → 将韩语问题同样向量化后检索最相似的 2 个文本块 → 把问题与检索到的上下文拼入提示词,交给 Mistral Large 生成自然语言回答。
整个示例同时验证了两点能力:多语言理解(问题为韩语、文档为英语)与 RAG 检索流程。这与仓库中 15-rag-and-vector-databases/README.md 一课讲授的 RAG 通用流程(分块 → 向量化 → 相似度检索 → 生成)完全对应,只是本课把向量库简化为了进程内的 FAISS。
安装依赖:
pip install faiss-cpu
完整示例代码(可直接复制到 Notebook 运行,环境变量配置见上节):
import requests
import numpy as np
import faiss
import os
from azure.ai.inference import ChatCompletionsClient
from azure.ai.inference.models import SystemMessage, UserMessage
from azure.core.credentials import AzureKeyCredential
from azure.ai.inference import EmbeddingsClient
# Get these from your Microsoft Foundry project's "Overview" page
endpoint = os.environ["AZURE_INFERENCE_ENDPOINT"]
model_name = "Mistral-large"
token = os.environ["AZURE_INFERENCE_CREDENTIAL"]
client = ChatCompletionsClient(
endpoint=endpoint,
credential=AzureKeyCredential(token),
)
# 下载 Paul Graham 随笔作为知识库文本
response = requests.get('https://raw.githubusercontent.com/run-llama/llama_index/main/docs/docs/examples/data/paul_graham/paul_graham_essay.txt')
text = response.text
# 按 2048 字符固定长度切块
chunk_size = 2048
chunks = [text[i:i + chunk_size] for i in range(0, len(text), chunk_size)]
len(chunks)
# 使用 Cohere 多语言 Embedding 模型
embed_model_name = "cohere-embed-v3-multilingual"
embed_client = EmbeddingsClient(
endpoint=endpoint,
credential=AzureKeyCredential(token)
)
# 对全部文本块批量向量化
embed_response = embed_client.embed(
input=chunks,
model=embed_model_name
)
text_embeddings = []
for item in embed_response.data:
length = len(item.embedding)
text_embeddings.append(item.embedding)
text_embeddings = np.array(text_embeddings)
# 构建 FAISS 精确(L2 距离)索引
d = text_embeddings.shape[1]
index = faiss.IndexFlatL2(d)
index.add(text_embeddings)
# 韩语问题:作者在进入大学前主要做的两件事是什么?
question = "저자가 대학에 오기 전에 주로 했던 두 가지 일은 무엇이었나요?"
question_embedding = embed_client.embed(
input=[question],
model=embed_model_name
)
question_embeddings = np.array(question_embedding.data[0].embedding)
# 检索最相似的 2 个文本块(k=2)
D, I = index.search(question_embeddings.reshape(1, -1), k=2) # D: 距离, I: 索引
retrieved_chunks = [chunks[i] for i in I.tolist()[0]]
# 将上下文与问题拼入提示词
prompt = f"""
Context information is below.
---------------------
{retrieved_chunks}
---------------------
Given the context information and not prior knowledge, answer the query.
Query: {question}
Answer:
"""
chat_response = client.complete(
messages=[
SystemMessage(content="You are a helpful assistant."),
UserMessage(content=prompt),
],
temperature=1.0,
top_p=1.0,
max_tokens=1000,
model=model_name
)
print(chat_response.choices[0].message.content)
配套 Notebook 20-mistral/python/githubmodels-assignment.ipynb 中保留了该单元格的真实运行输出,Mistral Large 2 的回答是:
The author primarily engaged in two activities before college: writing and programming. In terms of writing, they wrote short stories, albeit not very good ones... For programming, they started writing programs on the IBM 1401 used for data processing during their 9th grade, at the age of 13 or 14...
即准确回答了“写作”与“编程”两件事,并给出了原文细节。
实现要点解读:
faiss.IndexFlatL2(d):精确最近邻索引,d为 Embedding 维度(由cohere-embed-v3-multilingual决定)。FAISS 的IndexFlatL2通过 L2 欧氏距离衡量相似度,适合中小规模语料(本例仅十几个文本块)。index.search(query, k=2)返回距离矩阵D与索引矩阵I,I.tolist()[0]即前 2 个最相似块的原始下标;- 提示词设计:用
Given the context information and not prior knowledge, answer the query.显式约束模型只依据检索到的上下文作答,这是抑制 RAG 场景“幻觉”的常用做法; - 采样参数:示例中
temperature=1.0、top_p=1.0、max_tokens=1000为模型默认宽松采样配置,忠实复现了课程原始设置; - 切块策略:示例采用固定 2048 字符的简单切块(
chunk_size = 2048),未做句子边界对齐,这是教学示例的取舍;生产环境通常需按段落/句子切分并保留重叠(overlap)。
Mistral Small:为高频、低延迟场景而设计
Mistral Small 属于 Mistral 家族中 premier/enterprise 类别下的一个小语言模型(SLM)。相比 Mistral Large 等 LLM,它的优势是:
- 成本更低:相比 Mistral Large 和 NeMo 约有 80% 的价格降幅;
- 低延迟:响应速度比 Mistral 的 LLM 更快;
- 部署灵活:对资源要求更宽松,可跨不同环境部署。
课程给出的三类典型适用场景:
- 文本类任务:摘要、情感分析、翻译;
- 请求频繁、对成本敏感的应用(得益于高性价比);
- 低延迟代码任务,例如代码评审与代码建议。
对比实验:同一提示词下 Small 与 Large 的延迟差异
为了直观展示两者的延迟差距,课程设计了一个 A/B 对比实验:对同一句提示词(“Can you write a Python function to the fizz buzz test?”)分别调用 Mistral-small 与 Mistral-large,观察响应时间与回答风格。课程预期两者响应时间相差 3~5 秒,同时回答的长度与风格也会不同。
Mistral Small 的调用:
import os
endpoint = os.environ["AZURE_INFERENCE_ENDPOINT"]
model_name = "Mistral-small"
token = os.environ["AZURE_INFERENCE_CREDENTIAL"]
client = ChatCompletionsClient(
endpoint=endpoint,
credential=AzureKeyCredential(token),
)
response = client.complete(
messages=[
SystemMessage(content="You are a helpful coding assistant."),
UserMessage(content="Can you write a Python function to the fizz buzz test?"),
],
temperature=1.0,
top_p=1.0,
max_tokens=1000,
model=model_name
)
print(response.choices[0].message.content)
Mistral Large 的调用(仅 model_name 不同,其余参数完全一致,保证对比公平):
import os
from azure.ai.inference import ChatCompletionsClient
from azure.ai.inference.models import SystemMessage, UserMessage
from azure.core.credentials import AzureKeyCredential
endpoint = os.environ["AZURE_INFERENCE_ENDPOINT"]
model_name = "Mistral-large"
token = os.environ["AZURE_INFERENCE_CREDENTIAL"]
client = ChatCompletionsClient(
endpoint=endpoint,
credential=AzureKeyCredential(token),
)
response = client.complete(
messages=[
SystemMessage(content="You are a helpful coding assistant."),
UserMessage(content="Can you write a Python function to the fizz buzz test?"),
],
temperature=1.0,
top_p=1.0,
max_tokens=1000,
model=model_name
)
print(response.choices[0].message.content)
实验的公平性完全来自“只改模型名”这一控制变量:相同系统提示、相同用户提示、相同采样参数、相同 max_tokens。两个单元格的 client.complete(...) 走的是同一条 azure-ai-inference 调用链,因此测得的时差可以直接归因于模型规模差异。
Mistral NeMo:唯一的 Apache 2.0 开源选项
与本课讨论的另外两款模型相比,Mistral NeMo 是唯一的 Apache 2.0 许可免费模型,可视为 Mistral 早期开源 LLM(Mistral 7B)的升级版。它的三个独特特性:
- 更高效的分词(Tekken tokenizer):NeMo 采用 Mistral 自家的 Tekken 分词器,而不是业界更常见的 tiktoken,在多语言与代码场景下 token 利用率更高;
- 支持微调:基础模型(base model)开放微调,为需要微调的场景提供了更多灵活性;
- 原生函数调用:与 Mistral Large 一样,NeMo 经过函数调用训练,是首批原生支持函数调用的开源模型之一。
分词器对比实战:NeMo 128 tokens vs Large 135 tokens
课程用一个最小可复现实验量化了“分词效率差异”:对完全相同的聊天补全请求(包含一个天气查询函数定义 + 一句用户消息),分别用 open-mistral-nemo 和 mistral-large-latest 的分词器编码,比较输出 token 数。
安装依赖:
pip install mistral-common
NeMo 分词(open-mistral-nemo):
# Import needed packages:
from mistral_common.protocol.instruct.messages import (
UserMessage,
)
from mistral_common.protocol.instruct.request import ChatCompletionRequest
from mistral_common.protocol.instruct.tool_calls import (
Function,
Tool,
)
from mistral_common.tokens.tokenizers.mistral import MistralTokenizer
# Load Mistral tokenizer
model_name = "open-mistral-nemo"
tokenizer = MistralTokenizer.from_model(model_name)
# Tokenize a list of messages
tokenized = tokenizer.encode_chat_completion(
ChatCompletionRequest(
tools=[
Tool(
function=Function(
name="get_current_weather",
description="Get the current weather",
parameters={
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city and state, e.g. San Francisco, CA",
},
"format": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"description": "The temperature unit to use. Infer this from the user's location.",
},
},
"required": ["location", "format"],
},
)
)
],
messages=[
UserMessage(content="What's the weather like today in Paris"),
],
model=model_name,
)
)
tokens, text = tokenized.tokens, tokenized.text
# Count the number of tokens
print(len(tokens))
Mistral Large 分词(mistral-large-latest,其余代码完全相同):
# Import needed packages:
from mistral_common.protocol.instruct.messages import (
UserMessage,
)
from mistral_common.protocol.instruct.request import ChatCompletionRequest
from mistral_common.protocol.instruct.tool_calls import (
Function,
Tool,
)
from mistral_common.tokens.tokenizers.mistral import MistralTokenizer
# Load Mistral tokenizer
model_name = "mistral-large-latest"
tokenizer = MistralTokenizer.from_model(model_name)
# Tokenize a list of messages
tokenized = tokenizer.encode_chat_completion(
ChatCompletionRequest(
tools=[
Tool(
function=Function(
name="get_current_weather",
description="Get the current weather",
parameters={
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city and state, e.g. San Francisco, CA",
},
"format": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"description": "The temperature unit to use. Infer this from the user's location.",
},
},
"required": ["location", "format"],
},
)
)
],
messages=[
UserMessage(content="What's the weather like today in Paris"),
],
model=model_name,
)
)
tokens, text = tokenized.tokens, tokenized.text
# Count the number of tokens
print(len(tokens))
配套 Notebook 20-mistral/python/githubmodels-assignment.ipynb 中保留了这两段代码的真实运行输出:open-mistral-nemo 打印 128,mistral-large-latest 打印 135——同样的输入,NeMo 的 Tekken 分词器少用了 7 个 token,验证了原文档“NeMo returns fewer tokens than Mistral Large”的结论。
实现要点解读:
MistralTokenizer.from_model(model_name):mistral-common按模型名加载对应的分词器配置。注意此处传入的是 Mistral 官方模型名(open-mistral-nemo、mistral-large-latest),与前面通过 Foundry 端点调用时使用的Mistral-small/Mistral-large服务名是两套命名体系;- 为什么请求里带
tools:编码对象是完整的ChatCompletionRequest(含函数定义与消息),token 数反映的是真实调用时的完整输入开销,而非纯文本长度。函数定义的 JSON Schema 占据了相当一部分 token,这也解释了为何两个数字都在 120~140 量级; - token 数差异的实际意义:分词效率直接影响上下文利用率与调用成本。同样预算下,分词更紧凑的模型能装下更多有效内容,这一点对长文档、多语言与代码场景尤为明显。
实现细节提示:Notebook 中 NeMo 单元格的模型名实际带有一个制表符(
"open-mistral-nemo\t"),能运行是因为from_model按前缀匹配;在自写代码中请直接使用干净字符串open-mistral-nemo,避免踩坑。
三款模型如何选择
综合本课给出的事实,可以得到如下选型依据:
- 需要长文档问答、RAG、复杂工具编排、高质量代码生成 → Mistral Large 2:128k 上下文与原生函数调用是核心抓手;
- 请求量大、预算受限、追求秒级响应(摘要、情感分析、翻译、代码评审) → Mistral Small:约 80% 的降价与低延迟是主要收益;
- 需要自托管、微调,或希望代码可完全自由商用 → Mistral NeMo:Apache 2.0 许可 + 开放 base 模型 + 原生函数调用,是三款中唯一同时满足开源许可与工具调用训练的选项。
三款模型共享同一套 azure-ai-inference 调用方式,切换模型只需替换 model_name 参数,这意味着本课的实验代码可以零改动地迁移到任何一款模型上做基准对比。
本课小结
本课在 generative-ai-for-beginners 课程体系中的位置是“模型供应商实践课”:它不引入新的抽象概念,而是用三段可运行代码(RAG 检索问答、双模型延迟对比、双分词器编码对比)把三款 Mistral 模型的能力差异变成可测量的事实。课程源码骨架(20-mistral/README.md)与可执行 Notebook(20-mistral/python/githubmodels-assignment.ipynb)一一对应,环境配置统一由 00-course-setup/03-providers.md 与根目录 .env.copy 支撑,后续函数调用与 RAG 原理可分别衔接第 11 课与第 15 课继续深入。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00