generative-ai-for-beginners 第 20 课实战:Mistral Large / Small / NeMo 三款模型的选型与代码示例全解析
本篇文章完整拆解开源课程 generative-ai-for-beginners 中"使用 Mistral 模型构建应用"(Building with Mistral Models)一课的全部知识点与可运行代码。你将掌握 Mistral 家族中 Mistral Large 2、Mistral Small、Mistral NeMo 三款模型的定位差异、适用场景与调用方式,并通过本仓库附带的 Jupyter Notebook 示例,亲手跑通基于 faiss 的 RAG 检索增强生成、小/大模型延迟对比、Tekken 与 tiktoken 分词效率对比三组实验。本文以 translations/da/20-mistral/README.md(课程丹麦语译本)为讲解主线,并同步对照仓库中最新英文原版 20-mistral/README.md 与可直接运行的 Notebook 20-mistral/python/githubmodels-assignment.ipynb 进行深化解读。
本节课程概览:要探索什么
第 20 课是整个 21 课课程体系中的一个独立专题(课程大纲见根目录 README.md),面向已具备基础提示词与生成式 AI 概念的开发者。本课要解决的问题非常聚焦:当供应商(Mistral)同时提供多款模型时,究竟该选哪一款,以及每款模型独有的能力如何落地到代码里。
原文档在"Introduction"(Introduktion)一节给出的学习目标是:
- 探索不同的 Mistral 模型;
- 理解每款模型各自的使用场景(use-cases)与适用条件;
- 通过代码示例观察每款模型的独有特性。
课程选择的对比对象是三款风格差异明显的模型:Mistral Large(旗舰级、偏企业应用)、Mistral Small(小语言模型、低成本低延迟)与 Mistral NeMo(开源 Apache-2.0 模型、面向可本地化与微调场景)。三款模型并列讲解,恰好对应课程主线中 LLM 选型、SLM、函数调用、微调等多个横向主题的交叉点。
运行前提:模型从哪来、凭据如何配置
按丹麦语译本中的说明,这三款模型都可以在 GitHub Model Marketplace(对应英文新版中已迁移至 Microsoft Foundry Models)免费获取,课程 Notebook 直接以这些在线模型作为推理后端。从当前仓库可以看到模型市场的演进痕迹:
- 丹麦语译本 translations/da/20-mistral/README.md 的代码快照仍使用硬编码 endpoint
https://models.inference.ai.azure.com并从环境变量读取GITHUB_TOKEN; - 而仓库主 README 与 20-mistral/README.md 均标注:GitHub Models 将于 2026 年 7 月底退役,官方推荐改用 Microsoft Foundry Models 的模型推理服务,即从 Microsoft Foundry 项目的 Overview 页面获取
AZURE_INFERENCE_ENDPOINT与AZURE_INFERENCE_CREDENTIAL两个环境变量。
因此,如果你的代码运行在今天的环境,建议按新版 Notebook 的写法配置两个环境变量;若沿用旧版(GitHub Models),则把 endpoint 写成 models.inference.ai.azure.com、token 从 GITHUB_TOKEN 读取。仓库中的环境变量工程实践可以参考 shared/python/env_utils.py 中安全读取密钥的写法,以及课程第 00 课的供应商对比说明 00-course-setup/03-providers.md。完整的本地开发环境搭建方式见 00-course-setup/02-setup-local.md。
代码统一通过 Azure AI Inference SDK(azure-ai-inference)访问模型:聊天补全使用 ChatCompletionsClient,向量化使用 EmbeddingsClient。这一客户端模式与课程中其他"assignment"作业保持一致,例如 06-text-generation-apps/python/githubmodels-app.py 中也是相同风格的封装。
Mistral Large 2 (2407):面向企业的旗舰模型
Mistral Large 2 是 Mistral 当前的旗舰模型,设计目标就是企业级应用。按原文档,它是初代 Mistral Large 的升级版,主要提升体现在三方面:
| 能力维度 | Mistral Large 2 | 原版 Mistral Large |
|---|---|---|
| 上下文窗口 | 128k | 32k |
| 数学与代码任务平均准确率 | 76.9% | 60.4% |
| 多语言 | 英语、法语、德语、西班牙语、意大利语、葡萄牙语、荷兰语、俄语、中文、日语、韩语、阿拉伯语、印地语 | —— |
这些指标与语言列表均出自课程文档原文,用于说明"旗舰"定位而非营销表述。基于更大的上下文窗口与更强的代码能力,原文档总结 Mistral Large 2 最擅长以下三类任务:
- 检索增强生成(RAG)——得益于更大的 128k 上下文窗口,可以把大段检索到的资料拼进提示词中一并推理;
- 函数调用(Function Calling)——模型原生支持函数调用,可与外部工具和 API 集成,调用既可以并行(parallel)发出,也可以按顺序逐个完成;
- 代码生成——在 Python、Java、TypeScript、C++ 代码生成上表现突出。
其中"更大的上下文窗口正是 RAG 的理想宿主"这一设计逻辑,可与本课程第 15 课 15-rag-and-vector-databases/README.md 中关于 RAG 原理与向量数据库的讲解互相印证。
实战:用 Mistral Large 2 跑通一个完整 RAG 流程
原文档给出的 RAG 示例非常完整,它是把"向量检索 + 大模型生成"拼成一个最小可用流水线的绝佳范本。整个流程如下:
- 用
requests下载一篇英文长文(Paul Graham 的自述文章); - 按
2048字符切块(chunking),得到文本片段列表; - 用 Cohere 的
cohere-embed-v3-multilingual多语言向量模型把每个片段转成 embedding; - 用
faiss的IndexFlatL2(欧氏距离暴力检索索引)作为内存向量库,把所有片段向量加入索引; - 用户用韩语提问("作者上大学前主要做的两件事是什么?"),将问题同样向量化后,以
k=2召回最相似的两个片段; - 把"召回片段 + 问题"拼进一段带约束的提示词,交给 Mistral Large 2 生成自然语言答案。
先安装向量检索依赖:
pip install faiss-cpu
备注:Notebook 输出显示实际安装版本为
faiss-cpu 1.8.0.post1,依赖numpy<2.0,>=1.0,Python 运行环境为 3.12。若在 Jupyter 内核中安装新包,注意按提示重启内核。
完整代码(与仓库 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),
)
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
chunk_size = 2048
chunks = [text[i:i + chunk_size] for i in range(0, len(text), chunk_size)]
len(chunks)
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)
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)
D, I = index.search(question_embeddings.reshape(1, -1), k=2) # distance, index
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)
代码要点逐段解读
- 切块长度:
chunk_size = 2048按字符切割。文档越长的段落越能塞进 128k 上下文,这里为了演示召回逻辑采用相对粗粒度的等长切块; - 向量维度对齐:
d = text_embeddings.shape[1]从真实 embedding 数组推断维度,再据此实例化faiss.IndexFlatL2(d),避免硬编码维度导致维度不匹配; - 召回:
index.search(question_embeddings.reshape(1, -1), k=2)返回(D, I),其中D为距离、I为命中的片段下标;retrieved_chunks就是被召回的两个原文片段; - 提示词约束:提示词明确要求"仅依据上下文信息回答、不要依赖先验知识"(
Given the context information and not prior knowledge),这是 RAG 提示词的标准写法,可以显著降低模型"想当然"生成答案的风险; - 生成参数:
temperature=1.0、top_p=1.0表示保留较大随机性,max_tokens=1000限制输出长度;model="Mistral-large"指定模型。实践中做事实性问答往往会把temperature调低以提升稳定性。
在仓库 Notebook 的已执行输出中可以看到该示例的真实运行结果——模型用英文正确回答了韩语问题,指出作者上大学前主要从事的两项活动是写作与编程,并补充了关于在 IBM 1401 上使用早期 Fortran 编写程序的细节。这证明:即使查询是韩语、召回的是英文原文,多语言 embedding 模型与 Mistral Large 2 的组合也能给出合理回答,这正是本示例选择 cohere-embed-v3-multilingual 的原因。
Mistral Small:主打成本与延迟的小语言模型
Mistral Small 属于 Mistral 家族中 premier/enterprise 分类下的另一款模型。顾名思义,它是一款 Small Language Model(SLM)。围绕 SLM 的价值主张,本课程第 19 课 19-slm/README.md 有专门讨论,可在读完本节后对照学习。
原文档总结了使用 Mistral Small 的三大优点:
- 成本节省——相比 Mistral Large、NeMo 等大模型,价格下降约 80%;
- 低延迟——相比 Mistral 的大模型响应更快;
- 灵活——可以部署在多种环境,对算力资源的要求更低、限制更少。
对应的最佳使用场景是:
- 文本类任务:摘要(summarization)、情感分析(sentiment analysis)、翻译(translation);
- 需要高频发起请求的应用(得益于其成本效益);
- 低延迟代码类任务,如代码审查与代码补全建议。
这些场景共同点是"调用频繁"或"对响应速度敏感",因此用更小、更便宜的模型换取吞吐与延迟收益,是典型的工程取舍。
对照实验:同一提示词下对比 Small 与 Large 的延迟
为了直观展示 Mistral Small 与 Mistral Large 在延迟上的差异,原文档要求对两个模型发送完全相同的提示词并观察响应。按文档说明,两个模型的响应时间差应在 3~5 秒左右;同时值得留意的是,面对同一提示词,两者返回的回答长度与风格也不相同。
两个模型各自独立创建 ChatCompletionsClient,仅 model_name 不同,其余调用参数完全一致。首先是用 Mistral Small 生成 FizzBuzz 函数:
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:
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)
注意,若沿用丹麦语译本对应的旧版配置,需把两处 endpoint/token 替换为 endpoint = "https://models.inference.ai.azure.com" 与 token = os.environ["GITHUB_TOKEN"]。建议在终端分别计时执行两段代码,把"实测延迟差异"作为选型依据之一:如果应用对延迟不敏感,Large 在复杂推理上可能更稳;如果是高频低价值请求,Small 显然更合适。
Mistral NeMo:唯一的 Apache-2.0 开源选项
相比前两款模型,Mistral NeMo 最突出的区别是:它是本课三款模型中唯一采用 Apache-2.0 许可证、可免费使用的模型,被看作是 Mistral 早期开源 LLM Mistral 7B 的升级版。其核心特性有三点:
- 更高效的分词(tokenization):NeMo 采用 Tekken 分词器,而非更常见的 tiktoken,因此在更多语言与代码上的分词表现更好(即同样的文本能拆出更少的 token,从而降低推理成本、扩大有效上下文);
- 可微调(finetuning):基础模型开放给开发者微调,为需要定制行为的场景提供了更大灵活性(可对照第 18 课 18-fine-tuning/README.md 了解微调方法论);
- 原生函数调用(Native Function Calling):与 Mistral Large 一样经过函数调用训练,这使它成为最早支持函数调用的开源模型之一。
对照实验:NeMo(Tekken)与 Large 的分词效率对比
原文档用一段包含函数定义的消息(查询巴黎天气并附带 get_current_weather 工具)来对比两个模型的分词数量。先安装 Mistral 的官方分词工具包:
pip install mistral-common
Notebook 输出显示
mistral-common 1.4.4安装成功,并会连带安装sentencepiece 0.2.0、tiktoken 0.7.0、regex等依赖(numpy、pydantic、jsonschema等作为既有依赖保留)。
第一段代码使用 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))
这段对比中包含了两个值得展开的技术点:
- 函数定义的 JSON Schema 如何影响 token 数:两段代码都把
get_current_weather的完整 JSON Schema(属性、枚举、必填项)编码进消息流。函数 schema 是函数调用场景下"隐形 token 消耗"的主要来源,schema 写得越冗长,每轮请求的基础 token 开销就越大; - Tekken 的效率直观可见:在仓库 Notebook 的真实输出中,同一请求在
open-mistral-nemo上分词得到 128 个 token,而在mistral-large-latest上得到 135 个 token。NeMo 用更少 token 表达同等内容,正是课程所说"更高效分词"的可量化证据——在长对话与高频调用场景中,这种差距会累积成显著的成本差异。
三款模型如何选:一张决策清单
把原文档三节内容汇总成可落地的选型逻辑:
- 做企业级 RAG、复杂函数调用、多语言/代码生成 → 选 Mistral Large 2:128k 上下文窗口能容纳更多检索证据,数学与代码任务准确率更高;
- 做高频、对成本与延迟敏感的任务(摘要、情感分析、翻译、代码审查)→ 选 Mistral Small:便宜约 80%、响应快、部署门槛低;
- 需要开源合规、可自托管或深度微调 → 选 Mistral NeMo:Apache-2.0、Tekken 分词更省 token、支持原生函数调用与微调。
在课程中继续深入的方向
Mistral 只是课程中众多模型家族之一(可对比第 21 课 Meta 模型专题 21-meta/README.md)。若要进一步消化本课涉及的能力点,建议按主题回到课程对应章节:
- RAG 与向量数据库的完整原理:15-rag-and-vector-databases/README.md;
- 函数调用的业务场景与实现机制:11-integrating-with-function-calling/README.md;
- 小语言模型 SLM 的整体收益分析:19-slm/README.md;
- 何时需要微调、如何微调:18-fine-tuning/README.md;
- 更多模型供应商(OpenAI、Meta、Mistral、Cohere 等)的统一接入方式与选型对比:00-course-setup/03-providers.md。
想直接动手运行,推荐把 20-mistral/python/githubmodels-assignment.ipynb 导入到本地 Jupyter 或 Visual Studio Code Notebook 环境中,配置好推理凭据后从上到下逐格执行——RAG 示例与分词对比两节均已预置了完整输出,可作为你运行结果的对照基准。
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 StartedRust0627
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