Langchain.js | Basic promptTemplate | 重拳出击(一)👊👊👊

544 阅读4分钟

前言

开始了~

了解什么是 PromptTemplate

根据官网定义 :

Prompt templates help to translate user input and parameters into instructions for a language model. This can be used to guide a model's response, helping it understand the context and generate relevant and coherent language-based output.

意思是 :

提示模板有助于将用户输入和参数转换为语言模型的指令。这可以用来指导模型的响应,帮助它理解上下文并生成相关且连贯的语言输出。

参考:

js.langchain.com/docs/concep…

提示模板接受一个对象作为输入,其中每个键代表提示模板中的一个变量以填充。

上面的提示模板会产生一个 PromptValue , 可以被传递给LLM或聊天模型,也可以转换为字符串或消息列表。

而 PromptValue 存在的原因是方便在字符串和消息之间切换。

promptTemplate 类型

对于 promptTemplate 有很多的分类 :

在官网中搜了一下 , 似乎分类不是很明确 , 可能没搜到

我也不管了 🤡👈

直接按照普通 ,特殊来分类 :

我按照功能和复杂性分为以下类型(只供自己自娱自乐🤡)

  • basic-promptTemplate
    • 一些基本的模板
  • chat-promptTemplate
    • 构建聊天信息时的模板
  • pipeline-promptTemplate
    • 组合多个 Template , 构建复杂的 prompt

部分参考 :

我将分为三篇文章 , 逐一 demo 级落地 😗 , 以下是第一篇

basic promptTemplate

这篇文章 , 我会对 basic-promptTemplate 进行展开

思路大体如下 :

  • 无变量 promptTemplate

  • 含变量 promptTemplate

  • 部分格式化提示模板(langchain.js 分为两种)

    • Partial formatting with string values.
      部分格式化使用字符串值。
    • Partial formatting with functions that return string values.
      部分格式化,使用返回字符串值的函数。

部分格式化提示模板官网参考:js.langchain.com/docs/how_to…

无变量 promptTemplate

import { PromptTemplate } from "@langchain/core/prompts";

const MyPrompt = new PromptTemplate({
  inputVariables: [],
  template: "Are you ok ?",
});
const formattedPrompt = await MyPrompt.format();

console.log(formattedPrompt);

直接传入template , 对于变量inputVariables: [] 不输入

含变量 promptTemplate

构造函数初始化PromptTemplate

const multiVariableGreetingPrompt = new PromptTemplate({
    inputVariables: ["who", "shcool"],
    template: "Hi {who} 来自 {shcool}",
  });
  const formattedMultiVariableGreeting = await multiVariableGreetingPrompt.format({
    who: "你",
    shcool: "清华大学",
  });
  
  console.log(formattedMultiVariableGreeting);
 

使用fromTemplate 初始化PromptTemplate

import { PromptTemplate } from "@langchain/core/prompts";

const promptTemplate = PromptTemplate.fromTemplate(
  "Tell me a joke about {topic}"
);

await promptTemplate.invoke({ topic: "cats" });

部分格式化 promptTemplate

partial formatting | string values.

Partial formatting with string values.

举出一下例子 :

const initialPrompt = new PromptTemplate({
  template: "我是一名{identy} , 喜欢{hobby}",
  inputVariables: ["identy", "hobby"],
});


const partialedPrompt = await initialPrompt.partial({
  identy: "学生",
});

const formattedPrompt = await partialedPrompt.format({
  hobby: "编程",
});

console.log(formattedPrompt);


const formattedPrompt2 = await partialedPrompt.format({
  hobby: "音乐",
});

console.log(formattedPrompt2)
  

注意 : 在使用 partial 方法补全变量 identy 之后 , 不能再改变 identy 值了 ~

const initialPrompt = new PromptTemplate({
  template: "我是一名{identy} , 喜欢{hobby}",
  inputVariables: ["identy", "hobby"],
});


const partialedPrompt = await initialPrompt.partial({
  identy: "学生",
});

const formattedPrompt = await partialedPrompt.format({
  hobby: "编程",
});

console.log(formattedPrompt);


const formattedPrompt2 = await partialedPrompt.format({
  hobby: "音乐",
});


console.log(formattedPrompt2)

// 增添样例 , 报错! 为什么?
const formattedPrompt3 = await partialedPrompt.format({
  identy: "叼毛",
});

console.log(formattedPrompt3)

对于 const formattedPrompt3 = await partialedPrompt.format({ identy: "叼毛" }); 这行代码报错的原因如下:

在前面已经通过 partial 方法对 initialPrompt 进行了部分参数填充,将 identy 变量的值固定为 "学生" 了。

当再次调用 format 方法时,partialedPrompt **这个对象已经处于一个只期望接收剩余未填充变量(也就是这里的 **hobby** 变量)值的状态,它内部的逻辑是基于之前已经部分填充好的前提来进行的。**而此时又试图重新为 identy 这个已经被赋值过的变量再次赋值,这就违背了 PromptTemplate 的使用逻辑,导致了错误的发生,因为它不符合该模板对象当前所处的参数填充阶段和期望的操作流程。

简单来说,partialedPrompt 此时只允许传入 hobby 变量的值来完成最终的格式化,不允许再对之前已经部分填充好的 identy 变量进行重新赋值操作了。

即报错是因为 <font style="color:rgba(0, 0, 0, 0.85);">PromptTemplate</font> 为了实现有序、可预测且逻辑连贯的带变量模板处理流程,通过内部状态管理、函数参数约束等多方面设计共同作用的结果,促使开发者按照合理的方式使用它来生成期望的文本内容。

Partial formatting | functions

官方案例 :

const getCurrentDate = () => {
    return new Date().toISOString();
  };
  
  const prompt = new PromptTemplate({
    template: "Tell me a {adjective} joke about the day {date}",
    inputVariables: ["adjective", "date"],
  });
  //这个是确定要的 ,所以直接partial🤔
  const partialPrompt = await prompt.partial({
    date: getCurrentDate,
  });
  //这个需要自定义,所以format🤔
  const formattedPrompt = await partialPrompt.format({
    adjective: "funny",
  });
  
  console.log(formattedPrompt);
  
  // Tell me a funny joke about the day 2023-07-13T00:54:59.287Z

自我案例 :

我画出以下逻辑图 , 搞一下Partial formatting with functions that return string values.🤡👈

画板

import { PromptTemplate } from "@langchain/core/prompts";
const getDate = () =>{
    //获取星期几 ?
    const weekday = ["星期日","星期一","星期二","星期三","星期四","星期五","星期六"];
    return weekday[new Date().getDay()];
}

const getResult = () =>{
        const  day = getDate();
        return day === "星期四" ? `很高兴${day}见到你 ~ vivo 50` : `不是星期四,今天是${day} `
}

const prompt = new PromptTemplate(
    {
        template: "{result}",
        inputVariables: ["result"],
    }
)

const  partialPrompt  =  await prompt.partial({
    result : getResult()
})
const formattedPrompt = await partialPrompt.format({})

console.log(formattedPrompt)

总结

  • 无变量 promptTemplate

    • 最简单 , 只需要传入字符串
  • 含变量 promptTemplate

    • 造函数初始化PromptTemplate
    • 使用fromTemplate 初始化PromptTemplate
  • 部分格式化提示模板(langchain.js 分为两种)

    • Partial formatting with string values.
      部分格式化使用字符串值 ,注意partial 后可修改
    • Partial formatting with functions that return string values.
      部分格式化,使用返回字符串值的函数

下篇文章见 ~