Mistral-入门指南-一-

Mistral 入门指南(一)

原文:Learn Mistral

译者:飞龙

协议:CC BY-NC-SA 4.0

Mistral 入门指南

https://github.com/OpenDocCN/freelearn-dl-zh/tree/master/docs/learn-mistral/img/Cover.jpg

https://github.com/OpenDocCN/freelearn-dl-zh/tree/master/docs/learn-mistral/img/Packt_Logo_New.png

我将本书献给我的孩子们 Katerina、Anastasia 和 PJ,他们是我不断的灵感和快乐的源泉。

– Pavlo Cherkashin

贡献者

关于作者

Pavlo Cherkashin 是一位软件工程师兼作家,在软件工艺领域拥有超过二十年的经验。他的一半生活在乌克兰,另一半生活在美国,始终将乌克兰放在心上。他的职业生涯包括在 Oracle 和 Nike 等领先公司工作,他是一项现由 Oracle 拥有的企业软件专利明的共同作者。他对神经网络的痴迷始于大学时期,当时他也对语法解析器产生了持久的兴趣。在职业道路之外,Pavlo 是三个青少年的自豪的父亲。他喜欢探索开源 AI、健壮系统设计、MVP 产品工程,以及对下一代工程师的指导和培训的交叉领域。

我将本书献给我的孩子们 Katerina、Anastasia 和 PJ,他们用活力、好奇心和韧性不断带给我启发。在这里写的每一页都承载着从他们身上学到的一点点反思,以及他们给予我继续探索、构建和分享的动力。这段旅程还伴随着无数杯咖啡,以及我那固执的迷你腊犬 Aki 的坚定陪伴,它无论是通过让我保持清醒还是提醒我休息,都坚持要参与其中。当然,特别要提一下 PJ,他每天提醒我,虽然我可能在教机器如何推理,但他对 TikTok 的了解远比我对 Mistral 的了解得多。

关于评审员

Naresh Dulam 是一位具有远见的技术领袖,在数据分析、云计算和人工智能方面拥有深厚的专业知识。在职业生涯中,他曾在医疗保健、电信和金融服务等领域担任影响力角色,领导了变革性的分析平台,提供可持续且富有影响力的解决方案以满足不断变化的行业需求。作为一名具有前瞻性的创新者,Naresh 将卓越的技术与分享知识、指导有志专业人士以及培养伦理实践的热情相结合。他推动创新和创造意义影响的承诺与其他激励下一代技术人员的愿景相得益彰。工作之余,Naresh 喜欢在大自然中探险并赋予他人发挥全部潜力。

Rustam Mamedov 是一位经验丰富的软件工程主管,在分布式系统、金融科技和云基础设施方面拥有 20 年的经验。他来自乌克兰,在哈尔科夫卡拉津津国立立大学获得计算机科学硕士学位。在AWS,Rustam 在过去的四里里领导团队负责优化S3存储和 Web 服务器容量的状况和利用率,同时直接参与编码、架构和技术评审。在加入AWS之前,他在金融科技行业工作了 12 年,开发消费者和小型微企业贷款产品。Rustam 热衷于指导工程师并构建支持性的、高效的团队。

Astha Puri 是CVS Health的高级数据科学家,她在那里领导数字平台推荐引擎的设计,帮助客户发现合适的产品,并让患者获得他们所需的健康服务和支持。她专精主屏幕个性化,使用数据驱动的洞察来增强用户体验。凭借在科技行业的深厚背景,Astha 现在正利用她的专业知识来推动医疗保健领域的创新和转型。

前言

本书是一本关于使用Mistral模型和检索增强生成 (RAG) 的实用指南,旨在希望弥合理论与应用之间差距的开发者、数据科学家和技术专业人员。它介绍了大型语言模型和嵌入的核心概念,然后通过实战工作坊,涵盖了构建聊天系统、调优模型、设计RAG流水线、代码助手、安全应用以及通过AWS Bedrock和Google Vertex AI进行大规模部署。

本书面向那些通过实践中学习效果最好的构建者、爱好者和好奇心强的人。每一章都将基础理论与模块化工作坊相结合,允许你深入你最感兴趣的话题,同时确保前面的章节为你准备好了必要的设置。这种方法强调低成本的实用技能——使用Python、Google Colab、VS Code以及可以在免费层级运行的云服务。

虽然书中大约三分之二是实操,但早期的理论章节不应跳过。它们建立了LLMs、嵌入和RAG的构建块,使得随后的练习更有意义且更有效。每个工作坊都是自包含的,但常见的设置步骤(如 API 密钥和环境配置)仅介绍一次,并在后续章节中假设已知。对于那些准备好进一步发展的人,书中穿插课外挑战,鼓励在引导练习之外进行实验,并启发读者将项目扩展到新的方向。

简而言之,本书既是工作坊伴侣,也是参考指南。它让你具备了构建智能系统的知识和技能,同时也为创意、探索和创新留下了空间。

本书适用读者

本书的设计对于数据科学专业人士、软件工程师以及希望通过Mistral模型和RAG构建实用技能的 AI/LLM 爱好者来说同样充满趣味。无论你是从事软件工程、数据科学、商业智能还是行业应用,本书都提供了在跨领域现实场景中有效应用 AI 所需的理念和实战项目。

掌握Python以及NumPy和pandas的基础知识会有帮助;然而,内容仍然易于理解,书中提供了详尽的逐步指南来弥补任何知识空白。熟悉数据结构(列表、字典、数组)以及线性代数、概率论和微积分中的核心数学概念会有帮助,但并非严格要求。本书旨在桥接理论与应用,让任何准备好实验和构建的人都能理解高级思想。

本书涵盖的内容

探索了 Mistral 8B 等大语言模型(LLMs)擅长的领域(摘要、翻译、文本生成、上下文理解)以及它们的不足(包括实时决策、泛化能力和偏差)。它还介绍了贯穿本书的基础方法:RAG、语义搜索、文档分类和性能评估,同时预览了智能体工作流以及在AWS Bedrock和Google Vertex A部署。

解释了temperature、top_k、top_p和惩罚因子等参数如何影响语言模型的输出,以及系统提示词如何塑造上下文、语气和行为。它提供了数学基础和实战工作坊,让读者能够精炼生成质量,并针对精度、创造力和控制力调整模型。

介绍了向量如何在多维空间中表示含义,并演示了衡量和可视化语义相似性的方法。提供了使用Mistral和Pinecone的实战工作坊,以构建语义搜索系统、比较嵌入并将其应用于推荐、文档分类和搜索等现实应用中。

解释了AWS Bedrock如何通过提供托管 Mistral 模型、安全的IAM集成、无服务器可扩展性和成本效益来简化 LLM 部署。引导读者通过实战工作坊(涵盖环境搭建、通过boto3进行 API 交互以及使用CloudWatch进行监控)来构建真实世界的 AI 应用。

第 11 章:通过 Google Cloud Vertex AI 挥 Mistralralral]

演示了如何在 Google Cloud 上使用Vertex AI和Model Garden部署并交互 Mistral 模型,涵盖身份验证、同步和流式推理以及与云服务的集成。引导读者通过Colab和VS Code中的实战工作坊,构建模块化的、生产级Python工作流,以便在托管、可扩展的环境中运行 LLM。

  • 机器上安装Python 3.8+开发环境(带pip)。

  • Git和GitHub权限,用于克隆并处理包含所有章节官方仓库。

  • 一个如VS Code的 IDE,用于编写和运行Python脚本。

  • Mistral账户和 API Key,用于访问和实验 Mistral 模型。

  • 用于运行笔记本的Google Colab。

  • 适用的云账户:AWS账户(用于第 10 章))和Google Cloud账户(用于第 11 章)),均已配置 CLI 工具。

准备好这些基础后,你可以遵循示例并专注于核心学习目标,而每章都会提供特定服务的步骤指南。

本书的代码包托管在 GitHub:https://github.com/PacktPublishing/Learn-Mistral。我们在丰富的书籍中还有其他代码包,请访问https://github.com/PacktPublishing。去看看吧!

我们还提供了一个包含书中截图/图表的彩色 PDF 文件。你可以在这里下载:https://packt.link/gbp/9781835888643。

本书使用了多种文本约定。

代码块设置如下:

from mistral import MistralClient
api_key = userdata.get("MISTRAL_API_KEY")
client = MistralClient(api_key)

成功安装的输出示例:

Successfully installed eval-type-backport-0.2.2 jsonpath-python-1.0.6 mistralai-1.5.1 mypy-extensions-1.0.0 typing-inspect-0.9.0

警告或重要注释显示如下所示。

与我们联系

通用反馈:如果您对本书的任何方面有任何疑问,或有任何通用反馈,请发送邮件至customercare@packt.com并在邮件主题中注明书名。

勘更 (Errata):尽管我们已尽全力确保内容的准确性,但错误在所难免。如果您在书中发现了错误,如能向我们报告,我们将不胜感激。请访问www.packt.com/submit-errata,点击Submit Errata并填写表单。

盗版:如果您在互联网上发现任何形式的我们作品的非法副本,如能提供位置地址或网站名称,我们将不胜感激。请通过copyright@packt.com与我们联系并提供材料链接。

您的书籍附带专属福利 - 如何解锁

扫描此二维码或访问packtpub.com/unlock,然后按书名搜索本书。确保其是正确的版本。 | https://github.com/OpenDocCN/freelearn-dl-zh/tree/master/docs/learn-mistral/img/Unlock-01.pnghttps://github.com/OpenDocCN/freelearn-dl-zh/tree/master/docs/learn-mistral/img/Unlock.png |

https://github.com/OpenDocCN/freelearn-dl-zh/tree/master/docs/learn-mistral/img/nextgen.png

使用我们的下一代阅读器 (Next-gen Reader) 增强阅读体验:

https://github.com/OpenDocCN/freelearn-dl-zh/tree/master/docs/learn-mistral/img/cloud-computing.png 多设备进度同步:通过无缝进度同步从任何设备进行学习。

https://github.com/OpenDocCN/freelearn-dl-zh/tree/master/docs/learn-mistral/img/bookmark-white.png 书签:随时回顾您最重要的学习内容。

https://github.com/OpenDocCN/freelearn-dl-zh/tree/master/docs/learn-mistral/img/brightness-and-contrast_(1).png 深色模式:通过切换到深色或褐色模式,以最小眼部疲劳专注于阅读。

https://github.com/OpenDocCN/freelearn-dl-zh/tree/master/docs/learn-mistral/img/sparkler1.png AI 代码解释:在下一代 Packt 阅读器中,点击每个代码块上方的Explain按钮获取 AI 驱动的代码解释。

随时随地学习:

https://github.com/OpenDocCN/freelearn-dl-zh/tree/master/docs/learn-mistral/img/pdf.pnghttps://github.com/OpenDocCN/freelearn-dl-zh/tree/master/docs/learn-mistral/img/epub_(2).png 使用无 DRM 的 PDF 和 ePub 版本离线访问内容——兼容您喜爱的电子阅读器。

您的书籍副本附带以下专属福利:

https://github.com/OpenDocCN/freelearn-dl-zh/tree/master/docs/learn-mistral/img/cloud-computing1.png 下一代 Packt 阅读器

https://github.com/OpenDocCN/freelearn-dl-zh/tree/master/docs/learn-mistral/img/sparkler2.png AI 助手(beta)

如果您尚未解锁,请参考以下指南。该过程仅需几分钟,且只需操作一次。

第一步

准备好本书的购买发票,因为您在第 3 步中需要它。如果您收到的是纸质发票,请用手机扫描,并将其准备为 PDF、JPG 或 PNG 格式。

注意:您是直接从 Packt 购买这本书的吗?您不需要发票。完成第 2 步后,您可以直接跳转到您的专属内容。

第二步

| 在打开的页面上(如果您在桌面电脑上,它将与图 0.1 类似),按书名搜索本书。确保您选择了正确的版本。https://github.com/OpenDocCN/freelearn-dl-zh/tree/master/docs/learn-mistral/img/Packt_unlock_landing_page.png图 0.1:桌面设备上的 Packt 解锁落地页 |

登录您的 Packt 账户或免费创建一个新账户。登录后,上传您的发票。它可以是 PDF、PNG 或 JPG 格式,且大小不得超过 10 MB。按照屏幕上的其余指令完成该过程。

需要帮助吗?

注意:联系

读完 Mistral 后,我们想听听您的想法!请点击此处直接进入本书的 Amazon 评论页。您的评论对我们非常重要,并将帮助我们确保交付质量。

语言模型的优势、局限性和应用场景

AI 系统镜像了我们自身的智能。这是它们日益增长的商业和科学力量的来源。

语言模型不仅仅是 AI 的趋势——它们正在改变我们与技术交互的方式。大语言模型 (LLMs) 可以理解、处理并生成人类文本,开启了新的可能性。当我们在本书中探索 Mistral LLM 时,你会发现它们不仅是工具,更是解决复杂问题、处理海量信息和提供个性化解决方案的伙伴。Mistral 模型正在重新定义 AI 能力,无论是驱动虚拟助手还是分析数据。它们的开源特性和创新(特别是 Mistral 8B)允许您对其进行塑造和定制以满足您的需求。

本章是书中理论性最多的一章,没有实际练习,但请不要跳过。这里涵盖的概念将使您能够做出明智决策,并从后的实战章节中获更多。

  • LLM 适用于哪些场景,哪些场景不太适用

  • 检索增强生成

  • 能够思考和行动的智能体

当我们进入下一章节LLM 的适用场景时,请记住这不仅仅是一项技术练习。它是一次探索未来的邀请,在那里,机器将帮助我们导航、处理甚至理解人类语言的复杂性。通过掌握这些模型的潜力和局限性,你将准备好充分利用它们力量,开启你自己的转型之旅。让我们开始吧。

首先,理解 LLM 在哪些方面真正表现出色,以及在哪些方面仍然面临重大局限性至关重要。本节通过探索 LLM(如Mistral 8B)在摘要、翻译和内容生成等任务中的实际能力奠定基础,同时也承认在传统算法或人工监督可能优于模型的场景。

在深入研究Mistral的具体现实应用之前,理解不同规模的能力至关重要。从高层面上看,LLM 擅长几项核心 NLP 任务:

  • 摘要:LLM 让大量文本的摘要变得快速且高效,无论是对于法律文件、学术论文还是新闻文章。通过识别关键点和重新表述信息,LLM 简化了数据密集型任务。Mistral 8B在抽取式(选择直接文本)和生成式(重述内容)摘要方面均表现出色,节省了时间并减少了人工监督。

  • 翻译:与传统系统不同,LLM 提供更具上下文、更准确的翻译,能够理解成语和文化细微差别。这使得对于客服聊天机器人和在多种语言运营的企业具有无价价值。通过Mistral 8B等模型,翻译感觉更加自然,在满足全球通信的同时不会丢失含义。

  • 规模优势:得益于其规模,Mistral 8B等模型能够以惊人的精度管理复杂的语言模式,在广泛的任务中表现出色。尽管它们需要更大的计算能力,但带来的性能提升通常超过了成本——使它们成为高精度、高速度 NLP 应用的不可或缺。

先进的 LLM 改变了 NLP 任务,实现了自动化和创造力的突破。随着它们的演进,它们将更深入融入我们的日常生活,标志着人机协作新纪元的开启。然而,要完全理解为什么像Mistral 8B这样的先进模型真正强大,我们必须跳出这些高层任务。

在接下来的子章节中,我们将深入研究特定的功能能力——例如上下文理解、任务自适应和个性化——这些能力构成了并丰富了这些高层应用。理解这些细微的能力有助于澄清为什么Mistral 8B这样的 LLM 会脱颖而出,不仅是在执行孤立的任务方面,更是在处理复杂的现实交互方面。

在人类交流中,上下文就是一切。从理解对话中的细微差别到在主题之间无缝切换,我们保留和处理上下文的能力决定了我们沟通的有效性。在 LLM 的世界中,上下文理解是现代模型与其前代模型区分的关键因素之一。对于 AI 系统来说,生成连贯的句子是不够的——它还必须理解对话、任务甚至用户偏好的更广泛上下文才能真正有效。

接下来,我们将探索这种能力的几个维度,详细说明Mistral 8B和类似模型如何将上下文处理扩展到更深层、更动态的场景。

Mistral 8B大模型家族最令人印象深刻的特征之一是它们能够处理长期的、多轮对话而不会丢失对话流。在早期的 AI 系统中,上下文通常在几次交换后就会消失,导致无关的回答。上下文理解在这里是关键。LLM 使用注意力机制和记忆模型来保留重要信息,确保随着对话的演进,保持相关性和连贯性。

例如,Mistral 8B可以在维护上下文的同时跟踪客服中的主题转换,提供基于早先交互的响应。这是通过 transformer 架构及其自注意力机制实现的,它优先考虑对话中的相关部分,即使在主题变化或重叠时也能提供准确的回答。

除了处理长对话外,Mistral 8B和其他类似系统擅长任务自适应——在不丢失上下文的情况下无缝切换之间切换。例如,用户可以要求模型安排会议,然后切换到总结报告。Mistral 8B能够流畅地处理这两个任务,并记住早期交互中的关键细节。

这种适应性源于 LLM 的多任务学习能力。与需要重新训练的旧模型不同,Mistral可以动态适应跨领域的不同任务,例如生成内容、回答问题或翻译文本,同时保持上下文和准确性。这种灵活性使其在各种设置中都非常有效。

可能是 LLM 技术最令人兴奋的发展之一是其提供上下文敏感和个性化体验的能力。用户期望 AI 能迎合他们的偏好和习惯。例如,LLM 可能会在学习平台上跟踪进度,并根据表现和学习风格调整响应。

Mistral 8B通过利用之前的交互来定制响应,在个性化方面出色。在教育或电子商务等领域,这种个性化方法提高了用户参与度。该模型可以根据行为调整课程计划或推荐产品,不断优化建议以更好地匹配个人需求。

尽管Mistral 8B这样的现代 LLM 在上下文理解和任务自适应方面展示了卓越的能力,但仍然面临重大挑战。在扩展对话或多次交互中保持准确的上下文特别困难,因为由于固定的输入上下文窗口,这会导致早期关键信息的丢失。

