LangChain4j 提示词模版及角色设置的原理与示例

1,442 阅读3分钟

本篇文章主要介绍LangChain4j对ChatGPT角色设置、提示词模版的使用,最后实现一个只做汉语到英语的翻译助手,对于别的事情一概不做。

实现一个仅支持英文的翻译助手,需要两个方面的内容:

  • 角色设定:指定是一个专业英文翻译官
  • 模版:如何设置合理的提示词模版,当要翻译其它语言就返回不会翻译

角色设定

角色设置就是规定大模型可以干什么,比如你是一个诗人、或者你是画家。这样让大模型更专注于某个领域知识的回答。在Spring AI 专栏# 05. Spring AI 实现ChatGPT的人设(角色)定义 中有详细的说明。

回顾一下大模型的消息类型; image.png 角色的设定主要利用大模型消息的特性来实现,其中的SystemMessage可以指定角色。因为其特性比其他类型的消息优先级更高。

模版使用

  • @UserMessage/@SystemMessage + @V

     @UserMessage("You are a good friend of mine. Answer using slang. {{message}}")  
     String chat(@V("message") String userMessage);
    

    在使用上的几点说明:

    • 如果只有一个参数,可以使用 {{it}}, 无需在使用@V指定参数名称。
    • @UserMessage/@SystemMessage注解 可以直接指定字符串也可以使用fromResource字段可以引用一个文件。
  • 使用 @StructuredPrompt 先定义一个模版请求类,然后将注解加 @StructuredPrompt 注解即可

    @Getter
    @AllArgsConstructor
    @StructuredPrompt("xxx  {{aa}}, yyyyy {{bb}}") // 按照需要定义
    class XxxxPrompt {
        private String aa;
        private String bb;
    }
    
  • PromptTemplate

    PromptTemplate promptTemplate = PromptTemplate.from("Say 'hi' in {{it}}.");
    Prompt prompt = promptTemplate.apply("German");
    System.out.println(prompt.text()); // Say 'hi' in German.
    

实现原理

底层使用就是String 类的字符串替换,没有用到其它技术,主要实现类(默认) DefaultTemplate

// 生成提示词字符串
public String render(Map<String, Object> variables) {
    ensureAllVariablesProvided(variables);

    String result = template;
    for (Map.Entry<String, Object> entry : variables.entrySet()) {
        result = replaceAll(result, entry.getKey(), entry.getValue());
    }

    return result;
}
// 使用值替换到{{变量名}}
private static String replaceAll(String template, String variable, Object value) {
    if (value == null || value.toString() == null) {
        throw illegalArgument("Value for the variable '%s' is null", variable);
    }
    return template.replace(inDoubleCurlyBrackets(variable), value.toString());
}

private static String inDoubleCurlyBrackets(String variable) {
    return "{{" + variable + "}}";
}

LangChain4j框架在设计上给开发者通过SPI方式留出扩展点,可以自定义模型解析方式。默认提供了一个DefaultTemplate实现类。

翻译助手

Translator

package org.ivy.chatmemory.service;

import dev.langchain4j.service.SystemMessage;
import dev.langchain4j.service.UserMessage;
import dev.langchain4j.service.V;
import dev.langchain4j.service.spring.AiService;

@AiService
public interface Translator {
    // 指定角色
    @SystemMessage("You are a professional translator. You can only translate Chinese text to English. If other languages You response I can not translate, ")
    // 翻译文本
    @UserMessage("Translate the following text: {{text}} to {{language}}")
    String translate(@V("text") String text, @V("language") String language);
}

Controller

package org.ivy.chatmemory.controller;

import org.ivy.chatmemory.service.Translator;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TranslatorController {
    private final Translator translator;

    public TranslatorController(Translator translator) {
        this.translator = translator;
    }

    @GetMapping("/translate")
    public String translate(@RequestParam("text") String text, @RequestParam("language") String language) {
        return translator.translate(text, language);
    }
}

测试

翻译为英文 image.png 翻译为日语 image.png 当让翻译助手将中文翻译为日语时,提示不会翻译!

总结与示例代码

本文实现了一个仅支持英文的翻译助手,主要实践实现角色定义和提示词的使用,如何设定角色,如何使用提示词模板。

示例代码:template