From 647a07ff08be4594c142380f8766668da4a43144 Mon Sep 17 00:00:00 2001
From: 0007 <0007@qq.com>
Date: Wed, 27 Aug 2025 19:58:32 +0800
Subject: [PATCH] Add File
---
.../prompt/template/TextPromptTemplate.java | 202 ++++++++++++++++++
1 file changed, 202 insertions(+)
create mode 100644 agents-flex-core/src/main/java/com/agentsflex/core/prompt/template/TextPromptTemplate.java
diff --git a/agents-flex-core/src/main/java/com/agentsflex/core/prompt/template/TextPromptTemplate.java b/agents-flex-core/src/main/java/com/agentsflex/core/prompt/template/TextPromptTemplate.java
new file mode 100644
index 0000000..890d055
--- /dev/null
+++ b/agents-flex-core/src/main/java/com/agentsflex/core/prompt/template/TextPromptTemplate.java
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2023-2025, Agents-Flex (fuhai999@gmail.com).
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.agentsflex.core.prompt.template;
+
+import com.agentsflex.core.prompt.TextPrompt;
+import com.agentsflex.core.util.MapUtil;
+import com.alibaba.fastjson.JSONPath;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class TextPromptTemplate implements PromptTemplate {
+
+ private static final Pattern PLACEHOLDER_PATTERN = Pattern.compile("\\{\\{\\s*(.+?)\\s*}}");
+ private static final Map CACHES = new ConcurrentHashMap<>();
+
+ private final String originalTemplate;
+ private final List tokens;
+
+ /**
+ * 构造函数:初始化时解析模板内容
+ *
+ * @param template 模板字符串
+ */
+ public TextPromptTemplate(String template) {
+ this.originalTemplate = template != null ? template : "";
+ this.tokens = parseTemplate(this.originalTemplate);
+ }
+
+ /**
+ * 创建 TextPromptTemplate 实例
+ */
+ public static TextPromptTemplate of(String template) {
+ String finalTemplate = template != null ? template : "";
+ return MapUtil.computeIfAbsent(CACHES, finalTemplate, k -> new TextPromptTemplate(finalTemplate));
+ }
+
+ /**
+ * 格式化模板
+ */
+ public TextPrompt format(Map rootMap) {
+ return new TextPrompt(formatToString(rootMap));
+ }
+
+ /**
+ * 格式化模板
+ */
+ public String formatToString(Map rootMap) {
+ if (tokens.isEmpty()) return "";
+
+ if (rootMap == null) {
+ rootMap = Collections.emptyMap();
+ }
+
+ StringBuilder sb = new StringBuilder(originalTemplate.length() + 256);
+
+ for (TemplateToken token : tokens) {
+ if (token.isStatic()) {
+ sb.append(token.content);
+ } else {
+ Object value = getValueByJsonPath(rootMap, token.expression);
+ String replacement = value != null ? value.toString() : token.defaultValue;
+ sb.append(replacement);
+ }
+ }
+
+ return sb.toString();
+ }
+
+ /**
+ * 解析模板为 Token 列表
+ */
+ private List parseTemplate(String template) {
+ List result = new ArrayList<>();
+
+ if (template == null || template.isEmpty()) return result;
+
+ Matcher matcher = PLACEHOLDER_PATTERN.matcher(template);
+ int lastEnd = 0;
+
+ while (matcher.find()) {
+ int start = matcher.start();
+ int end = matcher.end();
+
+ // 添加前面的静态文本
+ if (start > lastEnd) {
+ result.add(TemplateToken.staticText(template.substring(lastEnd, start)));
+ }
+
+ // 解析占位符
+ String content = matcher.group(1);
+ ParseResult parseResult = parseExpressionWithDefault(content);
+ result.add(TemplateToken.dynamic(parseResult.expression, parseResult.defaultValue));
+
+ lastEnd = end;
+ }
+
+ // 添加结尾的静态文本
+ if (lastEnd < template.length()) {
+ result.add(TemplateToken.staticText(template.substring(lastEnd)));
+ }
+
+ return result;
+ }
+
+ /**
+ * 解析带默认值的表达式,如 "user.name ?? '匿名'"
+ */
+ private ParseResult parseExpressionWithDefault(String content) {
+ String[] parts = content.split("\\s*\\?\\?\\s*", 2);
+ if (parts.length == 2) {
+ String expr = parts[0].trim();
+ String defaultValue = unquote(parts[1].trim());
+ return new ParseResult(expr, defaultValue);
+ } else {
+ return new ParseResult(content.trim(), null);
+ }
+ }
+
+ /**
+ * 去掉字符串两边的引号(单引号或双引号)
+ */
+ private String unquote(String str) {
+ if ((str.startsWith("'") && str.endsWith("'")) ||
+ (str.startsWith("\"") && str.endsWith("\""))) {
+ return str.substring(1, str.length() - 1);
+ }
+ return str;
+ }
+
+ /**
+ * 使用 FastJSON JSONPath 获取嵌套值
+ */
+ private Object getValueByJsonPath(Map root, String path) {
+ try {
+ return JSONPath.eval(root, "$." + path);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ /**
+ * Token 类型定义
+ */
+ private static class TemplateToken {
+ boolean isStatic;
+ String content;
+ String expression;
+ String defaultValue;
+
+ private TemplateToken(boolean isStatic, String content, String expression, String defaultValue) {
+ this.isStatic = isStatic;
+ this.content = content;
+ this.expression = expression;
+ this.defaultValue = defaultValue == null ? "" : defaultValue;
+ }
+
+ static TemplateToken staticText(String text) {
+ return new TemplateToken(true, text, null, null);
+ }
+
+ static TemplateToken dynamic(String expr, String defaultValue) {
+ return new TemplateToken(false, null, expr, defaultValue);
+ }
+
+ boolean isStatic() {
+ return isStatic;
+ }
+ }
+
+ /**
+ * 内部类:用于保存解析后的表达式和默认值
+ */
+ private static class ParseResult {
+ String expression;
+ String defaultValue;
+
+ ParseResult(String expression, String defaultValue) {
+ this.expression = expression;
+ this.defaultValue = defaultValue;
+ }
+ }
+
+}