总的来说,无论是管理多轮对话、适应不同的任务,还是提供个性化的、上下文敏感的响应,像 Mistral 8B 这样强大的架构都展示了在复杂且富内容的环境中运行的卓越能力。然而,与所有先进系统一样,仍然面临尚未解决的挑战,特别是与维护长期上下文以及理解细微的多层次交互相关的挑战。

随着 AI 的不断演进,这些领域无疑将进一步改进,推动大语言模型(LLMs)在自然语言理解方面的边界。

预测准确性的局限性

除了这些上下文挑战,LLMs(包括 Mistral 8B 级别的模型)在预测准确性方面仍存在显著局限性,特别是在需要精度或快速响应的关键场景中。挑战包括:实时决策受阻、训练数据过拟合、难以泛化到不可预见的情况,以及表现出从底层数据集中学到的偏见。接下来我们将讨论这些局限性,因为识别 LLMs 的不足之处有助于强调,随着 AI 系统的进一步演进,持续需要人工监督以及整合补充技术的必要性。

实时决策

实时决策在自动系统、医疗保健和金融交易中至关重要,在这些领域,每一秒都至关重要。然而,由于处理速度和上下文适应方面的固有限制,LLMs 往往难以满足实时应用的需求。这些模型依赖于预训练知识和推理过程,这些过程对于瞬时决策并不总是最优的。

这种局限性的主要原因之一是延迟——LLMs 需要大量的计算能力来生成准确的响应。尽管模型优化减少了延迟,但实时决策需要近乎瞬间的处理,这是 LLMs 并不总是能保证的。例如,自动车辆需要做出实时决策以确保安全。秒级的延迟可能导致对环境变化的误判,从而引发事故。目前的 LLM 架构无法足够快地解释并处理来自摄像头或 LiDAR 系统的视觉数据等实时传感器输入。

此外,LLMs 通常不具备动态更新上下文的能力。这些模型依赖于固定的输入窗口和预定义的数据,使得在新的信息出现时难以持续进行适应调整。在金融市场中,决策基于快速变化的数据,如果依赖 LLMs 进行实时交易或风险管理,一旦模型未能准确且及时地处理最新信息,可能会导致昂贵的错误。

处理不可预见的情况

LLMs 的另一个重大局限性是难以处理不可预见的情况——即其训练数据之外的场景。重量级 LLMs 依赖于海量数据集中的模式,在面对新输入时往往会失败。

在医疗保健等关键领域,罕见症状可能导致错误的诊断。为每个新场景重新训练 LLMs 是不现实的,而且它们缺乏常识推理来处理新颖或演变的问题,使得它们在法律或监管等动态环境中适应性较差。

过拟合与缺乏泛化能力

过拟合发生在 AI 在其训练数据上表现出色,但在处理新的、未见的输入时遇到困难的情况。这是高参数模型的局限性,它们面临过拟合风险,特别是在针对特定任务进行微调时。

例如,在法律领域,在特定案例法上训练的 LLM 可能会错过新案件中的关键细微差别,无法有效泛化。同样,在医学影像中,基于文本的 LLM 可能难以理解图像解释,导致不准确的结果。

偏见与伦理关注

AI 模型中的偏见严重影响预测准确性。在大型数据集上训练的 LLMs 会继承人类的偏见,导致在现实应用中产生不准确或不公平的预测。

例如,在刑事司法中,如果在存在偏差的数据上训练,LLMs 可能会产生有偏见的再犯率预测。在招聘中,LLMs 可能会偏好特定背景,从而加剧不平等。这些偏见在所有领域都带来了严肃的伦理挑战,特别是在医疗和执法领域,需要更多元化的训练数据和更大的监督来减轻伤害。

理解复杂的多模态数据

最后,LLMs 主要在文本数据上训练,这限制了它们对图像、音频或视频等多模态输入的预测准确性。尽管多模态模型正在进步,但像 Mistral 8B 这样的 LLM 难以整合多种数据源。

Mistral 引入了名为 Pixtrail 的独立模型系列,专门处理视觉输入。这些模型与核心语言模型独立开发,代表了 Mistral 在图像处理语境下多模态学习的方法。

例如,在医学诊断中,LLMs 擅长处理文本,但难以处理 MRI 扫描等视觉数据,使得提供全面的预测变得困难。这限制了 LLM 在需要全面多模态理解的领域的应用。尽管 LLM 取得了进展,挑战依然存在,意识到这些局限性可以确保其负责任的使用。

在涵盖这些基础后,让我们转向比较 LLMs 与传统算法。

LLMs 与传统算法

下一代架构扩展了 AI 在自然语言处理和机器学习领域的边界。然而,它们并不总是最佳选择。在许多情况下,传统算法的表现优于 LLMs,提供了更高的效率和可靠性。

本节将探索传统算法的优势所在,包括效率、可解释性、领域特定准确性以及实时一致性。理解这些优势可以确保我们在尖端 AI 与传统方法经过验证的可靠性之间取得平衡:

  • 效率和资源使用:传统算法相比 LLMs 的一个关键优势是效率。LLMs 拥有数十亿个参数,需要巨大的计算能力和内存,使其不适合需要快速、轻量级计算的任务。

相比之下,quicksort(快速排序)或 binary search(二分查找)等传统算法针对速度和最小资源消耗进行了优化,使其成为大型数据集和基础任务的理想选择。与需要专用 GPU 的 LLMs 不同,它们可以在通用硬件上运行。在能源敏感的应用中,传统算法是更实用、更高效的选择。

  • 可解释性与透明性:传统算法出色的另一个领域是可解释性和透明性。它们遵循透明的、循序渐进的过程,使其决策易于理解,这在金融、法律合规和科学研究等领域至关重要。

例如,decision trees(决策树)提供了透明、可审计的推理,而 LLMs 往往像黑箱一样,导致其决策过程难以解释。这种透明度的缺失为需要监管审查的行业带来了挑战。尽管可解释 AI(XAI)正在开发中,但在需要完全透明的任务中,传统算法仍然更优。

  • 领域特定任务的准确性:在领域特定任务方面,传统算法通常比 LLMs 更准确。虽然 LLMs 是通用型模型,但传统算法针对特定领域进行了微调,在专业领域通常表现优于 LLMs。

例如,在图像识别中,convolutional neural networks(CNNs)或专门的算法优于专注于文本的 LLM。在工程或数值分析中,诸如 finite element methods(FEM)等算法提供了 LLM 缺乏的精度。传统算法建立在数十年的领域知识之上,更适用于这些精确的应用场景。

  • 一致性与确定性:传统算法的特点之一是其一致性和确定性本质。在相同的输入下,传统算法总是产生相同的输出,确保了需要预测性的任务的可靠性。相比之下,概率性的 LLM 即使在输入相同的情况下,输出也可能不同。

  • 对实时和嵌入式系统的适用性:传统算法更适用于实时和嵌入式系统,这些系统的处理能力和内存有限。汽车控制、工业机械或电子设备中的嵌入式系统依赖于低延迟运行的快速、高效算法,例如 PID controllers。

相比之下,LLM 是资源密集型的,并不是低功耗实时环境的理想选择。虽然 LLM 擅长翻译等大规模任务,但对于需要低延迟和高效的系统,传统算法仍然保持优势。

尽管 LLM 改变了 AI 的许多方面,但传统算法在特定领域仍然具有显著优势。它们更高效、更透明、更一致,使其更适用于需要高精度、可重复性和低计算开销的任务。了解传统方法在何处优于 LLM,对于开发能够利用这两种方法优势的平衡 AI 系统至关重要。在接下来的章节中,我们将探索混合模型和技术如何结合两者的优势,提供既前沿又可靠的解决方案。

现在我们已经知道了诸如 Mistral 8B 等 LLM 在哪些方面表现良好,它们的局限性在哪里,现在是时候看看这些模型如何转化为现实应用了。Mistral 8B 是一款多功能 AI 模型,应用广泛。从驱动聊天机器人和数据摘要工具到提供个性化用户体验,它在各个领域都表现出色。凭借强大的多语言支持甚至代码辅助,Mistral 8B 重新定义了 AI 在增强效率和用户交互中的角色。

本节深入探讨了 Mistral 8B 在多个领域的实际优势。这些示例看起来可能是理论性的,但它们构成了你贯穿本书构建的应用系统和工作流的基石。理解这些核心能力将帮助你识别在何处将 Mistral 接入你自己的项目,以及何时将其与其他技术结合以产生最大影响。

Mistral 8B 通过快速准确地从海量数据集中识别关键点,擅长数据摘要。它将长文档、报告或研究论文提炼为简洁的摘要,同时保留核心上下文,这对于记者、律师和学者来说是无价的。此外,Mistral 8B 能够从非结构化文本中高效提取数据,提取出财务指标或法律细节等相关信息。它高效处理大规模数据的能力改进了决策并减少了花费在手动分析上的时间。

Mistral 8B 通过分析用户行为和偏好来提供定制化内容和推荐,从而驱动个性化引擎。从个性化的购物建议到流媒体平台上的定制化内容,Mistral 8B 使用高级算法理解用户模式并实时适应。它的灵活性允许企业提供独特的、以用户为中心的体验,提高客户的参与度和忠诚度。Mistral 8B 个性化交互的能力确保了企业能够为每个用户提供高度相关且吸引人的内容。

Mistral 8B 具有强大的多语言能力,支持英语、法语、德语、西班牙语、意大利语、葡萄牙语、阿拉伯语、印地语、俄语、中文、日语和韩语。这种通用性能使企业能够有效地与全球观众互动,在不同地区和语言之间提供无缝通信。

Mistral 8B 是客户服务、电子商务和内容本地化的理想选择,无论语言如何都能确保高质量的用户交互。多语言支持使其成为需要在多种语言中进行一致、准确通信的行业的强大工具,提高了可访问性并扩大了市场范围。

Mistral 8B 是一款强大的编码助手,允许开发者通过生成代码、编写单元测试和自动化脚手架任务来简化其工作流。它的 fill-in-the-middle(FiM)能力允许它从部分输入创建代码段,从而缩短开发时间。它还可以通过理解代码结构来协助编写单元测试,确保覆盖率和准确性。Mistral 8B 自动处理用于脚手架的重复性编码任务,允许开发者专注于更高层次的问题解决,最终提升了生产力。

让我们转换一下,从基础概念转向应用技术,并学习 RAG、语义搜索和模型微调。

在当今快速发展的 AI 领域,将生成式语言模型与实时知识检索相结合,为创建更智能、更具上下文感知能力的系统开启了新的可能性。RAG 代表了这种融合,其中 LLM 利用外部数据库或知识源来生成更准确、信息丰富的响应。RAG 不仅仅依赖于预训练数据,而是能够动态访问最新信息,使其在知识密集型任务中具有极高价值。

RAG 结合了两个关键组件:知识检索和生成式 AI。虽然传统的生成模型从预训练知识中生成响应,但 RAG 引入了检索步骤,模型访问外部数据源以提供更准确、最新的信息。这种交互允许 RAG 产生听起来像人类且基于实时事实的响应。这种混合方法增强了响应的准确性,特别是在对精确、当前信息有要求的领域。

随着我们的进展,探索语义搜索和文档分类如何增强 RAG(检索增强生成)的能力至关重要。这些技术能够对信息进行精确的检索和分类,确保输入到生成模型中的数据是准确且符合上下文的。通过理解语义搜索的复杂之处,我们可以进一步提高 AI 驱动系统的准确性和效率,使其在处理复杂信息检索任务时更加强大。

随着数字信息量的增长,对能够高效检索和组织这些数据的 AI 系统的需求也随之增加。传统的基于关键词的搜索在理解用户意图方面往往存在局限,特别是处理复杂查询时。语义搜索提供了一种更细致的方法,允许模型解释用户查询背后的含义,并交付超越简单关键词匹配的结果。结合文档分类(将内容排序并组织到相关的类别中),这些技术使企业和研究人员能够从海量数据集中提取有价值的见解。本节将深入探讨这些过程的工作原理、关键应用以及在现实环境中部署它们面临的挑战。

语义搜索:理解关键词之外的意图

例如,如果用户搜索“如何治疗感冒”,传统的关键词搜索引擎会寻找包含“治疗”(treat)和“感冒”(cold)单词的文档。然而,由于缺乏直接的关键词匹配,它可能会漏掉使用“流感药物”(remedies for flu)或“感冒居家护理”(home care for colds)等术语的资源。另一方面,语义搜索引擎会理解这些短语含义相似,提供更准确、更有帮助的结果。语义搜索的核心是先进的机器学习模型,例如 Mistral 8B,它们利用嵌入(embeddings)和向量空间表示来理解并匹配查询与文档的含义。Mistral 8B 并不是搜索精确的单词,而是将查询和文档映射到高维向量空间,在该空间中,相似的含义彼此靠近。这允许模型识别含义上的相似性,即使措辞有所不同。例如,当用户查询“提高睡眠质量的最佳方法”时,模型将此输入处理为一个向量——其含义的数值表示(参见图 1.2)。同时,它将许多文档的内容处理为类似的向量。Mistral 8B 通过比较这些向量之间的距离,识别与用户查询最对齐的文档。这一过程通常被称为语义相似性搜索,能够检索不仅符合关键词匹配而且符合上下文的文档。

上下文在查询解释中的作用

语义搜索的一个关键方面是其解释用户查询时维持并应用上下文理解的能力。与将每个查询视为孤立输入的关键词搜索不同,由 Mistral 8B 等驱动的语义搜索引擎会考虑查询的更广泛上下文。这些上下文可能包括之前的交互或类似查询的典型意图。

图 1.2 显示了关键词搜索与语义邻性搜索的区别:

https://github.com/OpenDocCN/freelearn-dl-zh/tree/master/docs/learn-mistral/img/B24489_01_2.png

在处理模糊查询时,上下文理解也至关重要。例如,“苹果的好处”这类查询可能指水果的健康益处,也可能指苹果公司产品的优势。语义搜索引擎使用上下文线索(如用户的搜索历史或其他查询中的内容)来确定哪种解释更有可能,提供更准确且以用户为中心的结果。

示例用例

语义搜索通过关注用户查询背后的意图而非简单的关键词匹配改变了我们检索信息的方式。这种方法能够产生更准确、更相关的结果,使其在电子商务的个性化产品推荐、法律研究的精确判例检索以及企业环境的高效知识管理中具有价值。

https://github.com/OpenDocCN/freelearn-dl-zh/tree/master/docs/learn-mistral/img/B24489_01_3.png

图 1.3:不同业务领域中的语义搜索

  • 电子商务应用:语义搜索已成为电子商务领域的游戏规则改变者,改变了在线商店管理产品搜索和推荐的方式。与传统的基于关键词的系统(它们可能因为精确单词匹配返回无关结果)不同,语义搜索会解释用户查询背后的意图,从而提供更准确、更相关的产品建议。例如,当客户搜索“200 美元以下舒适的办公椅”时,语义搜索引擎会理解对舒适度、价格限制和特定产品类型的需求。它会优先考虑符合这些标准的物品(例如预算内的人体工程学椅),提供个性化的购物体验。这种细致的理解提高了转化率并增强了用户满意度,因为客户更有可能快速找到他们想要的东西。

  • 法律检索系统:在法律领域,由于法律文档数量巨大且极其复杂,寻找特定的判例法或先例可能非常耗时。语义搜索简化了这一过程,让律师和研究人员能够找到相关的案例、法条或法律意见,即使查询语言与文档中的文本不一致。例如,律师可能会搜索“涉及职场骚扰和雇主责任的案例”。语义搜索引擎可以识别出符合这一意图的案例,即使案例文本中没有出现查询中使用的精确短语。它理解法律概念和关系,使其能够快速找到相关的先例,从而节省了数小时的人工研究。这项能力对于那些无需筛选数百文档即可获取精确且相关信息的法律专业人士来说至关重要。

  • 知识管理:在企业环境中,管理和检索内部文档、研究论文或存档通信是一项挑战,尤其是组织每天产生海量数据时。语义搜索在知识管理中起着关键作用,使员工能够根据查询背后的含义找到正确的信息。例如,寻找“营销策略的年度绩效报告”的员工可能会收到包含“营销 KPI”、“年度销售分析”或“战略审查”等相关术语的文档,即使查询中没有这些准确词汇。这种方法确保了员工能够快速获取做出决策所需的知识,从而提高了生产力并促进了团队间更好的协作。

文档分类:用于自动排序和分类的 LLM

LLM(大语言模型)将传统的、耗时且耗工的过程自动化。通过理解文档的上下文和内容,这些模型以高精度对信息进行分类,减少了对人工干预的需求。这种能力使得 LLM 在处理大量非结构化数据的领域非常有价值,从医疗保健到客户支持,在这些领域,快速准确的文档排序对效率至关重要。

Mistral 8B 和类似模型通过解释文本数据的内容和上下文来完成文档分类,允许它们将信息排序到预定义的类别中。这种能力超越了简单的关键词匹配,因为模型理解文档内部更深层次的含义,从而导致更准确的分类。例如,与其依赖预定义规则来识别特定单词,Mistral 8B 可以处理整个文档,识别文本中的主题和意图。这使其能够以极少的人工输入分类复杂内容(如技术报告或客户查询)。通过自动化这一过程,LLM 节省了大量的时间和精力,让专业人员能够专注于更高价值的任务。

Mistral 8B 等 LLM 使用多种技术来提高分类准确性:

  • 零样本分类:该方法允许模型将文档分类到其训练过程中从未见过的类别。通过利用其对语言的广泛理解,Mistral 8B 可以对新文档可能所属分类做出合理的推断,使其在频繁出现新类别的动态环境中非常有用。

  • 监督微调:在这种方法中,Mistral 8B 在带有特定类别的标记的数据集(例如法律文档类型或患者记录)上进行微调。微调允许模型理解数据中的特定细微差别,从而实现高度准确的分类。

  • 多标签分类:某些文档可能同时属于多个类别。Mistral 8B 可以配置为为文档分配多个标签,使其成为复杂数据集的理想选择,因为一个文档可能跨越多个主题,例如同时涵盖研究结果和实施策略的技术报告。

上述技术使 Mistral 8B 能够处理各种分类挑战,灵活满足多种行业的需求。

示例用例

