微软官方推出的生成式人工智能(openai chatgpt )官方攻略(高级提示技巧)

微软官方推出了专门的AI课程,(该课程主要是模拟创建一个使用生成式AI技术的创业公司。) 一共包含12 课时的课程, 旨在教授初学者如何构建生成式AI应用;每节课都涵盖了AI原理和应用开发的关键。 前五章主要介绍何为生成式人工智能,以及一些高级的提示工程技巧,对我们日常应用帮助很大,后七章需要一些编码基础,如果只是了解和使用只看 前五节即可。

内容目录 隐藏

第一章 : 生成式人工智能和 LLMs 介绍

生成式人工智能是能够生成文本、图像和其他类型内容的人工智能。 它之所以成为一项出色的技术,是因为它使人工智能更通用化,任何人都可以使用它, 只需简单文本提示,使用自然语言编写的提示词。 你不需要学习 Java 或 SQL 这样的语言来完成一些有价值的事情,你只需要使用你的日常语言,描述需要的东西,然后LLMs就会给出相关建议。 其应用场景和影响是巨大的,您可以在几秒钟内完成写作或理解报告、编写应用程序等。

生成式人工智能模也称为 LLM,因为它们使用文本输入和输出的架构。 这些模型的有趣之处在于,它们经过来自书籍、文章和网站等不同来源的大量未标记数据的训练,可以适应各种各样的任务, 并以创造性的方式生成语法正确的文本。 因此,它们不仅极大地增强了机器“理解”输入文本的能力,而且使机器能够以人类语言生成原始响应。

LLMs 如何工作?

* **分词器,文本到数字**: 大型语言模型接收文本作为输入并生成文本作为输出。 然而,作为统计模型,它们对数字的处理效果对比起文本序列的处理效果要好得多。 这就是为什么模型的每个输入在被核心模型使用之前都由分词器处理。 标记是一段文本——由可变数量的字符组成,因此标记器的主要任务是将输入分割成标记数组。 然后,每个令牌都映射有一个令牌索引,该索引是原始文本块的整数编码。

* **预测输出标记**: 给定 n 个标记作为输入(最大 n 因模型而异),模型能够预测一个标记作为输出。 然后,该标记会以扩展窗口模式合并到下一次迭代的输入中,从而获得一个(或多个)句子作为答案,生成结果有更好的用户体验。 这解释了为什么如果您曾经使用过 ChatGPT,您可能会注意到有时它在生成结果时在句子中间出现停顿。

* **选择过程,概率分布**: 模型根据其在当前文本序列之后出现的概率来选择输出标记。 这是因为该模型预测了根据其训练计算出的所有可能的“下一个标记”的概率分布。 然而,并不总是从结果分布中选择概率最高的标记。 这种选择增加了一定程度的随机性,模型以非确定性方式运行——对于相同的输入,我们不会得到完全相同的输出。 添加这种程度的随机性是为了模拟人类创造性思维的过程,您可以使用称为温度的模型参数进行调整。

如何利用 LLMs

我们说过, LLMs 的主要功能是从头开始生成文本,从文本输入开始,用自然语言编写。

但是是什么样的文本输入和输出呢? 大型语言模型的输入称为提示,而输出称为补全,术语指的是生成下一个标记来完成当前输入的模型机制。 我们将深入探讨什么是提示以及如何设计它以充分和我们的模型进行交流。 但现在,我们假设提示可能包括:

* 通过一条**指令**,指定我们期望模型输出的类型。 该指令有时可能会嵌入一些示例或一些附加数据。

1. 文章、书籍、产品评论等的总结,以及从非结构化数据中提取见解。

 

2. 文章、论文、作业等的创意构思和设计。

* **问题**,以与代理对话的形式提出。

* **文本补全**,这隐含着对写作帮助的请求。

* **代码**解释和记录需求,或者要求生成执行特定任务的一段代码的注释。

以上的例子非常简单,并不是对生成式人工智能功能的详尽演示。 只是想展示使用生成式人工智能的潜力,并不局限于教育领域。

此外,生成式人工智能模型的输出并不完美,有时模型的创造力可能会对其产生不利影响,导致输出是人类用户可以将其解释为现实神秘化的单词组合, 或者具有攻击性。 生成式人工智能并不智能——至少在更全面的智能定义中是这样,包括批判性和创造性推理或情商; 它不是确定性的,也不值得信赖,因为错误的引用、内容和陈述等幻觉可能会与正确的信息结合起来,并以有说服力和自信的方式呈现。 接下来我们将处理所有这些限制,并了解可以采取哪些措施来降低影响。

第二章 : 探索和比较不同的 LLMs

认识不同的 LLMs

大型语言模型 (LLM) 可以根据其架构、训练数据和用例进行多种分类。 了解这些差异将有助于“Our startup”根据场景选择正确的模型, 并了解如何测试、迭代和提高性能。 LLM 模型有许多不同类型,您选择的模型取决于您的用途、您的数据、您准备支付的费用等等。 根据您是否打算使用模型进行文本、音频、视频、图像生成等,您可能会选择不同类型的模型。

– **音频和语音识别**。

