Enjoy 模版引擎

简介

tio-boot 内置 Enjoy 模版引擎,使用 Enjoy 模版引擎可以非常方便的返回网页内容

使用

使用 Enjoy 模版引擎拼接 JSON

场景描述

在大模型开发过程中,我们需要向大模型发送 prompt。如果在 Java 中使用 map 对象生成这个 prompt 费时费力,可以考虑使用 Enjoy 来返回完整的 JSON prompt。以下是具体的介绍。

开发

添加依赖

    <dependency>
      <groupId>com.jfinal</groupId>
      <artifactId>enjoy</artifactId>
      <version>5.1.3</version>
    </dependency>
  • EnjoyEngineConfig 加载模版文件
import com.jfinal.template.Engine;

public class EnjoyEngineConfig {

  private final String RESOURCE_BASE_PATH = "/prompt/";

  public void config() {
    Engine engine = Engine.use();
    engine.setBaseTemplatePath(RESOURCE_BASE_PATH);
    engine.setToClassPathSourceFactory();
    // 支持模板热加载,绝大多数生产环境下也建议配置成 true,除非是极端高性能的场景
    engine.setDevMode(true);
    // 配置极速模式,性能提升 13%
    Engine.setFastMode(true);
    // jfinal 4.9.02 新增配置:支持中文表达式、中文变量名、中文方法名、中文模板函数名
    Engine.setChineseExpression(true);
  }
}
  • EnjoyEngineConfigTest 读取 json 文件
package com.litongjava.ai.db.assistant.config;

import java.util.HashMap;
import java.util.Map;

import org.junit.BeforeClass;
import org.junit.Test;

import com.jfinal.template.Engine;
import com.jfinal.template.Template;

public class EnjoyEngineConfigTest {

  @BeforeClass
  public static void beforeClass() {
    new EnjoyEngineConfig().config();
  }

  @Test
  public void test() {
    Engine engine = Engine.use();
    Template template = engine.getTemplate("init_prompt.txt");
    Map<String, String> values = new HashMap<>();
    values.put("value", "postgresql");
    String renderToString = template.renderToString(values);
    System.out.println(renderToString);
  }
}

init_prompt.txt

{
  "messages":
  [
    {
      "role": "system",
      "content": "#include("init_prompt_message.txt")"
    }
  ],
  "functions":
  [
    {
      "name": "find",
      "description": "根据sql查询数据库",
      "parameters":
      {
        "type": "object",
        "properties":
        {
          "sql":
          {
            "description": "需要执行的sql语句",
            "type": "string"
          }
        },
        "required":
        [
          "sql"
        ]
      }
    }
  ]
}

init_prompt_message.txt

你是一名优秀的sql工程师,你可以根据用户的需求执行任何sql命令,你连接的数据库是 #(value)

最终返回 json 内容

{
  "messages": [
    {
      "role": "system",
      "content": "你是一名优秀的sql工程师,你可以根据用户的需求执行任何sql命令,你连接的数据库是 postgresql"
    }
  ],
  "functions": [
    {
      "name": "find",
      "description": "根据sql查询数据库",
      "parameters": {
        "type": "object",
        "properties": {
          "sql": {
            "description": "需要执行的sql语句",
            "type": "string"
          }
        },
        "required": ["sql"]
      }
    }
  ]
}

获取到上面的 json 之后就可以直接发送 json 到 chatgpt 进行推理

TioBoot 返回 Engjoy 模引擎

配置 EnjoyEngine


package com.litongjava.ai.chat.config;

import com.jfinal.template.Engine;
import com.litongjava.jfinal.aop.annotation.Bean;
import com.litongjava.jfinal.aop.annotation.Configuration;

@AConfiguration
public class EnjoyEngineConfig {

private final String RESOURCE_BASE_PATH = "/templates/";

  @ABean
  public Engine engine() {
    Engine engine = Engine.use();
    engine.setBaseTemplatePath(RESOURCE_BASE_PATH);
    engine.setToClassPathSourceFactory();
    // 支持模板热加载,绝大多数生产环境下也建议配置成 true,除非是极端高性能的场景
    engine.setDevMode(true);
    // 配置极速模式,性能提升 13%
    Engine.setFastMode(true);
    // jfinal 4.9.02 新增配置:支持中文表达式、中文变量名、中文方法名、中文模板函数名
    Engine.setChineseExpression(true);
    return engine;
  }

}

在 Controoler 使用 Engine 获取网页并返回


package com.litongjava.ai.chat.AController;

import com.jfinal.template.Engine;
import com.jfinal.template.Template;
import com.litongjava.jfinal.aop.Aop;
import com.litongjava.tio.http.common.HttpRequest;
import com.litongjava.tio.http.common.HttpResponse;
import com.litongjava.tio.http.server.annotation.RequestPath;
import com.litongjava.tio.http.server.util.Resps;
@AController
@RequestPath()
public class TemplatesController {
  private Engine engine = Aop.get(Engine.class);

  @RequestPath("/404")
  public Template notFound(HttpRequest request) {
    String fileName = "/404.html";
    Template template = engine.getTemplate(fileName);
    return template;
  }

  @RequestPath("/chat")
  public HttpResponse chat(HttpRequest request) {
    String fileName = "/chat.html";
    return renderHtml(request, fileName);
  }

  private HttpResponse renderHtml(HttpRequest request, String fileName) {
    Template template = engine.getTemplate(fileName);
    String string = template.renderToString();
    HttpResponse html = Resps.html(request, string);
    return html;
  }
}

解释一下上面的代码

这段代码包含两个类,配置了 JFinal 的 Enjoy 模板引擎,并在控制器中使用了该引擎。

  1. EnjoyEngineConfig 类:

    • 使用 @AConfiguration 注解标记,表示这是一个配置类。
    • engine 方法创建并配置 Engine 实例。设置了基础模板路径、类路径源工厂、开发模式、极速模式和支持中文表达式的选项。
  2. TemplatesController 类:

    • 使用 @RequestPath 注解,无指定路径,表明它是一个处理 HTTP 请求的控制器。
    • notFound 方法通过 Enjoy 模板引擎处理 /404 请求,返回 /404.html 模板。
    • chat 方法处理 /chat 请求,返回 /chat.html 模板。

3.HandlerDispatcher.afterExecuteAction(HttpRequest, HttpResponse, Object) 方法中会 Template 类进行渲染并返回,可以在 action 使用 request.setAttribute("key", "value");设置参数到模版中