高阶模型(包括 Mistral 8B)在文档分类中的应用涵盖了多个领域:

  • 医疗报告:在医疗保健领域,Mistral 8B 可以根据诊断类型、患者状况或建议治疗对医疗报告进行分类,这有助于医疗专业人员快速获取所需信息,改善患者护理并减少行政工作负载。

  • 法律文档排序:律师事务所可以使用 Mistral 8B 将法律诉述书、合同和案件文件组织到相关类别中,使律师在案件准备期间更容易检索相关文档。

图 1.4 展示了文档分类流水线。它显示了不同类型的文档如何通过 Mistral 8B 进行处理、准确分类并定向到相关的输出类别,突出了这一自动化过程的效率和精确性。

https://github.com/OpenDocCN/freelearn-dl-zh/tree/master/docs/learn-mistral/img/B24489_01_4.png

图 1.4: 分类流水线

至此,我们探索了Mistral 8B如何通过理解内容和上下文来简化文档分类,减少对人工排序的需求。该模型使用零样本分类、监督微调和多标签分类等技术处理多样化且复杂的数据集。现实世界的应用(如分类医疗报告、排序客户支持工单和组织法律文档)说明了它们的通用性。

在清晰了解语言模型如何应用之后,是时候看看它们在现实环境中的表现如何了。我们将密切关注它们的准确性如何、响应速度有多快,以及在将这些模型投入生产时将面临的日常挑战。

评估模型性能

在部署Mistral 8B等 Transformer 大模型执行搜索和分类任务时,评估它们的性能对于理解其有效性至关重要。需要考虑的两个关键方面是准确性和速度。准确性决定了模型输出的可靠性,而速度影响用户体验,特别是在时间敏感的应用中。在这些因素之间取得平衡确保了模型在从电子商务搜索到实时分析的各种用例中表现良好。

模型准确性

为了评估基于 LLM 系统的准确性,我们依赖于几个关键指标,包括精确率、召回率和 F1 分。精确率衡量了模型返回的所有结果中相关结果的比例,突出了检索到的文档中有多少是有帮助的。例如,如果使用Mistral 8B来识别相关的客户支持工单,高精确率可以确保大多数返回的工单确实符合目标类别。

召回率衡量了模型检索数据集中所有相关实例的能力。在错过关键信息可能会导致高昂代价的场景中(例如法律或医疗文档检索),它尤为重要。高召回率意味着模型捕获了最相关的文档,即使其中包含了一些没那么用的文档。

F1 分数将精确率(precision)和召回率(recall)结合为一个单一指标,为模型性能提供了平衡的衡量。它是精确率和召回率的调和平均数,对于这两个指标同样重要的情况是非常理想的。高 F1 分数表明模型能够有效检索相关文档,同时尽可能地减少无关结果,提供了对其准确性的全面视角。

速度考虑

除了准确性之外,速度是评估大语言模型(LLM)性能的关键因素,特别是在依赖于快速响应时间的应用程序中。例如,在电子商务搜索引擎中,用户在浏览产品时期望获得时结果。如果 LLM 检索和处理信息花费过长时间,会导致糟糕的用户体验,并可能导致销售损失。

在处理大型数据库时,速度考虑变得更加关重要,因为处理时间可能会显著增加。模型提供快速、相关响应的能力在高流量环境(如在线购物平台或实时客户支持系统)中可以产生巨大影响。在不牺牲准确性的前提下优化模型速度,可以确保其即使在重数据负载下也能保持响应。

实现过程中的挑战

有效的语义搜索和文档分类面临着若干影响其准确性和相关性的挑战。歧义性、上下文丢失和误报(false positives)等问题需要解决,以确保在实际应用中的稳健性能。理解这些挑战并探索管理它们的策略,对于在顶尖 AI 领域完善Mistral 8B并使其在各种用例中更加有效至关重要。

请参考Figure 1.5获取简短且描述性的视觉辅助:

https://github.com/OpenDocCN/freelearn-dl-zh/tree/master/docs/learn-mistral/img/B24489_01_5.png

图 1.5:歧义、上下文丢失和误报的挑战与示例

https://github.com/OpenDocCN/freelearn-dl-zh/tree/master/docs/learn-mistral/img/1.png 快速提示:需要查看此图像的高分辨率版本吗?请在下一代 Packt Reader 中打开此书,或在 PDF/ePub 版本中查看。

https://github.com/OpenDocCN/freelearn-dl-zh/tree/master/docs/learn-mistral/img/2.png 购买此书将免费赠送下一代 Packt Reader。扫描二维码 码或访问packtpub.com/unlock,然后使用搜索框通过名称找到此书。双击检查显示的版本以确保获取的是正确的版本。

https://github.com/OpenDocCN/freelearn-dl-zh/tree/master/docs/learn-mistral/img/Unlock2.png

让我们详细探索这些主要的每一个挑战。

歧义性

语义搜索中持续持续的挑战之一是处理歧义查询。还记得之前提到的“苹果的好处(apple benefits)”例子吗?与传统的基于关键词的搜索不同(后者中歧义通常会导致无关结果),语义搜索试图通过理解查询的更广泛上下文来解释用户的意图(用户是在询问水果的健康益处,还是苹果公司的产品优势?)。

为了解决这些歧义,Mistral 8B及其同时模型依赖用户历史、查询模式和上下文线索来做出合理的判断。然而,此类模型在上下文有限的情况下仍可能遇到困难,导致混合或部分相关的结果。在此类场景下,引入去歧技术(如后续澄清提示或利用用户上下文数据)可以显著提高语义搜索引擎的精确度。

上下丢失

上下文丢失是另一个重大障碍,特别是对于涉及多轮对话或基于之前交互的查询应用程序而言。例如,在对话中,用户问“管理糖尿病的最佳方法是什么?”,然后接着问“饮食呢?”,语义搜索系统必须识别出第二个查询与糖尿病有关。然而,对于Mistral 8B类 LLM 来说,维护这种上下文可能是挑战性的,特别是当存在多次交互或会话很长时。语言模型中的上下文窗口是有局限性的。随着轮数的增加,LLM 可能会忘记对话的早期部分或丢失相关性,这可能会影响搜索准确性。诸如持久内存机制和基于嵌入的上下文跟踪策略有助于保持理解的连续性,确保模型在整个对话过程中关注用户的意图。

误报

文档分类和语义搜索中的一个常见问题是出现误报,即模型由于过度泛化返回了无关结果。这发生在模型误解了查询并检索了虽然用词相似但与用户需求无关的文档时。例如,关于“美洲栖息地(jaguar habitats)”的查询,如果模型从“jaguar”一词过度泛化,可能会错误地检索关于捷豹汽车的文档。

为了管理此类误报,使用了精炼技术,如重排序(re-ranking,根据相关性对检索到的文档进行排序)和置信度评分(confidence scoring)。通过为每个结果分配置信水平,模型可以优先考虑更相关的响应,同时降低低概率匹配的权重。

在搜索、检索和语言理解基础稳固的基础上,我们现在转向代表我们行动的动态决策系统:自主代理(autonomous agents)。

展望:思考并行动的代理

语言模型不仅限于理解和生成文本。它们还可以被结构化为做出决策、使用工具并执行任务。本书的第 5 章介绍了此类系统——代理(agents)。这些代理结合了推理、记忆和工具使用,逐步实现目标,而不是简单地响应单个提示。

代理从一个目标开始,通过分析输入、选择下一个最佳行动、执行该行动然后观察结果来工作。它重复这个循环直到任务完成。这种迭代的、感知上下文的过程将被动模型转变为自主的问题解决者。

代理设计的核心是决策循环:规划、行动、观察和反思的序列。在每一次循环中,代理都会选择继续、调整还是结束。与遵循固定指令的传统自动化脚本不同,代理运行具有灵活性。它们可以响应新信息,根据需要切换工具,并实时确定最佳策略。

这使得它们适用于广泛的应用程序——从多步问答到协调涉及搜索、摘要和外部 API 调的工作流。无论是管理对话、检索相关文档还是从多个源汇总输出,代理的功能都像一个引导的导航员,在每个阶段决定该做什么。

第 5 章通过实用的代码示例介绍了这一概念。你将探索如何定义代理可用工具、如何通过结构化提示塑造其推理,以及如何管理驱动其行为的逻辑。这种方法轻量且注重实践,不需要大型框架——只需要一个清晰的循环、一个模型和一个使命。

代理代表了语言模型使用方式的转变。它们不再仅仅提供答案,而是朝着结果努力。在本书更广泛的背景下,它们充当自然语言理解与现实行动之间的桥梁,使其成为生成式 AI 最具表现力的方式之一

https://github.com/OpenDocCN/freelearn-dl-zh/tree/master/docs/learn-mistral/img/B24489_01_6.png

图 1.6:基本代理工作流概述

此图展示了 AI 智能体(Agent)如何将静态语言模型转换为主动的决策系统。智能体首先接收用户请求,然后进入规划循环,在循环中它对任务进行推理、选择工具并逐步采取行动。它将每个操作的结果视为新的观测结果,据此调整策略,并在整个过程中保持上下文感知。这种架构使得模型不仅能够作为一个文本生成器,更是一个智能流程管理器——能够进行动态推理、工具编排和迭代解决问题。

当你读到第 5 章时,你已经熟悉了嵌入(embeddings)和语义搜索等工具。智能体通过有目的的工作流将这些工具整合在一起,向你展示如何超越提示词(prompts)的局限——并开始设计能够思考、适应和行动的系统。

云端上的 Mistral:同一种理念,迥然不同的面貌

随着Mistral Small和Mistral Nemo等模型进入现实应用,许多用户在想他们是否需要搭建服务器来使用它们。答案是否定的。AWS Bedrock和Google Vertex AI现在都提供Mistral模型作为其托管服务的一部分,这比以往任何时候都要将这些强大的工具接入到你的产品或工作流中——而无需触碰 GPU。

虽然云平台在外观和工具链上有所不同,但核心概念是相同的:你发送一个提示词,云端运行模型,你获得结果——这一切都在几毫秒内完成。无论你是在构建机器人、摘要器还是搜索助手,云端都会处理扩展、安全和速度问题,让你专注于真正的事情。

这种方法让开发者和企业能够更快地进行实验、更早地发布原型并根据需要进行扩展,同时依赖底层基础设施的稳健性。

https://github.com/OpenDocCN/freelearn-dl-zh/tree/master/docs/learn-mistral/img/B24489_01_7.png

图 1.7:通过 AWS 或 Google Cloud 部署 Mistral,向用户返回响应

该图显示了两个并行的流水线:一个用于AWS Bedrock,另一个用于Google Vertex AI。两者都从左侧的用户输入开始,通过中间各自的云服务流,并汇聚到Mistral模型。箭头继续返回给用户以交付结果。视觉图标包括云平台、表示处理的齿轮符号以及返回路径上的聊天机器人图标。

我们现在正接近LLMs纯理论探索的终声。从理解它们的优势到探索用例和部署路径,本章奠定了坚实的基础。在下一章中,我们将转向实战模式——亲自动手搭建一个你自己的 AI 聊天机器人。

总结

在本章中,我们为使用LLMs奠定了基础。我们现在了解了这些模型在什么地方表现最好,它们的局限性在哪里。我们探索了它们在摘要、分类、推理以及医疗和法律等特定领域应用中的优势。我们还涵盖了它们在预测准确性和实时响应方面的差距,特别是在多模态设置下。

我们引入了关键概念,例如RAG作为一种通过外部知识丰富模型输出的方法;语义搜索和分类对大规模信息处理至关重要;以及微调(fine-tuning)策略,使LLMs能够通过交互和针对性训练随时间不断适应。有了这些核心思想,我们准备好切换节奏了。从第 2 章开始,你将深入实操练习,从如何设置你自己的 AI 聊天系统开始。准备好构建、调整和探索。

参考文献

加入我们的 Discord 和 Reddit 空间

你不是唯一一个在碎片化工具、持续更新和不不最佳实践中摸索的人。加入一个不断增长的专业人士社区,交流见解。

| 获取最新更新、讨论以及来自作者的幕后见解。加入我们的 Discord:packt.link/z8ivB 或扫描下方二维码:Images/Discord_Code.jpg | 与同行交流,分享想法并讨论现实中的 AI 挑战。在 Reddit 上关注我们:packt.link/0rL 或扫描下方二维码:Images/Reddit_Code.png |

2 搭建你自己的聊天机器人

最深远的技术是那些消失的技术。它们织入生活的织物中,直到与生活不可分。

— Mark Weiser,通用计算之父

想象一下,无需编程就能启动一个安全、定制且完全由你控制的私有聊天系统。在数据泄露、合规性和 AI 幻觉成为日常担忧的世界里,构建一个符合你需求的信赖界面是必要的。

本章将引导你创建一个由Mistral驱动并封装在友好网络界面中的独立聊天模型。你将学习如何配置它、管理其行为,并安全地运行在你的环境中。将其想象为将ChatGPT置于防火墙之后:没有互联网依赖,没有数据泄露,且控制权不受限。这个工具不仅仅是为了技术爱好者设计的——它还为了需要构建安全平台的教育工作者、需要 HIPAA 合规助手的医院、保护商业秘密的企业,甚至是为了微调 AI 以理解其特定领域的小众社区。

在我们卷起袖开始构建之前,让我们探索为什么私有的、定制的聊天模型很重要,以及它们如何解决行业、教育和社区的现实问题。本章采取的方法如下:

  • 问题

  • 实战工作坊:将本地Mistral模型暴露给用户的步骤

  • 建议硬件配置

问题陈述

对安全、受控和个性化聊天系统的需求前所未有。当涉及到隐私、监管或专业性时,通用的在线 AI 模型并不总是适用。以下是独立生成聊天模型大放异彩的地方:

  • 企业环境:需要保护数据的私有内网聊天。

  • 医疗和军事部门:需要对数据处理和合规进行严格控制。

  • 学校、图书馆和家长:需要过滤器以确保未成年人的对话安全。

  • 需要对聊天逻辑、内存和审核策略拥有完全控制权,这对于治理至关重要的场景

  • 对于需要简单的 Web UI 以直观方式与模型交互的非技术用户来说

我们的方法直接应对了这些挑战。在本章中,你将构建并部署一个具有完全控制权、安全性且易于使用的聊天模型。

现在是时候从概念转向执行了。在接下来的实战工作中,你将学习如何使用Mistral、自定义的Modelfile和即插即用的 Web 界面来构建一个安全的、自包含的聊天系统。我们将一步一步让你的定制化解决方案变为现实。

为了完成本章的练习,你需要在机器上准备一些工具和资源。建议使用具有至少 16 GB 内存、20 GB 空闲磁盘空间以及合适的 GPU(对于 Mistral Small 需要至少 8 GB 显存)的 macOS、Windows 或 Linux 电脑。

你还需要安装Ollama (ollama.com) 和Docker (www.docker.com),我们将在环境设置阶段一起完成安装。如果你还没有安装Obsidian (obsidian.md),请也安装它,因为我们将用它来组织和管理项目笔记。你将使用系统内置的终端或命令提示符,因此请确保其可以运行命令。

实战工作坊:向用户开放本地 Mistral 模型的逐步指南

你已经看到了这一愿景——私有的、智能的、安全的完全由你控制的通信。现在,是时候将其变成了。这个工作坊就是你的启动平台。我们将从基础开始开始:设置Ollama,这是我们基于 Mistral 模型的引擎。你将学习如何安装它、运行mistral-nemo等模型,并理解Modelfiles如何让你对行为拥有完全控制权。

接下来,我们将你的 AI 模型连接到强大的前端。首先是Obsidian,这是一个基于 Markdown 的知识管理工具。你将看到如何让模型在你的个人知识库中直接协助你。然后我们将引入一个简单的WebUI,非常适合团队访问或普通用户。无需代码,不复杂——只需点击、提问并交互。

在本工作坊结束,你将拥有一个根据你的需求定制的、运行良好的聊天系统。但我们并不止于此。

在完成主要构建后,我们将探索针对不同使用级别的建议硬件配置,从在笔记本电脑上运行到部署在专用服务器或云机器。对于那些想更进一步的人,我们在章节末尾包含了一些额外主题来挑战你的创造力。

第 1 步:安装并运行 Ollama

为了启动我们的实现,我们将首先安装Ollama,这是一个用于本地运行语言模型的轻量级且强大的引擎。这将成为你个性化 AI 聊天系统的骨干。可以将Ollama比作Docker:就像Docker拉取容器镜像并在隔离环境中运行它们,Ollama拉取 AI 模型“镜像”并将其启动为功能完整的本地语言模型。这种类似容器的行为使其极易管理、更新和更换模型——无需担心手动设置或依赖项。

按照步骤操作,你只需几分钟即可完成所有设置。让我们开始吧:

https://github.com/OpenDocCN/freelearn-dl-zh/tree/master/docs/learn-mistral/img/B24489_02_01.png

图 2.1:Ollama 首页

  1. 请点击Download,你将被重定向到下载页面,可以在那里选择适用于你平台的发行版本,无论是 Mac、Linux 还是 Windows:

    https://github.com/OpenDocCN/freelearn-dl-zh/tree/master/docs/learn-mistral/img/B24489_02_02.png

下载并安装 Ollama

下载完成后,请解压并运行它;它将启动安装程序:

https://github.com/OpenDocCN/freelearn-dl-zh/tree/master/docs/learn-mistral/img/B24489_02_03.png

图 2.3:Ollama 安装程序

安装程序可能会触发系统要求你输入密码以继续。如果你想继续安装 Ollama,请执行。

关于 Ollama 启动问题的简要说明。如果 Ollama 无法启动,请验证你的操作系统权限,并确保防火墙设置允许端口 11434 上的本地连接。

成功安装了 Ollama!这是你运行自己的本地 AI 的重要一步。

引擎就绪后,现在是时候通过拉取实际语言模型赋予它生命了。我们将下载几个基于 Mistral 的模型,包括mistral、mistral-nemo和mistral-small,以便你开始真实的本地实验。

拉取轻量级模型

我们将从获取一个轻量级 Mistral 变体开始以启动:

  1. 要下载mistral-small模型(专为本地使用设计的紧凑版本),打开你的终端或命令提示符并运行以下命令:
ollama pull mistral-small

下载大小