为此,Whisper 模型是一个不错的选择,因为它们是通常用于语音识别。 它经过不同音频数据的训练,可以执行多语言语音识别。 例如,您可以使用所有的模型,从价格便宜但功能强大的模型(如 Curry)到更昂贵拥有高性能的达芬奇(Davinci)模型。 详细了解 [ Whisper 类型模型](https://platform.openai.com/docs/models/whisper?WT.mc_id=academic-105485-koreyst)。

– **图像生成**。 对于图像生成,DALL-E 和 Midjourney 是两个最佳的选择。

DALL-E 由 Azure OpenAI 提供。 [在此处阅读有关 DALL-E 的更多信息](https://platform.openai.com/docs/models/dall-e?WT.mc_id=academic-105485-koreyst) 以及本课程的第九章。

– **文本生成**。

大多数模型都经过文本生成训练,您有从 GPT-3.5 到 GPT-4 的多种选择。 它们的成本各不同,其中 GPT-4 是最昂贵的。 值得研究一下 [Azure OpenAI Playground](https://oai.azure.com/portal/playground?WT.mc_id=academic-105485-koreyst), 以评估哪些模型在功能和成本方面适合你的实际需求。 选择模型意味着您能获得一些基本功能,但这可能还不够。 通常,您有公司特定的数据,您需要以某种方式告诉 LLMs。 关于如何解决这个问题,有几种不同的选择,接下来的部分将详细介绍。

认识基础模型与 LLMs

“基础模型”是[由斯坦福大学研究人员创造](https://arxiv.org/abs/2108.07258?WT.mc_id=academic-105485-koreyst), 定义为遵循某些标准的人工智能模型,

例如:

– **他们使用无监督学习或自监督学习进行训练**,这意味着他们接受未标记的多模式数据的训练,并且他们的训练过程不需要人工注释或数据标记。

– **它们是非常大的模型**,基于经过数十亿参数训练的深度神经网络。

– **它们通常旨在作为其他模型的“基础”**,这意味着它们可以用作构建其他模型的起点,可以通过微调方式来完成。

图片来源:【基础模型和大语言模型基本指南| 巴巴尔·M·巴蒂 (Babar M Bhatti) | Medium] (https://thebabar.medium.com/essential-guide-to-foundation-models-and-large-language-models-27dab58f7404)

为了进一步阐明这种区别,我们以 ChatGPT 为例。 为了构建 ChatGPT 的第一个版本,名为 GPT-3.5 的模型作为基础模型。 这意味着 OpenAI 使用一些特定于聊天的数据来创建 GPT-3.5 的调整版本,专门用于在对话场景(例如聊天机器人)中让其有更好的表现。

图片来源:[2108.07258.pdf (arxiv.org)](https://arxiv.org/pdf/2108.07258.pdf?WT.mc_id=academic-105485-koreyst)

认识开源模型与专有模型

对 LLM 进行分类的另一种方法是它们是开源的还是专有的。开源模型是向公众开放并且任何人都可以使用的模型。

它们通常由创建它们的公司或研究团体提供。 这些模型可以针对 LLMs 的各种用例进行检查、修改和定制。

然而,它们并不总是针对生产用途进行优化,并且可能不如专有模型具备高性能。

此外,开源模型的资金可能有限,并且它们可能无法长期维护或可能无法根据最新研究进行更新。

流行的开源模型的例子包括

[Alpaca](https://crfm.stanford.edu/2023/03/13/alpaca.html)、

[Bloom](https://sapling.ai/llm/bloom)

和 [ LLaMA](https://sapling.ai/llm/llama?WT.mc_id=academic-105485-koreyst)。

专有模型是公司拥有的模型,不向公众提供。 这些模型通常针对生产用途进行了优化。

但是,不允许针对特定的使用场景进行检查、修改或定制它们。 另外,它们并不总是免费提供,可能需要订阅或付费才能使用。

此外,用户无法控制用于训练模型的数据,这意味着他们应该委托模型所有者确保对数据隐私和负责任地使用人工智能的承诺。 流行的专有模型的例子包括 [OpenAI 模型](https://platform.openai.com/docs/models/overview)、

[Google Bard](https://sapling.ai/llm/bard?WT.mc_id=academic-105485-koreyst)

或 [Claude 2] (https://www.anthropic.com/index/claude-2)。

认识嵌入式,图像生成,文本或代码生成

LLMs 还可以根据其产生的输出进行分类。 嵌入是一组可以将文本转换为数字形式的模型,称为嵌入,它是输入文本的数字表示。 嵌入使机器更容易理解单词或句子之间的关系,并且可以用作其他模型的输入,例如分类模型或对数值数据具有更好性能的聚类模型。 嵌入模型通常用于迁移学习,其中为有大量数据的代理任务构建模型,然后将模型权重(嵌入)重新用于其他下游任务。 此类别的一个示例是 [OpenAI 嵌入](https://platform.openai.com/docs/models/embeddings?WT.mc_id=academic-105485-koreyst)。

图像生成模型主要是用来生成图像。 这些模型通常用于图像编辑、图像合成和图像翻译。 图像生成模型通常在大型图像数据集上进行训练, 例如 [LAION-5B](https://laion.ai/blog/laion-5b/?WT.mc_id=academic-105485-koreyst), 并且可用于生成新图像或编辑现有图像 修复、超分辨率和着色技术。 如 [DALL-E-3](https://openai.com/dall-e-3) 和 [StableDiffusion](https://github.com/Stability-AI/StableDiffusion?WT.mc_id=academic-105485-koreyst)。

文本或代码生成模型主要是生成文本或代码。 这些模型通常用于文本摘要、翻译和问答。 文本生成模型通常在大型文本数据集上进行训练, 例如 [BookCorpus](https://www.cv-foundation.org/openaccess/content_iccv_2015/html/Zhu_Aligning_Books_and_ICCV_2015_paper.html), 并且可用于生成新文本或回答问题。 代码生成模型, 例如 [CodeParrot](https://huggingface.co/codeparrot?WT.mc_id=academic-105485-koreyst), 通常在大型代码数据集(如 GitHub)上进行训练,可用于生成新代码或修复现有代码中的错误。

了解编码-解码器与独立解码器

为了讨论 LLMs 的不同类型的架构,让我们来打个比方。

想象一下,您的经理给您一个为学生编写测验题目的任务。 您有两个同事; 一名负责监督内容的创建,另一名负责审查内容。

内容创建者就像一个独立解码器的模型,他们可以查看主题并查看您已经写的内容,然后他可以基于这些内容来编写课程。
他们非常擅长撰写引人入胜且内容丰富的内容,但不太擅长理解主题和学习目标。 独立解码器模型如 GPT 系列模型,例如 GPT-3。

审阅者就像一个独立编码器的模型,他们查看编写的课程和答案,注意它们之间的关系并通过上下文进行理解,但他们不擅于生成内容。独立编码器模型的一个例子是 BERT。

想象一下,我们也可以有人可以创建和审查测验,这是一个编码器-解码器模型如 BART 和 T5

理解服务与模型

现在,我们来谈谈服务和模型之间的区别。 服务是云服务提供商提供的产品,通常是模型、数据和其他组件的结合。 模型是服务的核心组件,通常是基础模型,例如各种 LLM。

服务通常针对生产环境进行了优化,并且通常比模型让用户通过图形界面使用。

但服务并不总是免费提供的,可能需要订阅或付费才能使用,以换取服务所有者的设备和相关资源,优化费用并轻松扩展。 服务的一个例子是

[Azure OpenAI 服务](https://learn.microsoft.com/azure/ai-services/openai/overview?WT.mc_id=academic-105485-koreyst),

它提供按需付费计划,意味着用户根据服务用量付费。

此外,Azure OpenAI Service 在模型功能上还提供企业级安全性和负责任的 AI 框架。

模型是带有参数、权重等的神经网络。 允许公司在本地运营需要购买设备、构建并购买许可证或使用开源模型。 像 LLaMA 这样的模型使用就需要额外的算力运行

如何使用不同的模型进行测试和迭代从而了解 Azure 上的运行性能

一旦我们的团队探索了当前的 LLMs 前景并为他们的场景确定了一些好的候选模型后,下一步就是根据他们的数据和工作负载行测试。

这是一个迭代过程,通过实验和量化来完成。
我们在前面的段落中提到的大多数模型(OpenAI 模型、Llama2 等开源模型和 Hugging Face transformers)都可以在

[Azure 机器学习工作室](https://ml.azure.com/?WT.mc_id=academic-105485-koreyst) 中的目录中找到

[基础模型](https://learn.microsoft.com/azure/machine-learning/concept-foundation-models?WT.mc_id=academic-105485-koreyst) 。

[Azure 机器学习](https://azure.microsoft.com/products/machine-learning/?WT.mc_id=academic-105485-koreyst) 是一项云服务, 专为数据科学家和机器学习工程师设计,用于管理整个机器学习生命周期(训练、测试、部署和 MLOps 相关的工作) 在一个平台上。 机器学习工作室为此服务提供图形用户界面,使用户能够: – 在目录中查找感兴趣的基础模型,按任务、许可证或名称进行过滤。 还可以导入尚未包含在目录中的新模型。 – 查看模型名片(包括详细描述和代码示例,并通过提供示例提示来测试结果),使用示例推理小部件对其进行测试。

– 使用特定工作负载和输入中提供的特定数据集的评估指标来评估模型性能。

– 利用 Azure 机器学习的实验和跟踪功能,根据自定义训练数据微调模型,以提高特定工作负载中的模型性能。

– 将原始预训练模型或微调版本模型部署到远程实时推理或批处理端点,以使应用程序能够直接使用。

提升 LLM 的输出结果准确度

我们与 “Our startup” 团队一起探索了不同类型的 LLMs 和云平台(Azure 机器学习),使我们能够比较不同的模型,根据测试数据对其进行评估,提高性能并将其部署在推理端点上。

但是他们什么时候应该考虑微调模型而不是使用预先训练的模型呢? 是否有其他方法可以提高模型在特定工作负载上的性能?

企业可以使用多种方法从 LLMs 获得所需的结果,您可以选择具有不同训练程度的不同类型的模型

在生产中部署 LLMs ,具有不同程度的复杂性、成本和质量。 以下是一些不同的方法:

– **根据上下文的提示工程**。

这个想法是在提示时提供足够的背景信息,以确保获得所需的结果。

– **检索增强生成,RAG**。

例如,您的数据可能存在于向量数据库或 Web 端点中,为了确保在提示时包含此数据或其子集,您可以获取相关数据并对用户进行提示。

– **微调模型**。

在这里,您根据自己的数据进一步训练模型,这使得模型更加准确并且能够响应您的需求,但可能成本高昂。

图片来源: [企业部署LLM的四种方式| Fiddler AI 博客](https://www.fiddler.ai/blog/four-ways-that-enterprises-deploy-llms?WT.mc_id=academic-105485-koreyst)

通过上下文的提示工程

预先训练的 LLMs 在广义自然语言任务上表现得非常好,甚至可以用简短的提示来调用它们,比如要完成的句子或问题——即所谓的“零样本”学习。

然而,用户越能通过详细的请求和示例(上下文)来构建他们的查询,就会得到最准确、最接近用户期望的答案。 在这种情况下,如果提示仅包含一个示例,我们讨论“单样本”学习;如果提示包含多个示例,我们讨论“少样本学习”。

根据上下文进行快速工程设计是最具成本效益的启动方法。

检索增强生成 (RAG)

LLMs 有一个限制,即他们只能使用训练期间使用过的数据来生成答案。 这意味着他们对训练过程后发生的事情一无所知,并且无法访问非公开信息(例如公司数据)。
这可以通过 RAG 来克服,RAG 是一种考虑提示长度限制的技术,以文档块的形式使用外部数据来增强提示。

矢量数据库工具

(例如 [Azure 向量搜索](https://learn.microsoft.com/azure/search/vector-search-overview?WT.mc_id=academic-105485-koreyst))

支持此功能,

可检索有用的信息来自各种预定义数据源的块并将它们添加到提示上下文中。

当企业没有足够的数据、足够的时间或资源来微调 LLMs,但仍希望提高特定工作负载的性能并减少幻觉的风险(即对现实的神秘化或有害的风险)时,此技术非常有用

微调模型

微调是一个利用迁移学习使模型“适应”下游任务或解决特定问题的过程。 与少样本学习和 RAG 不同,它会生成一个新模型,并更新权重和偏差。

它需要一组训练示例,其中包含单个输入(提示)及其关联的输出(完成)。

如果出现以下情况,这将是首选方法:

– **使用微调模型**。 企业希望使用经过微调能力较差的模型(例如嵌入模型)而不是高性能模型,从而获得更具成本效益和快速的解决方案。

– **考虑延迟**。 延迟对于特定用例很重要,因此不可能使用很长的提示,或者应该从模型中学习的示例数量不符合提示长度限制。

– **保持最新状态**。 企业拥有大量高质量的数据和真实标签,以及随着时间的推移保持这些数据最新所需的资源。

 

训练垂直行业模型

从头开始培训 LLMs 无疑是最困难、最复杂的方法,需要大量数据、熟练资源和适当的计算能力。

仅在企业具有特定领域的用例和大量以特定领域为中心的数据的情况下才应考虑此选项。

第三章 : 负责任地使用生成式人工智能

负责任的人工智能原则

生成式人工智能的热度非常高。 这种热度为这个领域带来了许多新的开发人员、关注和资金。
虽然这对于任何想要使用生成式人工智能构建产品和公司的人来说都是非常积极的,但我们负责任地行事也很重要。

在整个课程中,我们专注于构建“Our startup”和相关人工智能教育产品。
我们将使用负责任的人工智能的原则:公平、包容、可靠性/安全、安全和隐私、透明度和问责制。
根据这些原则,我们将探讨它们与我们在产品中使用生成式人工智能的关系。

为什么你应该优先考虑负责任的人工智能

在构建产品时,采取以人为本的方法并牢记用户的最大利益会带来最大爱意

生成式人工智能的独特性在于它能够为用户创建有用的答案、信息、指导和内容。 无需许多手动步骤即可完成此操作,这可以带来非常令人印象深刻的结果。 不幸的是如果没有适当的规划和策略,它也可能会给您的用户、产品和整个社会带来一些有害的结果。

让我们看看这些潜在有害结果中的一些(但不是全部)

幻觉

幻觉是一个术语,用于描述 LLMs 产生的内容要么完全无意义,要么根据给出其他错误的信息

举个例子,我们为“Our startup”构建了一个功能,允许学生向模型提出历史问题。 一名学生问“泰坦尼克号的唯一幸存者是谁?”

该模型产生如下响应:

![提示说“谁是泰坦尼克号的唯一幸存者”]

给出了一个非常确切的答案。 不幸的是,这是不正确的。 即使极少了解,人们也会发现泰坦尼克号幸存者不止一名。

但对于刚开始研究这个领域的学生来说,这个答案足以有说服力,不会被质疑并被视为事实。 这样做的后果可能会导致人工智能系统不可靠,并对我们初创公司的声誉产生负面影响。

在任何给定的 LLMs 的每次迭代中,我们都看到了在最大限度地减少幻觉方面的性能改进。 即使有了这样的改进,我们作为应用程序构建者和用户仍然需要意识到这些限制。

有害内容

我们在前面的部分中介绍了 LLMs 会产生不正确或毫无意义的回答。 我们需要注意的另一个风险是模型产生有害内容。

有害内容可以定义为:

– 提供指示或鼓励自残或伤害某些群体。
– 仇恨或侮辱性内容。
– 指导策划任何类型的攻击或暴力行为。
– 提供有关如何查找非法内容或实施非法行为的说明。
– 展示露骨的色情内容

对于我们的初创公司来说,我们希望确保拥有正确的工具和策略来防止学生看到此类内容。

 

缺乏公平性

公平的定义是“确保人工智能系统没有偏见和歧视,并公平、平等地对待每个人。” 在生成式人工智能的世界中,我们希望确保模型的输出不会强化边缘群体的排他性世界观。

这些类型的输出不仅会破坏为用户建立积极的产品体验,还会造成进一步对社会进行危害。 作为应用程序构建者,在使用生成式人工智能构建解决方案时,

我们应该始终牢记广泛且多样化的用户群。

如何负责任地使用生成式人工智能

现在我们已经确定了负责任的生成式人工智能的重要性,让我们看看我们可以采取的 4 个步骤来负责任地构建我们的人工智能解决方案:

衡量潜在危害

在软件测试中,我们测试用户对应用程序的预期操作。 同样,测试用户最有可能使用的一组不同的提示是衡量潜在危害的好方法。

由于“Our startup”正在开发教育产品,因此最好准备一份与教育相关的提示列表。 这可以涉及某个主题、历史事实和有关学生生活的提示。

减轻潜在危害

现在是时候寻找方法来预防或限制模型及其响应造成的潜在危害了。 我们可以从 4 个不同的层面来看待这个问题:

– **模型**

为正确的用例选择正确的模型。 当应用于更小、更具体的用例时,更大、更复杂的模型(例如 GPT-4)可能会导致更大的有害内容风险。

使用训练数据进行微调还可以降低有害内容的风险。

– **安全系统**

安全系统是平台上为模型服务的一组工具和配置,有助于减轻伤害。 Azure OpenAI Service 上的内容过滤系统就是一个例子。

系统还应该检测越狱攻击和不需要的活动,例如来自网络机器人的请求。

– **元提示**

元提示和基础是我们可以根据某些行为和信息指导或限制模型的方法。

这可以使用系统输入来定义模型的某些限制。 此外,提供与系统范围或领域更相关的输出。

它还可以使用检索增强生成 (RAG) 等技术,让模型仅从选定的可信来源中提取信息。

– **用户体验**

最后一层是用户通过应用程序界面以某种方式直接与模型交互的地方。

通过这种方式,我们可以设计 UI/UX 来限制用户可以发送到模型的输入类型以及向用户显示的文本或图像。

在部署人工智能应用程序时,我们还必须透明地了解我们的生成式人工智能应用程序可以做什么和不能做什么。

 

– **评估模型**

与 LLMs 合作可能具有挑战性,因为我们并不总是能够控制模型训练的数据。

无论如何,我们应该始终评估模型的性能和输出。 衡量模型的准确性、相似性、基础性和输出的相关性仍然很重要。 这有助于为应用相关人员和用户提供透明度和信任。

运营负责任的生成式人工智能解决方案

围绕人工智能应用程序构建操作实践是最后阶段。 这包括与“Our startup”的其他部门(例如法律和安全部门)合作,以确保我们遵守所有监管政策。 在发布之前,我们还希望围绕交付、处理事件和回滚制定计划,以防止扩大对用户造成的任何伤害。

 

相关工具

虽然开发负责任 AI 解决方案的工作量可能看起来很多,但这是值得付出的。

随着生成式人工智能领域的发展,更多帮助开发人员有效地将责任整合到工作流程中的工具将会更成熟。

如,[Azure AI 内容安全](https://learn.microsoft.com/azure/ai-services/content-safety/overview?WT.mc_id=academic-105485-koreyst )

可以通过 API 请求帮助检测有害内容和图像。

 

第四章:提示工程基础

如何撰写 LLM 的提示很重要,精心设计的提示可以比不精心设计的提示取得更好的结果。但这些概念到底是什么,提示、提示工程以及我如何改进我发送给 LLMs 的内容?诸如此类的问题正是本章和下一章想要解答的。

_生成式人工智能_能够根据用户请求创建新内容(例如文本、图像、音频、代码等)。

它使用 LLMs 来实现这一目标,例如 OpenAI 的 GPT 模型系列,这些模型通过使用自然语言和代码进行训练。

用户现在可以使用熟悉的语言(如聊天)与这些模型进行交互,而无需任何技术专业知识或培训。

这些模型是基于提示的——用户发送文本输入(提示)并获取人工智能响应(完成)。

然后,他们可以在多轮对话中迭代地“与人工智能聊天”,完善他们的提示,直到响应符合他们的预期。 “提示”现在成为生成式人工智能应用程序的主要_编程界面_,告诉模型要做什么并影响返回响应的质量。 “提示工程”是一个快速发展的研究领域,专注于提示的“设计和优化”,以大规模提供一致且高质量的响应。

学习沙盒

目前,提示工程更多的是玄学而不是科学提高我们直觉的最佳方法是“更多练习”并采用试错方法,将应用程序领域的专业知识与推荐的技术和特定于模型的优化相结合。

本课程附带的 Jupyter Notebook 提供了一个_沙盒_环境,您可以在其中尝试所学内容 – 边学边做,或者作为最后代码挑战的一部分。 要完成练习,您需要:

1. 设置 OpenAI API 密钥 – 已部署的 LLM 的服务端点。

2. Python 运行时 – 可以让 Notebook 运行。

我们使用一个带有 Python 3 运行时的开发容器来检测这个存储库。 只需在 GitHub Codespaces 或本地 Docker 桌面上打开 Repo,即可自动激活运行时。 然后打开笔记本并选择Python 3.x 内核以准备 Notebook。

默认 Notebook 设置为与 OpenAI API 密钥一起使用。 只需将文件夹根目录中的“.env.copy”文件复制到“.env”,并使用您的 API 密钥更新“OPENAI_API_KEY=”行 – 一切就完成了。

该 Notebook 附带入门练习 – 但我们鼓励您添加自己的Markdown描述)和代码(提示请求)部分来尝试更多示例或想法 – 并建立您对提示工程设计的感觉。

Our Startup 的使命

现在,让我们来谈谈这个主题与 Our Startup 的使命[将人工智能创新带入教育]有何关系

(https://educationblog.microsoft.com/2023/06/collaborating-to-bring-ai-innovation-to-education) 。

我们希望构建由人工智能驱动的个性化学习应用程序 – 所以让我们考虑一下我们应用程序的针对不同用户如何“设计”提示:

– **管理员**可能会要求人工智能分析课程数据以识别覆盖范围的差距_。 人工智能可以总结结果或用代码将其可视化。
– **教育者**可能会要求人工智能为目标受众和主题生成教学计划。 AI可以按照指定的格式构建个性化计划。
– **学生**可能会要求人工智能辅导他们学习困难的科目。 人工智能现在可以通过适合学生水平的课程、结合提示和示例来指导学生。

这只是冰山一角。

查看 [教育中的提示工程](https://github.com/microsoft/prompts-for-edu/tree/main?WT.mc_id=academic-105485-koreyst) –

一个由教育专家设计的开源提示库 ! 尝试在沙箱中运行其中一些提示或使用 OpenAI Playground 看看会产生什么结果!

<!–
LESSON TEMPLATE:
This unit should cover core concept #1.
Reinforce the concept with examples and references.

CONCEPT #1:
Prompt Engineering.
Define it and explain why it is needed.
–>

什么是提示工程?

在本章中,我们将**提示工程**定义为设计和优化文本输入(提示)的过程,以便为指定的应用程序目标和模型提供一致且高质量的响应(完成)。 我们可以将其视为一个两步过程:

– 设计指定模型和目标的初始提示
– 通过迭代的方式提炼提示语以提高响应质量

这必然是一个反复尝试的过程,需要用户的直觉和努力才能获得最佳结果。 那么为什么它很重要呢? 要回答这个问题,我们首先需要了解三个概念:

– _Tokenization_ = 模型如何“看到”提示
– _Base LLMs_ = 基础模型如何“处理”提示
– _Instruction-Tuned LLM_ = 模型现在如何查看“任务”

 

Tokenization

LLM 将提示视为标记序列,其中不同的模型(或模型的版本)可以以不同的方式对同一提示进行标记。

由于 LLM 是根据标记(而不是原始文本)进行训练的,因此提示标记化的方式对生成的响应的质量有直接影响。

要直观地了解标记化的工作原理,请尝试使用如下所示的 [OpenAI Tokenizer](https://platform.openai.com/tokenizer?WT.mc_id=academic-105485-koreyst) 等工具。

复制您的提示 – 并查看如何将其转换为标记,注意空白字符和标点符号的处理方式。

请注意,此例子显示的是较旧的 LLM (GPT-3) – 因此使用较新的模型尝试此操作可能会产生不同的结果。

概念: 基础模型

Once a prompt is tokenized, the primary function of the [“Base LLM”](https://blog.openai.com/an-introduction-to-base-and-instruction-tuned-large-language-models-8de102c785a6?WT.mc_id=academic-105485-koreyst) (or Foundation model) is to predict the token in that sequence. Since LLMs are trained on massive text datasets, they have a good sense of the statistical relationships between tokens and can make that prediction with some confidence. Not that they don’t understand the _meaning_ of the words in the prompt or token; they just see a pattern they can “complete” with their next prediction. They can continue predicting the sequence till terminated by user intervention or some pre-established condition.

Want to see how prompt-based completion works? Enter the above prompt into the Azure OpenAI Studio [_Chat Playground_](https://oai.azure.com/playground?WT.mc_id=academic-105485-koreyst) with the default settings. The system is configured to treat prompts as requests for information – so you should see a completion that satisfies this context.

But what if the user wanted to see something specific that met some criteria or task objective? This is where _instruction-tuned_ LLMs come into the picture.

一旦提示被标记化,[“Base LLM”]

(https://blog.gopenai.com/an-introduction-to-base-and-instruction-tuned-large-language-models-8de102c785a6?WT.mc_id=academic-105485-koreyst)的主要功能 (或基础模型)是预测该序列中的标记。

由于 LLMs 接受过大量文本数据集的训练,因此他们对标记之间的统计关系有很好的理解,并且可以自信地做出预测。 并不是说他们不理解提示或标记中单词的含义,他们只是看到了一个可以通过下一个预测“完成”的模式。 他们可以继续预测序列,直到被用户干预或某些预先设定的条件终止。

想了解基于提示补全是如何工作的吗? 使用默认设置将上述提示输入到 Azure OpenAI Studio [_Chat Playground_](https://oai.azure.com/playground?WT.mc_id=academic-105485-koreyst)。 系统配置会将提示视为信息请求 – 因此您应该看到满足此上下文的补全。

但是,如果用户想要查看满足某些标准或任务目标的特定内容怎么办? 这就是通过 LLMs 进行指令调整发挥作用的地方。

概念: LLMs 中的指令调整

[ LLMs 中的指令调整](https://blog.gopenai.com/an-introduction-to-base-and-instruction-tuned-large-language-models-8de102c785a6?WT.mc_id=academic-105485-koreyst) 从基础模型开始,并使用以下参数对其进行微调 可以包含明确指令的示例或输入/输出对(例如多轮“消息”),以及人工智能尝试遵循该指令的响应。

它使用诸如人类反馈强化学习 (RLHF) 之类的技术,可以训练模型“遵循指令”并“从反馈中学习”,从而产生更适合实际应用且与用户目标更相关的响应。

让我们尝试一下 – 重新访问上面的提示,但现在更改系统消息,提供以下指令作为上下文:

> _Summarize content you are provided with for a second-grade student. Keep the result to one paragraph with 3-5 bullet points._

看看现在如何调整结果以反映所需的目标和格式? 教育工作者现在可以直接在该课程的 ppt 中使用此结果。

为什么我们需要提示工程

现在我们知道了 LLMs 如何处理提示,让我们谈谈为什么我们需要提示工程。 答案在于,当前的 LLMs 的算法也有许多挑战,如果不及时优化,就很难实现“可靠且一致的补全”。 例如:

1. **模型响应是随机的。

**相同的提示可能会针对不同的模型或模型版本产生不同的响应。 甚至可能在不同时间使用相同模型产生不同的结果。 提示工程技术可以通过提供更好帮助我们最大限度地减少这些变化所带来的影响。

2. **模型可以产生幻觉响应。

**模型是使用大型但有限数据集进行预训练的,这意味着它们缺乏有关训练范围之外的概念的知识。 因此,它们可能会产生不准确、虚构或与已知事实直接矛盾的完成结果。 提示工程技术可以帮助用户识别和减轻幻觉,例如通过向人工智能询问出处或推理过程。

3. **模型功能会有所不同。

** 较新的模型或模型迭代将具有更丰富的功能,但也会带来独特的怪癖以及成本和复杂性方面的平衡。 提示工程可以帮助我们开发最佳实践和工作流程,以可扩展和无缝的方式消除差异并适应特定于模型的要求。

让我们看看 OpenAI 或 Azure OpenAI Playground 中的实际情况:

– 对不同的 LLM 部署(例如 OpenAI、Azure OpenAI、Hugging Face)使用相同的提示 – 您看到差异了吗?
– 对相同的 LLM 部署(例如 Azure OpenAI Playground)重复使用相同的提示 – 产生的结果有何不同?

幻觉示例

想了解幻觉是如何运作的吗? 想象一个提示,指示人工智能为不存在的主题生成内容(以确保在训练数据集中没有该信息)。 例如 – 我尝试了这个提示:

**Prompt:** generate a lesson plan on the Martian War of 2076.

网络搜索显示,有关于火星战争的虚构叙述(例如电视剧或书籍),但没有 2076 年的故事。常识还告诉我们,2076 年是“未来”,因此无法与真实事件联系起来。 那么,当我们对不同的 LLMs 提供者运行此提示时会发生什么? > **响应 1**: OpenAI Playground (GPT-35)

**响应 2**: Azure OpenAI Playground (GPT-35)

**响应 3**: : Hugging Face Chat Playground (LLama-2)

正如预期的那样,由于随机行为和模型能力变化,每个模型(或模型版本)都会产生略有不同的响应。

例如,一个模型针对八年级受众,而另一个模型则假设高中生。 但所有三个模型确实生成了可以让不知情的用户相信该事件是真实的响应

像元提示和温度配置这样的提示工程技术可以在一定程度上减少模型幻觉。 新的提示工程架构还将新工具和技术无缝地融入到提示流程中,以减轻或减少其中一些影响。

案例学习: GitHub Copilot

让我们通过一个案例研究来了解如何在实际解决方案中使用提示工程:[GitHub Copilot](https://github.com/features/copilot?WT.mc_id=academic-105485-koreyst)。

GitHub Copilot 是您的“AI 结对编程器” – 它将文本提示转换为代码补全,并集成到您的开发环境(例如 Visual Studio Code)中,以提供无缝的用户体验。

正如下面的系列博客中所述,最早的版本基于 OpenAI Codex 模型 – 工程师很快意识到需要微调模型并开发更好的提示工程技术,以提高代码质量。

7 月,他们 [首次推出了超越 Codex 模型的改进人工智能模型]

(https://github.blog/2023-07-28-smarter-more-efficient-coding-github-copilot-goes-beyond-codex-with-improved-ai-model/?WT.mc_id=academic-105485-koreyst) 以获得更快的建议。

按顺序阅读帖子,了解他们的成长过程

– **2023 年 5 月** | [GitHub Copilot is Getting Better at Understanding Your Code]

(https://github.blog/2023-05-17-how-github-copilot-is-getting-better-at-understanding-your-code/?WT.mc_id=academic-105485-koreyst)
– **2023 年 5 月** | [Inside GitHub: Working with the LLMs behind GitHub Copilot]

(https://github.blog/2023-05-17-inside-github-working-with-the-llms-behind-github-copilot/?WT.mc_id=academic-105485-koreyst).
– **2023 年 6 月** | [How to write better prompts for GitHub Copilot]

(https://github.blog/2023-06-20-how-to-write-better-prompts-for-github-copilot/?WT.mc_id=academic-105485-koreyst).
– **2023 年 7 月** | [.. GitHub Copilot goes beyond Codex with improved AI model]

(https://github.blog/2023-07-28-smarter-more-efficient-coding-github-copilot-goes-beyond-codex-with-improved-ai-model/?WT.mc_id=academic-105485-koreyst)
– **2023 年 7 月** | [A Developer’s Guide to Prompt Engineering and LLMs]

(https://github.blog/2023-07-17-prompt-engineering-guide-generative-ai-llms/?WT.mc_id=academic-105485-koreyst)
– **2023 年 9 月** | [How to build an enterprise LLM app: Lessons from GitHub Copilot]

(https://github.blog/2023-09-06-how-to-build-an-enterprise-llm-application-lessons-from-github-copilot/?WT.mc_id=academic-105485-koreyst)

您还可以浏览他们的[工程师博客](https://github.blog/category/engineering/?WT.mc_id=academic-105485-koreyst)以获取更多帖子,

例如[该链接](https://github.blog/2023-09-27-how-i-used-github-copilot-chat-to-build-a-reactjs-gallery-prototype/?WT.mc_id=academic-105485-koreyst) 展示了如何应用这些模型和技术来驱动现实世界的应用程序。

<!–
LESSON TEMPLATE:
This unit should cover core concept #2.
Reinforce the concept with examples and references.

CONCEPT #2:
Prompt Design.
Illustrated with examples.
–>

 

构建提示的方法

我们已经了解了为什么提示工程重要性 – 现在让我们了解提示是如何构建的,以便我们可以评估针对不同的技术以实现更有效的提示设计。

基础提示

让我们从基础提示开始:发送到模型的文本输入,没有其他上下文。 这是一个例子 – 当我们将美国国歌的前几个单词发送到

OpenAI [Completion API](https://platform.openai.com/docs/api-reference/completions?WT.mc_id=academic-105485-koreyst) 时,它会立即完成下一个单词的响应 几行,说明了基本的预测行为。

| Prompt (Input) | Completion (Output) |
|:—|:—|
| Oh say can you see | It sounds like you’re starting the lyrics to “The Star-Spangled Banner,” the national anthem of the United States. The full lyrics are … |

复杂的提示

现在让我们为基础提示添加上下文和说明。 [

Chat Completion API](https://learn.microsoft.com/azure/ai-services/openai/how-to/chatgpt?WT.mc_id=academic-105485-koreyst)

让我们可以将复杂的提示构建为集合 messages 包含:

– 反映用户输入和助理响应的输入/输出对。
– 系统消息设置助理行为或个性化。

该请求现在采用以下形式,其中标记化有效地从上下文和对话中捕获相关信息。 现在,更改系统上下文对补全质量的影响并与提供的用户输入一样。

“`python
response = openai.ChatCompletion.create(
model=”gpt-3.5-turbo”,
messages=[
{“role”: “system”, “content”: “You are a helpful assistant.”},
{“role”: “user”, “content”: “Who won the world series in 2020?”},
{“role”: “assistant”, “content”: “The Los Angeles Dodgers won the World Series in 2020.”},
{“role”: “user”, “content”: “Where was it played?”}
]
)
“`

指令式的提示

在上面的示例中,用户提示是一个简单的文本查询,可以解释为信息请求。 通过指令提示,我们可以使用该文本更详细地指定任务,从而为人工智能提供更好的指导。 这是一个例子:

| Prompt (Input) | Completion (Output) | Instruction Type |
|:—|:—|:—|
| Write a description of the Civil War | _returned a simple paragraph_ | Simple|
|Write a description of the Civil War. Provide key dates and events and describe their significance | _returned a paragraph followed by a list of key event dates with descriptions_| Complex |
|Write a description of the Civil War in 1 paragraph. Provide 3 bullet points with key dates and their significance. Provide 3 more bullet points with key historical figures and their contributions. Return the output as a JSON file | _returns more extensive details in a text box, formatted as JSON that you can copy-paste to a file and validate as needed_| Complex. Formatted. |

主要内容

在上面的示例中,提示仍然相当开放,允许 LLMs 决定其预训练数据集的哪一部分是相关的。 使用主要内容设计模式,输入文本分为两部分:

– 指令(动作)
– 相关内容(影响响应)

下面是一个示例,其中的指令是“用 2 句话总结这一点”。

“`text
| Prompt (Input) | Completion (Output) |
|:—|:—|
| Jupiter is the fifth planet from the Sun and the largest in the Solar System. It is a gas giant with a mass one-thousandth that of the Sun, but two-and-a-half times that of all the other planets in the Solar System combined. Jupiter is one of the brightest objects visible to the naked eye in the night sky, and has been known to ancient civilizations since before recorded history. It is named after the Roman god Jupiter.[19] When viewed from Earth, Jupiter can be bright enough for its reflected light to cast visible shadows,[20] and is on average the third-brightest natural object in the night sky after the Moon and Venus. <br/> **Summarize this in 2 short sentences** | Jupiter, the fifth planet from the Sun, is the largest in the Solar System and is known for being one of the brightest objects in the night sky. Named after the Roman god Jupiter, it’s a gas giant whose mass is two-and-a-half times that of all other planets in the Solar System combined. |
“`

主要内容片段可以通过多种方式使用来驱动更有效的指令:

– **示例** – 不要用明确的指令告诉模型要做什么,而是给它提供要做什么的示例,并让它进行推断。
– **暗示** – 遵循带有“暗示”的说明,引导完成,引导模型做出更相关的响应
– **模板** – 这些是带有占位符(变量)提示的可重复“配方”,可以使用特定用例的数据进行自定义。

 

用例方式

这种方法中,您使用主要内容来“向模型提供”给定指令所需输出的一些示例,并让它推断所需输出的模式。 根据提供的示例数量,我们可以有零样本提示、单样本提示、少样本提示等。

提示现在由三个部分组成:

– 任务描述
– 所需输出的一些示例
– 新示例的开始(成为隐式任务描述)

“`text
| Learning Type | Prompt (Input) | Completion (Output) |
|:—|:—|:—|
| Zero-shot | “The Sun is Shining”. Translate to Spanish | “El Sol está brillando”.|
| One-shot | “The Sun is Shining” => “”El Sol está brillando”. <br> “It’s a Cold and Windy Day” => | “Es un día frío y ventoso”. |
| Few-shot | The player ran the bases => Baseball <br/> The player hit an ace => Tennis <br/> The player hit a six => Cricket <br/> The player made a slam-dunk => | Basketball |
| | | |
“`

请注意,我们如何必须在零样本提示中提供明确的指令(“翻译为西班牙语”),但它是在一次提示示例中推断出来的。 这个少样本示例展示了如何添加更多示例来让模型在不添加指令的情况下做出更准确的推理。

 

提示模版

提示模板是预定义的提示配方,可以根据需要进行存储和重用,以大规模推动更一致的用户体验。 最简单的形式是,它只是一组提示示例的集合,

例如 [OpenAI 中的这个例子](https://platform.openai.com/examples?WT.mc_id=academic-105485-koreyst),

它提供了交互式提示组件(用户和系统消息)和 AP驱动请求格式来支持重用。

在它更复杂的形式中,

比如[LangChain的这个例子](https://python.langchain.com/docs/modules/model_io/prompts/prompt_templates/?WT.mc_id=academic-105485-koreyst),

它包含占位符,可以替换为来自各种来源的数据(用户 输入、系统上下文、外部数据源等)来动态生成提示。 这使我们能够创建一个可重用的提示库,可用于大规模地**以编程方式**驱动一致的用户体验。

最后,模板的真正价值在于能够为垂直应用程序领域创建和发布提示库 – 其中提示模板现在已优化以反映特定于应用程序的上下文或示例,使响应对于目标用户受众更加相关和准确 。 [Prompts For Edu](https://github.com/microsoft/prompts-for-edu?WT.mc_id=academic-105485-koreyst) repo 是这种方法的一个很好的例子,它为教育领域策划了一个提示库,重点关注课程计划等关键目标, 课程设计、学生辅导等

支持内容

如果我们将提示构建视为具有指令(任务)和目标(主要内容),那么次要内容_像我们提供的附加上下文**以某种方式影响输出**。 它可以是调整参数、格式化指令、主题分类法等,可以帮助模型定制其响应以适应所需的用户目标或期望。

例如:给定一个包含课程表中所有可用课程的广泛元数据(名称、描述、级别、元数据标签、讲师等)的课程目录:

– 我们可以定义一条指令来“总结 2023 年秋季课程目录”
– 我们可以使用主要内容来提供所需输出的一些示例
– 我们可以使用次要内容来识别最感兴趣的 5 个“标签”。

现在,该模型可以按照几个示例所示的格式提供摘要 – 但如果结果具有多个标签,它可以优先考虑辅助内容中标识的 5 个标签。

<!–
LESSON TEMPLATE:
This unit should cover core concept #1.
Reinforce the concept with examples and references.

CONCEPT #3:
Prompt Engineering Techniques.
What are some basic techniques for prompt engineering?
Illustrate it with some exercises.
–>

提示最佳实践

现在我们知道了如何构建提示,我们可以开始思考如何设计它们以反映最佳实践。 我们可以从两部分来思考这个问题——拥有正确的心态和采用正确的技术。

 

提示工程思维

提示工程是一个反复试验的过程,因此请记住三个广泛的指导因素:

1. **领域理解很重要。

** 响应准确性和相关性是应用程序或用户操作的与特定领域相关的函数。 运用您的直觉和领域专业知识进一步**定制技术**。 例如,在系统提示中定义特定于某个领域的个性化,或在用户提示中使用特定于某领域的模板。 提供反映特定领域上下文的辅助内容,或使用特定领域的提示和示例来指导模型走向熟悉的使用模式。

2. **模型理解很重要。

** 我们知道模型产生的结果本质上是随机的。 但模型实现也可能因它们使用的训练数据集(预先训练的知识)、它们提供的功能(例如,通过 API 或 SDK)以及它们优化的内容类型(例如,代码与图像与文本)。 了解您正在使用的模型的优点和局限性,并利用这些知识来确定任务的优先级或构建针对模型功能进行优化的自定义模板。

3. **迭代和验证很重要。

** 模型正在迅速发展,提示工程技术也在迅速发展。 作为领域专家,您可能有其他特定应用程序的背景或标准,这些背景或标准可能不适用于更广泛的社区。 使用提示工程工具和技术“快速启动”提示构建,然后使用您自己的直觉和领域专业知识迭代和验证结果。 记录您的见解并创建一个**知识库**(例如提示库),其他人可以将其用作新的基线,以便将来更快地迭代。

最佳实践

Now let’s look at common best practices that are recommended by [Open AI](https://help.openai.com/en/articles/6654000-best-practices-for-prompt-engineering-with-openai-api) and [Azure OpenAI](https://learn.microsoft.com/azure/ai-services/openai/concepts/prompt-engineering#best-practices?WT.mc_id=academic-105485-koreyst) practitioners.

现在让我们看看从业者推荐的常见最佳实践文档,包括

[Open AI](https://help.openai.com/en/articles/6654000-best-practices-for-prompt-engineering-with-openai-api) 和

[ Azure OpenAI](https://learn.microsoft.com/azure/ai-services/openai/concepts/prompt-engineering#best-practices?WT.mc_id=academic-105485-koreyst)

“`text
| What | Why |
|:—|:—|
| Evaluate the latest models. | New model generations are likely to have improved features and quality – but may also incur higher costs. Evaluate them for impact, then make migration decisions. |
| Separate instructions & context | Check if your model/provider defines _delimiters_ to distinguish instructions, primary and secondary content more clearly. This can help models assign weights more accurately to tokens. |
|Be specific and clear | Give more details about the desired context, outcome, length, format, style etc. This will improve both the quality and consistency of responses. Capture recipes in reusable templates. |
|Be descriptive, use examples |Models may respond better to a “show and tell” approach. Start with a `zero-shot` approach where you give it an instruction (but no examples) then try `few-shot` as a refinement, providing a few examples of the desired output. Use analogies.|
| Use cues to jumpstart completions | Nudge it towards a desired outcome by giving it some leading words or phrases that it can use as a starting point for the response.|
|Double Down | Sometimes you may need to repeat yourself to the model. Give instructions before and after your primary content, use an instruction and a cue, etc. Iterate & validate to see what works.|
| Order Matters | The order in which you present information to the model may impact the output, even in the learning examples, thanks to recency bias. Try different options to see what works best.|
|Give the model an “out” | Give the model a _fallback_ completion response it can provide if it cannot complete the task for any reason. This can reduce chances of models generating false or fabricated responses. |
| | |
“`

任何最佳实践一样,请记住,_您的结果可能会因模型、任务和领域而异。 使用这些作为起点,并迭代以找到最适合您的方法。 随着新模型和工具的出现,不断重新评估您的提示工程,重点关注该提示工程的可扩展性和响应质量。

<!–
LESSON TEMPLATE:
This unit should provide a code challenge if applicable

CHALLENGE:
Link to a Jupyter Notebook with only the code comments in the instructions (code sections are empty).

SOLUTION:
Link to a copy of that Notebook with the prompts filled in and run, showing what one example could be.
–>

第五章:创建高级的提示工程技巧

提示工程

提示工程是创建将产生所需结果的提示的过程。 提示工程不仅仅是编写文本提示。提示工程不是一门工程学科,它更像是一组可以应用以获得所需结果的技术。

一个例子

让我们看一个像这样的基本提示:

> Generate 10 questions on geography.

在这个提示中,实际上应用了一组不同的提示技巧。

让我们来分解一下。

– **上下文**,您指定它应该与“地理”有关。
– **限制输出**,您希望不超过 10 个问题。

简单提示的局限性

您可能会也可能不会得到想要的结果。 你会得到你的问题,但地理是一个大话题,你可能无法得到你想要的,原因如下:

– **大话题**,你不知道它是否会涉及国家、首都、河流等等。
– **格式**,如果您希望问题以某种方式格式化怎么办?

正如您所看到的,创建提示时需要考虑很多因素。

到目前为止,我们已经看到了一个简单的提示示例,但生成式人工智能能够为各种角色和行业的人们提供更多帮助。 接下来让我们探讨一些基本技术。

提示技巧

首先,我们需要了解提示是 LLM 的一个紧急属性,这意味着这不是模型中内置的功能,而是我们在使用模型时发现的东西

我们可以使用一些基本技巧来提示 LLM。 让我们来探索一下它们。

– **少样本提示**,这是最基本的提示形式。 这是一个带有几个示例的提示。

– **思维链**,这种类型的提示告诉 LLMs 如何将问题分解为步骤。

– **生成的知识**,为了提高提示的响应,您可以在提示中额外提供生成的事实或知识。

– **从最少到最多**,就像链式分析一样,这种技术是将问题分解为一系列步骤,然后要求按顺序执行这些步骤。

– **自我完善**,这种技术是修正 LLM 的输出,然后要求其改进。

– **多维度提示**。 您在这里想要的是确保 LLM 答案是正确的,并要求它解释答案的各个部分。 这是一种自我完善的形式。

少样本提示

这种提示风格非常简单,它可能由一个提示和几个示例组成。 当您开始学习 LLMs 时,您可能正在使用这种技术。 这是一个例子:

– Prompt: “What is Algebra?”
– Answer: “Algebra is a branch of mathematics that studies mathematical symbols and the rules for manipulating these symbols.”

思维链

思想链是一项非常有趣的技术,因为它涉及到 LLMs 的分步。 这个想法是以一种让 LLMs 了解如何做某种事情的方式来指导 LLMs。 考虑下面的例子,无论有没有思想链:

– Prompt: “Alice has 5 apples, throws 3 apples, gives 2 to Bob and Bob gives one back, how many apples does Alice have?”
– Answer: 5

LLM 给出的答案为 5,这是不正确的。 根据计算结果 (5 -3 -2 + 1 = 1),正确答案是 1 个苹果。

那么我们怎样才能教LLM正确地做到这一点呢?

让我们尝试一下思维链。 应用思维链意味着:

1. 给LLM一个类似的例子。
2. 展示计算结果,以及如何正确计算。
3. 提供原始提示。

 Prompt:

“Lisa has 7 apples, throws 1 apple, gives 4 apples to Bart and Bart gives one back:
7 -1 = 6
6 -4 = 2
2 +1 = 3
Alice has 5 apples, throws 3 apples, gives 2 to Bob and Bob gives one back, how many apples does Alice have?”

Answer: 1

请注意我们如何用另一个示例、计算和原始提示编写更长的提示,然后得出正确答案 1。

正如您所看到的,思维链是一种非常强大的技术。

生成的知识

很多时候,当您想要构建提示时,您希望使用自己公司的数据来实现。 您希望提示的一部分来自公司,另一部分应该是您感兴趣的实际提示。

举个例子,如果您从事保险业务,那么您的提示可能如下所示:

“`text
{{company}}: {{company_name}}
{{products}}:
{{products_list}}
Please suggest an insurance given the following budget and requirements:
Budget: {{budget}}
Requirements: {{requirements}}
“`

在上面,您可以看到如何使用模板构建提示。 模板中有许多变量,用“{{variable}}”表示,这些变量将替换为公司 API 中的实际值。

以下示例展示了变量被公司内容替换后提示的外观:

“`text
Insurance company: ACME Insurance
Insurance products (cost per month):
– Car, cheap, 500 USD
– Car, expensive, 1100 USD
– Home, cheap, 600 USD
– Home, expensive, 1200 USD
– Life, cheap, 100 USD

Please suggest an insurance given the following budget and requirements:
Budget: $1000
Requirements: Car, Home
“`

通过 LLM 运行此提示将产生如下响应:

“`output
, and Life insurance

Given the budget and requirements, we suggest the following insurance package from ACME Insurance:
– Car, cheap, 500 USD
– Home, cheap, 600 USD
– Life, cheap, 100 USD
Total cost: $1,200 USD
“`

正如您所看到的,它还建议购买人寿保险,但事实并非如此。 此结果表明我们需要通过更改提示来优化提示,使其更清楚地了解其允许的内容。 经过一些试验和错误之后,我们得到以下提示:

“`text
Insurance company: ACME Insurance
Insurance products (cost per month):
– type: Car, cheap, cost: 500 USD
– type: Car, expensive, cost: 1100 USD
– type: Home, cheap, cost: 600 USD
– type: Home, expensive, cost: 1200 USD
– type: Life, cheap, cost: 100 USD

Please suggest an insurance given the following budget and requirements:
Budget: $1000 restrict choice to types: Car, Home
“`

请注意添加 _type_ 和 _cost_ 以及使用关键字 _restrict_ 如何帮助 LLM 理解我们想要的内容。

现在我们得到以下响应:

“`output
Given the budget and requirements, we suggest the Car, Cheap insurance product which costs 500 USD per month.
“`

这个例子的目的是表明,即使我们使用像_生成知识_这样的基本技术,我们仍然需要在大多数情况下优化提示以获得所需的结果。

从少到多

从最少到最多提示的想法是将一个更大的问题分解为多个子问题。 这样,您就可以帮助指导 LLMs 如何“克服”更大的问题。 数据科学就是一个很好的例子,你可以要求 LLMs 来划分问题,如下所示:

> Prompt: How to perform data science in 5 steps?

你的人工智能助理会回答:

1. 收集数据
2. 清理数据
3. 分析数据
4. 绘制数据
5. 现有数据

自我完善,质疑结果

对于生成式人工智能和 LLMs,你不能相信其输出。 你需要验证一下。 毕竟, LLMs只是向您展示下一个最有可能说的话,而不是正确的内容。 因此,一个好主意是要求 LLMs 自我批评,这引导我们自我完善技术。

其工作原理是按照以下步骤操作:

1. 要求LLM解决问题的初始提示
2. LLM产生答案
3. 质疑答案并要求人工智能改进
4. LLM 再次回答,这次考虑了质疑并提出了解决方案

您可以根据需要多次重复此过程。

这是使用此技术的示例:

> Prompt: “Create a Python Web API with routes products and customers”

AI Answer:

```python
import flask
app = Flask(__name__)

@app.route('/products')
def products():
return 'Products'

@app.route('/customers')
def customers():
return 'Customers'
```

> Prompt: suggest 3 improvements of the above code

AI Answer:

“`text
Sure, here are three suggestions to improve the code:

Import the correct module: The first line should import Flask instead of flask. The correct import statement should be from flask import Flask.

Add a main function: Add a if __name__ == ‘__main__’: block to the end of the file to run the application when the file is executed.

Use f-strings: Use f-strings to format the return statements in the route functions. For example, return ‘Products’ can be changed to return f’This is the {request.path} page’.
“`

```python
from flask import Flask, request

app = Flask(__name__)

@app.route('/products')
def products():
return f'This is the {request.path} page'

@app.route('/customers')
def customers():
return f'This is the {request.path} page'

if __name__ == '__main__':
app.run()
```

正如您所看到的,由于对第一个答案的批评,上述人工智能响应正在改进第一个建议的代码。

多维度的提示

多维度的提示是一种类似于自我完善的技术,但它更多的是要求 LLMs 解释自己。 目标是减少 LLMs 输出不一致,以确保得出正确的答案。 要遵循的工作流程是:

1. 请 LLM 回答问题
2. 对于答案的每一部分,请LLM更深入地解释
3. 如果存在不一致,则丢弃不一致的部分

重复 2 和 3,直到您完成所有部分并对答案感到满意为止。

> prompt: How can I create a crisis plan to mitigate for a pandemic in 5 steps?
LLM answer:

“`text
1. Identify the risks
1. Identify the stakeholders
1. Identify the resources
1. Identify the actions
1. Identify the communication channels
“`

它确定了 5 个步骤,但是我们可以确定这是否正确吗? 让我们请LLM解释一下每一步:

> prompt: Explain the first step in more detail, what are the risks in detail with a pandemic?

“`text
The risks are the following:

– Loss of life
– Loss of business
– Loss of reputation
– Loss of customers
– Loss of employees
“`

此时,我们希望确保 LLM 是正确的,因此我们要求它更详细地解释第一个风险,并希望它与上面的答案一致:

> prompt: In a Pandemic, which is the biggest risk and why?

“`text
The biggest risk is loss of life because it’s the most important thing to protect.
“`

> What are the two biggest risks in a pandemic?

“`text
The two biggest risks are loss of life and loss of business.
“`

在这一点上,LLMs 是一致的,并提到“生活”和“商业”是两大风险。 我们现在可以继续下一步并感到相当有信心。 然而,我们不应该盲目相信 LLM,我们应该始终验证输出。

改变您的输出

LLM 本质上是不确定的,这意味着每次运行相同的提示时都会得到不同的结果。 例如尝试以下提示:

> "Generate code for a Python Web API"

```text
# Import necessary modules
import flask
from flask import request, jsonify

# Create a Flask app
app = flask.Flask(__name__)

# Create a route for the API
@app.route('/api', methods=['GET'])
def api():
# Get the data from the request
data = request.args

# Process the data
result = process_data(data)

# Return the result as JSON
return jsonify(result)

# Function to process the data
def process_data(data):
# Do something with the data
result = data + 1

# Return the result
return result

# Run the app
if __name__ == '__main__':
app.run()

```

再次运行相同的提示会生成略有不同的响应:

```text
#import necessary packages
import flask
from flask import request, jsonify

#create the Flask application
app = flask.Flask(__name__)
app.config["DEBUG"] = True

#create a list of books
books = [
{'id': 0,
'title': 'A Fire Upon the Deep',
'author': 'Vernor Vinge',
'first_sentence': 'The coldsleep itself was dreamless.',
'year_published': '1992'},
{'id': 1,
'title': 'The Ones Who Walk Away From Omelas',
'author': 'Ursula K. Le Guin',
'first_sentence': 'With a clamor of bells that set the swallows soaring, the Festival of Summer came to the city Omelas, bright-towered by the sea.',
'published': '1973'},
{'id': 2,
'title': 'Dhalgren',
'author': 'Samuel R. Delany',
'first_sentence': 'to wound the autumnal city.',
'published': '1975'}
]

#create an endpoint for the API
@app.route('/', methods=['GET'])
def home():
return '''<h1>Books API</h1>
<p>A prototype API for retrieving books.</p>'''

#create an endpoint to return all books
@app.route('/api/v1/resources/books/all', methods=['GET'])
def api_all():
return jsonify(books)

#create an endpoint to return a single book
@app.route('/api/v1/resources/books', methods=['GET'])
def api_id():
#check if an ID was provided as part of the URL
#if ID is provided, assign it to a variable
#if no ID is provided, display an error
if 'id' in request.args:
id = int(request.args['id'])
else:
return "Error: No id field provided. Please specify an id."

#create an empty list for our results
results = []

#loop through the data and match results that fit the requested ID
#IDs are unique, but other fields might return many results
for book in books:
if book['id'] == id:
results.append(book)

#use the jsonify function from Flask to convert our list of
#Python dictionaries to the JSON format
return jsonify(results)

app.run()
```

> So is the varied output a problem?

取决于你想做什么。 如果你想要一个具体的回应,那就是一个问题。 如果您可以接受诸如“生成任意 3 个地理问题”之类的不同输出,那么这不是问题。

利用温度来改变输出

好的,所以我们决定将输出限制为更可预测,即更具确定性。 我们该怎么做呢?

温度是 0 到 1 之间的值,其中 0 最具确定性,1 最具变化性。 默认值为 0.7。 让我们看看在温度设置为 0.1 的情况下两次运行相同的提示会发生什么:

> "Generate code for a Python Web API"

```python
#import necessary libraries
import flask
from flask import request, jsonify

#create an instance of the Flask class
app = flask.Flask(__name__)

#create an endpoint for the API
@app.route('/api/v1/endpoint', methods=['GET'])
def api_endpoint():
#get the request data
data = request.get_json()

#process the data
result = process_data(data)

#return the result
return jsonify(result)

#function to process the data
def process_data(data):
#process the data
result = {'result': 'success'}

#return the result
return result

#run the Flask app
if __name__ == '__main__':
app.run()

```

再次运行提示符会给我们这样的结果:

```python
#import necessary libraries
import flask
from flask import request, jsonify

#create a Flask app
app = flask.Flask(__name__)

#create a route for the API
@app.route('/api', methods=['GET'])
def api_call():
#get the data from the request
data = request.get_json()

#process the data
result = process_data(data)

#return the result
return jsonify(result)

#define the process_data function
def process_data(data):
#do something with the data
result = data + 1

#return the result
return result

#run the app
if __name__ == '__main__':
app.run()

```

这两个输出之间只有很小的差异。 这次我们反其道而行之,将温度设置为 0.9:

```python
# Import necessary libraries
import flask
from flask import request, jsonify

# Create a Flask app
app = flask.Flask(__name__)

# Create a route for the API
@app.route('/api', methods=['GET'])
def api_call():
# Get the data from the request
data = request.args

# Process the data
result = process_data(data)

# Return the result
return jsonify(result)

# Function to process the data
def process_data(data):
# Do something with the data
result = data + 1

# Return the result
return result

# Run the app
if __name__ == '__main__':
app.run()

```

第二次尝试使用 0.9 作为温度值:

“`python import flask from flask import request, jsonify # create the Flask app app = flask.Flask(__name__) app.config[‘DEBUG’] = True # create some test data books = [ {‘id’: 0, ‘title’: ‘A Fire Upon The Deep’, ‘author’: ‘Vernor Vinge’, ‘first_sentence’: ‘The coldsleep itself was dreamless.’, ‘year_published’: ‘1992’}, {‘id’: 1, ‘title’: ‘The Ones Who Walk Away From Omelas’, ‘author’: ‘Ursula K. Le Guin’, ‘first_sentence’: ‘With a clamor of bells that set the swallows soaring, the Festival of Summer came to the city Omelas, bright-towered by the sea.’, ‘published’: ‘1973’}, {‘id’: 2, ‘title’: ‘Dhalgren’, ‘author’: ‘Samuel R. Delany’, ‘first_sentence’: ‘to wound the autumnal city.’, ‘published’: ‘1975’} ] # create an endpoint @app.route(‘/’, methods=[‘GET’]) def home(): return ”'<h1>Welcome to our book API!</h1>”’ @app.route(‘/api/v1/resources/books “`

正如您所看到的,结果各式各样。

> 请注意,您可以更改更多参数来改变输出,例如 top-k, top-p, repetition penalty, length penalty and diversity penalty ,但这些不属于本课程的范围。

最佳实践

您可以应用许多实践来尝试获得您想要的东西。 当你越来越多地使用提示时,你会发现自己的风格。

除了我们介绍的技术之外,在调用 LLMs 时还需要考虑一些好的做法。

以下是一些值得考虑的良好做法:

– **指定上下文**。 上下文很重要,您可以指定的领域、主题等越多越好。

– 限制输出。 如果您想要特定数量的项目或特定长度,请指定。

– **指定内容和方式**。 请记住提及您想要什么以及您想要如何实现,例如“创建一个包含路由产品和客户的 Python Web API,将其分为 3 个文件”。

– **使用模板**。 通常,您会希望使用公司的数据来丰富提示。 使用模板来执行此操作。 模板可以包含用实际数据替换的变量。

– **拼写正确**。 LLMs 可能会为您提供正确的答案,但如果您拼写正确,您会得到更好的答案。

第六章:创建文本生成应用

什么是文本生成应用

一般来说当您构建应用程序时,它具有某种界面,如下所示:

– 基于命令。 控制台应用程序是典型的应用程序,您可以在其中键入命令并执行任务。 例如,“git”是一个基于命令的应用程序。
– 用户界面(UI)。 某些应用程序具有图形用户界面 (GUI),您可以在其中单击按钮、输入文本、选择选项等。

 传统控制台和 UI 应用程序的局限性

将其与输入命令的传统应用程序进行比较:

– **存在局限性**。 您不能输入任意命令,只能键入该应用程序支持的命令。
– **特定于某种语言**。 某些应用程序支持多种语言,但默认情况下,即使可以添加更多语言支持,该应用程序也是针对有限的语言构建的。

文本生成应用程序的优势

文本生成应用程序有何不同呢?

在文本生成应用程序中,您拥有更大的灵活性,不再局限于一组特定的命令或特定的输入语言。 相反,您可以使用自然语言与应用程序交互。 另一个好处是,因为您已经在与经过大量信息库训练的数据源进行交互,而传统应用程序可能仅限于在数据库中存储的有限内容。

使用文本生成应用程序构建什么?

您可以创建很多东西。 例如:

– **聊天机器人** 回答有关您的公司及其产品等主题的问题的聊天机器人可能是一个不错的选择。
– **协同助手** LLMs 擅长总结文本、从文本中获取见解、生成简历等文本等。
– **代码助手** 根据您使用的编程语言模型,您可以构建一个代码助手来帮助您编写代码。 例如,您可以使用 GitHub Copilot 和 ChatGPT 等产品来帮助您编写代码。

如何入门?

您需要找到一种与 LLMs 结合的方法,通常使用以下两种方法:

– API 在这里,您将根据提示构建 Web 请求并返回生成的文本。
– Libraries 库有助于封装 API 调用并使其更易于使用。

Libraries/SDKs

有一些比较通用的与 LLMs 整合的 librarys,例如:

– **openai**,这个 librarys 可以轻松连接到您的模型并发送提示。

还有一些在更高级别的框架运行的 librarys,例如:

– **Langchain**。 Langchain 支持 Python 比较通用的 library
– **Semantic Kernel**。 Semantic Kernel 是 Microsoft 提供的一个 library,支持 C#、Python 和 Java 语言。

人生中第一个 openai 应用

Let’s see how we can build our first app, what libraries we need, how much is required and so on.

让我们看看如何构建人生中第一个 openai 应用,我们需要哪些libraries,需要多少技能等等。

安装 openai

There are many libraries out there for interacting with OpenAI or Azure OpenAI. It’s possible to use numerous programming languages as well like C#, Python, JavaScript, Java and more. We’ve chosen to use the `openai` Python library, so we’ll use `pip` to install it.

有许多 libraries 可用于与 OpenAI 或 Azure OpenAI 交互。 还可以使用不同的编程语言,如 C#、Python、JavaScript、Java 等。 我们选择使用 `openai` Python 库,通过 `pip` 来安装它。

```bash
pip install openai
```

创建资源

您需要执行以下步骤:

– 在 Azure [https://azure.microsoft.com/free/](https://azure.microsoft.com/free/?WT.mc_id=academic-105485-koreyst) 上创建帐户。
– 访问 Azure Open AI。

进入到 [https://learn.microsoft.com/azure/ai-services/openai/overview#how-do-i-get-access-to-azure-openai](https://learn.microsoft.com/azure/ai-services/openai/overview#how-do-i-get-access-to-azure-openai?WT.mc_id=academic-105485-koreyst) 并请求访问权限。

> [!注意]
> 您需要申请访问 Azure Open AI Service 的访问。

– 安装 Python <https://www.python.org/>
– 已创建 Azure OpenAI 服务。 请参阅本指南,了解如何[创建资源](https://learn.microsoft.com/azure/ai-services/openai/how-to/create-resource?pivots=web-portal?WT.mc_id=academic-105485-koreyst).

添加 API key and endpoint

您需要告诉“openai”库要使用什么 API key。 要查找 API key ,请转到创建好的 Azure Open AI Service 中的 “Keys and Endpoint”部分并复制 “Key 1” 值。

![Keys and Endpoint resource blade in Azure Portal](https://learn.microsoft.com/azure/ai-services/openai/media/quickstarts/endpoint.png?WT.mc_id=academic-105485-koreyst)

复制 Key 后,让我们调用 libraries 使用它。

> [!注意]
> 通过设置环境变量将 API Key 与代码分开是很重要的
>
> – 为您的 API key 中设置 `OPENAI_API_KEY`
> – `export OPENAI_API_KEY=’sk-…’`

配置 Azure 环境

如果您使用 Azure OpenAI , 请按照以后步骤进行设置

```python
openai.api_type = 'azure'
openai.api_key = os.environ["OPENAI_API_KEY"]
openai.api_version = '2023-05-15'
openai.api_base = os.getenv("API_BASE")
```

设置相关的补充

– `api_type` 为 `azure`. 这告诉 librarys 使用 Azure Open AI 而不是 OpenAI。
– `api_key`, 对应 Azure Portal 中的 API Key
– `api_version`, 这是您要使用的 API 版本。 在撰写本文时,最新版本是’2023-05-15’。
– `api_base`, 这是 API 的 endpoint 。 您可以在 Azure Portal 中 API Key 下方找到它。

> [注意]
> `os.getenv` 是一个读取环境变量的函数。 您可以使用它来读取“OPENAI_API_KEY”和“API_BASE”等环境变量。 在终端中或使用“dotenv”等库设置这些环境变量。

文字生成

生成文本的方法是使用“Completion”类。 这是一个例子:

```python
prompt = "Complete the following: Once upon a time there was a"

completion = openai.Completion.create(model="davinci-002", prompt=prompt)
print(completion.choices[0].text)
```

在上面的代码中,我们创建一个 completion 对象并传入我们要使用的模型和提示。 然后我们输出生成的文本。

聊天补全

到目前为止,您已经了解了我们如何使用“Completion”来生成文本。 但还有另一个更适合聊天机器人的类,称为“ChatCompletion”。 这是例子:

```python
import openai

openai.api_key = "sk-..."

completion = openai.ChatCompletion.create(model="gpt-3.5-turbo", messages=[{"role": "user", "content": "Hello world"}])
print(completion.choices[0].message.content)
```

下一章将详细介绍此功能。

练习 – 您的人生中首个文本生成应用

现在我们已经了解了如何设置和配置 openai,是时候构建您的第一个文本生成应用程序了。 请按照下列步骤操作:

1. 创建虚拟环境并安装openai:

```bash
python -m venv venv
source venv/bin/activate
pip install openai
```

> [!注意]
> 如果您使用的是 Windows,请输入 `venv\Scripts\activate` 而不是 `source venv/bin/activate`。

> [!注意]
> 转至 [https://portal.azure.com/](https://portal.azure.com/?WT.mc_id=academic-105485-koreyst)

找到您的 Azure Open AI Key ,在资源中搜索“Open AI” ` 并选择“打开 AI 资源”,然后选择 `Keys and Endpoint` 并复制 `Key 1` 值。

2. 创建 *app.py* 文件并添加以下代码:

```python
import openai

openai.api_key = "您的 openai key 或 Azure OpenAI key"

openai.api_type = 'azure'
openai.api_version = '2023-05-15'
openai.api_base = "您的 Azure OpenAI Endpoint"
deployment_name = "部署模型的名字"

# add your completion code
prompt = "Complete the following: Once upon a time there was a"

# make completion
completion = openai.Completion.create(engine= deployment_name, model="davinci-002", prompt=prompt)

# print response
print(completion.choices[0].text)
```

> [!注意]
> 如果您使用的是 Azure Open AI,则需要将 `api_type` 设置为 `azure`,并将 `api_key` 设置为您的 Azure Open AI Key

您应该看到如下所示的输出结果:

```output
very unhappy _____.

Once upon a time there was a very unhappy mermaid.
```

不同类型的提示,针对不同的事情

现在您已经了解了如何使用提示生成文本。 您甚至可以启动并运行一个程序,可以对其进行修改以生成不同类型的文本。

提示可用于各种任务。 例如:

– **生成一种类型的文本**。 例如,生成一首诗、测验题目等。
– **查找信息**。 您可以使用提示来查找信息,例如以下示例’What does CORS mean in web development?’。
– **生成代码**。 您可以使用提示来生成代码,例如开发用于验证电子邮件的正则表达式,或者为什么不生成整个程序,例如web 应用?

进阶学习:菜谱生成器

想象一下,你家里有食材,你想煮点东西。 为此,你需要一个食谱。 查找食谱的一种方法是使用搜索引擎,或者您可以使用 LLMs 来这样做。

你可以这样写一个提示:

> “Show me 5 recipes for a dish with the following ingredients: chicken, potatoes, and carrots. Per recipe, list all the ingredients used”

鉴于上述提示,您可能会得到类似于以下结果:

“`output
1. Roasted Chicken and Vegetables:
Ingredients:
– 4 chicken thighs
– 2 potatoes, cut into cubes
– 2 carrots, cut into cubes
– 2 tablespoons olive oil
– 2 cloves garlic, minced
– 1 teaspoon dried thyme
– 1 teaspoon dried oregano
– Salt and pepper, to taste

1. Chicken and Potato Stew:
Ingredients:
– 2 tablespoons olive oil
– 1 onion, diced
– 2 cloves garlic, minced
– 2 chicken breasts, cut into cubes
– 2 potatoes, cut into cubes
– 2 carrots, cut into cubes
– 1 teaspoon dried oregano
– 1 teaspoon dried thyme
– 1 cup chicken broth
– Salt and pepper, to taste

1. Chicken and Potato Bake:
Ingredients:
– 2 tablespoons olive oil
– 2 chicken breasts, cut into cubes
– 2 potatoes, cut into cubes
– 2 carrots, cut into cubes
– 1 onion, diced
– 2 cloves garlic, minced
– 1 teaspoon dried oregano
– 1 teaspoon dried thyme
– 1 cup chicken broth
– Salt and pepper, to taste

1. Chicken and Potato Soup:
Ingredients:
– 2 tablespoons olive oil
– 1 onion, diced
– 2 cloves garlic, minced
– 2 chicken breasts, cut into cubes
– 2 potatoes, cut into cubes
– 2 carrots, cut into cubes
– 1 teaspoon dried oregano
– 1 teaspoon dried thyme
– 4 cups chicken broth
– Salt and pepper, to taste

1. Chicken and Potato Hash:
Ingredients:
– 2 tablespoons olive oil
– 2 chicken breasts, cut into cubes
– 2 potatoes, cut into cubes
– 2 carrots, cut into cubes
– 1 onion, diced
– 2 cloves garlic, minced
– 1 teaspoon dried oregano
“`

结果很好,我知道该怎么做菜了。但希望有更进一步的改进是:

– 过滤掉我不喜欢或过敏的成分。
– 制作一份购物清单,以防我家里没有所有原料。

针对上述情况,我们添加一个额外的提示:

> “Please remove recipes with garlic as I’m allergic and replace it with something else. Also, please produce a shopping list for the recipes, considering I already have chicken, potatoes and carrots at home.”

现在你有了一个新的结果,即:

“`output
1. Roasted Chicken and Vegetables:
Ingredients:
– 4 chicken thighs
– 2 potatoes, cut into cubes
– 2 carrots, cut into cubes
– 2 tablespoons olive oil
– 1 teaspoon dried thyme
– 1 teaspoon dried oregano
– Salt and pepper, to taste

1. Chicken and Potato Stew:
Ingredients:
– 2 tablespoons olive oil
– 1 onion, diced
– 2 chicken breasts, cut into cubes
– 2 potatoes, cut into cubes
– 2 carrots, cut into cubes
– 1 teaspoon dried oregano
– 1 teaspoon dried thyme
– 1 cup chicken broth
– Salt and pepper, to taste

1. Chicken and Potato Bake:
Ingredients:
– 2 tablespoons olive oil
– 2 chicken breasts, cut into cubes
– 2 potatoes, cut into cubes
– 2 carrots, cut into cubes
– 1 onion, diced
– 1 teaspoon dried oregano
– 1 teaspoon dried thyme
– 1 cup chicken broth
– Salt and pepper, to taste

1. Chicken and Potato Soup:
Ingredients:
– 2 tablespoons olive oil
– 1 onion, diced
– 2 chicken breasts, cut into cubes
– 2 potatoes, cut into cubes
– 2 carrots, cut into cubes
– 1 teaspoon dried oregano
– 1 teaspoon dried thyme
– 4 cups chicken broth
– Salt and pepper, to taste

1. Chicken and Potato Hash:
Ingredients:
– 2 tablespoons olive oil
– 2 chicken breasts, cut into cubes
– 2 potatoes, cut into cubes
– 2 carrots, cut into cubes
– 1 onion, diced
– 1 teaspoon dried oregano

Shopping List:
– Olive oil
– Onion
– Thyme
– Oregano
– Salt
– Pepper
“`

That’s your five recipes, with no garlic mentioned and you also have a shopping list considering what you already have at home.

这是根据您的购买清单生成你的食谱(不包含大蒜)

实战 – 打造一个菜谱生成器

根据场景,让我们编写代码来完整代码。为此,请按照下列步骤操作:

1. 使用现有的 *app.py* 文件作为起点
2. 找到 `prompt` 变量并将其代码更改为以下内容:

“`python
prompt = “Show me 5 recipes for a dish with the following ingredients: chicken, potatoes, and carrots. Per recipe, list all the ingredients used”
“`

运行代码,您应该会看到类似以下内容的输出:

“`output
-Chicken Stew with Potatoes and Carrots: 3 tablespoons oil, 1 onion, chopped, 2 cloves garlic, minced, 1 carrot, peeled and chopped, 1 potato, peeled and chopped, 1 bay leaf, 1 thyme sprig, 1/2 teaspoon salt, 1/4 teaspoon black pepper, 1 1/2 cups chicken broth, 1/2 cup dry white wine, 2 tablespoons chopped fresh parsley, 2 tablespoons unsalted butter, 1 1/2 pounds boneless, skinless chicken thighs, cut into 1-inch pieces
-Oven-Roasted Chicken with Potatoes and Carrots: 3 tablespoons extra-virgin olive oil, 1 tablespoon Dijon mustard, 1 tablespoon chopped fresh rosemary, 1 tablespoon chopped fresh thyme, 4 cloves garlic, minced, 1 1/2 pounds small red potatoes, quartered, 1 1/2 pounds carrots, quartered lengthwise, 1/2 teaspoon salt, 1/4 teaspoon black pepper, 1 (4-pound) whole chicken
-Chicken, Potato, and Carrot Casserole: cooking spray, 1 large onion, chopped, 2 cloves garlic, minced, 1 carrot, peeled and shredded, 1 potato, peeled and shredded, 1/2 teaspoon dried thyme leaves, 1/4 teaspoon salt, 1/4 teaspoon black pepper, 2 cups fat-free, low-sodium chicken broth, 1 cup frozen peas, 1/4 cup all-purpose flour, 1 cup 2% reduced-fat milk, 1/4 cup grated Parmesan cheese

-One Pot Chicken and Potato Dinner: 2 tablespoons olive oil, 1 pound boneless, skinless chicken thighs, cut into 1-inch pieces, 1 large onion, chopped, 3 cloves garlic, minced, 1 carrot, peeled and chopped, 1 potato, peeled and chopped, 1 bay leaf, 1 thyme sprig, 1/2 teaspoon salt, 1/4 teaspoon black pepper, 2 cups chicken broth, 1/2 cup dry white wine

-Chicken, Potato, and Carrot Curry: 1 tablespoon vegetable oil, 1 large onion, chopped, 2 cloves garlic, minced, 1 carrot, peeled and chopped, 1 potato, peeled and chopped, 1 teaspoon ground coriander, 1 teaspoon ground cumin, 1/2 teaspoon ground turmeric, 1/2 teaspoon ground ginger, 1/4 teaspoon cayenne pepper, 2 cups chicken broth, 1/2 cup dry white wine, 1 (15-ounce) can chickpeas, drained and rinsed, 1/2 cup raisins, 1/2 cup chopped fresh cilantro
“`

> NOTE, your LLM is nondeterministic, so you might get different results every time you run the program.

Great, let’s see how we can improve things. To improve things, we want to make sure the code is flexible, so ingredients and number of recipes can be improved and changed.

3. 让我们按以下方式更改代码:

```python
no_recipes = input("No of recipes (for example, 5: ")

ingredients = input("List of ingredients (for example, chicken, potatoes, and carrots: ")

# interpolate the number of recipes into the prompt an ingredients
prompt = f"Show me {no_recipes} recipes for a dish with the following ingredients: {ingredients}. Per recipe, list all the ingredients used"
```

Taking the code for a test run, could look like this:

```output
No of recipes (for example, 5: 3
List of ingredients (for example, chicken, potatoes, and carrots: milk,strawberries

-Strawberry milk shake: milk, strawberries, sugar, vanilla extract, ice cubes
-Strawberry shortcake: milk, flour, baking powder, sugar, salt, unsalted butter, strawberries, whipped cream
-Strawberry milk: milk, strawberries, sugar, vanilla extract
“`

 通过添加过滤器和购物清单进行改进

我们现在有一个能够生成食谱的应用,并且它使用很方便,基于用户的输入和食谱的数量所使用的成分。

为了进一步改进它,添加以下内容:

– **过滤掉成分**。 我们希望能够过滤掉我们不喜欢或过敏的成分。 要完成此更改,我们可以编辑现有提示并在其末尾添加过滤条件,如下所示:

“`python
filter = input(“Filter (for example, vegetarian, vegan, or gluten-free: “)

prompt = f”Show me {no_recipes} recipes for a dish with the following ingredients: {ingredients}. Per recipe, list all the ingredients used, no {filter}”
“`

Above, we add `{filter}` to the end of the prompt and we also capture the filter value from the user.

An example input of running the program can now look like so:

“`output
No of recipes (for example, 5: 3
List of ingredients (for example, chicken, potatoes, and carrots: onion,milk
Filter (for example, vegetarian, vegan, or gluten-free: no milk

1. French Onion Soup

Ingredients:

-1 large onion, sliced
-3 cups beef broth
-1 cup milk
-6 slices french bread
-1/4 cup shredded Parmesan cheese
-1 tablespoon butter
-1 teaspoon dried thyme
-1/4 teaspoon salt
-1/4 teaspoon black pepper

Instructions:

2. In a large pot, sauté onions in butter until golden brown.
3. Add beef broth, milk, thyme, salt, and pepper. Bring to a boil.
4. Reduce heat and simmer for 10 minutes.
5. Place french bread slices on soup bowls.
6. Ladle soup over bread.
7. Sprinkle with Parmesan cheese.

8. Onion and Potato Soup

Ingredients:

-1 large onion, chopped
-2 cups potatoes, diced
-3 cups vegetable broth
-1 cup milk
-1/4 teaspoon black pepper

Instructions:

9. In a large pot, sauté onions in butter until golden brown.
10. Add potatoes, vegetable broth, milk, and pepper. Bring to a boil.
11. Reduce heat and simmer for 10 minutes.
12. Serve hot.

13. Creamy Onion Soup

Ingredients:

-1 large onion, chopped
-3 cups vegetable broth
-1 cup milk
-1/4 teaspoon black pepper
-1/4 cup all-purpose flour
-1/2 cup shredded Parmesan cheese

Instructions:

14. In a large pot, sauté onions in butter until golden brown.
15. Add vegetable broth, milk, and pepper. Bring to a boil.
16. Reduce heat and simmer for 10 minutes.
17. In a small bowl, whisk together flour and Parmesan cheese until smooth.
18. Add to soup and simmer for an additional 5 minutes, or until soup has thickened.
“`

正如您所看到的,任何含有牛奶的食谱都已被过滤掉。 但是,如果您患有乳糖不耐症,您可能也想过滤掉含有奶酪的食谱,因此有必要明确一下。

“`python

– **制作购物清单**。 我们想根据家里已有的物品制定一份购物清单。

对于此功能,我们可以尝试在一个提示中解决所有问题,也可以将其分成两个提示。 让我们尝试一下后一种方法。 在这里,我们建议添加一个额外的提示,但为了使其起作用,我们需要将前一个提示的结果作为上下文添加到后一个提示中。

找到代码中打印第一个提示结果的部分,并添加以下代码:

```python
old_prompt_result = completion.choices[0].text
prompt = "Produce a shopping list for the generated recipes and please don't include ingredients that I already have."

new_prompt = f"{old_prompt_result} {prompt}"
completion = openai.Completion.create(engine=deployment_name, prompt=new_prompt, max_tokens=1200)

# print response
print("Shopping list:")
print(completion.choices[0].text)
```

请注意以下事项:

1. 我们通过将第一个提示的结果添加到新提示来构造一个新提示

“`python
new_prompt = f”{old_prompt_result} {prompt}”
“`

2. 我们提出一个新的请求,但也考虑到我们在第一个提示中请求的 token 数量,所以这次我们说 `max_tokens` 是1200。

“`python
completion = openai.Completion.create(engine=deployment_name, prompt=new_prompt, max_tokens=1200)
“`

运行代码,结果如下:

“`output
No of recipes (for example, 5: 2
List of ingredients (for example, chicken, potatoes, and carrots: apple,flour
Filter (for example, vegetarian, vegan, or gluten-free: sugar
Recipes:
or milk.

-Apple and flour pancakes: 1 cup flour, 1/2 tsp baking powder, 1/2 tsp baking soda, 1/4 tsp salt, 1 tbsp sugar, 1 egg, 1 cup buttermilk or sour milk, 1/4 cup melted butter, 1 Granny Smith apple, peeled and grated
-Apple fritters: 1-1/2 cups flour, 1 tsp baking powder, 1/4 tsp salt, 1/4 tsp baking soda, 1/4 tsp nutmeg, 1/4 tsp cinnamon, 1/4 tsp allspice, 1/4 cup sugar, 1/4 cup vegetable shortening, 1/4 cup milk, 1 egg, 2 cups shredded, peeled apples
Shopping list:
-Flour, baking powder, baking soda, salt, sugar, egg, buttermilk, butter, apple, nutmeg, cinnamon, allspice
“`

改进您的设置

到目前为止,我们拥有的是可以运行的代码,但是我们应该做一些调整来进一步改进。 我们应该做的一些事情是:

– **将 Key 与代码分开**,例如 API Key。Key 不属于代码,应存储在安全的位置。 为了将 Key 与代码分开,我们可以使用环境变量和像`python-dotenv` 这样的 libraries 从文件中加载它们。 代码如下:

1. 创建一个包含以下内容的 `.env` 文件:

“`bash
OPENAI_API_KEY=sk-…
“`

> Note, for Azure, you need to set the following environment variables:

“`bash
OPENAI_API_TYPE=azure
OPENAI_API_VERSION=2023-05-15
OPENAI_API_BASE=<replace>
“`

In code, you would load the environment variables like so:

“`python
from dotenv import load_dotenv

load_dotenv()

openai.api_key = os.environ[“OPENAI_API_KEY”]
“`

– **关于 token 长度**。 我们应该考虑需要多少 token 来生成我们想要的文本。 token 需要花钱,因此在可能的情况下,我们应该尽量节约使用 token 的数量。 例如,我们可以对提示进行调整,以便我们可以使用更少的 token

要更改使用的 token,您可以使用 `max_tokens` 参数。 例如,如果您想使用 100 个 token,您可以这样做:

“`python
completion = openai.Completion.create(model=”davinci-002″, prompt=prompt, max_tokens=100)
“`

**进行 temperature 调整试验**。 temperature 是我们到目前为止还没有提到的东西,但它是我们的程序如何执行的重要元素。 temperature 值越高,输出就越随机。 相反, temperature 值越低,输出就越可预测。 考虑一下您是否希望输出有所变化。

要改变 temperature ,您可以使用 `temperature` 参数。 例如,如果您想使用 0.5 的 temperature ,您可以这样做:

“`python
completion = openai.Completion.create(model=”davinci-002″, prompt=prompt, temperature=0.5)
“`

> 请注意,越接近 1.0,输出的变化就越多。

作业

对于此作业,选择要构建的内容。

以下是一些建议:

– 调整食谱生成器应用程序以进一步改进它。 尝试一下温度值和提示,看看你能想出什么。
– 建立一个“学习伙伴”。 这个应用程序应该能够回答有关某个主题(例如 Python)的问题,您可能会收到诸如“Python 中的某个主题是什么?”之类的提示,或者您可能会收到一个提示,显示某个主题的代码等。
– 历史机器人,让历史变得生动起来,指导机器人扮演某个历史人物,并向其询问有关其生活和时代的问题。

解决方案

### 学习伙伴

下面是一个基础提示,看看如何使用它并根据自己的喜好进行调整。

“`text
– “You’re an expert on the Python language

Suggest a beginner lesson for Python in the following format:

Format:
– concepts:
– brief explanation of the lesson:
– exercise in code with solutions”
“`

### 历史机器人

以下是您可能会使用的一些提示:

“`text
– “You are Abe Lincoln, tell me about yourself in 3 sentences, and respond using grammar and words like Abe would have used”
– “You are Abe Lincoln, respond using grammar and words like Abe would have used:

Tell me about your greatest accomplishments, in 300 words:”
“`

第七章:创建聊天应用

将生成式人工智能集成到聊天应用程序中

通过生成式人工智能提升聊天应用程序不仅是为了让它们变得更智能,也是为了让它们变得更聪明。 这是关于优化其架构、性能和用户界面以提供优质的用户体验。 这涉及研究架构基础、API 集成和用户界面注意事项。 本章旨在为您提供一个全面的路线图,用于导航这些复杂的环境,无论您是将它们插入现有系统还是将它们构建为独立平台。

读完本节后,您将具备高效构建和合并聊天应用程序所需的专业知识。

聊天机器人还是聊天应用程序?

在我们深入构建聊天应用程序之前,让我们将“传统聊天机器人”与“生成式人工智能驱动的人工智能”进行比较,它们具有不同的角色和功能。 传统聊天机器人的主要目的是自动执行特定的对话任务,例如回答常见问题或跟踪包裹。 它通常由基于规则的逻辑或复杂的人工智能算法控制。 相比之下,人工智能驱动的聊天应用程序是一个更加广泛的环境,旨在促进各种形式的数字通信,例如用户之间的文本、语音和视频聊天。 其定义特征是集成了生成式人工智能模型,该模型可以模拟细致入微的拟人对话,并根据各种输入和上下文提示生成响应。 生成式人工智能驱动的聊天应用程序可以参与开放领域的讨论,适应不断变化的对话环境,甚至产生创造性或复杂的对话。

下表概述了主要差异和相似之处,以帮助我们了解它们在数字通信中的独特作用。

 

| 传统聊天机器人 | 生成式人工智能驱动的人工智能 |
| ————————————- | ————————————– |
| 以任务为中心、基于预定义规则 | 情境感知 |
| 集成到大型的行业系统中 | 可以托管一个或多个聊天机器人 |
| 通过编程实现 | 结合生成式人工智能模型 |
| 专业相对固化的交互 | 能够进行更开放关于专业领域讨论 |

结合成熟的 SDK 和 API 构建生成式人工智能驱动的人工智能

在构建聊天应用程序时,重要的第一步是评估已有的内容。 基于多种原因,使用 SDK 和 API 构建聊天应用程序是一种有利的策略。 通过集成成熟的 SDK 和 API,可以战略性地定位您的应用程序,以实现长期成功,并解决可扩展性和维护问题。

– **加快开发过程并减少开销**:依靠预构建的功能而不是自己构建它们的昂贵过程,可以让您专注于您可能发现更重要的应用程序的其他方面,例如业务逻辑。
– **更好的性能**:从头开始构建功能时,您最终会问自己“它如何扩展?这个应用程序是否能够处理突然涌入的用户?” 维护功能好的 SDK 和 API 通常针对这些问题内置了解决方案。
– **更容易维护**:更新和改进更易于管理,因为大多数 API 和 SDK 在发布新版本时只需要更新库。
– **获得尖端技术**:利用经过微调和在广泛数据集上训练的模型为您的应用程序提供自然语言功能。

访问 SDK 或 API 的功能通常涉及获取使用所提供服务的许可,这通常是通过使用唯一 kwy 或身份验证 token 来实现的。 我们将使用 OpenAI Python library 来探索它是什么样子。 您也可以在本章的

[OpenAI notebook](../../notebook-openai.ipynb?WT.mc_id=academic-105485-koreyst)

[Azure OpenAI notebook](../../notebook-azure-openai.ipynb?WT.mc_id=academic-105485-koreyst)

中自行尝试。

“`python
import os
import openai

openai.api_key = os.getenv(“OPENAI_API_KEY”)

chat_completion = openai.ChatCompletion.create(model=”gpt-3.5-turbo”, messages=[{“role”: “user”, “content”: “Suggest two titles for an instructional lesson on chat applications for generative AI.”}])
“`

上面的示例使用 GPT-3.5 Turbo 模型来完成提示,但请注意,API 密钥是在执行此操作之前设置的。 如果未设置 key,您将收到以下错误。

“`output
AuthenticationError: No API key provided. You can set your API key in code using ‘openai.api_key = <API-KEY>’, or you can set the environment variable OPENAI_API_KEY=<API-KEY>). If your API key is stored in a file, you can point the openai module at it with ‘openai.api_key_path = <PATH>’. You can generate API keys in the OpenAI web interface. See https://platform.openai.com/account/api-keys for details.
“`

用户体验(UX)

一般用户体验原则适用于聊天应用程序,但由于涉及机器学习组件,这里有一些额外考虑因素,这就变得特别重要。

– **解决模糊性的机制**:生成式人工智能模型偶尔会生成模糊的答案。 如果用户遇到此问题,允许用户要求进行澄清可能会有所帮助。
– **上下文保留**:先进的生成式人工智能模型能够记住对话中的上下文,这可能是用户体验的必要资产。 赋予用户控制和管理上下文的能力可以改善用户体验,但会带来保留敏感用户信息的风险。 考虑这些信息的存储时间(例如引入保留策略)可以平衡上下文需求和隐私。
– **个性化**:人工智能模型具有学习和适应能力,为用户提供个性化体验。 通过用户个人资料等功能定制用户体验,不仅让用户感到亲切,而且还有助于他们得到特定答案,创造更高效、令人满意的交互。

个性化的一个例子是 OpenAI 的 ChatGPT 中的“自定义指令”设置。 它允许您提供有关您自己的信息,这些信息可能是您的提示的重要背景。 以下是自定义指令的示例。

“配置文件”提示 ChatGPT 在链接列表上创建课程计划。 请注意,ChatGPT 可以按照用户的特点获得更深入的课程计划。

微软的 LLMs 系统消息框架

[微软指引](https://learn.microsoft.com/azure/ai-services/openai/concepts/system-message#define-the-models-output-format?WT.mc_id=academic-105485-koreyst) 用于在 LLM 生成响应时编写有效的系统消息,分为 4 个区域:

1. 定义模型的适用对象及其功能和限制。
2. 定义模型的输出格式。
3. 提供展示模型预期行为的具体示例。
4. 提供额外的行为护栏。

辅助功能

无论用户是否有视觉、听觉、运动或认知障碍,设计良好的聊天应用程序都应该可供所有人使用。 以下列表详细列出了旨在增强各种用户障碍的可访问性的特定功能。

– **针对视觉障碍的功能**:高对比度主题和可调整大小的文本、屏幕阅读器兼容性。
– **针对听觉障碍的功能**:文本转语音和语音转文本功能、音频通知的视觉提示。
– **针对运动障碍的功能**:键盘导航支持、语音命令。
– **认知障碍功能**:简化的语言选项。

特定领域语言模型的定制和微调

想象一下,一个聊天应用程序可以理解您公司的行话并预测其用户群通常有的特定查询。 有几种方法值得一提:

– **利用 DSL 模型**。 DSL 代表领域特定语言。 您可以利用在特定领域训练的所谓 DSL 模型来了解其概念和场景。
– **应用微调**。 微调是使用特定数据进一步训练模型的过程。

定制:使用 DSL

利用特定于领域的语言模型(DSL 模型)可以通过提供专门的、上下文相关的交互来增强用户参与度。 它是一个经过训练或微调的模型,可以理解和生成与特定领域、行业或主题相关的文本。 使用 DSL 模型的选项多种多样,从头开始训练到通过 SDK 和 API 使用预先存在的模型。 另一种选择是微调,其中涉及采用现有的预训练模型并将其适应特定领域。

定制:应用微调

当预训练模型在专门领域或特定任务中达不到要求时,通常会考虑微调。

例如,医疗查询很复杂并且需要大量上下文。 当医疗专业人员诊断患者时,它会基于多种因素,例如生活方式或既往病史,甚至可能依赖最近的医学期刊来验证他们的诊断。 在这种微妙的场景中,通用的人工智能聊天应用程序不可能成为可靠的来源。

场景:医疗应用**

考虑一个聊天应用程序,旨在通过提供治疗指南、药物相互作用或最新研究结果的快速参考来帮助医生。

通用模型可能足以回答基本的医学问题或提供一般建议,但可能会遇到以下问题:

– **高度具体或复杂的案例**。 例如,神经科医生可能会询问应用程序:“目前治疗儿科患者耐药性癫痫的最佳实践是什么?”
– **缺乏最新进展**。 通用模型可能很难提供包含神经学和药理学最新进展的当前答案。

在此类情况下,使用专门的医疗数据集对模型进行微调可以显着提高其更准确、更可靠地处理这些复杂的医疗查询的能力。 这需要访问大型且相关的数据集,这些数据集代表了需要解决的特定领域的挑战和问题。

高质量 AI 驱动的聊天体验的注意事项

本节概述了“高质量”聊天应用程序的标准,其中包括捕获可操作的指标以及遵守负责任地利用人工智能技术的框架。

关键指标

为了保持应用程序的高质量性能,跟踪关键指标和注意事项至关重要。 这些测量不仅可以确保应用程序的功能,还可以评估人工智能模型和用户体验的质量。 下面的列表涵盖了需要考虑的基本、人工智能和用户体验指标。

| 指标 | 定义 | 开发人员需要 |
| —————————– | ———————————————————————————————————————- | ————————————————————————- |
| **正常运行时间** | 衡量应用程序运行和用户访问的时间。 | 您将如何最大限度地减少停机时间? |
| **响应时间** | 应用程序回复用户查询所花费的时间。 | 如何优化查询处理以缩短响应时间? |
| **精确** | 真阳性预测占阳性预测总数的比率 | 您将如何验证模型的精度? |
| **召回率(灵敏度)** | 真阳性预测与实际阳性数量的比率 | 您将如何衡量和提高召回率? |
| **F1 得分** | 精确率和召回率的调和平均值,平衡两者之间的权衡。 | 您的目标 F1 分数是多少? 您将如何平衡精确度和召回率? |
| **困惑** | 衡量模型预测的概率分布与数据实际分布的吻合程度。 | 您将如何最大程度地减少困惑? |
| **用户满意度指标** | 衡量用户对应用程序的感知。 通常通过调查捕获。 | 您多久收集一次用户反馈? 在此基础上你将如何适应? |
| **错误率** | 模型在理解或输出方面出错的比率。 | 您采取了哪些策略来降低错误率? |
| **再培训周期** | 更新模型以纳入新数据和见解的频率。 | 您多久重新训练一次模型? 是什么触发了再培训周期? |
| **异常检测** | 用于识别不符合预期行为的异常模式的工具和技术。 | 您将如何应对异常情况? |

在聊天应用程序中实施负责任的人工智能实践

Microsoft 的 Responsible AI 方法确定了指导 AI 开发和使用的六项原则。 以下是聊天开发人员应该考虑的原则、定义以及聊天开发人员应该考虑的事项以及为什么他们应该认真对待它们。

| 原则| 微软的定义| 聊天开发人员的注意事项 | 为什么它很重要 |
| ———————- | —————————————————– | ———————————————————————- | ————————————————————————————– |
| 公平| 人工智能系统应该公平对待所有人。 | 确保聊天应用程序不会根据用户数据进行歧视。 | 在用户之间建立信任和包容性; 避免法律后果。 |
| 可靠性和安全性| 人工智能系统应该可靠、安全地运行。 | 实施测试和故障保护以最大限度地减少错误和风险。 | 确保用户满意度并防止潜在危害。 |
| 隐私与安全 | 人工智能系统应该安全并尊重隐私。 | 实施强有力的加密和数据保护措施。 | 保护敏感的用户数据并遵守隐私法。 |
| 包容性| 人工智能系统应该赋予每个人力量并吸引人们。 | 设计适合不同受众且易于使用的 UI/UX。 | 确保更广泛的人可以有效地使用该应用程序。 |
| 透明度 | 人工智能系统应该是可以理解的。 | 为人工智能响应提供清晰的文档和推理。 | 如果用户能够理解决策的制定方式,他们就更有可能信任系统。 |
| 问责制 | 人们应该对人工智能系统负责。 | 建立清晰的审核和改进人工智能决策的流程。 | 允许持续改进并在出现错误时采取纠正措施。 |

第八章:创建搜索应用

为什么要构建搜索应用?

创建搜索应用将帮助您了解如何使用嵌入来搜索数据。 您还将学习如何构建可供学生快速查找信息的搜索应用程序。

本课程包括 Microsoft [AI Show](https://www.youtube.com/playlist?list=PLlrxD0HtieHi0mwteKBOfEeOYf0LJU4O1?WT.mc_id=academic-105485-koreyst) YouTube 频道的 YouTube 记录的嵌入索引。 AI Show 是一个 YouTube 频道,向您介绍人工智能和机器学习。 嵌入索引包含截至 2023 年 10 月每个 YouTube 记录的嵌入。您将使用嵌入索引为“Our Startup”构建搜索应用程序。 搜索应用程序返回视频中问题答案所在位置的链接。 这是学生快速找到所需信息的好方法。

以下是问题“can you use rstudio with azure ml?”的语义查询示例。 查看 YouTube 网址,您会看到该网址包含一个时间戳,可将您带到视频中问题答案所在的位置。

什么是语义搜索?

现在您可能想知道什么是语义搜索? 语义搜索是一种使用查询中单词的语义或含义来返回相关结果的搜索技术。

这是语义搜索的示例。 假设您想买一辆汽车,您可能会搜索“我的梦想汽车”,语义搜索会理解您并不是在“梦想”一辆车,而是想购买您的“理想”汽车。 语义搜索了解您的意图并返回相关结果。 另一种方法是“关键字搜索”,它会逐字搜索有关汽车的梦想,但通常会返回不相关的结果。

 什么是文本嵌入?

[文本嵌入](https://en.wikipedia.org/wiki/Word_embedding)是[自然语言处理](https://en.wikipedia.org/wiki/Natural_language_processing?WT.mc_id=academic-105485-koreyst)中使用的文本表示技术。 文本嵌入是文本的语义数字表示。 嵌入用于以机器易于理解的方式表示数据。 用于构建文本嵌入的模型有很多,在本章中,我们将重点关注使用 OpenAI 嵌入模型生成嵌入。

下面是一个示例,图像以下文本是 AI Show YouTube 频道上某一集的文字记录:

“`text
Today we are going to learn about Azure Machine Learning.
“`

我们将文本传递给 OpenAI Embedding API,它将返回以下由 1536 个数字(也称为向量)组成的嵌入。 向量中的每个数字代表文本的不同方面。 为简洁起见,这里是向量中的前 10 个数字。

“`python
[-0.006655829958617687, 0.0026128944009542465, 0.008792596869170666, -0.02446001023054123, -0.008540431968867779, 0.022071078419685364, -0.010703742504119873, 0.003311325330287218, -0.011632772162556648, -0.02187200076878071, …]
“`

Embedding 索引是如何创建的?

本章的嵌入索引是使用一系列 Python 脚本创建的。 您可以在本章的“scripts”文件夹中的 [README](../../scripts/README.md?WT.mc_id=academic-105485-koreyst) 中找到脚本和说明。 您无需运行这些脚本即可完成本章,因为我们为您提供了嵌入索引。

这些脚本执行以下操作:

1. 下载 [AI Show](https://www.youtube.com/playlist?list=PLlrxD0HtieHi0mwteKBOfEeOYf0LJU4O1?WT.mc_id=academic-105485-koreyst) 播放列表中每个 YouTube 视频的文字记录。
2. 使用[OpenAI Functions](https://learn.microsoft.com/azure/ai-services/openai/how-to/function-calling?WT.mc_id=academic-105485-koreyst),尝试 从 YouTube 记录的前 3 分钟中提取演讲者姓名。 每个视频的演讲者姓名存储在名为 `embedding_index_3m.json` 的嵌入索引中。
3. 然后将转录文本分成 **3 分钟的文本片段**。 该片段包含大约 20 个与下一个片段重叠的单词,以确保该片段的嵌入不会被切断并提供更好的搜索上下文。
4. 然后,每个文本片段都会传递到 OpenAI Chat API,将文本总结为 60 个单词。 摘要也存储在嵌入索引 `embedding_index_3m.json` 中。
5. 最后,将片段文本传递到 OpenAI Embedding API。 Embedding API 返回一个由 1536 个数字组成的向量,这些数字表示该段的语义含义。 该段与 OpenAI 嵌入向量一起存储在嵌入索引 `embedding_index_3m.json` 中。

### 向量数据库

为了简单起见,嵌入索引存储在名为 `embedding_index_3m.json` 的 JSON 文件中,并加载到 Pandas Dataframe 中。 但是,在生产中,嵌入索引将存储在向量数据库中,例如 [Azure Cognitive Search](https://learn.microsoft.com/training/modules/improve-search-results-vector-search?WT.mc_id=academic-105485-koreyst), [Redis](https://cookbook.openai.com/examples/vector_databases/redis/readme?WT.mc_id=academic-105485-koreyst), [Pinecone](https://cookbook.openai.com/examples/vector_databases/pinecone/readme), [Weaviate](https://cookbook.openai.com/examples/vector_databases/weaviate/readme?WT.mc_id=academic-105485-koreyst)

 理解余弦相似度

我们已经了解了文本嵌入,下一步是学习如何使用文本嵌入来搜索数据,特别是使用余弦相似度找到与给定查询最相似的嵌入。

### 什么是余弦相似度?

余弦相似度是两个向量之间相似度的度量,您还会听到这被称为 `近邻搜索`。 要执行余弦相似度搜索,您需要使用 OpenAI Embedding API 对 _查询_ 文本进行 _向量化_。 然后计算查询向量与嵌入索引中每个向量之间的余弦相似度。 请记住,嵌入索引对于每个 YouTube 转录文本片段都有一个向量。 最后,按余弦相似度对结果进行排序,余弦相似度最高的文本片段与查询最相似。

从数学角度来看,余弦相似度测量投影在多维空间中的两个向量之间的角度的余弦。 这种测量是有益的,因为如果两个文档由于大小而相距欧几里得距离很远,它们之间的角度仍然较小,因此余弦相似度较高。 有关余弦相似度方程的更多信息,请参阅[余弦相似度](https://en.wikipedia.org/wiki/Cosine_similarity?WT.mc_id=academic-105485-koreyst)。

构建您的第一个搜索应用程序

接下来,我们将学习如何使用嵌入构建搜索应用程序。 搜索应用将允许学生通过输入问题来搜索视频。 搜索应用程序将返回与问题相关的视频列表。 搜索应用程序还将返回视频中问题答案所在位置的链接。

此解决方案是使用 Python 3.10 或更高版本在 Windows 11、macOS 和 Ubuntu 22.04 上构建和测试的。 您可以从 [python.org](https://www.python.org/downloads/?WT.mc_id=academic-105485-koreyst) 下载 Python。

作业 – 构建一个让学生能够使用的搜索应用程序

我们在本章开始时介绍了“Our Startup”。 现在是时候让学生为他们的评估构建搜索应用程序了。

您将创建用于构建搜索应用程序的 Azure OpenAI 服务。 您将创建以下 Azure OpenAI 服务。 你需要 Azure 订阅才能完成此任务。

### 启动 Azure Cloud Shell

1. 登录[Azure 门户](https://portal.azure.com/?WT.mc_id=academic-105485-koreyst)。
2. 选择 Azure 门户右上角的 Cloud Shell 图标。
3. 选择 **Bash** 作为环境类型。

#### 创建资源组

> 通过指引我们使用美国东部名为“semantic-video-search”的资源组。
> 您可以更改资源组的名称,更改资源的位置等
> 检查[可用的模型](https://aka.ms/oai/models?WT.mc_id=academic-105485-koreyst)。

“`shell
az group create –name semantic-video-search –location eastus
“`

#### 创建 Azure OpenAI Service 资源

从 Azure Cloud Shell 运行以下命令来创建 Azure OpenAI Service 资源。

“`shell
az cognitiveservices account create –name semantic-video-openai –resource-group semantic-video-search \
–location eastus –kind OpenAI –sku s0
“`

#### Get the endpoint and keys for usage in this application
#### 获取此应用程序中使用的 endpoint 和 keys

从 Azure Cloud Shell 运行以下命令以获取 Azure OpenAI 服务资源的终 endpoint 和 keys

“`shell
az cognitiveservices account show –name semantic-video-openai \
–resource-group semantic-video-search | jq -r .properties.endpoint
az cognitiveservices account keys list –name semantic-video-openai \
–resource-group semantic-video-search | jq -r .key1
“`

#### 部署 OpenAI Embedding 模型

从 Azure Cloud Shell 运行以下命令来部署 OpenAI 嵌入模型。

“`shell
az cognitiveservices account deployment create \
–name semantic-video-openai \
–resource-group semantic-video-search \
–deployment-name text-embedding-ada-002 \
–model-name text-embedding-ada-002 \
–model-version “2” \
–model-format OpenAI \
–scale-settings-scale-type “Standard”
“`

解决方案

在 GitHub Codespaces 中打开 [solution notebook](../../solution.ipynb?WT.mc_id=academic-105485-koreyst) 并按照 Jupyter Notebook 中的说明进行操作。

当您运行 notebook 时,系统将提示您输入查询。 输入框将如下所示:

第九章:构建图像生成应用

为什么要构建图像生成应用程序?

图像生成应用程序是探索生成式人工智能功能的好方法。 它们可用于,例如:

– **图像编辑和合成**。 您可以为各种用例生成图像,例如图像编辑和图像合成。

– **适用于多种行业**。 它们还可以用于为医疗科技、旅游、游戏开发等各种行业生成图像。

 场景 Edu4All

作为本章的一部分,我们将在本章中继续与 “Our Startup” Edu4All 合作。 学生将为他们的评估创建图像,具体图像由学生决定,但它们可以是他们自己的童话故事的插图,或者为他们的故事创建一个新角色,或者帮助他们形象化他们的想法和概念。

例如,如果 Edu4All 的学生在课堂上研究纪念碑,他们可以生成以下内容:

提示词如下

> “Dog next to Eiffel Tower in early morning sunlight”

 什么是 DALL-E 和 Midjourney?

[DALL-E](https://openai.com/dall-e-2) 和 [Midjourney](https://www.midjourney.com/?WT.mc_id=academic-105485-koreyst) 是两种最流行的图像生成模型,它们允许您使用提示词生成图像。

### DALL-E

让我们从 DALL-E 开始,它是一种生成式 AI 模型,可以根据文本描述生成图像。

> [DALL-E 是 CLIP 和 diffused attention 两种模型的组合]
(https://towardsdatascience.com/openais-dall-e-and-clip-101-a-brief-introduction-3a4367280d4e)。

– **CLIP**,是一种从图像和文本生成嵌入的模型,嵌入是数据的数字表示。

– **diffused attention**,是一种从嵌入生成图像的模型。 DALL-E 在图像和文本数据集上进行训练,可用于从文本描述生成图像。 例如,DALL-E 可用于生成戴帽子的猫或留着莫霍克发型的狗的图像。

### Midjourney

Midjourney 的工作方式与 DALL-E 类似,它根据文本提示生成图像。 Midjourney 还可以用于使用“戴帽子的猫”或“莫西干狗”等提示来生成图像。

 

DALL-E 和 Midjourney 如何运作

首先,[DALL-E](https://arxiv.org/pdf/2102.12092.pdf?WT.mc_id=academic-105485-koreyst)。 DALL-E 是一种基于带有 *autoregressive transformer* 的 transformer 架构的生成式人工智能模型。

“autoregressive transformer”定义了模型如何根据文本描述生成图像,它一次生成一个像素,然后使用生成的像素生成下一个像素。 经过神经网络中的多个层,直到图像完整。

通过此过程,DALL-E 可以控制其生成的图像中的属性、对象、特征等。 DALL-E 2和3对生成的图像有更多的控制权,

构建您的第一个图像生成应用程序

那么构建图像生成应用程序需要什么? 您需要以下 Library:

– **python-dotenv**,强烈建议您使用此库将您的秘密保存在远离代码的 *.env* 文件中。
– **openai**,您将使用该库与 OpenAI API 进行交互。
– **pillow**,用于在 Python 中处理图像。
– **requests**,发出 HTTP 请求。

1. 创建一个包含以下内容的文件 *.env*:

“`text
AZURE_OPENAI_ENDPOINT=<your endpoint>
AZURE_OPENAI_KEY=<your key>
“`
在 Azure 门户中的 “Keys and Endpoint” 部分中找到资源的此信息。

2. 将上述库收集到名为 *requirements.txt* 的文件中,如下所示:

“`text
python-dotenv
openai
pillow
requests
“`

3. 接下来,创建虚拟环境并安装库:

“`bash
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
“`

对于 Windows,使用以下命令创建并激活虚拟环境:

“`bash
python3 -m venv venv
venv\Scripts\activate.bat
““

4. 在名为 *app.py* 的文件中添加以下代码:

“`python
import openai
import os
import requests
from PIL import Image
import dotenv

# import dotenv
dotenv.load_dotenv()

# Get endpoint and key from environment variables
openai.api_base = os.environ[‘AZURE_OPENAI_ENDPOINT’]
openai.api_key = os.environ[‘AZURE_OPENAI_KEY’]

# Assign the API version (DALL-E is currently supported for the 2023-06-01-preview API version only)
openai.api_version = ‘2023-06-01-preview’
openai.api_type = ‘azure’

try:
# Create an image by using the image generation API
generation_response = openai.Image.create(
prompt=’Bunny on horse, holding a lollipop, on a foggy meadow where it grows daffodils’, # Enter your prompt text here
size=’1024×1024′,
n=2,
temperature=0,
)
# Set the directory for the stored image
image_dir = os.path.join(os.curdir, ‘images’)

# If the directory doesn’t exist, create it
if not os.path.isdir(image_dir):
os.mkdir(image_dir)

# Initialize the image path (note the filetype should be png)
image_path = os.path.join(image_dir, ‘generated-image.png’)

# Retrieve the generated image
image_url = generation_response[“data”][0][“url”] # extract image URL from response
generated_image = requests.get(image_url).content # download the image
with open(image_path, “wb”) as image_file:
image_file.write(generated_image)

# Display the image in the default image viewer
image = Image.open(image_path)
image.show()

# catch exceptions
except openai.error.InvalidRequestError as err:
print(err)

“`

我们来解释一下这段代码:

– 首先,我们导入我们需要的 Library ,包括OpenAI 、dotenv 、requests和Pillow。

“`python
import openai
import os
import requests
from PIL import Image
import dotenv
“`

– 接下来,我们从 *.env* 文件加载环境变量。

“`python
# import dotenv
dotenv.load_dotenv()
“`

– 之后,我们设置 OpenAI API 的 endpoint 、 key 、版本和类型。

“`python
# Get endpoint and key from environment variables
openai.api_base = os.environ[‘AZURE_OPENAI_ENDPOINT’]
openai.api_key = os.environ[‘AZURE_OPENAI_KEY’]

# add version and type, Azure specific
openai.api_version = ‘2023-06-01-preview’
openai.api_type = ‘azure’
“`

– 接下来,我们生成图像:

“`python
# Create an image by using the image generation API
generation_response = openai.Image.create(
prompt=’Bunny on horse, holding a lollipop, on a foggy meadow where it grows daffodils’, # Enter your prompt text here
size=’1024×1024′,
n=2,
temperature=0,
)
“`

上面的代码返回一个 JSON 对象,其中包含生成图像的 URL。 我们可以使用 URL 下载图像并将其保存到文件中。

– 最后,我们打开图像并使用标准图像查看器来显示它:

“`python
image = Image.open(image_path)
image.show()
“`

### 有关生成图像的更多详细信息

让我们更详细地看一下生成图像的代码:

“`python
generation_response = openai.Image.create(
prompt=’Bunny on horse, holding a lollipop, on a foggy meadow where it grows daffodils’, # Enter your prompt text here
size=’1024×1024′,
n=2,
temperature=0,
)
“`

– **prompt**,是用于生成图像的文本提示。 在本例中,我们使用提示”Bunny on horse, holding a lollipop, on a foggy meadow where it grows daffodils”。
– **size**,是生成的图像的尺寸。 在本例中,我们生成一个 1024×1024 像素的图像。
– **n**,是生成的图像数量。 在本例中,我们生成两个图像。
– **temperature**,是控制生成人工智能模型输出随机性的参数。 temperature 是 0 到 1 之间的值,其中 0 表示输出是确定性的,1 表示输出是随机的。 默认值为 0.7。

您可以对图像执行更多操作,我们将在下面中介绍这些操作。

图像生成的附加功能

到目前为止,您已经了解了如何使用 Python 中的几行代码来生成图像。 但是,您还可以对图像执行更多操作。

您还可以执行以下操作:

– **执行编辑**。 通过为现有图像提供遮罩和提示,您可以更改图像。 例如,您可以向图像的一部分添加某些内容。 想象一下我们的兔子图像,您可以给兔子添加一顶帽子。 您将如何做到这一点,方法是提供图像、遮罩(标识要更改的区域的部分)和文本提示来说明应该做什么。

“`python
response = openai.Image.create_edit(
image=open(“base_image.png”, “rb”),
mask=open(“mask.png”, “rb”),
prompt=”An image of a rabbit with a hat on its head.”,
n=1,
size=”1024×1024″
)
image_url = response[‘data’][0][‘url’]
“`

The base image would only contain the rabbit but the final image would have the hat on the rabbit.

基本图像仅包含兔子,但最终图像将在兔子上戴上帽子。

– **创建变体**。 这个想法是,你采用现有的图像并要求创建变体。 要创建变体,您需要提供图像和文本提示以及代码,如下所示:

“`python
response = openai.Image.create_variation(
image=open(“bunny-lollipop.png”, “rb”),
n=1,
size=”1024×1024″
)
image_url = response[‘data’][0][‘url’]
“`

> 注意,这仅在 OpenAI 上支持

## Temperature

Temperature 是控制生成式 AI 模型输出随机性的参数。 Temperature 是 0 到 1 之间的值,其中 0 表示输出是确定性的,1 表示输出是随机的。 默认值为 0.7。

让我们通过运行此提示两次来看看 temperature 如何工作的示例:

> Prompt : “Bunny on horse, holding a lollipop, on a foggy meadow where it grows daffodils”

现在让我们运行相同的提示,我们不会两次获得相同的图像:

正如您所看到的,图像相似,但不相同。 让我们尝试将 temperature 值更改为 0.1,看看会发生什么:

“`python
generation_response = openai.Image.create(
prompt=’Bunny on horse, holding a lollipop, on a foggy meadow where it grows daffodils’, # Enter your prompt text here
size=’1024×1024′,
n=2
)
“`

### 改变 temperature

因此,让我们尝试使响应更加确定。 我们可以从生成的两张图像中观察到,在第一张图像中,有一只兔子,在第二张图像中,有一匹马,因此图像差异很大。

因此,让我们更改代码并 temperature 设置为 0,如下所示:

“`python
generation_response = openai.Image.create(
prompt=’Bunny on horse, holding a lollipop, on a foggy meadow where it grows daffodils’, # Enter your prompt text here
size=’1024×1024′,
n=2,
temperature=0
)
“`

现在,当您运行此代码时,您会得到这两个图像:

在这里您可以清楚地看到图像彼此之间的相似程度。

如何使用元提示定义应用程序的边界

通过我们的演示,我们已经可以为客户生成图像。 然而,我们需要为我们的应用程序创建一些边界。

例如,我们不想生成不适合工作或不适合儿童的图像。

我们可以通过 *元提示* 来做到这一点。 元提示是用于控制生成式 AI 模型的输出的文本提示。 例如,我们可以使用元提示来控制输出,并确保生成的图像对于工作来说是安全的,或者适合儿童。

### 它是如何工作的?

现在,元提示如何工作?

元提示是用于控制生成式 AI 模型的输出的文本提示,它们位于文本提示之前,用于控制模型的输出并嵌入到应用程序中以控制模型的输出。 将提示输入和元提示输入封装在单个文本提示中。

元提示的一个示例如下:

“`text
You are an assistant designer that creates images for children.

The image needs to be safe for work and appropriate for children.

The image needs to be in color.

The image needs to be in landscape orientation.

The image needs to be in a 16:9 aspect ratio.

Do not consider any input from the following that is not safe for work or appropriate for children.

(Input)

“`text

现在,让我们看看如何在例子中使用元提示。

“`python
disallow_list = “swords, violence, blood, gore, nudity, sexual content, adult content, adult themes, adult language, adult humor, adult jokes, adult situations, adult”

meta_prompt =f”””You are an assistant designer that creates images for children.

The image needs to be safe for work and appropriate for children.

The image needs to be in color.

The image needs to be in landscape orientation.

The image needs to be in a 16:9 aspect ratio.

Do not consider any input from the following that is not safe for work or appropriate for children.
{disallow_list}
“””

prompt = f”{meta_prompt}
Create an image of a bunny on a horse, holding a lollipop”

# TODO add request to generate image
“`
从上面的提示中,您可以看到正在创建的所有图像如何考虑元提示。

作业 – 让我们帮助学生

我们在本课开始时介绍了 Edu4All。 现在是时候让学生生成用于评估的图像了。

学生们将为他们的评估创建包含纪念碑的图像,而纪念碑到底是什么由学生决定。 学生们被要求在这项任务中发挥他们的创造力,将这些纪念碑放置在不同的环境中。

 解决方案

这是一种可能的解决方案:

“`python
import openai
import os
import requests
from PIL import Image
import dotenv

# import dotenv
dotenv.load_dotenv()

# Get endpoint and key from environment variables
openai.api_base = “<replace with endpoint>”
openai.api_key = “<replace with api key>”

# Assign the API version (DALL-E is currently supported for the 2023-06-01-preview API version only)
openai.api_version = ‘2023-06-01-preview’
openai.api_type = ‘azure’

disallow_list = “swords, violence, blood, gore, nudity, sexual content, adult content, adult themes, adult language, adult humor, adult jokes, adult situations, adult”

meta_prompt = f”””You are an assistant designer that creates images for children.

The image needs to be safe for work and appropriate for children.

The image needs to be in color.

The image needs to be in landscape orientation.

The image needs to be in a 16:9 aspect ratio.

Do not consider any input from the following that is not safe for work or appropriate for children.
{disallow_list}”””

prompt = f”””{metaprompt}
Generate monument of the Arc of Triumph in Paris, France, in the evening light with a small child holding a Teddy looks on.
“”””

try:
# Create an image by using the image generation API
generation_response = openai.Image.create(
prompt=prompt, # Enter your prompt text here
size=’1024×1024′,
n=2,
temperature=0,
)
# Set the directory for the stored image
image_dir = os.path.join(os.curdir, ‘images’)

# If the directory doesn’t exist, create it
if not os.path.isdir(image_dir):
os.mkdir(image_dir)

# Initialize the image path (note the filetype should be png)
image_path = os.path.join(image_dir, ‘generated-image.png’)

# Retrieve the generated image
image_url = generation_response[“data”][0][“url”] # extract image URL from response
generated_image = requests.get(image_url).content # download the image
with open(image_path, “wb”) as image_file:
image_file.write(generated_image)

# Display the image in the default image viewer
image = Image.open(image_path)
image.show()

# catch exceptions
except openai.error.InvalidRequestError as err:
print(err)
“`

第十章:创建低代码的人工智能应用

Power Platform 中的生成式 AI

通过生成式 AI 增强低代码开发和应用是 Power Platform 的重点关注领域。 目标是让每个人都能够构建人工智能驱动的应用程序、网站、仪表板并利用人工智能实现流程自动化,*无需任何数据科学专业知识*。 这一目标是通过将生成式 AI 以 Copilot 和 AI Builder 的形式集成到 Power Platform 的低代码开发体验中来实现的。

这是如何运作的?

Copilot 是一款 AI 助手,可让您使用自然语言以一系列对话步骤描述您的需求,从而构建 Power Platform 解决方案。 例如,您可以指示 AI 助手说明您的应用程序将使用哪些字段,它将创建应用程序和底层数据模型,或者您可以指定如何在 Power Automate 中设置流程。

您可以使用 Copilot 驱动的功能作为应用程序屏幕中的一项功能,使用户能够通过对话交互发现见解。

AI Builder 是 Power Platform 中提供的低代码 AI 功能,使您能够使用 AI 模型来帮助您自动化流程并预测结果。 借助 AI Builder,您可以将 AI 引入连接到 Dataverse 或各种云数据源(例如 SharePoint、OneDrive 或 Azure)中的数据的应用程序和流程。

Copilot 适用于所有 Power Platform 产品:Power Apps、Power Automate、Power BI、Power Pages 和 Power Virtual Agent。 AI Builder 可在 Power Apps 和 Power Automate 中使用。 在本课程中,我们将重点介绍如何在 Power Apps 和 Power Automate 中使用 Copilot 和 AI Builder 为我们的教育初创公司构建解决方案。

Power Apps 中的 Copilot

作为 Power Platform 的一部分,Power Apps 提供了一个低代码开发环境,用于构建应用程序来跟踪、管理数据并与数据交互。 它是一套应用程序开发服务,具有可扩展的数据平台以及连接到云服务和本地数据的能力。 Power Apps 允许您构建在浏览器、平板电脑和手机上运行并可以与同事共享的应用程序。 Power Apps 通过简单的界面让用户轻松进行应用程序开发,以便每个业务用户或专业开发人员都可以构建自定义应用程序。 通过 Copilot 的生成式 AI 也增强了应用程序开发体验。

Power Apps 中的 Copilot AI 助手功能使您能够描述您需要哪种类型的应用程序以及您希望应用程序跟踪、收集或显示哪些信息。 然后,Copilot 根据您的描述生成响应式 Canvas 应用程序。 然后,您可以自定义应用程序以满足您的需求。 AI Copilot 还会生成并建议一个 Dataverse 表,其中包含存储要跟踪的数据和一些示例数据所需的字段。 稍后我们将在本章中了解什么是 Dataverse 以及如何在 Power Apps 中使用它。 然后,您可以通过对话步骤使用 AI Copilot 助手功能自定义表格以满足您的需求。 通过 Power Apps 主屏幕轻松使用此功能。

Power Automate 中的 Copilot

作为 Power Platform 的一部分,Power Automate 允许用户在应用程序和服务之间创建自动化工作流程。 它有助于自动化重复的业务流程,例如通信、数据收集和决策批准。 其简单的界面允许具有各种技术能力的用户(从初学者到经验丰富的开发人员)自动执行工作任务。 通过 Copilot 的生成式 AI 也增强了工作流程开发体验。

Power Automate 中的 Copilot AI 助手功能使您能够描述您需要哪种流程以及您希望流程执行哪些操作。 然后 Copilot 根据您的描述生成流程。 然后,您可以自定义流程以满足您的需求。 AI Copilot 还会生成并建议您执行想要自动化的任务所需的操作。 我们将在本章中稍后介绍什么是流以及如何在 Power Automate 中使用它们。 然后,您可以通过对话步骤使用 AI Copilot 助手功能自定义操作以满足您的需求。 通过 Power Automate 主屏幕轻松使用此功能。

作业:使用 Copilot 管理 “Our Startup” 的学生作业和发票

“Our Startup” 为学生提供在线课程。 这家初创公司发展迅速,目前正在努力满足其课程的需求。 该初创公司聘请您作为 Power Platform 开发人员,帮助他们构建低代码解决方案,以帮助他们管理学生作业和发票。 他们的解决方案应该能够帮助他们通过应用程序跟踪和管理学生作业,并通过工作流程自动化发票处理过程。 您被要求使用生成式人工智能来开发解决方案。

当您开始使用 Copilot 时,可以使用 [Power Platform Copilot Prompt 库](https://pnp.github.io/powerplatform-prompts/?WT.mc_id=academic-109639-somelezediko) 作为提示词。 该库包含一系列提示,您可以使用这些提示与 Copilot 一起构建应用程序和流程。 您还可以使用库中的提示来了解如何向 Copilot 描述您的需求。

为 “Our Startup” 构建学生作业跟踪应用程序

“Our Startup” 的教育工作者一直在努力跟踪学生的作业。 他们一直使用电子表格来跟踪作业,但随着学生数量的增加,这变得难以管理。 他们要求您构建一个应用程序来帮助他们跟踪和管理学生作业。 该应用程序应使他们能够添加新作业、查看作业、更新作业和删除作业。 该应用程序还应该使教育工作者和学生能够查看已评分和未评分的作业。

您将按照以下步骤使用 Power Apps 中的 Copilot 构建应用程序:

1. 导航到 [Power Apps](https://make.powerapps.com?WT.mc_id=academic-105485-koreyst) 主屏幕。

1. 使用主屏幕上的文本区域描述您要构建的应用程序。 例如,***我想构建一个应用程序来跟踪和管理学生作业***。 单击 **发送** 按钮将提示发送到 AI Copilot。

1. AI Copilot 将建议一个 Dataverse 表,其中包含存储要跟踪的数据所需的字段以及一些示例数据。 然后,您可以通过对话步骤使用 AI Copilot 助手功能自定义表格以满足您的需求。

> **重点事项**:Dataverse 是 Power Platform 的底层数据平台。 它是一个用于存储应用程序数据的低代码数据平台。 它是一项完全托管的服务,可将数据安全地存储在 Microsoft 云中,并在您的 Power Platform 环境中进行配置。 它具有内置的数据治理功能,例如数据分类、数据沿袭、细粒度访问控制等。 您可以在[此处](https://docs.microsoft.com/powerapps/maker/data-platform/data-platform-intro?WT.mc_id=academic-109639-somelezediko)了解有关Dataverse的更多信息。

2. 教育工作者希望向已提交作业的学生发送电子邮件,以便让他们了解作业的最新进度。 您可以使用 Copilot 向表中添加新字段来存储学生电子邮件。 例如,您可以使用以下提示向表中添加新字段:***我想添加一列来存储学生电子邮件***。 单击 **发送** 按钮将提示发送到 AI Copilot。

1. AI Copilot 将生成一个新字段,您可以自定义该字段以满足您的需求。

1. 完成表格后,单击 **创建应用程序** 按钮来创建应用程序。

1. AI Copilot 将根据您的描述生成响应式 Canvas 应用程序。 然后,您可以自定义应用程序以满足您的需求。

1. 对于要向学生发送电子邮件的教育工作者,您可以使用 Copilot 向应用程序添加新屏幕。 例如,您可以使用以下提示向应用程序添加新屏幕:***我想添加一个屏幕来向学生发送电子邮件***。 单击 **发送** 按钮将提示发送到 AI Copilot。

1. AI Copilot 将生成一个新屏幕,然后您可以自定义屏幕以满足您的需求。

1. 完成应用程序后,单击 **保存** 按钮保存应用程序。

1. 要与教育工作者共享应用程序,请单击 **共享** 按钮,然后再次单击 **共享** 按钮。 然后,您可以通过输入教育工作者的电子邮件地址与他们共享该应用程序。

> **提升**:你刚刚构建的应用程序是一个良好的开端,但还可以改进。 通过电子邮件功能,教育工作者只能通过键入电子邮件来手动向学生发送电子邮件。 您能否使用 Copilot 构建一个自动化系统,使教育工作者能够在学生提交作业时自动向他们发送电子邮件? 您的提示是正确的提示,您可以为 “Our Startup” 构建发票信息表

“Our Startup” 的财务团队一直在努力跟踪发票。 他们一直使用电子表格来跟踪发票,但随着发票数量的增加,这变得难以管理。 他们要求您构建一个表来帮助他们存储、跟踪和管理收到的发票信息。 该表应用于构建一个自动化程序,提取所有发票信息并将其存储在表中。 该表还应使财务团队能够查看已支付和未支付的发票。

Power Platform 有一个名为 Dataverse 的底层数据平台,使您能够存储应用程序和解决方案的数据。 Dataverse 提供了一个低代码数据平台来存储应用程序的数据。 它是一项完全托管的服务,可将数据安全地存储在 Microsoft 云中,并在您的 Power Platform 环境中进行配置。 它具有内置的数据治理功能,例如数据分类、数据沿袭、细粒度访问控制等。 您可以在此处了解[有关 Dataverse 的更多信息](https://docs.microsoft.com/powerapps/maker/data-platform/data-platform-intro?WT.mc_id=academic-109639-somelezediko)。

为什么我们的初创公司应该使用 Dataverse? Dataverse 中的标准和自定义表为您的数据提供安全且基于云的存储选项。 表可让您存储不同类型的数据,类似于在单个 Excel 工作簿中使用多个工作表的方式。 您可以使用表来存储特定于您的组织或业务需求的数据。 我们的初创公司将从使用 Dataverse 中获得的一些好处包括但不限于:

– **易于管理**:元数据和数据都存储在云端,因此您不必担心它们如何存储或管理的细节。 您可以专注于构建您的应用程序和解决方案。

– **安全**:Dataverse 为您的数据提供安全且基于云的存储选项。 您可以使用基于角色的安全性来控制谁有权访问表中的数据以及他们如何访问数据。

– **丰富的元数据**:数据类型和关系直接在 Power Apps 中使用

– **逻辑和验证**:您可以使用业务规则、计算字段和验证规则来强制执行业务逻辑并保持数据准确性。

现在您已经了解了 Dataverse 是什么以及为什么应该使用它,让我们看看如何使用 Copilot 在 Dataverse 中创建表来满足我们财务团队的要求。

>**注意**:您将在下面内容中使用此表来构建自动化,该自动化将提取所有发票信息并将其存储在表中。

要使用 Copilot 在 Dataverse 中创建表,请按照以下步骤操作:

1. 导航到 [Power Apps](https://make.powerapps.com?WT.mc_id=academic-105485-koreyst) 主屏幕。

2. 在左侧导航栏上,选择 **表** ,然后单击 **描述新表** 。

1. 在 **描述新表** 屏幕上,使用文本区域描述您要创建的表。 例如,***我想创建一个表来存储发票信息***。 单击 **发送** 按钮将提示发送到 AI Copilot。

1. AI Copilot 将建议一个 Dataverse 表,其中包含存储要跟踪的数据所需的字段以及一些示例数据。 然后,您可以通过对话步骤使用 AI Copilot 助手功能自定义表格以满足您的需求。

1. 财务团队希望向供应商发送电子邮件,以更新其发票的当前状态。 您可以使用 Copilot 向表中添加新字段来存储供应商电子邮件。 例如,您可以使用以下提示向表中添加新字段:***我想添加一列来存储供应商电子邮件***。 单击 **发送** 按钮将提示发送到 AI Copilot。

1. AI Copilot 将生成一个新字段,您可以自定义该字段以满足您的需求。

1. 完成表后,单击 **创建** 按钮创建表。

Power Platform 中的 AI 模型与 AI Builder

AI Builder 是 Power Platform 中提供的低代码 AI 功能,使您能够使用 AI 模型来帮助您自动化流程并预测结果。 借助 AI Builder,您可以将 AI 引入连接到 Dataverse 或各种云数据源(例如 SharePoint、OneDrive 或 Azure)中的数据的应用程序和流程。

预定义 AI 模型与自定义 AI 模型

AI Builder 提供两种类型的 AI 模型:预构建 AI 模型和自定义 AI 模型。 预构建的 AI 模型是即用型 AI 模型,由 Microsoft 训练并在 Power Platform 中提供。 这些可以帮助您为应用程序和流程添加智能,而无需收集数据,然后构建、训练和发布您自己的模型。 您可以使用这些模型来自动化流程并预测结果。

Power Platform 中提供的一些预构建 AI 模型包括:

– **关键短语提取**:该模型从文本中提取关键短语。
– **语言检测**:此模型检测文本的语言。
– **情绪分析**:此模型检测文本中的积极、消极、中性或混合情绪。
– **名片阅读器**:此模型从名片中提取信息。
– **文本识别**:该模型从图像中提取文本。
– **对象检测**:该模型从图像中检测并提取对象。
– **表单处理**:该模型从表单中提取信息。
– **发票处理**:此模型从发票中提取信息。

通过自定义 AI 模型,您可以将自己的模型引入 AI Builder,以便它可以像任何 AI Builder 自定义模型一样运行,从而允许您使用自己的数据训练模型。 您可以使用这些模型来自动化流程并预测 Power Apps 和 Power Automate 中的结果。 使用您自己的模型时存在一些限制。 了解有关这些[限制](https://learn.microsoft.com/ai-builder/byo-model#limitations?WT.mc_id=academic-105485-koreyst)的更多信息

作业 – 为 “Our Startup” 构建发票处理流程

财务团队一直在努力处理发票。 他们一直使用电子表格来跟踪发票,但随着发票数量的增加,这变得难以管理。 他们要求您构建一个工作流程,帮助他们使用人工智能处理发票。 该工作流程应使他们能够从发票中提取信息并将信息存储在 Dataverse 表中。 该工作流程还应该使他们能够向财务团队发送包含提取信息的电子邮件。

现在您已经了解了 AI Builder 是什么以及为什么应该使用它,让我们看看如何使用我们之前介绍过的 AI Builder 中的发票处理 AI 模型来构建帮助财务团队处理发票的工作流程。

要构建一个工作流程来帮助财务团队使用 AI Builder 中的发票处理 AI 模型处理发票,请按照以下步骤操作:

1. 导航至 [Power Automate](https://make.powerautomate.com?WT.mc_id=academic-105485-koreyst) 主屏幕。

2. 使用主屏幕上的文本区域描述您要构建的工作流程。 例如,***当发票到达我的邮箱时对其进行处理***。 单击 **发送** 按钮将提示发送到 AI Copilot。

3. AI Copilot 将建议您执行想要自动化的任务所需的操作。 您可以单击 **下一步** 按钮来完成后续步骤。

4. 在下一步中,Power Automate 将提示您设置流程所需的连接。 完成后,单击 **创建流** 按钮来创建流。

5. AI Copilot 将生成流程,然后您可以自定义流程以满足您的需求。

6. 更新流程的触发器并将 **文件夹** 设置为将存储发票的文件夹。 例如,您可以将文件夹设置为**收件箱**。 单击“**显示高级选项**”并将“**仅包含附件**”设置为“**是**”。 这将确保该流程仅在文件夹中收到带有附件的电子邮件时运行。

7. 从流程中删除以下操作:**HTML 到文本**、**Compose**、**Compose 2**、**Compose 3** 和 **Compose 4**,因为您不会使用 他们。

8. 从流程中删除 **Condition** 操作,因为您不会使用它。 它应该类似于以下屏幕截图:

9. 单击 **添加操作** 按钮并搜索 **Dataverse**。 选择 **添加新行** 操作。

10. 在 **从发票中提取信息** 操作中,更新 **发票文件** 以指向电子邮件中的 **附件内容**。 这将确保流程从发票附件中提取信息。

11. 选择您之前创建的 **表**。 例如,您可以选择 **发票信息** 表。 从上一个操作中选择动态内容以填充以下字段:

– ID
– 数量
– 日期
– 姓名
– 状态 – 将 **状态** 设置为 **待处理**。
– 供应商电子邮件 – 使用 **新电子邮件到达时** 触发器中的 **发件人** 动态内容。

12. 完成流程后,单击 **保存** 按钮保存流程。 然后,您可以通过将带有发票的电子邮件发送到您在触发器中指定的文件夹来测试流程。

> **提升**:你刚刚构建的流程是一个好的开始,现在你需要考虑如何构建一个自动化系统,使我们的财务团队能够向供应商发送电子邮件以更新他们的当前状态 他们的发票。 您的提示:当发票状态发生变化时,流程必须运行。

在 Power Automate 中使用文本生成 AI 模型

AI Builder 中的使用 GPT AI 模型创建文本使您能够根据提示生成文本,并由 Microsoft Azure OpenAI Service 提供支持。 借助此功能,您可以将 GPT 技术合并到您的应用程序和流程中,以构建各种自动化流程和富有洞察力的应用程序。

GPT 模型经过大量数据的广泛训练,使它们能够在有提示时生成与人类语言非常相似的文本。 当与工作流程自动化集成时,可以利用 GPT 等人工智能模型来简化和自动化各种任务。

例如,您可以构建流程来自动生成各种用例的文本,如:电子邮件草稿、产品描述等。 您还可以使用该模型为各种应用程序生成文本,如聊天机器人和客户服务应用程序,使客户服务代理能够有效且高效地响应客户查询。

要了解如何在 Power Automate 中使用此 AI 模型,请浏览[使用 AI Builder 和 GPT 添加智能](https://learn.microsoft.com/training/modules/ai-builder-text-generation/?WT.mc_id=academic-109639-somelezediko) 模块。

第十一章:为生成式 AI 添加 function calling

场景:通过功能改进我们的聊天机器人

在本课程中,我们希望为 “Our Startup” 构建一个功能,允许用户使用聊天机器人来查找技术课程。 我们将推荐适合他们的技能水平、当前角色和感兴趣的技术的课程。

为了完成这个场景,我们将使用以下组合:

– “Azure Open AI” 为用户创建聊天体验。
– “Microsoft Learn Catalog API” 帮助用户根据用户的请求查找课程。
– “Function Calling” 接受用户的查询并将其发送到相关函数以发出 API 请求。

首先,让我们看看为什么我们要首先使用 Function Calling:

为什么需要 Function Calling

在函数调用之前,LLMs 的回复是非结构化且不一致的。 开发人员需要编写复杂的验证代码,以确保他们能够处理响应的每种变化。 用户无法获得诸如“斯德哥尔摩现在的天气怎么样?”之类的答案。 这是因为模型局限于数据训练的时间。

Function Calling 是 Azure Open AI Service 的一项功能,旨在克服以下限制:

– **一致的响应格式**。 如果我们能够更好地控制响应格式,我们就可以更轻松地将响应下游集成到其他系统。
– **外部数据**。 能够在聊天上下文中使用应用程序其他来源的数据

通过场景说明问题

> 如果您想运行以下场景,我们建议您创建一个文件 *Notebook.ipynb* 并将以下代码粘贴到单独的代码单元格中。 您也可以继续阅读,因为我们正在尝试说明函数可以帮助解决问题的问题。

让我们看一下说明响应格式问题的示例:

假设我们想要创建一个学生数据数据库,以便我们可以向他们建议正确的课程。 下面我们有两个对学生的描述,它们所包含的数据非常相似。

1. 创建与我们的 Azure OpenAI 资源的连接:

“`python
import os
import openai
import json
openai.api_type = “azure”
openai.api_base = “YOUR OPENAI API BASE URL”
openai.api_version = “2023-07-01-preview”
openai.api_key = os.getenv(“OPENAI_API_KEY”)
“`

Below is some Python code for configuring our connection to Azure Open AI where we set `api_type`, `api_base`, `api_version` and `api_key`.

2. 使用变量 ‘student_1_description’ 和 ‘student_2_description’ 创建两个学生描述。

“`python
student_1_description=”Emily Johnson is a sophomore majoring in computer science at Duke University. She has a 3.7 GPA. Emily is an active member of the university’s Chess Club and Debate Team. She hopes to pursue a career in software engineering after graduating.”

student_2_description = “Michael Lee is a sophomore majoring in computer science at Stanford University. He has a 3.8 GPA. Michael is known for his programming skills and is an active member of the university’s Robotics Club. He hopes to pursue a career in artificial intelligence after finishing his studies.”
“`

We want to send the above student descriptions to an LLM to parse the data. This data can later be used in our application and be sent to an API or stored in a database.

3. 让我们创建两个相同的提示,指引 LLM 给我们指出哪些兴趣点:

“`python
prompt1 = f”’
Please extract the following information from the given text and return it as a JSON object:

name
major
school
grades
club

This is the body of text to extract the information from:
{student_1_description}
”’

prompt2 = f”’
Please extract the following information from the given text and return it as a JSON object:

name
major
school
grades
club

This is the body of text to extract the information from:
{student_2_description}
”’
“`

上述提示指示 LLM 提取信息并以 JSON 格式返回响应。

4. 设置提示并连接到 Azure OpenAI 后,我们现在将使用 `openai.ChatCompletion` 将提示发送到 LLM。 我们将提示存储在 `messages` 变量中,并将角色分配给 `user`.。 这是为了模仿用户写入聊天机器人的消息。

“`python
# response from prompt one
openai_response1 = openai.ChatCompletion.create(
engine=”gpt-function”,
messages = [{‘role’: ‘user’, ‘content’: prompt1}]
)
openai_response1[‘choices’][0][‘message’][‘content’]

# response from prompt two
openai_response2 = openai.ChatCompletion.create(
engine=”gpt-function”,
messages = [{‘role’: ‘user’, ‘content’: prompt2 }]
)
openai_response2[‘choices’][0][‘message’][‘content’]
“`

现在我们可以将两个请求发送到 LLM 并通过查找 `openai_response1[‘choices’][0][‘message’][‘content’]` 来检查我们收到的响应。

1. 最后,我们可以通过调用 `json.loads` 将响应结果转换为JSON格式:

“`python
# Loading the response as a JSON object
json_response1 = json.loads(openai_response1[‘choices’][0][‘message’][‘content’])
json_response1
“`

Response 1:

“`json
{‘name’: ‘Emily Johnson’,
‘major’: ‘computer science’,
‘school’: ‘Duke University’,
‘grades’: ‘3.7’,
‘club’: ‘Chess Club’}
“`

Response 2:

“`json
{‘name’: ‘Michael Lee’,
‘major’: ‘computer science’,
‘school’: ‘Stanford University’,
‘grades’: ‘3.8 GPA’,
‘club’: ‘Robotics Club’}
“`

尽管提示相同且描述相似,但我们看到 `Grades` 属性值的格式不同,例如有时我们可以获得“3.7”或“3.7 GPA”格式。

这个结果是因为 LLM 以书面提示的形式获取非结构化数据并返回非结构化数据。 我们需要有一个结构化的格式,以便我们知道在存储或使用这些数据时会发生什么

那么我们该如何解决格式化问题呢? 通过使用 function calling,我们可以确保收到返回的结构化数据。 当使用 function calling 时,LLM 实际上并不调用或运行任何函数。 相反,我们为 LLMs 创建了一个响应结构。 然后,我们使用这些结构化响应来了解要在应用程序中运行哪些功能。.

然后我们可以获取函数返回的内容并将其发送回 LLM。 然后, LLM 将使用自然语言来回答用户的查询。

使用 function calling 的用例

在许多不同的用例中,function calling 可以改进您的应用程序,例如:

– **调用外部工具**。 聊天机器人非常擅长回答用户的问题。 通过使用函数调用,聊天机器人可以使用来自用户的消息来完成某些任务。 例如,学生可以要求聊天机器人“向我的老师发送电子邮件,说我需要有关该主题的更多帮助”。 这可以对 ‘send_email(to: string, body: string)’ 进行函数调用

– **创建 API 或数据库查询**。 用户可以使用自然语言查找信息,并将其转换为格式化查询或 API 请求。 举个例子,老师请求“谁是完成最后作业的学生”,该老师可以调用名为 ‘get_completed(student_name: string, assignment: int, current_status: string)’ 的函数

– **创建结构化数据**。 用户可以获取一段文本或 CSV 并使用 LLM 从中提取重要信息。 例如,学生可以将有关和平协议的维基百科文章转换为创建人工智能闪存卡。 这可以通过使用名为 ‘get_important_facts(agreement_name:string,date_signed:string,partys_involved:list)’ 的函数来完成

创建您的第一个 function calling

创建 function calling 的过程包括 3 个主要步骤:

1. **调用** Chat Completions API,并提供您的函数列表和用户消息。
2. **读取**模型的响应以执行操作,即执行函数或 API 调用。
3. **使用**函数的响应再次调用 Chat Completions API,以使用该信息创建对用户的响应。

Step 1 – 创建消息

Step 1 是创建用户消息。 这可以通过获取文本输入的值来动态分配,或者您可以在此处分配一个值。 如果这是您第一次使用聊天完成 API,我们需要定义消息的“角色”和“内容”。

`role` 可以是`system` (创建规则)、`assistant` 模型)或`user`最终用户)。 对于函数调用,我们将其指定为 `user` 和一个示例问题。

“`python
messages= [ {“role”: “user”, “content”: “Find me a good course for a beginner student to learn Azure.”} ]
“`

通过分配不同的角色, LLMs 可以清楚地知道是系统在说话还是用户在说话,这有助于建立 LLMs 可以建立的对话历史记录。

Step 2 – 创建 functions

接下来,我们将定义一个函数以及该函数的参数。 我们在这里仅使用一个名为“search_courses”的函数,但您可以创建多个函数。

> **重要**:功能包含在发给 LLM 的系统消息中,并将包含在您拥有的可用 tokens 数量中。

下面,我们将函数创建为项目数组。 每个项目都是一个函数,并具有属性 `name`, `description` 和 `parameters`:

“`python
functions = [
{
“name”:”search_courses”,
“description”:”Retrieves courses from the search index based on the parameters provided”,
“parameters”:{
“type”:”object”,
“properties”:{
“role”:{
“type”:”string”,
“description”:”The role of the learner (i.e. developer, data scientist, student, etc.)”
},
“product”:{
“type”:”string”,
“description”:”The product that the lesson is covering (i.e. Azure, Power BI, etc.)”
},
“level”:{
“type”:”string”,
“description”:”The level of experience the learner has prior to taking the course (i.e. beginner, intermediate, advanced)”
}
},
“required”:[
“role”
]
}
}
]
“`

下面让我们更详细地描述每个函数实例:

– `name` – 我们想要调用的函数的名称。
– `description` – 这是函数如何工作的描述。 在这里,重要的是要具体和清晰。
– `parameters` – 您希望模型在其响应中生成的值和格式的列表。 参数数组由项目组成,其中项目具有以下属性:
1. `type` – 将存储属性的数据类型。
2. `properties` – 模型将用于其响应的特定值的列表
1. `name` – 键是模型将在其格式化响应中使用的属性的名称,例如,`product`。
2. `type` – 该属性的数据类型,例如,`string`。
3. `description` – 特定属性的描述。

还有一个可选属性“required” – 完成 function call 所需的属性。

Step 3 – 进行 function call

定义函数后,我们现在需要将其包含在对聊天完成 API 的调用中。 我们通过向请求添加 `functions` 来做到这一点。 在这种情况下 `functions=functions`。

还有一个选项可以将“function_call”设置为“auto”。 这意味着我们将让 LLM 根据用户消息决定应该调用哪个函数,而不是我们自己分配它。

下面是我们调用 `ChatCompletion.create` 的一些代码,请注意我们如何设置 `functions=functions` 和 `function_call=”auto”` ,从而让 LLM 选择何时调用我们提供的函数:

“`python
response = openai.ChatCompletion.create( engine=”gpt-function”,
messages=messages,
functions=functions,
function_call=”auto”, )

print(response[‘choices’][0][‘message’])
“`

现在返回的响应结果如下所示:

“`json
{
“role”: “assistant”,
“function_call”: {
“name”: “search_courses”,
“arguments”: “{\n \”role\”: \”student\”,\n \”product\”: \”Azure\”,\n \”level\”: \”beginner\”\n}”
}
}
“`

在这里,我们可以看到如何调用函数 `search_courses` 以及使用哪些参数,如 JSON 响应中的 `arguments` 属性中所列。

结论是,LLMs 能够找到适合函数参数的数据,因为它从聊天完成调用中提供给“messages”参数的值中提取数据。 下面是“messages”值的提醒:

“`python
messages= [ {“role”: “user”, “content”: “Find me a good course for a beginner student to learn Azure.”} ]
“`

如您所见,`student`, `Azure` 和 `beginner` 是从`messages` 中提取的,并设置为函数的输入。 以这种方式使用函数是从提示中提取信息的好方法,同时也可以为 LLM 提供结构并具有可重用的功能。

接下来,我们需要看看如何在我们的应用程序中使用它。

## 将 function calling 集成到应用程序中

在我们测试了 LLM 的格式化响应后,现在我们可以将其集成到应用程序中。

### 管理流程

要将其集成到我们的应用程序中,我们需要执行以下步骤:

1. 首先,我们调用 Open AI 服务并将消息存储在名为 `response_message` 的变量中。

“`python
response_message = response[“choices”][0][“message”]
“`

2. 现在我们将定义调用 Microsoft Learn API 来获取课程列表的函数:

“`python
import requests

def search_courses(role, product, level):
url = “https://learn.microsoft.com/api/catalog/”
params = {
“role”: role,
“product”: product,
“level”: level
}
response = requests.get(url, params=params)
modules = response.json()[“modules”]
results = []
for module in modules[:5]:
title = module[“title”]
url = module[“url”]
results.append({“title”: title, “url”: url})
return str(results)
“`

请注意我们现在如何创建一个实际的 Python 函数,该函数映射到 `functions` 变量中引入的函数名称。 我们还进行真正的外部 API 调用来获取我们需要的数据。 在这种情况下,我们根据 Microsoft Learn API 来搜索培训模块。

好的,我们创建了 `functions` 变量和相应的 Python 函数,我们如何告诉 LLM 如何将这两个映射在一起,以便调用我们的 Python 函数?

3. 要查看是否需要调用 Python 函数,我们需要查看 LLM 响应并查看“function_call”是否是其中的一部分并调用所指出的函数。 以下是进行下面提到的检查的方法:

“`python
# Check if the model wants to call a function
if response_message.get(“function_call”):
print(“Recommended Function call:”)
print(response_message.get(“function_call”))
print()

# Call the function.
function_name = response_message[“function_call”][“name”]

available_functions = {
“search_courses”: search_courses,
}
function_to_call = available_functions[function_name]

function_args = json.loads(response_message[“function_call”][“arguments”])
function_response = function_to_call(**function_args)

print(“Output of function call:”)
print(function_response)
print(type(function_response))

# Add the assistant response and function response to the messages
messages.append( # adding assistant response to messages
{
“role”: response_message[“role”],
“function_call”: {
“name”: function_name,
“arguments”: response_message[“function_call”][“arguments”],
},
“content”: None
}
)
messages.append( # adding function response to messages
{
“role”: “function”,
“name”: function_name,
“content”:function_response,
}
)
“`

These three lines, ensure we extract the function name, the arguments and make the call:

“`python
function_to_call = available_functions[function_name]

function_args = json.loads(response_message[“function_call”][“arguments”])
function_response = function_to_call(**function_args)
“`

以下是运行代码的输出:

**Output**

“`Recommended Function call:
{
“name”: “search_courses”,
“arguments”: “{\n \”role\”: \”student\”,\n \”product\”: \”Azure\”,\n \”level\”: \”beginner\”\n}”
}

Output of function call:
[{‘title’: ‘Describe concepts of cryptography’, ‘url’: ‘https://learn.microsoft.com/en-us/training/modules/describe-concepts-of-cryptography/?
WT.mc_id=api_CatalogApi’}, {‘title’: ‘Introduction to audio classification with TensorFlow’, ‘url’: ‘https://learn.microsoft.com/en-
us/training/modules/intro-audio-classification-tensorflow/?WT.mc_id=api_CatalogApi’}, {‘title’: ‘Design a Performant Data Model in Azure SQL
Database with Azure Data Studio’, ‘url’: ‘https://learn.microsoft.com/en-us/training/modules/design-a-data-model-with-ads/?
WT.mc_id=api_CatalogApi’}, {‘title’: ‘Getting started with the Microsoft Cloud Adoption Framework for Azure’, ‘url’:
‘https://learn.microsoft.com/en-us/training/modules/cloud-adoption-framework-getting-started/?WT.mc_id=api_CatalogApi’}, {‘title’: ‘Set up the
Rust development environment’, ‘url’: ‘https://learn.microsoft.com/en-us/training/modules/rust-set-up-environment/?WT.mc_id=api_CatalogApi’}]
<class ‘str’>
“`
3. 现在我们将向 LLM 发送更新后的消息 `messages` ,以便我们可以接收自然语言响应,而不是 API JSON 格式的响应。

“`python
print(“Messages in next request:”)
print(messages)
print()

second_response = openai.ChatCompletion.create(
messages=messages,
engine=”gpt-function”,
function_call=”auto”,
functions=functions,
temperature=0
) # get a new response from GPT where it can see the function response

print(second_response[“choices”][0][“message”])
“`

**Output**

“`python
{
“role”: “assistant”,
“content”: “I found some good courses for beginner students to learn Azure:\n\n1. [Describe concepts of cryptography] (https://learn.microsoft.com/training/modules/describe-concepts-of-cryptography/?WT.mc_id=api_CatalogApi)\n2. [Introduction to audio classification with TensorFlow](https://learn.microsoft.com/training/modules/intro-audio-classification-tensorflow/?WT.mc_id=api_CatalogApi)\n3. [Design a Performant Data Model in Azure SQL Database with Azure Data Studio](https://learn.microsoft.com/training/modules/design-a-data-model-with-ads/?WT.mc_id=api_CatalogApi)\n4. [Getting started with the Microsoft Cloud Adoption Framework for Azure](https://learn.microsoft.com/training/modules/cloud-adoption-framework-getting-started/?WT.mc_id=api_CatalogApi)\n5. [Set up the Rust development environment](https://learn.microsoft.com/training/modules/rust-set-up-environment/?WT.mc_id=api_CatalogApi)\n\nYou can click on the links to access the courses.”
}

“`
作业

要继续学习 Azure 开放 AI function calling,您可以构建:

– 该功能的更多参数可以帮助学习者找到更多课程。 您可以在此处找到可用的 API 参数:
– 创建另一个函数调用,从学习者那里获取更多信息,例如他们的母语
– 当函数调用和/或API调用未返回任何合适的课程时创建错误处理

提示:按照 [Learn API 参考文档](https://learn.microsoft.com/training/support/catalog-api-developer-reference?WT.mc_id=academic-105485-koreyst) 页面了解此操作的方式和和哪些数据是可用的

第十二章:为人工智能应用程序添加用户体验

花一些时间阅读有关[用户体验和设计思维](https://learn.microsoft.com/training/modules/ux-design?WT.mc_id=academic-105485-koreyst)的更多信息。

用户体验简介和了解用户需求

在我们虚构的教育初创公司中,我们有两个主要用户:教师和学生。 这两个用户都有独特的需求。 以用户为中心的设计优先考虑用户,确保产品与其预期目标相关且有益。

该应用程序应该 **有用、可靠、易于访问且令人愉悦** ,以提供良好的用户体验。

可用性

可用意味着应用程序具有与其预期目的相匹配的功能,例如自动化评分过程或生成用于复习的卡片。 自动评分过程的应用程序应该能够根据预定义的标准准确有效地为学生的作业分配分数。 同样,生成卡片的应用程序应该能够根据其数据创建相关且多样化的问题。

可靠性

可靠意味着应用程序可以一致且无错误地执行其任务。 然而,人工智能就像人类一样并不完美,并且可能容易出错。 应用程序可能会遇到错误或意外情况,需要人工干预或纠正。 你如何处理错误? 在本章的最后一部分,我们将介绍如何设计人工智能系统和应用程序以实现协作和反馈。

无障碍性

无障碍意味着将用户体验扩展到具有各种能力的用户,包括残疾人,确保没有人被排除在外。 通过遵循可访问性指南和原则,人工智能解决方案变得更具包容性、可用性,并且对所有用户都有利。

满意性

令人满意意味着该应用程序使用起来令人愉快。 有吸引力的用户体验可以对用户产生积极影响,鼓励他们返回应用程序并增加业务收入。

并非所有挑战都可以通过人工智能解决。 人工智能可以增强您的用户体验,无论是自动化手动任务还是个性化用户体验。

设计人工智能应用程序以实现信任和透明

设计人工智能应用程序时,建立信任至关重要。 信任可确保用户确信应用程序能够完成工作、一致地交付结果并且结果是用户所需要的。 该领域的一个风险是不信任和过度信任。 当用户对人工智能系统怀疑时,就会出现不信任,这会导致用户拒绝您的应用程序。 当用户高估人工智能系统的能力,导致用户过于信任人工智能系统时,就会出现过度信任。 例如,自动评分系统在过度信任的情况下可能会导致老师不通过某些试卷进行校对以确保评分系统运作良好。 这可能会导致学生的成绩不公平或不准确,或者错过反馈和改进的机会。

确保将信任置于设计中心的两种方法是可解释性和可控性。

可解释性

当人工智能帮助做出决策(例如向后代传授知识)时,教师和家长了解人工智能决策是如何做出的至关重要。 这就是可解释性——理解人工智能应用程序如何做出决策。 可解释性设计包括添加人工智能应用程序可以做什么的示例的详细信息。 例如,系统可以使用:“使用 AI 总结笔记以便更轻松地复习”,而不是“开始使用 AI 教师”。

另一个例子是人工智能如何使用用户和个人数据。 例如,具有学生角色的用户可能具有基于其角色的限制。 人工智能可能无法揭示问题的答案,但可以帮助引导用户思考如何解决问题。

可解释性的最后一个关键部分是解释的简化。 学生和教师可能不是人工智能专家,因此对应用程序可以做什么或不能做什么的解释应该简化且易于理解。

控制

生成式人工智能在人工智能和用户之间创建协作,例如用户可以修改不同结果的提示。 此外,一旦生成输出,用户应该能够修改结果,从而给他们一种控制感。 例如,使用 Bing 时,您可以根据格式、语气和长度定制提示。 此外,您可以对输出添加更改并修改输出,如下所示:

Bing 中允许用户控制应用程序的另一个功能是能够选择加入和退出 AI 使用的数据。 对于学校申请,学生可能希望使用他们的笔记以及教师的资源作为复习材料。

> 在设计人工智能应用程序时,意向性是确保用户不会过度信任对其功能设定不切实际的期望的关键。 做到这一点的一种方法是在提示和结果之间制造摩擦。 提醒用户这是人工智能而不是人类

设计用于协作和反馈的 AI 应用程序

正如前面提到的,生成式人工智能在用户和人工智能之间建立了协作。 大多数交互都是由用户输入提示,然后人工智能生成输出。 如果输出不正确怎么办? 如果发生错误,应用程序如何处理? 人工智能会责怪用户还是需要时间来解释错误?

应内置人工智能应用程序来接收和提供反馈。 这不仅有助于人工智能系统的改进,还可以与用户建立信任。 设计中应包含反馈回路,例如对输出的简单赞成或反对。

处理此问题的另一种方法是清楚地传达系统的功能和限制。 当用户请求超出 AI 能力的内容时出错时,还应该有一种方法来处理此问题,如下所示。

系统错误在用户可能需要人工智能范围之外的信息帮助或者应用程序可能限制用户可以生成摘要的问题/主题的应用程序中很常见。 例如,使用有限科目(例如历史和数学)的数据训练的人工智能应用程序可能无法处理有关地理的问题。 为了缓解这种情况,人工智能系统可以给出这样的响应:“抱歉,我们的产品已经接受了以下主题的数据训练……,我无法回答您提出的问题。”

人工智能应用并不完美,因此,它们难免会犯错误。 在设计应用程序时,您应该确保以简单且易于解释的方式为用户反馈和错误处理留出空间。

 作业

对于您迄今为止构建的任何 AI 应用程序,请考虑在您的应用程序中实施以下步骤:

* **满意度:** 考虑如何使您的应用程序更加令人愉快。 您是否到处添加解释,是否鼓励用户探索? 您如何措辞错误消息?

* **可用性:** 构建网络应用程序。 确保您的应用程序可以通过鼠标和键盘进行导航。

* **信任和透明度:** 不要完全信任人工智能及其输出,考虑如何在流程中添加人员来验证输出。 此外,考虑并实施其他方法来实现信任和透明度。

* **可控:** 赋予用户对其提供给应用程序的数据的控制权。 实现用户可以选择加入和退出 AI 应用程序中的数据收集的方式。


 


      
欢迎访问掘财之道官网,我们一直在努力!
掘财之道 » 微软官方推出的生成式人工智能(openai chatgpt )官方攻略(高级提示技巧)

琼公网安备 46020202000054号 琼ICP备2022000735号-1