AI探索实践11 - 实现 Prompt Template (提示语模版) 功能

大家好,我是feng,感谢你阅读我的博文,如果你也关注AI应用开发,欢迎关注公众号和我一起​探索。如果文章对你有所启发,请为我点赞!

在博文《AI探索实践9 - 不用Python!用前端也能开发一个本地运行的"ChatGPT"!》,实现了仅依靠前端程序,就可以和本地大模型通信,实现了类似ChatGPT聊天的效果。但是在运行程序后,我发现本地模型的响应是一次性显示的,并没有像ChatGPT那样实现打字机的效果。本文就来研究如何实现流式输出的效果。

在博文《AI探索实践10 - 前端实现本地模型流式响应输出》,了解到前端程序如何将模型的响应以流式方式呈现在页面上。

本篇文章将介绍一个比较重要的概念 Prompt Template - 提示语模板,以及如何在前端实现。

一、重点回顾

在前端程序中,使用LangChain框架来实现大模型应用的开发。基本逻辑是:

  1. 声明一个 ChatOllama 对象,配置本地大模型参数:ip、模型名称、temperature等。
  2. 使用模型的invoke、batch或stream等方法,实现向模型发送请求和收到响应。
  3. 根据请求的方法不同,处理不同的响应数据对象,同步更新到模板。

二、问题

上面的代码逻辑,实现了类似ChatGPT聊天的效果。但是在使用过程中发现,我们在连续提出问题时,如果发的提示语比较简单、没有把相关的上下文也一起发送,那么模型回答会显得莫名其妙:

可以看出,模型的回答仅仅针对的是你这一次的提问。现有的代码逻辑,并没有将你这次提问的上下文一起发送给模型,所以在模型看来有些问题可能就会莫名奇妙,答案自然也很离谱。

人与人之间的交流过程中,如果你想得到期望的回答,你就需要说出让对方 听得懂的话,这很重要。话中的歧义越少,对方理解偏差就越小,给你的响应回答也就越符合你的期望。和大模型的通信也是一样的道理。提示语,就是我们发给模型的内容、说的话。好的提示语能够让模型更好的理解你的问题,从而给你更好的答案。

因此,提示语 Prompt很重要。

三、实现提示语模版功能

实际上,说提示语 prompt很重要,但这是针对现阶段大模型的处理能力来说的。理想情况下,大模型应该有能力充分的理解你想要表达的意思,我相信这在未来是会实现的。现实是大模型还不具备这样的能力,所以我们在实现大模型应用时,要充分的考虑到这一点。应该通过技术来提供一种机制,来优化和补充用户发出的提示语,帮助大模型更好的理解用户意图。

我们可以通过模型对象的方法(invoke/batch/stream),来获取模型的响应。我们也可以通过使用提示语模版对象(Prompt Template)来获得响应。提示语模版,常用于将用户的输入内容,转换为对于大语言模型更易于理解的内容。

创建一个提示语模板 Prompt Template,可以有2种不同的方法创建:

3.1 从字符串提示语模板中创建

第一种方法,是从字符串模版中创建。它需要以单个字符串作为输入,该字符串代表了系统消息,指示模型以某种方式运行。

新建一个 prompt-template.js 文件:

TypeScript 复制代码
import { ChatOllama } from '@langchain/community/chat_models/ollama';
import { ChatPromptTemplate } from '@langchain/core/prompts';

// 创建一个模型
const chatModel = new ChatOllama({
  baseUrl: 'http://localhost:11434', // Default value
  model: 'qwen:4b',
  temperature: 0.7,
});

const prompt = ChatPromptTemplate.fromTemplate(
  '你是一个喜剧演员,使用接下来的词创作一个笑话: {input}',
);

ChatPromptTemplate 类,可以帮助我们创建一个提示语模版对象。fromTemplate 函数中 {input} 代表用户输入的变量,使用大括号 {} 作为占位符。

在LangChain中,可以以某种方式组合模型和提示语,这被称之为:chain。接下来,我们创建一个chain,通过pipe方法将模型和提示语链接起来。当然也可以链接其他对象:

TypeScript 复制代码
const chain = prompt.pipe(chatModel);

接下来,我们不再是调用模型的方法来获取响应,而是调用 chain对象来做同样的事情:

TypeScript 复制代码
const response = await chain.invoke({
  input: '小狗',
});

// 在控制台中
console.log(response);

我们执行一下这个js,来看看控制台输出的内容:

可以看到,通过chain将模型与提示语模版对象链接起来,并调用chain的方法同样实现了对模型的请求与响应。我们再来梳理和说明一下逻辑:

模板字符串内容是:

你是一个喜剧演员,使用接下来的词创作一个笑话: {input}

这个提示语起到3个作用:

  1. 告诉了模型的定位:喜剧演员。模型将重点使用这个定位的知识来做响应。
  2. 创作笑话:任务指令,告诉模型要做什么
  3. {input}:告诉模型,要根据用户的数据,并且输入的变量名为:input

当我们调用链时:

input: '小狗',

这个小狗,实际上代表的是用户在页面文本框中输入的内容。也是告诉大模型,变量名为input的值是:小狗

3.2 从消息数组中创建

另一种创建提示语模板的方法是,从消息数组中创建。这个可以更好的控制模型的输出。在这个消息数组中,你可以指定角色以及角色要执行的任务。数组中,每一个元素是一个键值数组:

TypeScript 复制代码
const prompt2 = ChatPromptTemplate.fromMessages([
  ['system', '根据用户提供的词语,来创作一首四言绝句'],
  ['human', '{input}'],
]);

在代码中,定义了2个角色:system和human。system代表了系统角色,human代表了用户。

TypeScript 复制代码
const chain2 = prompt2.pipe(chatModel);
const response2 = await chain2.invoke({
  input: '大海',
});
console.log(response2);

执行代码,看看返回的结果:

四、总结

通过提示语模板功能,我们可以为用户发送的提示语,补充更多的上下文信息,从而得到更好的答案。

我们可以在提示语中间指定模型的角色、明确模型要做的任务,以及说明需要识别用户的输入占位符等。

很明显,质量更高的提示语内容能够帮助大模型给我们回答更准确的结果。如何编写高质量的提示语不在本文的讨论范围,网络也有很多资料可以学习。

相关推荐
肥猪猪爸31 分钟前
使用卡尔曼滤波器估计pybullet中的机器人位置
数据结构·人工智能·python·算法·机器人·卡尔曼滤波·pybullet
LZXCyrus1 小时前
【杂记】vLLM如何指定GPU单卡/多卡离线推理
人工智能·经验分享·python·深度学习·语言模型·llm·vllm
我感觉。1 小时前
【机器学习chp4】特征工程
人工智能·机器学习·主成分分析·特征工程
YRr YRr1 小时前
深度学习神经网络中的优化器的使用
人工智能·深度学习·神经网络
DieYoung_Alive1 小时前
一篇文章了解机器学习(下)
人工智能·机器学习
夏沫的梦1 小时前
生成式AI对产业的影响与冲击
人工智能·aigc
goomind2 小时前
YOLOv8实战木材缺陷识别
人工智能·yolo·目标检测·缺陷检测·pyqt5·木材缺陷识别
只怕自己不够好2 小时前
《OpenCV 图像基础操作全解析:从读取到像素处理与 ROI 应用》
人工智能·opencv·计算机视觉
幻风_huanfeng2 小时前
人工智能之数学基础:线性代数在人工智能中的地位
人工智能·深度学习·神经网络·线性代数·机器学习·自然语言处理
嵌入式大圣2 小时前
嵌入式系统与OpenCV
人工智能·opencv·计算机视觉