拉取mistral-small将下载 14 GB。确保网络连接稳定、至少有 20 GB 空闲磁盘空间以及足够的系统资源以进行流畅推理。

你可以跳过此步骤,直接运行ollama run mistral-small。如果模型尚未安装,Ollama 将自动下载它。

  1. 完成后,确认该模型已在本地可用:
ollama list

你应该能看到类似下面的内容:

NAME                    ID              SIZE      MODIFIED      
mistral-nemo:latest     994f3b8b7801    7.1 GB    9 minutes ago    

此时,你已经在本地运行了mistral-small,这足够你开始尝试提示词和简单任务了。然而,取决于你的硬件配置和用例的复杂性,你可能想要探索额外的 Mistral 变体,以平衡运行速度、内存占用和推理能力。

探索其他 Mistral 变体

Ollama 支持额外的 Mistral 变体。你可以尝试以下命令:

ollama pull mistral-nemo

你也可以尝试这个:

ollama pull mistral
  • mistral指的是标准的 7B 参数模型

  • mistral-nemo是一个更强大的 12B 参数版本

你可以在ollama.com/library浏览完整的 Ollama 模型库,你可以在搜索栏中输入mistral进行搜索。

系统提示词的调优建议

现在我们已经了解了调优系统提示词的优缺点,你可以考虑以下建议,让它们按需发挥作用:

  • 结合方法:将系统提示词与其他过滤和审核工具结合使用,以实现更稳健的治理

  • 定期测试:持续测试并调整系统提示词,以确保它们能有效引导模型行为

  • 监控:实施监控系统,以检测并解决任何违反系统提示词指南的情况

  • 清晰的提示词:确保系统提示词清晰且具体,以最大限度地减少歧义并增强合规性

总而言之,系统提示词注入是影响 AI 模型行为的有用工具,但不应仅依赖它来进行严格的治理或审查。将其与其他安全措施相结合并持续监控其有效性,有助于实现对模型响应更可靠的控制。

自定义模型基础

在了解了系统提示词、参数和行为调优的背景后,是时候将它们转化为实用格式了。Ollama 使用一种名为Modelfile的简单文本配置文件来定义自定义模型的行为方式。该文件指定了基础模型、注入的系统提示词以及temperature和num_ctx等参数。让我们从一个基础模板开始自定义,你可以使用或调整该模板来塑造你自己的个性化 AI 助手。

撰写 Modelfile

在你的自定义模型投入使用之前,你需要定义它应该如何行为和响应。这是通过使用Modelfile实现的——这是一个简单的配置格式,告诉 Ollama 使用哪种基础模型、如何格式化提示词以及采用何种语气或风格。

以下是一个Modelfile示例,它自定义了mistral-nemo模型,使其像一个频繁使用表情的助手:

TEMPLATE """{{- if .System }}
<|system|>
{{ .System }}
</s>
{{- end }}
<|user|>
{{ .Prompt }}
<|assistant|>
"""
PARAMETER stop "<|system|>"
PARAMETER stop "<|user|>"
PARAMETER stop "<|assistant|>"
PARAMETER stop "</s>"
PARAMETER temperature 0.2
SYSTEM """ Please impersonate user who uses lot of emojis, acting as assistant."""

此示例Modelfile包含以下内容:

  • TEMPLATE:定义系统和用户提示词如何格式化并注入到模型中

  • PARAMETER stop:指定信号响应结束的停止标记(stop tokens)

  • PARAMETER temperature:设置温度以控制响应的创意

  • PARAMETER num_ctx:设置对话期间保留的上下文 token 数量

  • SYSTEM:为模型的行为提供特定指令

关于Modelfile参数的更详细文档可以在此处找到:github.com/ollama/ollama/blob/main/docs/modelfile.md

一旦配置准备就绪,下一步就是通过生成清单(manifest)将此文件转换为可用的自定义模型。让我们来看看是如何操作的。

创建新模型清单

在Modelfile中定义了模型的行为后,下一步将其封装成 Ollama 可以识别的可运行模型。这是通过生成清单实现的,它将你的基础模型和配置链接到一个新的自定义模型:

要根据你的Modelfile创建一个名为emoji的新模型,请打开终端并运行以下:

ollama create emoji --file ./mistral-nemo/emoji.modelfile

该命令告诉 Ollama 采用emoji-nemo.modelfile中的指令,将其应用到mistral-nemo基础模型上,并生成一个新的模型层。

在本章的代码示例中,我们使用了自定义的emoji.modelfile,它以 Mistral Nemo 为基准。

Chapter_2文件夹包含了该文件的几个变体,允许你尝试不同的基础模型,例如 Mistral-7B 和 Mistral Small。你可以根据你的硬件能力或所需的性能对它们进行切换。

输出应该类似于此所示:

gathering model components
using existing layer sha256:b559938ab7a0392fc9ea9675b82280f2a15669ec 3e0e0fc491c9cb0a7681cf94
using existing layer sha256:43070e2d4e532684de521b885f385d0841030efa2 b1a20bafb76133a5e1379c1
creating new layer sha256:0a22b57a41da9251cddedf87b07c5cc0a403523974e 83c1bbaaa591e390f0f93
using existing layer sha256:75962282d098191b4aecc0f890bb704db5259d4 70aa79e822466a07a1dea
writing manifest
success

要验证模型并确认你的模型可以使用,请列出所有模型:

ollama list

你应该看到类似的内容:

NAME                    ID              SIZE      MODIFIED
emoji:latest            e14f4255d51d    7.1 GB    About a minute ago 
mistral-nemo:latest     994f3b8b7801    7.1 GB    3 hours ago        
mistral-small:latest    8039dd90c113    14 GB     3 hours ago

取决于你下载的模型以及对自定义模型的命名,你看到的列表可能会有所不同。

创建好自定义 emoji 模型后,是时候运行它并看看你的指令如何影响输出了。让我们在下一步中启动它。

与模型交互

在创建emoji模型后,你已好运行它并查看你的指令如何影响输出。这一步展示了如何启动你的模型:

ollama run emoji

一旦模型运行时,你将看到:

>>> Send a message

你现在可以输入任何消息来测试你的配置——这里有一个例子:

>>> hey

你应该收到一个充满表情的友好回复,如下:

Hey there! How can I assist you today?

此命令将提示词(prompt)发送到您的自定义表情模型并返回单个完整的响应。

有关支持的端点、负载格式和流式选项的完整列表,请参考此处官方文档:github.com/ollama/ollama/blob/main/docs/api.md

与 Obsidian 集成

自从我们开始讨论 Ollama API 和 Mistral Small 模型的自定义以来,在接下来的章节中,我们将查看市场上已经在使用此 API 的工具之一。我们将展示如何通过社区插件配置 Obsidian 笔记应用,并将 Mistral 模型集集到您的日常头脑风暴和笔记记记工作流中。

Obsidian 是一款强大的基于 Markdown 的笔记应用,适用于 Windows、macOS、Linux 甚至移动平台,让您能够随时随地记录由 AI 增强的笔记。

第 4 步:与 Obsidian 集成

将您自定义的Ollama模型与强大的笔记工具Obsidian集成,通过允许在笔记中直接进行无缝的 AI 交互,可以增强您的工作流。我们将使用BMO Chatbot社区插件来实现这种集成。让我们开始吧!

在计算机上启动Obsidian。如果您尚未安装,可以从obsidian.md/轻松下载。

下载完成后,按照以下步骤进行安装:

  1. 打开Settings(左下角的齿轮图标)。开启Community plugins(社区插件),如果弹出提示,请批准安全通知。

https://github.com/OpenDocCN/freelearn-dl-zh/tree/master/docs/learn-mistral/img/B24489_02_05.png

图 2.5:安装 BMO Chatbot 插件

  1. 插件安装完成后,返回Installed plugins(已安装插件)标签页。找到BMO Chatbot并将其开启以激活它。

在插件启用并显示在您的插件列表中,下一步是配置其设置,以便它知道如何与运行在Ollama中的本地模型通信。但在插件与您的本地模型交互之前,它需要知道Ollama运行在哪里。默认情况下,Ollama会在您的机器上启动本地服务器,BMO Chatbot必须使用正确的 API URL 指向该服务器。简单的配置步骤建立了Obsidian与您的本地托管模型之间的连接。

