在人工智能的海洋里,大型语言模型(LLM AI)是高速发展的一艘巨轮,而有效地与其沟通和指导其行为的锚,正是提示语(prompts)。提示语是我们提供给模型的输入或查询,以期获取特定的响应。当今,提示语工程(prompt engineering)已成为涌现的领域,它需要创造力和对细节的关注。接下来,我将带大家一同深入这个话题,探索怎样有效地设计提示语,成为一名出色的提示语工程师,并借助一个强大工具——Semantic Kernel——提高我们的能力。

提示语的微妙之处在于选词拼句,这就如同是为模型拟定一条生成高质量且相关文本的轨迹。比如,当你利用ChatGPT时,可以观察到基于你提供的不同输入,模型的行为会怎样剧烈变化。演示一下,以下两个提示语产生的输出截然不同:

提示语1:

Prompt:请给我讲述人类的历史。

提示语2:

Prompt:用三句话给我讲述人类的历史。

第一个提示语给出了一份长篇报告,而第二个提示语则给出了一个简洁的回答。设计提示语时要在具体性和相关性之间找到平衡点。

不仅如此,直接与LLM模型互动时,还可以利用如温度参数来控制模型输出的随机性,以及利用top-ktop-p、截断采样和截尾采样等参数来影响模型行为。

        提示语工程:新兴的职业前景 由于提示语工程对于操作LLM AI模型的影响力,它已经成为任何从事此领域工作人员的关键技能,并且随着越来越多的组织采用LLM AI模型以自动化任务和提高生产力,这个技能也越发受到追捧。一个优秀的提示语工程师能帮助组织通过精心设计的提示语来发挥出LLM AI模型的最大价值。

利用Semantic Kernel成为优秀的提示语工程师 Semantic Kernel是一个宝贵的提示语工程工具,因为它允许你通过一个通用界面在不同的模型上试验不同的提示语和参数,让你快速比较各种模型和参数的输出,以及对提示语进行迭代以达到预期结果。

熟悉了提示语工程后,你也可以利用Semantic Kernel将你的技能应用于真实场景。将你的提示语与原生函数和连接器结合起来,你可以构建出强大的AI驱动的应用程序。

此外,Semantic KernelVisual Studio Code的深度集成更是简化了将提示语工程纳入现有开发流程的过程。

  • 直接在你偏好的代码编辑器中创建提示语。

  • 使用现有的测试框架为它们编写测试。

  • 使用现有的CI/CD流程将它们部署到生产环境。

提示语工程的额外技巧 要成为一名熟练的提示语工程师,需要结合技术知识、创造力和实验。这里有一些卓越的提示语工程技巧:

  • 充分了解LLM AI模型:深入理解LLM AI模型的工作原理,包括它们的架构、训练过程和行为。

  • 领域知识:获取领域特定知识以便设计符合预期输出和任务要求的提示语。

  • 实验性:探索不同的参数和设置,以微调提示语,并优化模型在特定任务或领域中的行为。

  • 反馈与迭:持续分析模型生成的输出,并根据用户反馈迭代提示语,以提高它们的质量与相关性。

  • 保持更新:跟上提示语工程技术、研究和最佳实践的最新进展,以增强你的技能并在该领域保持领先。

提示语工程是一个动态发展的领域,其中,熟练的提示语工程师在有效利用LLM AI模型的能力方面起着关键作用。提示语是从AI模型中获取正确结果的核心。在本文中,我们演示了如何使用Semantic Kernel时共通的提示语工程技巧。

想看到这个教程的最终解决方案,你可以在公共文档存储库中查看以下的示例。创建一个检测用户意图的提示语 如果您曾经使用过ChatGPTMicrosoft Copilot,您已经熟悉提示语的概念。在接收到请求后,LLM会尝试预测最可能的响应。例如,如果发送了提示语"I want to go to the ",AI服务可能会返回"beach"来完成句子。这是一个非常简单的例子,但它演示了文本生成提示语工作的基本概念。

有了Semantic Kernel SDK,你可以轻松地在自己的应用程序中运行提示语。这允许你在你自己的应用程序中利用AI模型的能力。

一个常见的场景是检测用户的意图,以便之后可以运行一些自动化操作,所以在本文中,我们将展示如何创建一个检测用户意图的提示语。此外,我们将演示如何使用提示语工程技术逐步改进提示语。

本文中的许多建议都基于《提示语工程指南》。如果您想成为撰写提示语的专家,我们强烈建议您阅读这份指南,并利用他们的提示语工程技术。

通过Semantic Kernel运行你的第一个提示语 如果我们想让AI检测用户输入的意图,我们可以简单地询问这个意图是什么。在Semantic Kernel中,我们可以创建一个执行该操作的字符串,如下所示:

Console.Write("你的请求: ");
string request = Console.ReadLine()!; string prompt = $"这个请求的意图是什么? {request}";

要运行这个提示语,我们现在需要创建一个具有AI服务的kernel

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.SemanticKernel; // Create a kernel
var builder = Kernel.CreateBuilder();
// Add a text or chat completion service using either:
// builder.Services.AddAzureOpenAIChatCompletion()
// builder.Services.AddAzureOpenAITextGeneration()
// builder.Services.AddOpenAIChatCompletion()
// builder.Services.AddOpenAITextGeneration()

最后,我们可以使用我们的新kernel来调用我们的提示语。

Console.WriteLine(await kernel.InvokePromptAsync(prompt));

如果我们用输入"I want to send an email to the marketing team celebrating their recent milestone."运行这段代码,我们应该会获得以下类似的输出:

这个请求的意图是寻求指导或澄清如何有效地编写一封邮件,以庆祝市场营销团队最近的里程碑。

通过提示语工程改进提示语 虽然这个提示语“可行”,但由于你无法使用结果来可预测地触发自动化,所以并不实用。每次运行提示语,你可能会得到非常不同的响应。

为了使结果更为可预测,我们可以进行以下改进:

1)使提示语更具体 我们可以做的第一件事是让我们的提示语更具体。与其仅仅询问“这个请求的意图是什么?”不如我们向AI提供一系列可选择的意图。这将使提示语更可预测,因为AI只能从我们提供的意图列表中进行选择。

prompt = @$"这个请求的意图是什么? {request}
你可以在SendEmail、SendMessage、CompleteTask、CreateDocument之间进行选择。"

现在,当您用相同的输入运行提示语时,您应该会得到一个更有用的结果,但它仍然不完美,因为AI会以额外的信息作出回应。

这个请求的意图是发送一封电子邮件。因此,合适的行动将是使用SendEmail功能。

2)通过格式化添加结构到输出 虽然结果更可预测,但如果LLM以一种你不能轻易解析的结果进行响应,就有可能遇到问题。例如,如果LLM响应“意图是SendEmail”,你可能很难提取意图,因为它不在一个可预测的位置。

为了使结果更可预测,我们可以通过使用格式化来给提示语添加结构。在这种情况下,我们可以这样定义我们的提示语的不同部分:

prompt = @$"说明:此请求的意图是什么?
选择: SendEmail, SendMessage, CompleteTask, CreateDocument.
用户输入: {request}
意图:";

通过使用这种格式,AI不太可能响应一个结果,而只是意图。

在其他提示语中,您也可能想要尝试使用Markdown、XML、JSON、YAML或其他格式来添加结构到您的提示语及其输出。由于LLMs倾向于生成看起来像提示语的文本,因此建议您对于提示以及输出都使用相同的格式。

例如,如果您希望LLM生成一个JSON对象,您可以使用以下提示语:

