Name = "chat", Description = "给出一段对话记录,总结这部分对话.", Template = SummarizeConversationDefinition, TemplateFormat = "semantic-kernel", InputVariables = new List<InputVariable> { new InputVariable{Name = "request", Description = "用户的问题", IsRequired = true } }, ExecutionSettings = new Dictionary<string, PromptExecutionSettings> { { "default", new OpenAIPromptExecutionSettings() { MaxTokens = 1000, Temperature = 0 } }, { "gpt-3.5-turbo", new OpenAIPromptExecutionSettings() { ModelId = "gpt-3.5-turbo-0613", MaxTokens = 4000, Temperature = 0.2 } }, { "gpt-4", new OpenAIPromptExecutionSettings() { ModelId = "gpt-4-1106-preview", MaxTokens = 8000, Temperature = 0.3 } } }提示模板语法
目前,我们已经有两个地方使用到提示模板的语法,即变量和函数调用,因为前面已经介绍过相关的用法,因此这里再简单提及一下。
变量
变量的使用很简单,在提示工程中使用{{$变量名称}}标识即可,如{{$name}}。
然后在对话中有多种方法插入值,如使用 KernelArguments 存储变量值:
new KernelArguments { { "name", "工良" } });函数调用
在 实现总结 一节提到过,在提示模板中可以明确调用一个函数,比如定义一个函数如下:
// 没有 Kernel kernel [KernelFunction, Description("给你一份很长的谈话记录,总结一下谈话内容.")] public async Task<string> SummarizeConversationAsync( [Description("长对话记录\r\n.")] string input) { await Task.CompletedTask; return input; } // 有 Kernel kernel [KernelFunction, Description("给你一份很长的谈话记录,总结一下谈话内容.")] public async Task<string> SummarizeConversationAsync( [Description("长对话记录\r\n.")] string input, Kernel kernel) { await Task.CompletedTask; return input; } [KernelFunction] [Description("Sends an email to a recipient.")] public async Task SendEmailAsync( Kernel kernel, string recipientEmails, string subject, string body ) { // Add logic to send an email using the recipientEmails, subject, and body // For now, we'll just print out a success message to the console Console.WriteLine("Email sent!"); }函数一定需要使用[KernelFunction]标识,[Description]描述函数的作用。函数可以一个或多个参数,每个参数最好都使用[Description]描述作用。
函数参数中,可以带一个Kernel kernel,可以放到开头或末尾 ,也可以不带,主要作用是注入Kernel对象。
在 prompt 中使用函数时,需要传递函数参数:
总结如下:{{AAA.SummarizeConversationAsync $input}}.其它一些特殊字符的转义方法等,详见官方文档:https://learn.microsoft.com/en-us/semantic-kernel/prompts/prompt-template-syntax
文本生成
前面劈里啪啦写了一堆东西,都是说聊天对话的,本节来聊一下文本生成的应用。
文本生成和聊天对话模型主要有以下模型:
| Model type | Model |
|---|---|
| Text generation | text-ada-001 |
| Text generation | text-babbage-001 |
| Text generation | text-curie-001 |
| Text generation | text-davinci-001 |
| Text generation | text-davinci-002 |
| Text generation | text-davinci-003 |
| Chat Completion | gpt-3.5-turbo |
| Chat Completion | gpt-4 |
当然,文本生成不一定只能用这么几个模型,使用 gpt-4 设定好背景提示,也可以达到相应效果。
文本生成可以有以下场景:
使用文本生成的示例如下,让 AI 总结文本:
按照这个示例,我们先在 Env.cs 中编写扩展函数,配置使用.AddAzureOpenAITextGeneration()文本生成,而不是聊天对话。
public static IKernelBuilder WithAzureOpenAIText(this IKernelBuilder builder) { var configuration = GetConfiguration(); // 需要换一个模型,比如 gpt-35-turbo-instruct var AzureOpenAIDeploymentName = "ca"; var AzureOpenAIModelId = "gpt-35-turbo-instruct"; var AzureOpenAIEndpoint = configuration["AzureOpenAI:Endpoint"]!; var AzureOpenAIApiKey = configuration["AzureOpenAI:ApiKey"]!; builder.Services.AddLogging(c => { c.AddDebug() .SetMinimumLevel(LogLevel.Trace) .AddSimpleConsole(options => { options.IncludeScopes = true; options.SingleLine = true; options.TimestampFormat = "yyyy-MM-dd HH:mm:ss "; }); }); // 使用 Chat ,即大语言模型聊天 builder.Services.AddAzureOpenAITextGeneration( AzureOpenAIDeploymentName, AzureOpenAIEndpoint, AzureOpenAIApiKey, modelId: AzureOpenAIModelId ); return builder; }然后编写提问代码,用户可以多行输入文本,最后使用000结束输入,将文本提交给 AI 进行总结。进行总结时,为了避免 AI 废话太多,因此这里使用ExecutionSettings配置相关参数。
代码示例如下:
builder = builder.WithAzureOpenAIText(); var kernel = builder.Build(); Console.WriteLine("输入文本:"); var request = ""; while (true) { var input = Console.ReadLine(); if (input == "000") { break; } request += Environment.NewLine; request += input; } var func = kernel.CreateFunctionFromPrompt(new PromptTemplateConfig { Name = "chat", Description = "给出一段对话记录,总结这部分对话.", // 用户的文本 Template = request, TemplateFormat = "semantic-kernel", ExecutionSettings = new Dictionary<string, PromptExecutionSettings> { { "default", new OpenAIPromptExecutionSettings() { MaxTokens = 100, Temperature = (float)0.3, TopP = (float)1, FrequencyPenalty = (float)0, PresencePenalty = (float)0 } } } }); var result = await func.InvokeAsync(kernel); Console.WriteLine($""" 总结如下: {string.Join("\n", result)} """);