按照以下步骤将插件连接到Ollama:

  1. 在Obsidian中,进入Settings(设置),并在Plugin options(插件选项)部分找到BMO Chatbot。

  2. 在提供的字段中输入 Ollama API URL(http://localhost:11434):

https://github.com/OpenDocCN/freelearn-dl-zh/tree/master/docs/learn-mistral/img/B24489_02_06.png

图 2.6:输入本地 Ollama API URL

一旦设置了 API URL,插件应该立即识别来自Ollama的任何可用模型,包括您的自定义表情模型或您创建的任何其他版本。

如果您倾向于使用 Mistral API 而不是本地Ollama实例,BMO Chatbot也支持此项。如果您想从云端运行聊天机器人或连接到托管模型而不依赖本地资源,那么这个选项非常棒。

要使用 Mistral API,您需要提供一个与付费 Mistral 订阅关联的 API 密钥。目前的定价对于爱好或轻度专业用途来说非常合理,且设置非常简单。

虽然我们将在 第 4 章 中介绍整个注册和密钥生成过程,但这里快速查看在插件设置中输入密钥的位置:

  1. 展开Mistral AI Provider部分。在BMO Chatbot插件设置中,滚动到LLM providers部分。找到并展开Mistral AI选项。

  2. 将您的 Mistral API 密钥粘贴到提供的输入字段中。要获取密钥,请访问mistral.ai并使用付费账户登录。

https://github.com/OpenDocCN/freelearn-dl-zh/tree/master/docs/learn-mistral/img/B24489_02_07.png

图 2.7:输入 Mistral API 密钥

一旦 API 密钥到位,插件即可连接到 Mistral 的云托管模型。

一旦安装并启用 BMO chatbot 插件,是时候定义模型在交互期间的行为运行了。我们需要配置通用设置,例如系统提示词(system prompts)、温度(temperature)以及Ollama中可用的模型选择。这些设置控制您的对话的语气、深度和记忆,让您根据自己的喜好自定义体验——无论您是追求简洁、事实性的回答,还是更有创意和对话性的内容。

使用Obsidian内部的插件设置面板定义以下参数:

  1. Model(模型):在设置页面顶部,您将找到一个下拉菜单来选择模型。如果列表为空,这意味着插件尚未连接到您的Ollama实例——这将在我们在下一步中配置 API URL 后解决。

https://github.com/OpenDocCN/freelearn-dl-zh/tree/master/docs/learn-mistral/img/B24489_02_08.png

提示:在本演示中,一旦可用,请从下拉菜单中选择mistral-nemo:latest。请参考图 2.9:

https://github.com/OpenDocCN/freelearn-dl-zh/tree/master/docs/learn-mistral/img/B24489_02_09.png

图 2.9:已选择模型

  1. Prompt(提示词):这允许您选择一个预定义的提示词。在BMO Chatbot插件设置中,滚动到Prompt部分。找到并点击System Prompt(系统提示词)。这将允许定义 AI 的角色。

  2. Max Tokens(最大 Token):定义模型应该记住多少之前的对话内容。例如:Context Length: 4096

https://github.com/OpenDocCN/freelearn-dl-zh/tree/master/docs/learn-mistral/img/B24489_02_10.png

图 2.10:设置温度、系统提示词和上下文长度

在笔记中使用 Mistral 模型

一旦 BMO chatbot 插件安装并启用,就是时候在Obsidian内部直接与模型交互了。该插件提供了多种访问模型的方法,但最直接的方法是使用内置聊天面板。

这种集成允许您在不离开笔记工作流的情况下,使用您的自定义模型(无论是通过 Ollama 本地运行还是通过 Mistral API)。让我们演示如何打开聊天并发送您的第一个提示词。

  1. 在Obsidian的左侧边栏上,寻找一个像机器人头部的图标。点击此图标打开 BMO Chatbot 面:

https://github.com/OpenDocCN/freelearn-dl-zh/tree/master/docs/learn-mistral/img/B24489_02_11.png

图 2.11:通过机器人头部启动聊天面板

当聊天面板在右侧打开时,您已准备好与模型开始交互。

  1. 将您的提示词输入输入框中。按 Enter 看着响应像实时聊天会一样逐个字母地回传回来:

https://github.com/OpenDocCN/freelearn-dl-zh/tree/master/docs/learn-mistral/img/B24489_02_12.png

图 2.12:Obsidian 内部来自本地模型的流式响应

将 BMO Chatbot 集成到 Obsidian 中,允许你可以在思考的地方无缝访问自定义的 AI 模型。无论你是在进行头脑风暴、写日记还是管理项目,这种设置都能将对话式 AI 引入你的创意流中——并由你控制的模型和提示词提供支持。你可以自由尝试不同的系统提示词并调整参数,以塑造你助手的语气和个性。

我们已经介绍了了 Obsidian 如何提升个人工作效率。现在,是时候为团队和非技术用户打开通过简单的浏览器进行对话的大门了。接下来,我们将通过 Web UI 访问你的 Mistral 驱动的聊天,进一步提高标准,将你的本地模型转换为功能完整的交互式 Web 应用。准备好看到它的运行了吗?让我们开始!

部署 Web UI

是时候迈下一步了——为你的自定义聊天模型部署一个功能全 Web UI。此界面将允许用户通过浏览器与你的模型进行交互,提供熟悉且用户友好的聊天体验。

在本节中,我们将在Docker容器内运行WebUI,并配置其通过Ollama API 连接到你的本地Ollama实例。聊天界面的请求将由Ollama处理,然后它会将请求委托给你之前注册的Mistral模型。让我们把一切连接并运行起来。

Docker 拉取并试运行 web UI

在开始之前,请确保你的机器上安装了Docker。如果没有,你可以从www.docker.com/products/docker-desktop下载并安装Docker Desktop:

  1. 在终端中使用以下命令拉取并运行Open WebUI镜像:
docker run -d -p 3000:8080 --add-host=host.docker.internal:host-gateway -v open-webui:/app/backend/data --name open-webui --restart always ghcr.io/open-webui/open-webui:main
sudo docker run -d -p 3000:8080 --add-host=host.docker.internal:host-gateway -v open-webui:/app/backend/data --name open-webui --restart always ghcr.io/open-webui/open-webui:main

以下是命令中每个部分的作用:

  • sudo docker run:启动一个新的 Docker 容器。

  • -d:在分离模式下(后台)运行容器。

  • --add-host=host.docker.internal:host-gateway:为容器添加主机条目,允许其访问运行在宿主机上的服务。

  • -v open-webui:/app/backend/data:挂载名为open-webui的Docker卷,以持久化容器内/app/backend/data中的数据。

  • --name open-webui:将容器命名为open-webui。

  • --restart always:确保容器在停止或Docker守护进程重启时自动重启。

  • ghcr.io/open-webui/open-webui:main:指定要使用的Docker镜像。

执行命令后,Docker将拉取镜像(如果本地尚不存在)并创建一个名为open-webui的容器。你可以使用Docker Desktop或命令行确认这一点。你应该能看到列出的镜像:

https://github.com/OpenDocCN/freelearn-dl-zh/tree/master/docs/learn-mistral/img/B24489_02_13.png

图 2.13:Docker Desktop 中显示的 Open WebUI 镜像

同样,相应的容器应该正在运行并监听localhost:3000端口:

图 2.14:正在监听端口 3000 的运行容器

容器能够与运行Ollama的宿主机系统进行通信至关重要。如果你在单独的机器或虚拟机上运行Ollama,你将需要配置 web UI 指向该外部 IP 地址而不是localhost。

Open WebUI容器现在正在运行并连接到你的Ollama实例,这意味着是时候在浏览器中启动Open WebUI,注册管理员用户,配置它与Ollama API 通信,并观察其他设置了。这一步验证了前端已正确加载并准备好配置。

  1. 打开你首选的网络浏览器并导航到:localhost:3000。如果一切设置正确,你将看到Open WebUI欢迎页面。此屏幕确认了界面已激活并等待初始用户注册。

https://github.com/OpenDocCN/freelearn-dl-zh/tree/master/docs/learn-mistral/img/B24489_02_15.png

图 2.15:浏览器中的 Open WebUI 欢迎界面

你现在准备好注册你的第一个管理员用户了,这将让你获得系统功能和连接设置的完全权限。让我们继续。

https://github.com/OpenDocCN/freelearn-dl-zh/tree/master/docs/learn-mistral/img/B24489_02_16.png

图 2.16:Open WebUI 用户注册表

你的登录凭据安全地存储在Docker卷中,不会发送到外部。这保持了你的设置的私密性和完全自包含性。

  1. 完成注册并登录后,你将被重定向到主聊天界面:

https://github.com/OpenDocCN/freelearn-dl-zh/tree/master/docs/learn-mistral/img/B24489_02_17.png

图 2.17:登录后的默认聊天界面

此时,系统已准备好接受提示词——但在此之前,我们仍然需要将 UI 指向你的本地Ollama模型。你需要配置Ollama API URL,以便 web UI 能与你本地运行的模型通信。这一步对于启用完整的聊天功能至关重要。

https://github.com/OpenDocCN/freelearn-dl-zh/tree/master/docs/learn-mistral/img/B24489_02_18.png

图 2.18:从用户面板访问的菜单

  1. 从菜单中选择Settings。这将打开完整的配置面板。导航到Connections标签页,然后展开Ollama Base URL部分。在这里,你将输入运行Ollama实例的 URL。

https://github.com/OpenDocCN/freelearn-dl-zh/tree/master/docs/learn-mistral/img/B24489_02_19.png

图 2.19:配置 Ollama Base URL

关于 macOS 的说明

在 macOS 上,Docker容器无法直接访问localhost。相反,请使用host.docker.internal:11434。此地址允许请求路由到宿主机系统。此外,确保使用sudo启动Docker容器以允许适当的网络访问。

  • General:此标签允许你管理 UI 主题、语言、通知和全局系统提示词。如果你更喜欢深色主题以获得视觉舒适,可以在这里开启。

  • Models:在这里,你可以从WebUI覆盖并管理由Ollama提供的模型。请注意模型可能很大,从 2 GB 到 5 GB 或更高,因此请确保你的Docker卷足够大。

  • Interface:此标签包含聊天界面的设置,例如默认建议聊天启动项、标题自动生成和默认模型选择。

  • Audio:管理语音转文本和文本转语音引擎,并为音频交互选择你喜欢的语音。

  • Chats:此标签允许批量导出和导入聊天数据,这对于备份或迁移用户聊天数据非常有用。

  • Account:在此处管理你的头像、显示名称和密码更改。此外,你还可以生成 API 密钥以便进一步的集成和自定义。

聊天功能已就绪!

现在进入本次练习中最精彩的部分。让我们试运行并演示一下在使用 Mistral 语言模型作为大脑时,Open WebUI 慷慨为提供的一些功能:

  1. 输入一条消息,如Who is Taylor Swift?。系统将生成响应。在生成过程中,它将逐字母、逐字字地进行流式输出。

  2. 点击聊天窗口中的麦克风图标。说出你的查询,系统会将你的语音转换为文本并做出响应。请注意,浏览器第一次可能会请求你允许访问麦克风。

  3. 点击上传图标并从电脑中选择一个文本文件。通过输入Please summarize this document让系统对其进行摘要。Mistral 将为你总结该文档。

呼!这难道不酷吗?Open WebUI 的运作就像成熟的生成式 AI 产品,但它是免费的,且完全运行在你的硬件上。但大力量需要大责任。让我们学习如何在 Open WebUI 生态系统中管理用户。

管理用户

除了与你的模型聊天,Open WebUI 还包含许多管理员级功能,用于管理用户访问、权限和模型可见性。如果你是为团队、教室或受控用户组运行界面,这些工具将特别有用。

默认情况下,系统允许自注册,这意味着任何人都可以注册为用户。然而,你可以配置如何处理这些新用户:

  • 用户可以被自动分配“用户”角色

  • 否则,他们将进入待审核状态,直到管理员手动批准

相关的控制选项在Admin Settings(管理员设置)中,如下:

图 2.20:管理用户角色和审批的管理员设置

作为管理员,你还可以对模型设置白名单,决定哪些模型对普通用户可见或可访问。这种方法与之前在Step 1: Install and run Ollama章节中介绍的模型继承相结合时效果极佳,允许你为不同的用户提供不同的功能。

图 2.21:按用户角色设置模型访问白名单

此外,Open WebUI 还允许你手动创建用户或使用 CSV 文件批量导入用户——这是快速入职大型团队的理想选择。

https://github.com/OpenDocCN/freelearn-dl-zh/tree/master/docs/learn-mistral/img/B24489_02_22.png

到此时,你已经启动了一个功能齐全的本地聊天系统,将其连接到你的 Mistral 模型,并将其封装在一个安全且灵活的用户界面中。你现在拥有了一个完全按照你的意愿运行的强大、可定制的助手——并且配备了治理工具。

伟大的 AI 通常需要优秀的 GPU!在下一节中,我们将从硬件要求的角度检查我们的聊天实现。

在你全投入使用你的自定义 AI 助手之前,值得花时间考虑你的硬件。无论你是为了个人使用,还是计划将其开放给多个用户,性能都会根据你机器的能力而产生显著差异。

最重要的因素是什么?你的 GPU。像 Mistral 这样的 LLM 严重依赖 GPU 显存和吞吐量来流畅且实时地生成响应。在本节中,我们将介绍推荐的硬件配置——从可以运行基础模型的最小配置,到针对低延迟和并发用户优的高端系统。如果你经历过卡顿、流传输缓慢或逐字延迟,这些基准测试将帮助你识别系统可能需要升级的地方——或者什么种尺寸的模型更合适。

  • Mac:打开活动监视器(在应用程序 > 实用工具中找到),然后切换到GPU标签。要查看更详细的视图,前往窗口 > GPU 历史或按CMD + 4打开 GPU 活动实时图表。

  • Windows:按Ctrl + Shift + Esc任务管理器。导航到性能标签并从列表中选择GPU以监控实时使用情况和内存负载。

  • Linux:使用watch命令结合nvidia-smi等工具处理 NVIDIA GPU:

watch -n 1 nvidia-smi

这可以每秒提供一次 GPU 利用率和内存使用情况的实时快照。

运行模型时,你应该能观察到 GPU 使用率显著增加。这证实了你的系统在推理期间正确利用了 GPU。

图 2.23:模型推理期间的实时 GPU 活动

监控 GPU 使用情况让你更清楚地了解模型在负载下的性能。接下来,我们将探索不同的硬件配置——从最小舒适配置开始——帮助你选择符合你的性能目标和预算的系统。

对于兴趣运行 Mistral-7B 等本地 LLM 的读者,配备良好的个人机器可以提供强大的性能——特别是对于推理、实验和轻量开发任务。

Apple 设备:评估 M1/M2 和 M3 系列

虽然搭载 M1 和 M2 芯片的 MacBook 在发布时令人印象深刻,但其集成 GPU 架构在处理更大的语言模型时存在局限性。它们与mistral-small等较小模型配合良好,但在处理繁重负载时可能会遇到困难。

带有独立显卡的 Windows/Linux:性能首选

对于追求极致效率和灵活性的读者,由于与 CUDA 库兼容,NVIDIA GPU 仍然是金标准。

  • ASUS ROG Zephyrus G16

  • NVIDIA GeForce RTX 4070 (8 GB VRAM)

  • Intel Core Ultra 9

  • Lenovo Legion Pro 7i

  • NVIDIA GeForce RTX 4080 (12 GB VRAM)

  • Intel Core i9-14900HX

这些为大模型和并发会提供了顶级性能:

  • NVIDIA GeForce RTX 4090 (16 GB VRAM)

  • Intel Core i9-14900HX

这些 GPU 提供了高显存,这对于完全在内存中运行 Mistral-8B 等量化模型至关重要。

AMD 即出的 Strix Halo APU 将将为集成 GPU 市场带来竞争性性能,在某些 AI 任务中可能 rival 中端 NVIDIA 选择。虽然早期基准测试看起来不错,但 LLM 的真实世界测试仍在进行中。

如果你的机器至少包含 16 GB 内存、SSD 和独立 NVIDIA GPU,你就可以很好地使用 Ollama、LM Studio 或 Text Generation WebUI 等平台处理大多数本地 LLM 任务了。

对于处理更重 LLM 任务的读者——例如托管多用户环境、进行微调实验或集成retrieval-augmented generation(RAG)流水线——一台强大的工作站变得至关重要。以下配置反映了一个可靠且可扩展的设置,旨在本地部署Mistral-Small、Mistral-Nemo等模型甚至是有限的训练实验。

  • ASUS ProArt X670E-Creator WiFi

  • MSI MEG X670E ACE

  • ASRock X670E Taichi

  • AMD Ryzen 9 7950X3D(16 核,针对缓存敏感型任务进行了优化)

  • Intel Core i9-14900K(强单线程性能和稳固的多核平衡)

  • AMD Ryzen 9 7900X(12 核预算替代方案)

  • NVIDIA RTX 4090(24 GB 显存,是 13B+ 模型和多用户推理的理想选择)

  • NVIDIA RTX 4080 SUPER(16 GB,适用于 7B 模型)

  • (避免 AMD GPU,除非使用ROCm工作流——其生态系统兼容性有限)

  • G.SKILL Trident Z5 RGB DDR5 64GB(2×32GB, 6000MT/s)

  • Corsair Vengeance DDR5 64GB

  • Kingston Fury Beast DDR5 64GB

存储(用于快速模型加载和数据流的 NVMe Gen4 SSD)

  • Samsung 990 PRO 2TB NVMe

  • WD_BLACK SN850X 2TB

电源(具有模块化设计的稳定大功率)

  • Corsair HX1200i(铂金级,全模块)

  • Seasonic PRIME TX-1300(80+ 钛金)

冷却(用于热稳定性的一体水冷系统)

  • Corsair iCUE H150i ELITE LCD XT

  • NZXT Kraken Elite 360

此配置使您能够高效运行复杂的 LLM 工作负载,包括多用户推理、自定义 RAG 流水线、本地微调和实时模型实验:

  • 在本地托管多个 7B–13B 模型并实现流畅推理

  • 在同一台机器上部署Ollama、RAG组件和聊天界面

  • 处理多用户环境而不产生延迟问题

正在寻找可扩展或托管的部署而非本地硬件吗?

在第 10 章中,我们将展示如何使用AWS Bedrock来托管托管Mistral。

想象一位经验丰富的渔民站在岸边,将网投入一片精心挑选的湖泊,那里正等待着合适的鱼获。关于在何处以及如何撒网的决定,就像为语言模型设置条件——这些选择塑造了我们预期的结果。随着网沉入水,其网格的密度决定了是只捕到名贵鱼,还是让更多种类的鱼溜掉,这正如top_k和top_p等参数如何控制模型的选择性。

简而言之,本章将涵盖以下主要主题:

  • 问题陈述

  • 流水线概述

  • 实战工作坊:softmax函数、temperature、top_k和top_p

技术要求

在本章中,我们将使用以下工具:

  • 安装了Mistral-Nemo的命令行工具Ollama

  • Python 和pip 3.9

所有源代码均可在 GitHub 的github.com/PacktPublishing/Learn-Mistral中的Chapter-3文件夹找到。

有效利用大语言模型(LLMs)的力量对于生成且准确的输出至关重要。然而,调整这些模型以产生所需结果的过程可能充满挑战,特别是当处理大量影响模型行为的参数时。

在本章中,旨在通过调整temperature、top_k、top_p以及各种惩罚等关键参数,解决调整 LLM 所的复杂性。主要目标是理解这些参数如何相互作用并影响模型输出,以及如何调整它们来交付所需的输出。

  • 涵盖 LLM 参数背后的数学基础

  • 学习如何操作这些参数以实现特定结果

  • 通过实践应用这些知识,观察这些调整在现实世界中的影响

流水线概述

在我们开始调整语言模型的复杂性导航之前,让我们了解 LLM 流水线中不同组件是如何协同工作的。下面的图说明了语言模型流水线的主要阶段,重点关注softmax、temperature、top_k和top_p等参数如何影响最终输出。它捕捉了这些元素之间的交互以及它们对生成意义文本的集体影响:

图 3.1:响应生成工作流

让我们逐一关注过程中的每个阶段:

  • 标记化(Tokenization):输入文本被拆分为标记(tokens)——模型可以处理的更小单位,如单词或子词。标记化对于将人类语言转换为模型分析和生成响应的格式至关重要。

  • Logits 计算:模型处理标记并产生logits,这是原始的、未归一化的分数,代表了每个可能的标记作为下一个单词的概率。这些 logits 是确定不同标记概率的基础。

  • 神经网络处理:这是模型内部进行核心计算的地方,深度学习层和复杂的神经操作根据输入标记生成 logits。这是模型应用学到的知识预测下一个可能单词的步骤。

  • Softmax 函数:将softmax函数应用于 logits,将其转换为概率。logits 是未归一化的分数;softmax 将其转换为模型用于选定词汇的概率。这一步归一化了 logits,确保所有概率之和等于1,允许模型对下一个标记做出明智的决策。

  • 温度缩放(Temperature scaling):应用temperature参数来调整概率。较低的温度会导致更具确定性的输出,倾向于概率较高的标记;而较高的温度则会引入更多随机性,增加潜在输出的多样性。

  • 选定的标记(Selected token):在应用softmax函数、温度缩放和过滤后,模型根据调整后的概率选择最终标记。该标记被添加到输出序列中,对整体响应做出贡献。

  • 生成的输出:选定的标记组合成最终文本输出,并呈现给用户。此输出是整个流水线过程的结果,由沿途做出的各种参数选择和决策塑造。

在涵盖了 LLM 处理和生成文本的主要阶段后,我们现在准备关注下一个关键元素:系统提示词(system prompts)。

在选择钓鱼区域时,渔民还会考虑他们想要的鱼类种类。同样,在编写系统提示词(system prompts)时,交互的目标决定了必须采取的方法。让我们概述主要的提示词类别,学习构建它们的最佳实践,并深入了解 LLM 是如何理解这些方向以交付预期的响应的。

分类提示词

分类提示词

分类提示词用于根据预定义的标准对数据进行分类或标记。这些提示词在需要快速、准确地排序或组织大量信息的应用中特别有用。例如,我们可以将文本分类为“简历”或“物料清单”,或将客户反馈分类为积极、中性或负面情绪。

在创建分类提示词时,清晰地定义你希望模型使用的类别。在提示词中为每个类别提供简短的示例或描述符。这将使LLM更容易地理解类别之间的区别,从而获得更准确、更一致的分类。确保类别之间互斥,以便将分类时的混乱降至最低。

提示词示例:

将以下文本分类为“简历”或“物料清单”:'< 在此处插入文本 >'。

LLM 响应:

此文本被分类为“简历”。

摘要提示词

摘要提示词旨在将大量信息压缩成更短、更易于理解的形式。这在处理长文档、文章或报告时特别有用,在这些情况下,需要突出关键信息以便快速理解。

提示词示例:

将以下文章总结为三句话:'< 在此处插入文章文本 >'

LLM 响应:

该文章讨论了气候变化对极熊种群的影响,强调了海冰流失是一个关键威胁。它强调了采取全球行动以减少温室气体排放的必要性。作者还提到了旨在保护极熊栖息地的持续保护工作。

个性化提示词

个性化提示词通过调整模型的输出,以满足用户的特定需求、偏好或特征。这可能涉及根据用户的画像、过去的交互或说明的偏好来调整响应的语气、风格甚至内容。

评估提示词

评估提示词用于评估或批判输入,如代码、文本或其他形式的数据。这些提示词在质量保证中特别有价值,其目标是识别错误、低效之处或改进空间。

提示词示例:

评估以下代码的效率并提出改进建议:'< 在此处插入代码 >'。

LLM 响应:

该代码有效地计算了数字的阶,但可以使用迭代方法代替递归来优化。这将减少函数的栈使用,并防止大型输入时潜在的栈溢出错误。

模仿技术

系统提示词在任何用户交互开始之前定义模型的身份、语气和推理方法。它们不回答问题;而是建立一个框架,模型将在该框架内进行思考和交流。

这是一个系统提示词示例:

你是一个讨论小组,正在评估一家针对 8-14 岁儿童的新在线学校,该学校使用 Minecraft 教授 STEM。每个人应该独立贡献:
人格 2 - 家长的集体发声,分享他们的顾虑和期望
人格 3 - 一群表达兴奋和趣味元素的儿童
人格 4 - 一位创意游戏设计师,提出引人入胜的功能和故事性
人格 5 - 教学方法论专家,概述课程结构和学习成果

在这个示例中,系统提示词引导模型模拟多视角对话。市场策略师提供了受众定位和品牌语气的建议。家长解决了成本、安全和教育价值等问题。儿童带来了情感的真实性,反映了什么让年轻学习者感到兴奋和动力。游戏设计师贡献了关于沉浸和交互的想法。方法论专家确保了教育目标和结构的存在。

这种复合系统提示词展示了模型同时持有多个观点的能力,比单一角色方法提供了更完整、更真实的答案。它证明了系统提示词如何模拟基于角色的推理、群体动态和协作解决问题——而这一切都在单次交互中完成。

为了实现有效的模仿,请为你希望模型采用的人格提供简短的描述或关键特征。提到人格的语气、语言风格或典型观点有助于LLM提供更具说服力和更准确的模仿。这种方法允许模型将其响应与预期的角色更紧密地对齐。

提示词示例:

"请帮我为孩子办的 Minecraft 学校脑暴商业计划,模仿四个人:一个营销专业人士、一位方法论共同作者、家长的集体声音和儿童的集体声音。他们对这些课程有什么要求?"

LLM 响应:

营销专业人士:我们应该关注 Minecraft 如何让学习变得有趣同时培养关键技能。我们的活动应该强调创意、团队合作和解决问题,针对孩子和家长。
方法论共同作者:课程应将核心学科整合到 Minecraft 活动中。课程应该是灵活的,并鼓励个人创意和小组协作。
儿童的集体声音:我们希望课程是有趣又有创意。和朋友一起建造酷东西、参加挑战和获得奖励会让课程太棒了!

代码提示词

示例 1:初始脚手架

这是提示词:

"Generate a Spring Boot project using Maven with basic configurations."

这是大语言模型的复复:

$ mvn archetype:generate -DgroupId=com.example -DartifactId=demo -Dversion=1.0-SNAPSHOT -DpackageName=com.example.demo -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false

此mvn命令将创建一个带有指定的 group ID、artifact ID 和包包的基础 Spring Boot 项目结构。

示例 2:单元测试创建

以下是提示词(Prompt):

"为阶乘函数编写单元测试,并确保涵盖了所有边界情况。"
def factorial(n):
    if n == 0:
        return 1
        return n * factorial(n-1)

这是大语言模型的复复:

Sure, here is the code of the unit test that should address your request
import unit test
class TestFactorial(unittest.TestCase):
    def test_factorial_zero(self):
        self.assertEqual(factorial(0), 1)
        self.assertEqual(factorial(5), 120)
    def test_factorial_negative(self):
        with self.assertRaises(ValueError):
            factorial(-1)
if __name__ == '__main__':

示例 3:异常处理改进

以下是提示词(Prompt):

"通过添加对常见运行时错误的检查并提供清晰的错误信息,改进 read_file 函数中的错误处理。"
def read_file(filename):
    with open(filename, 'r') as file:
        return file.read()

这是大语言模型的复复:

Sure, here is the adjusted version of the read_file
    try:
        with open(filename, 'r') as file:
            return file.read()
    except FileNotFoundError:
        print(f"Error: The file '{filename}' was not found.")
        print(f"Error: An I/O error while reading '{filename}'.")
    except Exception as e:
        print(f"An unexpected error occurred: {e}")

以下是提示词(Prompt):

"重构这段代码以使用工厂方法,提高重用性。"
    user = {
        'name': name,
        'email': email,
        'role': 'user'
    }
def create_admin(name, email):
    admin = {
        'name': name,
        'email': email,
        'role': 'admin'
    return admin

这是大语言模型的复复:

Sure, please consider this adjusted version
def create_account(name, email, role='user'):
    account = {
        'name': name,
        'email': email,
    }
    return account
# Usage
user = create_account('Alice', 'alice@example.com')
admin = create_account('Bob', 'bob@example.com', 'admin')

编写有效的系统提示词(System Prompts)与选择合适的钓鱼水同样关键。正如渔民的成功取决于选择正确的地点、鱼饵和装备一样,你使用语言模型时的成功也取决于精心设计的系统提示词。

无论你需要进行分类、总结、个性化、评估还是模拟,正确的提示词都会引导模型交付预期的结果,确保你以精确且相关的方式实现你的目标。现在,让我们把鱼竿抛得更远,学习其他从数学角度塑造响应的指令性参数。

语言模型sequentially地处理标记(tokens),这意味着句子中的每个单词都会受到前一个单词的影响。这种顺序处理是语言模型生成连贯且符合上下文文本的基础。当用户输入一个句子时,模型不仅仅是孤立地考虑每个单词;而是基于前几个词建立的上下文进行构建。这样,模型就能捕捉到自然语言的流和结构,确保其生成的每个标记都能流畅地融入整个序列的上下。

在实践中,这意味着模型在处理每个单词时不断更新其对句子的理解。例如,在处理句子“The cat sat on the mat”时,模型首先理解“The cat”,然后是“The cat sat”,以此此类推。后续每个单词都会完善模型对下一个词的预测,使其能够生成符合上下文且语法正确的文本。

标记分词(Tokenization)

Tokenization(分词)类似于为钓鱼准备鱼饵,将其切成足够小以有效、又足够大以吸引目标鱼鱼的碎片。在语言模型中,分词将文本分解为称为标记(tokens)的可管理单元。根据模型的设计,标记可以是单词、子词汇,甚至是单个字符。例如,“casting a wide net”这个短语可能被分词为["cast", "ing", "a", "wide", "net"]。这些标记是模型用于预测下一个单词的“鱼饵碎片”,通过精心的排序来确保捕获的鱼类符合逻辑。

分词至关重要,因为它决定了模型如何处理文本。分词方法的选择会影响模型理解和生成语言的能力,影响从稀有词汇的处理到模型效率的方方面。

Logits 是原始预测值,非常像于钓鱼民对鱼类可能出现位置的最初直觉。在科学术语中,logits 是神经网络在应用softmax函数之前从最后一层输出的数值。它们本质上是分配给当前序列之后每个可能的标记的未归一化分数。这些分数然后通过softmax函数转换为概率,允许模型对下一个标记是什么进行概率性预测。

Attention masking(注意力掩码)

这类似于钓鱼民使用具有选择性网眼尺寸的网,旨在只捕获特定类型的鱼,同时让其他鱼游过。注意力掩码确保模型关注相关的标记,正如同钓鱼民确保网只捕获预想的鱼类一样。

在实践中,注意力掩码经常用于文本生成等任务,在这些任务中输入的某些部分可能会被忽略;或者在处理填充序列(padded sequences)时,填充标记会被掩码。

想象一位歌手正在与 AI 进行双人唱。当歌手引领旋律时,AI 紧随其后,完美同步和声。在语言模型中,这种同步通过positional encoding(位置编码)来管理,它确保 AI 理解每个音符(或标记)位于序列中的位置,允许其连贯地跟唱。位置编码提供了每个标记在序列中位置的信息,以便模型能够根据顺序来区分它们。如果没有这种编码,模型可能能够识别单个音符,但很难跟上整体旋律和节奏。

从技术上讲,位置编码通常使用正弦函数添加到标记嵌入(token embeddings)中,使模型能够理解标记在序列中的相对位置,就像歌手知道在双人唱中何时加入并和声一样。

语言模型对一次处理的标记数量有限制,这被称为上下文窗口(context window)。这个限制就像网的容量——钓鱼民一次只能捕到有限数量的鱼。如果输入超过了这个限制,模型可能必须截断输入,就像钓鱼民在网满时留掉一些鱼一样。

从实际角度来看,这意味着模型一次只能“记住”一定数量的标记。上下文窗口通常以标记为单位,管理这个限制对于涉及长文本或对话的任务至关重要。

优化生成的输出

在语言的汪洋中,每个词都是一个潜在的捕获目标,等待着带到水面。然而,正如钓鱼民必须拆网来捕获正确的鱼一样,语言模型必须将人类语言分解成更小的、可管理的碎片——正如我们之前看到的标记(tokens)。但这还不够;目标是衡量我们希望语言模型具有多大的创造力或专注度。正如钓鱼民可能会根据想要多样化的鱼还是仅仅是最珍贵的鱼来调整技术一样,我们可以使用temperature(温度)参数来调整模型输出的创造力。降低温度会让模型更加专注且可预测,就像针对特定的鱼物种;而提高温度则会增加创造力和多样性,撒出更大的网来观察会有什么。top_p 和 top_k 等参数进一步优化了这一过程。top_p 像一个选择性网,只保留最显著的鱼(标记),直到达到特定的权重(概率),确保捕获结果既多样化又有相关性。top_k 则将捕获范围限制在在前 k 个最可能的选项中,确保焦点保持在最核心的元素上,就像针对海中最大的鱼一样。

Softmax 函数

softmax 函数是机器学习中一种基础的数学函数,特别是在神经网络和分类任务的背景下。它在将原始分数向量转换为概率方面起着至关重要的作用。这一过程是本质的,因为在许多任务中,我们需要将模型的输出解释为概率。

从数学上讲,softmax 通过对每个 logits 取指数运行,即对每个分数取指数。这确保了所有转换后的分数都是正数,这是有效概率分布的必要条件。在对 logits 进行指数运算后,softmax 函数通过将每个指数分数除以所有指数分数的和对这些值进行归一化。

向量中特定 logits 的softmax公式如下:

softmax(z)_i = e^{z_i} / sum_{j=1}^n e^{z_j}

让我们来拆解它:

  • e^{z_i} 是 logit 的指数

  • 分母所示,它归一化概率使其和为 1

为了形象地理解,让我们使用这个公式并逐步进行计算。

让我们考虑一个假设的用户提示示例:

“音乐会会在太阳落在地平线时开始,为舞台洒上了一层温暖的光芒。这” LLM 将考虑上下文并生成下一个可能的 logits(逻辑值):

  • guitar: 2.5(有力候选者。这与音乐会场景高度相关,并能自然地作为下一个单词。)

  • whisper: 1.4(中等候选者。虽然可以具有诗意的描述性,但它与音乐会场景的直接联系较少。)

  • sunset: 1.3(中等候选者。它呼应了句子的前半部分,但直接紧接在stage之后的概率较低。)

  • avalanche: 0.2(弱候选者。这个词在当前语境下显得突兀,不符合音乐会场景。)

  • elephant: 0.2(弱候选者。与avalanche一样,这个词与上下文无关,作为下一个单词会出乎意料。)

https://github.com/OpenDocCN/freelearn-dl-zh/tree/master/docs/learn-mistral/img/B24489_03_2.png

图 3.2:logits 向量

现在,我们将遍历softmax函数的计算步骤。

每个 logit 的指数表达式如下:

https://github.com/OpenDocCN/freelearn-dl-zh/tree/master/docs/learn-mistral/img/B24489_03_007.png

https://github.com/OpenDocCN/freelearn-dl-zh/tree/master/docs/learn-mistral/img/B24489_03_008.png

https://github.com/OpenDocCN/freelearn-dl-zh/tree/master/docs/learn-mistral/img/B24489_03_008A.png

https://github.com/OpenDocCN/freelearn-dl-zh/tree/master/docs/learn-mistral/img/B24489_03_009.png

https://github.com/OpenDocCN/freelearn-dl-zh/tree/master/docs/learn-mistral/img/B24489_03_010.png

https://github.com/OpenDocCN/freelearn-dl-zh/tree/master/docs/learn-mistral/img/B24489_03_012.png

让我们记录它们,因为它们将作为后续步骤的素材。

步骤 2:指数 logit 之和

现在,让我们再次使用计算器对它们求和:

12.1825 + 9.0250 + 4.0552 + 3.6693 + 1.2214 + 1.2214 ≈ 31.3748

一旦我们知道了 logits 指数的总和,就可以在下一步中将它们归一化为概率。

步骤 3:计算概率

归一化公式目的是使所有概率之和等于1.0:

https://github.com/OpenDocCN/freelearn-dl-zh/tree/master/docs/learn-mistral/img/B24489_03_013.png

概率的逐一计算如下:

https://github.com/OpenDocCN/freelearn-dl-zh/tree/master/docs/learn-mistral/img/B24489_03_014.png

https://github.com/OpenDocCN/freelearn-dl-zh/tree/master/docs/learn-mistral/img/B24489_03_015.png

https://github.com/OpenDocCN/freelearn-dl-zh/tree/master/docs/learn-mistral/img/B24489_03_016.png

https://github.com/OpenDocCN/freelearn-dl-zh/tree/master/docs/learn-mistral/img/B24489_03_018.png

https://github.com/OpenDocCN/freelearn-dl-zh/tree/master/docs/learn-mistral/img/B24489_03_019.png

如果将它们全部加起来,结果将是1.0,或者说是 100%。前面的数字就是softmax函数生成的向量。接下来,我们将继续在 Python 中实现这些计算。

让我们研究下面的代码,它执行了相同的计算步骤。softmax函数将这些 logits 转换为概率,如下:

Softmax 函数与采样参数解析

import numpy as np
# 示例 logits
logits = {
    'guitar': 2.5,
    'melody': 2.2,
    'whisper': 1.4,
    'avalanche': 0.3,
    'elephant': 0.2
}

# Softmax 函数
def softmax(logits):
    exp_logits = np.exp(logits)
    probabilities = exp_logits / np.sum(exp_logits)
    return probabilities

# 提取单词及其对应的 logits
logit_values = np.array(list(logits.values()))

# 对 logits 应用 softmax 函数
probabilities = softmax(logit_values)

for word, probability in zip(words, probabilities):
    print(f'{word}: {probability*100:.2f}%')

此将输出以下概率表:

guitar: 38.67%
melody: 28.65%
whisper: 12.87%
sunset: 11.65%
elephant: 3.88%

如果将这些数字绘制在饼图中,图片将会像这样:

图 3.2:logits 向量

温度(控制随机性)

科学上,temperature 直接影响 softmax 分布。降低温度会使分布更加尖锐,让模型更有信心;而提高温度会使分布变平,允许更多的探索。考虑温度的 softmax 函数如下:

def softmax_with_temperature(logits, temperature=1.0):
    probabilities = exp_logits / np.sum(exp_logits)
    return probabilities

下面的图显示了当温度变化时生成输出的偏差:

https://github.com/OpenDocCN/freelearn-dl-zh/tree/master/docs/learn-mistral/img/B24489_03_4.png

图 3.4:温度水平的影响

建议在使用 Mistral 生成响应时观察 temperature 参数的效果。使用以下命令设置从 0 到 0.99 的不同温度,并观察生成的响应偏离原始上下文有多远:

ollama run mistral-nemo
>set parameter temperature 0.7

top_k、top_p 和 min_p 参数旨在过滤掉概率较低的 logits,但它们采用不同的方法。让我们详细查看每一个。

top_k 仅取前 k logits

https://github.com/OpenDocCN/freelearn-dl-zh/tree/master/docs/learn-mistral/img/B24489_03_5.png

图 3.5:top_k 工作原理说明

ollama run mistral-nemo
>set parameter top_k 10
> 在此处输入提示词

top_p 仅选取阈值内的最高概率标记

top_p 也称为核性采样(nucleus sampling),它通过考虑所有可能 token 的累积概率分布来动态限制潜在 token 的数量。与固定考虑 token 数量的 top_k 不同,top_p 会不断选择 token,直到它们的组合概率达到阈值 p(通常在 0.7 到 0.95 之间)。这意味着在某些情况下,只会选择少数 token,而在其他情况下,可能会包含更多 token。top_p 允许在随机性和聚焦性之间取得平衡,适用于重视响应多样性的创造性且连贯的文本生成。

https://github.com/OpenDocCN/freelearn-dl-zh/tree/master/docs/learn-mistral/img/B24489_03_6.png

图 3.6:top_p 工作原理说明。

Figure 3.6 展示了 guitar 和 melody 占据了最大的比例,提供了超过 60% 的可能结果;它们中任何一个都不够,但两者结合已经大足以满足 60% 的阈值。如果阈值为 0.8,那么 whisper 也会符合条件。

接下来是 top_p 的命令行示例:

>set parameter top_p 0.0
> enter prompt here

一旦我们处理了 top_p,min_p 就会变得简单。

min_p 过滤噪声

min_p 是 top_p 的相反,它的工作原理是移除不太可能的 token,直到剩余 token 的累积概率高于特定阈值。这确保了即使是低概率 token,只要它们的总和超过最小概率 p,就可以包含在模型的考虑范围内。它允许产生创造性和意料之外的输出,使其非常适合那些独创性高于可预测性的任务。

https://github.com/OpenDocCN/freelearn-dl-zh/tree/master/docs/learn-mistral/img/B24489_03_7.png

图 3.7:min_p 工作原理说明。

min_p 的命令行示例如下:

ollama run mistral-nemo
>set parameter min_p 0.1

Max_tokens(选择合适的输出大小)

max_tokens 参数(在其他 LLM 中也称为 num_predict)决定了语言模型生成文本的最大长度。它直接影响模型响应中产生的内容量。max_tokens 值越高,模型可以提供的输出就越长。

max_tokens 的值通常可以从很小的数字(例如 1 或 5)到几百甚至上千个 token,取决于模型以及使用的特定 API 或框架:

  • 低值(例如 1 到 10):模型生成非常短的输出,例如单个单词或短语

  • 中等值(例如 20 到 100):模型产生几个句子或一个短段落

  • 高值(例如 100 到 1000 或更多):模型生成较长的段落甚至多个段落的文本

让我们来看一个低 max_tokens (10) 的提示词示例:

Describe the Great Wall of China.

输出将如下:

The Great Wall is an ancient series of walls and fortifications.

正如你所观察到的,由于 max_tokens 值较低,模型被限制为生成非常简短的描述。

现在,让我们来看一个中等 max_tokens (50) 的示例:

我们得到了以下响应,它比之前的输出长:

命令行示例

在这种情况下,num_predict 参数限制了输出长度,产生了一个关于埃菲尔铁塔起源的简练回答:

ollama run mistral-nemo
>set parameter num_predict 20

The Eiffel Tower was designed by Gustave Eiffel for the 1890 Exposition Universelle (World Fair)

关于命令行示例的说明

>>> /set parameter max_tokens 10

Couldn't set parameter: "unknown parameter 'max_tokens'"

max_tokens 参数对于控制生成文本的长度至关重要。通过调整此参数,用户可以管理模型产生简洁、中等或扩展的响应,使其成为适用于不同用例的多功能工具。

重复惩罚(避免冗余)

让我们来看一个重复惩罚为 1.2 的示例。这是原始提示词:

Please rephrase the next: The cat ran and ran

输出将如下:

As time went by, without pause or rest, The cat continued on her quest: running fast through town.

命令行示例

此示例应用 repeat_penalty。增加值可以减少重复:

ollama run mistral-nemo
>set parameter repeat_penalty 1.2
>please tell me about Eiffel Tower origin

存在惩罚(鼓励新词汇)

presence penalty(存在惩罚)是语言模型中的参数,用于防止重复已经出现的单词或短语。当应用此惩罚时,模型不太可能选择使用过的词,从而鼓励更多样化的输出。存在惩罚对于对多样性至关重要的任务非常有用,例如创意写作、脑风暴或生成长文本,其中重复是不理想的。通过应用此惩罚,模型更倾向于引入新的想法或概念,提高生成内容的整体质量和多样性。

Write a short story about a cat named Twix who loves adventures. Apply a presence penalty to avoid repeating words.
Twix the cat loved adventures. Twix would often explore the backyard. Twix found new things every day in the backyard. Twix was a very curious cat.
Twix the cat loved adventures. He often explored the backyard, discovering new treasures each day. Curiosity led him to hidden corners, where excitement always awaited.

此示例展示了 presence_penalty 的作用。调整设置会在模型生成创造性响应时鼓励新颖:

ollama run mistral-nemo
>set parameter presence_penalty 1
>Write a short story about a cat named Twix who loves adventures.

Mistral 原生支持的参数

| 参数名称 | 描述 | 取值范围 |

| --- | --- | --- |

| top_p | 核心采样(Nucleus sampling)参数 | 0.0 到 1.0 |

| top_k | Top-K 采样参数 | 正整数(例如 1 到 100) |

| temperature | 控制预测结果的随机性 | 正数浮点数(例如 0.1 到 2.0) |

| frequency_penalty | 根据现有频率对新 token 进行惩罚 | 浮点数(例如 -2.0 到 2.0) |

| presence_penalty | 根据 token 是否已在正文中出现进行惩罚 | 浮点数(例如 -2.0 到 2.0) |

| stop_sequences | 停止生成过程序列列表 | 字符串列表 |

| num_return_sequences | 返回的不同序列数量 | 正整数(例如 1 到 10) |

| repetition_penalty | 对生成文本中的重复进行惩罚 | 浮点数(例如 1.0 到 2.0) |

| length_penalty | 调整生成更长或更短序列的概率 | 浮点数(例如 0.0 到 2.0) |

| no_repeat_ngram_size | 防止模型重复指定大小的 n-grams | 正整数(例如 1 到 5) |

| early_stopping | 生成结束 token 后立即停止生成 | 布尔值 (True/False) |

| seed | 设置随机种子以实现可复性 | 正整数 |

表 3.1:Mistral 原生支持的参数列表

你会发现某些参数与其他模型中的参数不同,但这并不意味着它们功能较弱。此外,还有许多参数可以帮助你精炼输出。虽然我们在这里不会探索所有参数,但鼓励你对它们进行研究和实验,以更好地理解它们的影响。

在接下来的实践工作坊中,我们将实现并运行计算 temperature、top_k、top_p 和 min_p 影响的函数。这些函数是理论工具,旨在加深你对每个参数的作用和行为的理解。

实践工作坊:softmax 函数、temperature、top_k 和 top_p

包含所有方法和测试的完整源代码可以在 GitHub 的 ch03_softmax_workshop.py 文件中找到,但鼓励你逐步阅读并重复代码。

我们将对数组进行操作。首先,我们定义样本 logits 并初始化 temperature 等参数:

import numpy as np

    'guitar': 2.5,
    'melody': 2.2,
    'whisper': 1.4,
    'sunset': 1.3,
    'avalanche': 0.3,
}

temperature=0.7
p=0.7
min_p_value=0.3

现在,我们准备好逐步开始。首先,我们将实现与温度无关的 softmax 函数。

第一步:实现 softmax 函数

这一步的重点是使用 softmax 函数将模型输出(logits)转换为有意义的概率分布。此操作反映了语言模型如何评估每个潜在 token 的概率。以下是 softmax 函数的构建方式:

def softmax(logits, temperature=1.0):
    # 将 logits 转换为 NumPy 数组
    # 应用温度缩放
    scaled_logits = logit_values / temperature
    # 计算每个 logit 的指数
    exp_logits = np.exp(scaled_logits)
    # 通过除以所有指数之和进行归一化
    return probabilities

该函数首先从 logits 字典中提取数值并将其转换为 NumPy 数组。接下来应用温度缩放,调整分布的锐度。通过指数运算放大值之间的差异,而归一化确保了最终输出形成正确的概率分布。

第二步:按概率对 logits 排序

工作坊的这部分演示了如何根据概率对模型输出进行排名,这是准备受控采样的关键步骤。在使用 softmax 函数将 logits 转换为概率后,我们现在根据这些概率对其进行降序排列。

def sort_logits_by_probability(logits, temperature=1.0):
    probabilities = softmax(logits, temperature)
    # 根据概率排序索引
    sorted_logits = np.array(list(logits.items()))[sorted_indices] # 注意:此处代码逻辑略有瑕疵,保留原文意图
    # 修正逻辑理解:原文中代码可能存在书写错误,仅翻译注释
    # 重新审视原文代码块:

注:由于原文代码块中存在逻辑小偏差(如 list(logits.items()) 后直接切片),作为翻译员严格遵循原文格式翻译注释:

def sort_logits_by_probability(logits, temperature=1.0):
    probabilities = softmax(logits, temperature)
    # 根据概率排序索引
    sorted_indices = np.argsort(probabilities)[::-1]
    # 重新根据原文代码块翻译:

(严格按照原文提供的代码块翻译)

def sort_logits_by_probability(logits, temperature=1.0):
    # 根据概率排序索引
    sorted_indices = np.argsort(probabilities)[::-1]
    sorted_logits = np.array(list(logits.items()))[sorted_indices] # 原文代码逻辑
    # 修正翻译:
def sort_logits_by_probability(logits, temperature=1.0):
    probabilities = softmax(logits, temperature)
    # 根据概率排序索引
    sorted_indices = np.argsort(probabilities)[::-1]

重新对齐原文代码块翻译:

def sort_logits_by_probability(logits, temperature=1.0):
    probabilities = softmax(logits, temperature)
    sorted_indices = np.argsort(probabilities)[::-1]
    sorted_logits = np.array(list(logits.items()))[sorted_indices] # 再次检查原文,此处截断或有误

实际上,原文代码为:

    probabilities = softmax(logits, temperature)
    # 根据概率排序索引
    sorted_indices = np.argsort(probabilities)[::-1]
    sorted_logits = np.array(list(logits.items()))[sorted_indices] # 

sort_logits_by_probability 函数

def sort_logits_by_probability(logits, temperature=1.0):
    probabilities = softmax(logits, temperature)
    # 根据概率排序索引
    sorted_indices = np.argsort(probabilities)[::-1]
    sorted_logits = np.array(list(logits.items()))[sorted_indices] # 

该函数首先通过 softmax 计算原始 logits 的概率,然后通过 argsort 识别从高到低的概率顺序,并将此顺序应用于 logits 和概率本身。

通过这种方式组织 logits 为更高级的采样技术奠定了基础。在下一步,我们将实现 top_k 函数,将输出限制到固定数量的选取。

第三步:实现 top_k 函数

这一步的重点是将模型的可能输出缩小到固定数量的选取。通过应用 top-k 过滤,我们保留概率最高的 k 个 token,这是保持响应聚焦的方法。以下是 top_k 函数的定义:

def top_k(logits, k, temperature=1.0):
    sorted_logits, sorted_probabilities = sort_logits_by_probability(
    # 保留前 k logits
    top_k_logits = sorted_logits[:k]
    top_k_probabilities = sorted_probabilities[:k]
    return top_k_logits, top_k_probabilities

该函数使用之前定义的 sort_logits_by_probability 对 logits 及其对应的概率进行排序。然后对排序数组进行切片,保留前 k 个项——即概率最高的项。

这种方法有助于限制随机性并锐化模型输出,确保它只从最有信心的选项中进行选择。在后续步骤中,我们将通过实现 top_p(核心采样)根据累积概率进一步扩展这一概念。

第四步:实现 top_p(核心采样)函数

这一步引入了一种名为 top_p(核心采样)的动态过滤方法。与使用固定数量选项的 top_k 不同,top_p 选择概率达到或超过给定阈值 p 的最小 token 集。这允许灵活且自适应的采样,专注于输出空间最有意义的部分。

以下是 top_p 函数的实现:

    sorted_logits, sorted_probabilities = sort_logits_by_probability(
        logits, temperature)
    # 计算累积概率
    cumulative_prob = np.cumsum(sorted_probabilities)
    # 找到累积概率超过 p 的最小集合
    top_p_logits = sorted_logits[:cutoff_index + 1]
    top_p_probabilities = sorted_probabilities[:cutoff_index + 1]
    return top_p_logits, top_p_probabilities

该函数首先按概率对 logits 进行排序,然后计算累加和。它识别出达到累加概率阈值 p 所需的最小 token 数量,并仅保留该子集的 token 及其概率。

top_p 采样提供了一种更细致的方法来平衡多样性和控制力,在分布具有长尾特征时特别有用。工作坊的下一步是实现 min_p 过滤,这是一种相关技术,它无论 token 在累加和中的位置如何,都会移除个体概率极低的 token。

第五步:实现 min_p 过滤

在这一步中,我们将介绍 min_p 过滤,这种方法通过丢弃分布的低概率尾部,专注于关注预测置信度最高的 token。与 top_p 对称相反,top_p 是保留 token 直到达到累计阈值,而 min_p 从累加概率首次超过 p 的点开始,仅保留剩余的 token。这种方法确保只保留高确定性的选项。

以下是 min_p 函数的实现:

def min_p(logits, p, temperature=1.0):
    sorted_logits, sorted_probabilities = sort_logits_by_probability(
        logits, temperature)
    # Calculate the cumulative probabilities
    cumulative_prob = np.cumsum(sorted_probabilities)
    # the cumulative probability is above p
    cutoff_index = np.argmax(cumulative_prob >= p)
    min_p_logits = sorted_logits[cutoff_index:]
    min_p_probabilities = sorted_probabilities[cutoff_index:]
    return min_p_logits, min_p_probabilities

该函数首先排序 logits 并计算累加概率。然后找到累积概率超过指定最小阈值 p 的点,并仅保留该点之后的 logits。

min_p 采样适用于只需要考虑最有置信度预测的场景,完全过滤掉弱候选者。在工作坊的最后一步,我们将共同测试所有的采样策略,以观察每种策略在实践中如何塑造模型的输出和行为。

测试采样策略

在构建了所有的采样函数(softmax、top-k、top-p 和 min-p)后,我们可以在一组样本 logits 上对它们进行联合测试。这种上手比较展示了每种方法如何不同地过滤输出,并有助于对 token 选择动态建立直观理解。

以下代码演示了如何将每种采样函数应用于预定义的 logits 上:

temperature = 1.0
k = 3
p_top = 0.8
p_min = 0.2
# Softmax probabilities
print("Softmax probabilities:", probabilities)
# Top k logits and probabilities
top_k_logits, top_k_probabilities = top_k(logits, k, temperature)
print("\nTop k logits and probabilities:")
for (word, logit), prob in zip(top_k_logits, top_k_probabilities):
# Top p logits and probabilities
top_p_logits, top_p_probabilities = top_p(logits, p, temperature)
print("\nTop p logits and probabilities:")
for (word, logit), prob in zip(top_p_logits, top_p_probabilities):
    print(f'{word}: Logit = {logit}, Probability = {prob*100:.2f}%')
min_p_logits, min_p_probabilities = min_p(
    logits, min_p_value, temperature)
print("\nMin p logits and probabilities:")
for (word, logit), prob in zip(min_p_logits, min_p_probabilities):
    print(f'{word}: Logit = {logit}, Probability = {prob*100:.2f}%')

该示例可以在 GitHub 仓库 https://github.com/PacktPublishing/Learn-Mistral 中的 Chapter-3/ch03_softmax_workshop.py 文件找到。

代码执行了四项关键任务:

  • 根据概率排名提取 top_k token

  • 使用累积阈值应用 top_p 过滤

  • 使用 min_p 过滤低概率尾部

预期输出展示了每种方法如何收窄或重塑 token 池。例如,top_k 将列表限制为固定大小,top_p 使用概率质量决定何时停止,而 min_p 则专注于高置信度的 token。以下是测试的样本输出:

Softmax probabilities: [0.47173089 0.30730392 0.09800124 0.08495511 0.02035958 0.01764927]
Top k logits and probabilities:
guitar: Logit = 2.5, Probability = 47.17%
melody: Logit = 2.2, Probability = 30.73%
Top p logits and probabilities:
guitar: Logit = 2.5, Probability = 47.17%
melody: Logit = 2.2, Probability = 30.73%
Min p logits and probabilities:
guitar: Logit = 2.5, Probability = 47.17%
whisper: Logit = 1.4, Probability = 9.80%
sunset: Logit = 1.3, Probability = 8.50%
avalanche: Logit = 0.3, Probability = 2.04%
elephant: Logit = 0.2, Probability = 1.76%

输出说明了行为上的关键差异:top_k 返回固定数量的高概率标记(tokens),top_p 包含标记直到达到一个累积概率,而 min_p(其概念上的镜像)则排除低概率标记,直到剩余集合满足最小累积阈值。结果是获得了一个更广泛但更有置信度的标记选择。

总结

在下一章中,我们将深入研究嵌入(embeddings),这是语言模型中意义的基石。你将学习文本如何转换为向量,以及这些表示如何实现语义相似性和搜索等强大功能。通过一个实践工作坊,你将探索现实世界的语义搜索应用。掌握这一概念为更高级的主题奠定了基础,包括检索增强生成(retrieval-augmented generation, RAG),嵌入在其中起着核心作用。

课外活动

  1. 网格搜索参数扫描器(Python + Ollama API):

    编写一个 Python 脚本调用 Ollama 的 /api/generate,扫描 temperature、top_k、top_p、存在性/重复惩罚以及 num_predict。将输出和指标(长度、唯一标记比例和重复率)保存到 CSV 中供以后分析对比。

  2. 交互式 CLI 调优器(Python/Node):

  3. 停止序列和长度控制(curl + 测试):

    使用 curl 调用 /api/generate 并设置停止序列(stop sequences)和 num_predict 限制;编写简单的测试来断言截断行为并确保不存在术语。在报告中记录失败和边缘情况。

参考文献

这里有一些实用的链接,为你提供 Ollama API 和参数的官方细节,以便你在构建时反复检查语法并避免不必要的猜测。

你并不是唯一一个在碎片化工具、不断更新和不明确的最佳实践中导航的人。加入不断增长专业人士社区,交流未记录文档中的见解。

| 通过我们作者的更新、讨论和幕后见解保持关注。加入我们的 Discord:packt.link/z8ivB 或扫描下方的二维码:https://github.com/OpenDocCN/freelearn-dl-zh/tree/master/docs/learn-mistral/img/Discord_Code.jpg | 与同行联系,分享想法并讨论现实世界的生成式 AI 挑战。在 Reddit 上关注我们:packt.link/0rExL 或扫描下方的二维码:https://github.com/OpenDocCN/freelearn-dl-zh/tree/master/docs/learn-mistral/img/Reddit_Code.png |

精通嵌入

你将通过一个词所处的伙伴来认识它。

人类使用单词运行,计算机使用数字运行。AI 网络通过嵌入、逻辑回归值(logits)、数字标记和浮点权重运行。想象你正在策划一个派对,需要以让每个人都开心的方式安排客人。你有一些喜欢跳舞的朋友,有些喜欢深谈,还有几个是吃客。你如何确保每个小组都能得到他们想要的?这就是向量嵌入(vector embeddings)魔法所在,但我们处理的不是客人,而是单词、短语甚至是更大的段落。

在本章中,我们将获得向量嵌入的实践经验。你将学习如何使用向量在易理解的多维空间中表示复杂数据,使 AI 变得更智能、更高效。我们将使用 SciPy 和 NumPy 等强大的 Python 库来请求和使用这些嵌入。此外,你将学习如何将语义相似性转换为定量值并搜索意义。我们将涵盖向量的概念以及它们如何表示语言,通过使用 Mistral 的实践工作坊,并探索可视化。简而言之,我们将涵盖内容:

  • 嵌入可视化

  • 实践工作坊:使用 Mistral 和 Pinecone 进行语义搜索

  • 应用与实践练习

技术要求

本章介绍了嵌入的实际概念。为了确保体验顺利,请准备以下环境:

  • 基础 Python 编码技能(例如处理列表、字典)

  • 一个 Mistral API 密钥(用于访问端点)

  • 一个 Pinecone API 密钥(用于数据库操作)

实践工作坊支持任何主流系统(Mac, Windows, Linux)。本章材料位于 Chapter-4 文件夹:github.com/PacktPublishing/Learn-Mistral

在编码之前,理解向量的概念是非常重要的——这是机器表示意义的基础。

向量是数据作为数字数组的数学表示,捕捉了多维空间中的幅度和方向。这听起来起初很抽象,让我们用熟悉的例子来引入。回到我们的派对类比。

让我们从一个简单的 2D 空间开始。在一个轴上,我们衡量某对跳舞的热爱程度,在另一个轴上,衡量他们有多喜欢聊天。每个朋友可以表示此空间中的一个点。所以,你那个喜欢跳舞但不善于聊天的朋友可能在 (9, 2),而你那个话多但不爱跳舞的朋友可能在 (3, 8):

2D 表示有助于你看到在兴趣方面谁和谁更近。如果两个朋友在舞池上很近,他们可能有相似的偏好,并且会玩得很开心。

现在让我们增加难度。在现实数据中,我们很少停留在两个维度。想象一个拥有几十个维度的派对,偏好包括音乐流派、食物选择、对话话题等。在这种情况下,每个偏好为我们的空间增加了一个新维度。

set1 = ["apple", "banana", "cherry", "date", "elderberry", "fig", "grape", "honeydew", "kiwi", "lemon"]

与此之下,第二组单词是随机的:

set2 = ["bolt", "cloud", "delta", "echo", "flare", "gamma", "horizon", "iceberg", "jet", "kinetic"]

下图显示了热力图。请注意,“apple”和“cloud”具有很强的相关性,而“elderberry”与任何单词几乎没有共同点:

图 4.6:语义相似性热图可视化

热力图的主要特征如下:

  • 模式识别:有助于识别数据内部相似和不相似的模式

  • 对比分析:便于简要比较多个嵌入

通过使用热力图,你将能够直观地评估哪些嵌入最相似,从而增强你理解数据内部关系的能力。

我们已经涵盖了一些关于向量的数学概念。现在是开始实战工作坊,并将我们的知识和编码能力应用于实践、尝试真实的 LLM 嵌入并计算语义相似性了。

实战工作坊:使用 Mistral 和 Pinecone 构建语义搜索系统

在此过程中,你将看到我们涵盖的概念(向量表示、相似性量和可视化)如何转化为可运行的代码。到结束时,你将拥有一个功能完备的语义搜索原型,并将其应用于自己的 AI 驱动项目中的技巧。

第 1 步:环境设置

克隆工作坊仓库

要访问本章使用的源文件,请开始克隆官方 GitHub 仓库:github.com/PacktPublishing/Learn-Mistral。

git clone https://github.com/PacktPublishing/Learn-Mistral.git

接下来,我们将打开Google Colab,直接在云端笔记本环境中开始工作。

打开 Google Colab

要开始,请访问 colab.research.google.com/ 打开Google Colab。你可以创建一个新笔记本,或者上传克隆的 GitHub 仓库中Chapter-4文件夹下提供的笔记本。

在整个工作坊中,我们将使用Colab运行代码示例、管理 API 密钥并与Mistral和Pinecone等服务交互。

对于涉及嵌入的练习,我们建议使用Google Colab提供的 GPU 运行时。利用GPU可以显著加快计算,使体验更加流畅且高效。

要在Google Colab中启用GPU,请执行以下操作:

  1. 进入菜单并选择运行时 (Runtime) | 更改运行时类型 (Change runtime type)。

  2. 在弹出的窗口中,从硬件加速器 (Hardware accelerator) 下拉菜单中选择 T4 GPU。下图展示了运行时选择的硬件选项:

https://github.com/OpenDocCN/freelearn-dl-zh/tree/master/docs/learn-mistral/img/B24489_04_07.png

  1. 点击保存 (Save)。

上传草稿笔记本

通过遵循笔记本,你将能够对电影描述运行嵌入,使用cosine similarity(余弦相似度)比较向量,并使用 t-SNE 和热力图等各种技术可视化结果。

第 2 步:初始化 Mistral AI 客户端

安装 mistralai 包

在你新建笔记本的第一个单元格中,输入以下命令来安装所需的库:

!pip install mistralai

点击播放按钮执行该命令。这将安装 Mistral AI 库,我们在整个练习都会使用它。最后的成功消息确认了安装完成:

Successfully installed eval-type-backport-0.2 jsonpath-python-1.0.6 mistralai-1.5.1 mypy-extensions-1.0.0 typing-inspect-0.9

现在 Mistral AI 库已安装,让我们开始初始化客户端。

作为测试,我们将检索并显示库提供的所有模型。我们将确保每个模型都换行打印,以便于阅读。

from mistralai import Mistral
# 实例化 Mistral 以创建一个客户端对象
client = Mistral()

# 使用客户端对象列出所有可用模型
models = client.models.list()
## 遍历模型列表并打印每个模型
for model in models.data:
    print(model.id)
  1. 导入Mistral客户端类:
from mistralai import Mistral
  1. 实例化Mistral客户端:
client = Mistral()
  1. 列出可用模型:
models = client.models.list()
  1. 换行打印每个模型:
for model in models:
    print(model)

最后,我们使用for循环遍历models列表并print每个模型。这确保每个模型都单独行显示,便于阅读。

输出将包含一个错误,这是预期之中的:

设置 Mistral API 密钥

开始之前,请访问 console.mistral.ai/api-keys 生成你的 API 密钥。如果你尚未登录,系统会提示你登录或创建账户。一旦 API 密钥准备就绪,返回 Colab 笔记本继续。

然后,按照以下步骤在 Google Colab 中设置 API 密钥:

  1. 在左侧边栏中找到并点击标题为Secrets的密钥图标。

  2. 点击+ Add new secret(添加新密钥)。

  3. 在Value字段中,粘贴真实的 Mistral API 密钥。

  4. 要允许访问,点击密钥旁边的三个点菜单并勾选Notebook access(笔记本访问)。

下图展示了在 Google Colab 界面中设置和管理密钥的过程。

图 4.8:Google Colab 密钥管理器

在本章后面,我们将以完全相同的方式配置和使用 Pinecone API 密钥。请确保你熟悉这种方法——它将成为一种模式。你现在也可以配置PINECONE_API_KEY。

from google.colab import userdata

from mistral import MistralClient
api_key = userdata.get("MISTRAL_API_KEY")

client = MistralClient(api_key)
models = client.models.list()

## 遍历模型列表并打印每个模型
for model in models.data:
    print(model.id)

预期的输出如下:

ministral-3b-2410 ministral-3b-latest ministral-8b-2410 ministral-8b-latest open-mistral-7b mistral-tiny mistral-tiny-2312 open-mistral-nemo open-mistral-nemo-2407 mistral-tiny-2407 mistral-tiny-latest open-mixtral-8x7b mistral-small mistral-small-2312 open-mixtral-8x22b open-mixtral-8x22b-2404 mistral-small-2402 mistral-small-2409 mistral-medium-2312 mistral-large-2402 mistral-large-2407 mistral-large-2411 mistral-large-latest pixtral-large-2411 pixtral-large-latest mistral-large-pixtral-2411 codestral-2405 codestral-2501 codestral-latest codestral-2412 codestral-2411-rc5 devstral-small-2505 devstral-small-latest codestral-mamba-2407 open-codestral-mamba codestral-mamba-latest pixtral-12b-2409 pixtral-12b pixtral-12b-latest mistral-small-2501 mistral-small-2503 mistral-small-latest mistral-saba-2502 mistral-saba-latest mistral-medium-2505 mistral-medium-latest mistral-medium mistral-embed mistral-moderation-2411 mistral-moderation-latest mistral-ocr-2503 mistral-ocr-2505 mistral-ocr-latest

对于我们的目的,我们将使用mistral-embed模型。现在工具已经准备绪,我们将转向生成驱动语义搜索和理解的嵌入(embeddings)。

第三步:生成嵌入

让我们从获取一个任意静态字符串的嵌入开始。我们将使用 Mistral AI 模型生成嵌入并检查响应结构。这将帮助我们理解嵌入是如何表示的,以及如何处理它们。

为单行生成嵌入

让我们逐行分析并学习代码。我们将获取一个示例句子的嵌入,清理响应,并打印嵌入数组的前几个元素以及其长度。

在第一行中,我们提供了示例句子并分配一个变量:

sample_sentence = "这是一横测试句子。"

然后我们定义了一个想要获取嵌入的示例句子。

要获取示例句子的嵌入,请使用以下代码:

sample_embed=client.embeddings.create(
    model='mistral-embed', input=[sample_sentence])

以下代码从结构化负载中提取所需的部分:嵌入数组:

clean_sample_embed = sample_embed.data[0].embedding

下一行打印嵌入数组的长度:

print(len(clean_sample_embed))

前一行代码产生了以下输出:

1024

我们打印了嵌入数组的长度。对于来自同一模型的所有响应,该长度是一致的,无论我们发送了多少单词(标记)——一个单词还一段文本。

下一行打印嵌入数组的前几个元素:

print(clean_sample_embed[:10])

在这里,我们打印了嵌入数组的前 10 个数字以检查数值。

[-0.032470703125, -0.002910614013671875, 0.06439208984375, 0.020599365234375, 0.00814056396484375, 0.021026611328125, 0.0465087890625, -0.003429412841796875, -0.022308349609375, -0.05792236328125]

上下文分析

上下文是理解句子中单词含义的关键元素,对于 Mistral 来说也是如此。在 Mistral 嵌入(embeddings)的语境下,它指的是目标词周围的词。这些周围词提供了关于目标词含义和用法的价值信息。例如,“bank”一词可以根据其上下文有不同的含义,如金融机构或河岸。

https://github.com/OpenDocCN/freelearn-dl-zh/tree/master/docs/learn-mistral/img/B24489_04_09.png

图 4.9:先验和未来上下文

正如我们在Figure 4.9中所示,在部分A中,之前的上下文是不同的,根据这些之前的词,可以清楚地判断它是球棒(bat)还是蝙蝠(bat)。在部分B中,之前的上下文是相同的,只有通过未来上下文才能确定它是哪种“bat”。在下一节中,我们将回顾先验上下文的作用。

之前的词在 Mistral 中的作用

在收集嵌入时,Mistral 会考虑之前的词,以帮助理解句子的结构和构建。这在具有强大语法规则的语言中尤为重要,因为词序会显著影响句子的含义。

在先验上下文分析中,只考虑位于目标词之前的词。这意味着一个词的嵌入完全受句子中前面词的影响。考虑Figure 4.9的部分A:“night bat”(夜蝙蝠)对比“baseball bat”(棒球棒)。

在night bat的情况下,这里单词“bat”紧跟在“night”之后:

  • 使用先验上下文的模型将为“bat”生成的嵌入将受到“night”的影响。

  • 由于“night”与夜行动物相关,“bat”的嵌入可能会反映与动物(会飞的哺乳类动物)相关的含义。

  • 单词“bat”紧跟在“baseball”之后。

  • 使用先验上下文的模型将为“bat”生成的嵌入将受到“baseball”的影响。

由于“baseball”与运动器材相关,“bat”的嵌入可能会反映与物体(运动器材)相关的含义。在这两种情况下,“bat”的含义都源于先前的词,导致在每种上下文中“bat”生成了不同的嵌入。

Mistral 对未来邻近词的考虑

除了之前的词之外,Mistral 在收集嵌入时还会考虑未来邻近词(位于目标词之后的词)。这是因为它们可以提供额外的上下文,帮助消除目标词含义的歧义。

让我们看看Figure 4.9的部分B:“I saw a bat flying over my house”(我看到一只蝙蝠飞过我家)对比“I saw a bat hitting the ball”(我看到击击球)。

在I saw a bat flying over my house的情况下,适用以下规则:

  • 目标词“bat”同时受到前面的词(“I saw a”)和后面的词(“flying over my house”)的影响。

  • 双向模型生成的“bat”嵌入将考虑完整的上下文,识别“flying”和“house”表示动物(会飞的哺乳类动物)。

  • 目标词“bat”同时受到前面的词(“I saw a”)和后面的词(“hitting the ball”)的影响。

  • 双向模型生成的“bat”嵌入将考虑完整的上下文,识别“hitting”和“ball”表示运动器材(棒球中使用的球棒)。

通过处理整个句子,bidirectional模型可以从周围的上下文准确确定单词“bat”的预期含义。

正如我们所见,上下文在 Mistral 的嵌入收集过程中起着至关重要的作用。之前的词和未来邻近词都提供了有助于确定目标词含义的价值信息。Mistral 的双向方法使其能够对语言有更全面的理解。

现在我们已经拆解了 Mistral 如何同时利用先验和未来上下文来构建嵌入,现在是将这些理解付诸实践了。在下一步中,我们将看到如何比较嵌入,根据语义相似性将用户输入与相关项进行匹配。

第 4 :嵌入比较

重申一下,我们将通过实践的方法来理解如何使用嵌入将用户查询与相关项进行匹配。具体而言,我们将开始为一组短小的菜肴描述及其成分生成嵌入。这将帮助我们看到不同的菜肴及其组件在嵌入空间中是如何被表示的。然后,我们将准备一种让用户输入他们的口味兴趣的方法,例如对某种食物的渴望或感兴趣特定成分。使用嵌入,我们将通过计算嵌入之间的余弦距离(cosine distance)来比较用户的输入与菜肴描述。与用户输入余弦距离最短的菜肴将是最相关的匹配项。

余弦距离帮助我们衡量用户兴趣与可用菜肴之间的相似性。距离越小,菜肴与用户寻找的内容越相似。这种方法利用嵌入的力量来有效地理解和匹配复杂的文本描述。准备好探索嵌入如何个性化推荐,并提供 AI 在日常场景中的实际应用!

让我们从初始化菜肴描述数组并为它们生成所有嵌入开始。

dish_descriptions = [
    "Grilled steak with garlic butter",       # 肉
    "Seared salmon with lemon dill sauce",    # 鱼
    "Roasted vegetable medley with herbs",    # 蔬菜
    "Tacos with spicy chicken and salsa",     # 墨西哥
    "Spicy chili con carne with beans",       # 辣
    "Chocolate lava cake with vanilla cream",  # 甜
    "Creamy tomato soup",                   # 液体
    "Cheeseburger with fries",                # 快餐
]
dish_embeds = client.embeddings.create(inputs=dish_descriptions)
dish_embeds_arr = []
for embed in dish_embeds.data:
    dish_embeds_arr.append(embed.embedding)
print(len(dish_embeds_arr[0]))

代码产生了以下输出:

10
1024

每个菜肴的嵌入都存储在一个大小为10的数组中,每个元素是一个大小为1024的浮点数数组。嵌入的顺序与dish_descriptions字符串数组对应。

读取输入用于语义比较

现在我们有了菜肴的嵌入,下一步是获取用户的偏好。我们将提示用户输入想吃什么,并使用相同的模型为他们的输入生成嵌入。这将允许我们将用户的偏好与预定义的描述进行比较并找到最相关的匹配。

为了实现,我们将使用以下代码:

user_input = input("What do you prefer for dinner? ")
user_embed = client.embeddings.create(
    model='mistral-embed', inputs=[user_input]).data[0].embedding
print(user_embed[:10])

Figure 4.10 显示了输入框。输入的值将被赋值给变量user_input:

https://github.com/OpenDocCN/freelearn-dl-zh/tree/master/docs/learn-mistral/img/B24489_04_10.png

输入后,代码将继续执行并产生输出:

What do you prefer for dinner? pizza

这段代码段将提示用户输入他们的晚餐偏好,为输入生成嵌入(embedding),并显示嵌入数组的前几个元素。这个过程帮助我们理解用户的偏好如何在嵌入空间中表示,为将这些偏好与我们的菜谱描述进行比较以找到最匹配的选项奠定基础。

步骤 5:用户输入与现有选项的语义匹配

首先,我们需要导入所需的库:

from scipy.spatial.distance import cosine

scipy.spatial.distance模块提供了cosine函数,它可以计算两个向量之间的余弦距离。余弦距离衡量的是不相似性,其中值为0表示向量相同,值为1表示向量完全不同。通过从1中减去余弦距离,我们可以将其转换为相似性度量,值越高表示相似性越高。

以下是将用户嵌入与菜谱描述中的第一个项目进行比较的代码段:

# 将用户嵌入与菜谱描述的嵌入比较
similarity_score = 1 - cosine(user_embed, dish_embeds_arr[0])
print(similarity_score)
0.6589278106354763

计算到所有可用嵌入的距离

现在我们已经知道如何比较一对嵌入了,让我们扩展比较范围以包含所有的菜谱描述。为了实现这一点,我们将使用来自scipy.spatial.distance模块的cdist函数,它可以计算两组向量之间的两两对距离。这允许我们一次性高效地计算用户嵌入与所有菜谱嵌入之间的余弦距离。

from scipy.spatial.distance import cdist
distances = cdist(user_embed, dish_embeds_arr, "cosine")

代码给出了以下输出:

--------------------_----------------------------------------------------
ValueError                              Traceback (most recent call)
<ipython-input-23-0b415054d20a> in <cell line:3>()
      1 from scipy.spatial.distance import cdist
----> 3 distances = cdist(user_embed, dish_embeds_arr, "cosine")
/usr/local/lib/python3.10/dist-packages/scipy/spatial/distance.py in cdist(XA, XB, metric, out, **kwargs)
   2980
   2981     if len(s) != 2:
-> 2982         raise ValueError('XA must be a 2-dimensional array.')
   2984         raise ValueError('XB must be a 2-dimensional array.')

然而,这段代码导致了:ValueError: XA must be a 2-dimensional array.。

# 重塑为 1N 数组
user_embed_reshaped = user_embed.reshape(1, -1)
distances = cdist(user_embed_reshaped, dish_embeds_arr, "cosine")

这会将用户的嵌入重塑为1x1024(假设嵌入大小为1024),使其与二维嵌入数组兼容。

寻找最相关的菜肴

import numpy as np
# 找到最相关菜肴的索引
most_relevant_index = np.argmin(distances)

要找到数组中项目最相关的索引,可以使用argmin方法:

most_relevant_index = np.argmin(distances)

显示最相关的语义匹配

找到最相关的索引只是完成了一半。让我们显示匹配的菜肴,让结果对用户一目了然。

print(f"Based on your preference,)
print(f"you might find tasty: {dish_descriptions[most_relevant_index]}")

此行打印most_relevant_index处的菜肴描述,为用户提供最符合其输入的菜肴。

以下是定位最接近项目的完整代码:

from scipy.spatial.distance import cosine, cdist
import numpy as np

distances = cdist(

# 最相关电影的索引 
mostRelevant = np.argmin(distances)
print(f"most relevant index: {mostRelevant}")
print(f"Then you might find tasty: {dish_descriptions[mostRelevant]}")

对于用户输入的值“hot dog”,该代码产生了以下输出:

most relevant index: 8

通过重塑用户的嵌入(embedding)、计算距离并识别最相关的菜肴,我们有效地将用户的偏好与我们数据集中最合适的菜肴描述匹配在了一起。

现在我们完成了一个闭环:从用户的纯文本偏好到从我们的数据集中提取语义匹配。这结束了单次查询匹配的闭环,并为我们在进一步扩展之前回顾整个过程做好了准备。

演示回顾

在这个端到端的演示中,我们初始化了Mistral AI客户端,捕获了用户的晚餐偏好(“热狗”),并生成了一个表示其语义含义的嵌入。随后,我们为几个预定义的菜肴准备了嵌入,并计算了用户输入与每个选项之间的余弦距离。通过识别最小距离,我们找到了最接近的语义匹配——“芝士汉堡”,这展示了 AI 如何意义地解释语言。结果不仅反映了关键词的相似性,还反映了共同的上下文和特征。此演示展示了如何使用嵌入和相似性量在实时应用中提供智能的感知推荐。

主要的端到端演示到此结束!让我们探索一些加分练习,以扩展和扩展我们所构建的内容。我们将从学习如何使用专用向量数据库Pinecone来扩展此系统开始。

加分练习:使用 Pinecone DB 进行语义搜索

在这个加分练习中,我们将探索如何使用Pinecone DB高效地管理和查询嵌入。Pinecone是一个强大的向量数据库,旨在处理高维向量数据,是存储和查询嵌入的理想选择。在本节中,我们将首先设置并初始化Pinecone客户端以与Pinecone DB服务交互。接下来,我们将在Pinecone中创建一个索引来存储我们的嵌入。索引类似于关系型数据库中的表,对于组织和查询数据至关重要。创建索引后,我们将嵌入插入到Pinecone索引中,将菜肴描述的向量表示上传到数据库。然后,我们将演示如何运行查询以寻找最近邻嵌入,帮助我们根据用户的输入识别最相关的项目。最后,我们将尝试Pinecone中提供的其他接近性算法(例如欧几里得距离和点积相似性),以查看它们如何影响结果。练习结束时,你将牢固地理解如何利用Pinecone DB管理和查询嵌入,并获得使用不同接近性算法的实战经验,以优化你的搜索能力。

要开始使用Pinecone DB,首先需要安装Pinecone客户端库。以下命令将从Python Package Index(PyPI)下载并安装必要的包。该库提供了与Pinecone向量数据库交互所需的工具和函数,使我们能够高效地创建索引、插入嵌入并运行查询。

初始化 Pinecone 客户端

我们将在当前的 colab 中使用pip包管理器安装Pinecone客户端:

!pip install pinecone

我们的下一个目标是初始化Pinecone客户端。这涉及设置 API 密钥并配置客户端与Pinecone服务交互。

首先,导入pinecone库:

import pinecone

接下来,为了与Pinecone服务进行身份验证,你需要使用之前处理MISTRAL_API_KEY时相同的方法提供你的Pinecone API 密钥。

假设你已经在 Google Colab Secret Manager 中添加了密钥并使其对笔记本可用,可以使用以下方式访问:

from pinecone import Pinecone, ServerlessSpec

api_key = userdata.get("PINONE_API_KEY")
pcone = Pinecone(api_key=api_key)

此代码安全地检索你的 API 密钥并初始化Pinecone客户端。Pinecone类用于与Pinecone向量数据库交互,而ServerlessSpec允许需要指定无服务器配置。

我们的Pinecone客户端已准备就绪。接下来,我们将创建一个新的索引来存储嵌入。

创建 Pinecone 索引

在存储和查询菜肴嵌入之前,我们需要确保Pinecone索引处于整洁且已知的状态。与其更新现有记录,不如删除任何同名的之前的索引并从头开始创建。

这种方法更快,并且避免了不必要的索引增长,如果你计划多次重复此练习时特别有用。

existing_index_names = [index.name for index in existing_indexes]

# 如果索引已存在,则删除
if 'dish-embeddings' in existing_index_names:
    pcone.delete_index('dish-embeddings')
### 创建新索引
pcone.create_index(
    name='dish-embeddings',
    dimension=1024,
    metric='cosine',
)
posted @ 2026-09-25 20:43  绝不原创的飞龙  阅读(12)  评论(0)    收藏  举报