prompt = @$"## 说明
使用以下格式提供请求的意图: ```json
{
"intent": {intent}
}
你可以在以下意图之间进行选择:
json
["SendEmail", "SendMessage", "CompleteTask", "CreateDocument"]
用户输入是:
{
"request": "{request}"
}

这将会产生以下输出:

{
"intent": "SendEmail"
}

3)使用少数样本提示提供示例 到目前为止,我们一直在使用零样本提示,这意味着我们没有给AI提供任何示例。虽然这对于入门是可以的,但对于更复杂的场景并不推荐,因为AI可能没有足够的训练数据来产生正确的结果。

为了添加示例,我们可以使用少数样本提示。通过少数样本提示,我们提供给AI一些我们希望它做到的例子。例如,我们可以提供以下例子来帮助AI区分发送电子邮件和发送即时消息。

prompt = @$"说明:此请求的意图是什么?
选项:SendEmail、SendMessage、CompleteTask、CreateDocument 用户输入:你能很快向营销团队发送批准吗?
意图:SendMessage 用户输入:你能将完整的更新发送给营销团队吗?
意图:SendEmail 用户输入:{request}
意图:";

4)告诉AI应该做什么以避免做错事 通常当AI开始错误响应时,我们的直觉是让AI停止做某些事情。不幸的是,这往往会导致AI做出更糟的事情。例如,如果你告诉AI停止返回一个幻想出的意图,它可能开始返回与用户请求完全无关的意图。

相反,我们推荐你告诉AI它应该做什么。例如,如果你想让AI停止返回幻想出的意图,你可能会写出如下提示语。

prompt = @$"说明:此请求的意图是什么?
如果你不知道其意图,不要猜测;而是以“未知”作为响应。
选项:SendEmail、SendMessage、CompleteTask、CreateDocument、Unknown。
用户输入:你能很快向营销团队发送批准吗?
意图:发送消息 用户输入:你能将完整的更新发送给营销团队吗?
意图:发送电子邮件 用户输入:{request}
意图:";

5)为AI提供上下文 在某些情况下,你可能想要给AI提供上下文,这样它可以更好地理解用户的请求。这对于长时间运行的聊天场景尤为重要,在这些场景中,用户的意图可能需要从前面的消息中获取上下文。

例如,以下对话:

用户:我讨厌发送电子邮件,没有人会读它们。AI:我很抱歉听到这一点。使用消息可能是一种更好的沟通方式。用户:我同意,你可以那样发送市场营销团队的全面状态更新吗?

如果AI只被给予最后一条消息,它可能错误地回应"SendEmail"而不是"SendMessage"。但是,如果AI被给予整个对话,它可能能够理解用户的意图。

为了提供这种上下文,我们可以简单地将之前的消息添加到提示语中。例如,我们可以更新我们的提示语使其看起来如下:

string history = @"用户输入:我讨厌发送电子邮件,没有人会读它们。
AI回应:我很抱歉听到这一点。使用消息可能是一种更好的沟通方式。"; prompt = @$"说明:此请求的意图是什么?
如果你不知道其意图,不要猜测;而是以"Unknown"作为响应。
选项:SendEmail、SendMessage、CompleteTask、CreateDocument、Unknown。 用户输入:你能很快给营销团队发一份批准书吗?
意图:发送消息 用户输入:你能把最新消息发给营销团队吗?
意图:发送电子邮件 {history} 用户输入:{request}
意图:";

6)在聊天完成提示语中使用消息角色 随着你的提示语变得越来越复杂,你可能会想要使用消息角色来帮助AI区分系统指令、用户输入和AI响应。这在我们开始将聊天历史添加到提示语时尤为重要。AI应该知道,一些先前的消息是由自己发送的,而非用户。

在Semantic Kernel中,使用特殊语法来定义消息角色。要定义消息角色,你只需用<message>标签包裹消息,并将角色名作为属性。这目前仅在C# SDK中可用。

history = @"<message role="user">我讨厌发电子邮件,从来没有人读过。</message>
<message role="assistant">听到这个消息我很难过。信息可能是更好的沟通方式。</message>"; prompt = @$"<message role="system">说明:此请求的意图是什么?
如果你不知道其意图,不要猜测;而是以"Unknown"作为响应。
选项:SendEmail、SendMessage、CompleteTask、CreateDocument、Unknown。</message> <message role="user">你能很快给营销团队发一份批准书吗?</message>
<message role="system">意图:</message>
<message role="assistant">SendMessage</message> <message role="user">你能将完整的更新发送给营销团队吗?</message>
<message role="system">意图:</message>
<message role="assistant">SendEmail</message> {history}
<message role="user">{request}</message>
<message role="system">意图:</message>";

7)鼓励你的AI 最后,研究表明,给AI鼓励能帮助其表现得更好。

就是夸它,说他棒!给他带高帽,比如你是某某领域的专家之类的。

另外也可以和博主一样,不断学习提示词工程,提升自己的提示词工程能力

下面是我的微信公众号,如果你想与我交流,可以通过公众号给我留言。

掌握语义内核(Semantic Kernel):如何精进你的提示词工程的更多相关文章

  1. Semantic Kernel 入门系列:🥑突破提示词的限制

    无尽的上下文 LLM的语言理解和掌握能力在知识内容的解读和总结方面提供了强大的能力. 但是由于训练数据本身来自于公共领域,也就注定了无法在一些小众或者私有的领域能够足够的好的应答. 因此如何给LLM ...

  2. Semantic Kernel 入门系列:🔥Kernel 内核和🧂Skills 技能

    理解了LLM的作用之后,如何才能构造出与LLM相结合的应用程序呢? 首先我们需要把LLM AI的能力和原生代码的能力区分开来,在Semantic Kernel(以下简称SK),LLM的能力称为 sem ...

  3. Semantic Kernel 知多少 | 开启面向AI编程新篇章

    引言 在ChatGPT 火热的当下, 即使没有上手亲自体验,想必也对ChatGPT的强大略有耳闻.当一些人在对ChatGPT犹犹豫豫之时,一些敏锐的企业主和开发者们已经急不可耐的开展基于ChatGPT ...

  4. Semantic Kernel 入门系列:🛸LLM降临的时代

    不论你是否关心,不可否认,AGI的时代即将到来了. 在这个突如其来的时代中,OpenAI的ChatGPT无疑处于浪潮之巅.而在ChatGPT背后,我们不能忽视的是LLM(Large Language ...

  5. Semantic Kernel 入门系列:💬Semantic Function

    如果把提示词也算作一种代码的话,那么语义技能所带来的将会是全新编程方式,自然语言编程. 通常情况下一段prompt就可以构成一个Semantic Function,如此这般简单,如果我们提前可以组织好 ...

  6. Semantic Kernel 入门系列:💾Native Function

    语义的归语义,语法的归语法. 基础定义 最基本的Native Function定义只需要在方法上添加 SKFunction 的特性即可. using Microsoft.SemanticKernel. ...

  7. Semantic Kernel 入门系列:🥑Memory内存

    了解的运作原理之后,就可以开始使用Semantic Kernel来制作应用了. Semantic Kernel将embedding的功能封装到了Memory中,用来存储上下文信息,就好像电脑的内存一样 ...

  8. Semantic Kernel 入门系列:📅 Planner 计划管理

    Semantic Kernel 的一个核心能力就是实现"目标导向"的AI应用. 目标导向 "目标导向"听起来是一个比较高大的词,但是却是实际生活中我们处理问题的 ...

  9. 语义分割(semantic segmentation) 常用神经网络介绍对比-FCN SegNet U-net DeconvNet,语义分割,简单来说就是给定一张图片,对图片中的每一个像素点进行分类;目标检测只有两类,目标和非目标,就是在一张图片中找到并用box标注出所有的目标.

    from:https://blog.csdn.net/u012931582/article/details/70314859 2017年04月21日 14:54:10 阅读数:4369 前言 在这里, ...

  10. Semantic Kernel 入门系列:🪄LLM的魔法

    ChatGPT 只是LLM 的小试牛刀,让人类能够看到的是机器智能对于语言系统的理解和掌握. 如果只是用来闲聊,而且只不过是将OpenAI的接口封装一下,那么市面上所有的ChatGPT的换皮应用都差不 ...

随机推荐

  1. Ubuntu更新软件的命令

    更新软件源 apt-get update 更新升级所有软件 apt-get upgrade 更新某个软件 apt-get upgrade 名 列出可更新的软件 apt list --upgradabl ...

  2. 一款Redis可视化工具:ARDM | 京东云技术团队

    出众的软件有很多,适合自己的才是最好的. Another Redis Desktop Manager 更快.更好.更稳定的Redis桌面(GUI)管理客户端,兼容Windows.Mac.Linux,性 ...

  3. Top 5 Code Smells Newbies Developers Could Easily Identify & Avoid

    Posted by Ajitesh Kumar / In Freshers, Software Quality / February 1, 2014 Following is one very pop ...

  4. MyBatis foreach循环批量修改数据时报错

    报错如下 org.springframework.jdbc.BadSqlGrammarException: ### Error updating database. Cause: java.sql.S ...

  5. 彻底搞懂Docker容器与Kraft模式kafka集群关于消息大小相关参数设置

    Docker部署的设置 部署背景: 在DockerHub拉取的bitnami/kafka:3.4.1 镜像,如果要部署在Docker-Swarm集群或者单Docker部署,对于消息大小设置需要添加参数 ...

  6. MIT协议原文及中文翻译

    MIT协议原文及翻译 参考链接 原文: Copyright ( C ) Permission is hereby granted, free of charge, to any person obta ...

  7. JavaScript高级程序设计笔记04 变量、作用域与内存

    变量.作用域与内存 变量 特定时间点一个特定值的名称. 分类 原始值:按值访问 复制:两个独立使用.互不干扰 引用值(由多个值构成的对象):按引用访问 操作对象时,实际上操作的是对该对象的引用(ref ...

  8. 01Java学习_概述

    概述 目录 概述 三个阶段 概述 历史(了解) Java 重要特点 开发工具 Java 运行机制及运行过程 下载和安装 JDK 配置环境变量 java 快速入门 博客中的图片内容全部采用 github ...

  9. .NET8依赖注入新特性Keyed services

    什么是Keyed service Keyed service是指,为一个需要注入的服务定义一个Key Name,并使用使用Key Name检索依赖项注入 (DI) 服务的机制. 使用方法 通过调用 A ...

  10. GPTs大受欢迎但问题多,企服软件厂商的AI Agent更被B端客户器重

    GPTs大受欢迎但问题多,企服软件厂商的AI Agent更被B端客户器重 比尔盖茨预言智能体是下个平台,超自动化平台的AI Agent更靠谱? 以GPTs为代表的AI Agent只是玩具?揭秘真实可用 ...