乐于分享
好东西不私藏

Spring AI PromptTemplate 实践指南(附 LangChain 对比)

Spring AI PromptTemplate 实践指南(附 LangChain 对比)

一、核心概念与理论基础

1.1 为什么需要 PromptTemplate?

在大模型应用中,提示词(Prompt)本质上是人机之间的"接口契约"。直接使用字符串拼接存在三个核心问题:

  1. 可维护性差
    :提示词与业务逻辑耦合,修改需重新编译
  2. 可测试性弱
    :难以对提示词渲染逻辑进行单元测试
  3. 协作成本高
    :产品/算法/开发三方对提示词的修改缺乏版本管理

PromptTemplate 的设计目标正是解决这些问题,其理论基础来自软件工程的"关注点分离"原则:将提示词的结构定义变量注入渲染执行三个环节解耦。

1.2 消息角色的设计原理

大模型通常支持多角色消息(System/User/Assistant),这种设计源于对话系统的状态机模型:

  • SystemMessage
    :定义全局约束和行为边界,相当于函数的"前置条件"
  • UserMessage
    :表达当前请求意图,相当于函数的"输入参数"
  • AssistantMessage
    :提供历史响应,用于维持对话状态,相当于"上下文栈"

这种分层结构能有效减少指令冲突(Instruction Interference),提升模型对复杂任务的理解能力。


二、基础使用示例(保留原始代码)

辅助方法:打印流式响应

/** * 辅助方法:打印流式响应(ChatResponse) */privatevoidprintStreamResponseFromChatResponse(Flux<ChatResponse> response) throws InterruptedException {    CountDownLatch latch = new CountDownLatch(1);    response        .doOnNext(chatResponse -> {            String content = chatResponse.getResult().getOutput().getText();            if (content != null) {                System.out.print(content);            }        })        .doOnComplete(() -> {            System.out.println("\n[完成]");            latch.countDown();        })        .doOnError(error -> {            System.err.println("\n[错误]: " + error.getMessage());            latch.countDown();        })        .subscribe();    latch.await(30, TimeUnit.SECONDS);}

示例 1:最简单的字符串 Prompt

@Testvoid demo1_SimpleStringPrompt() throws InterruptedException {    System.out.println("========== 示例 1:简单字符串 Prompt ==========");    // 直接传入字符串,Spring AI 内部会转换为 Prompt    String message = "你好,请介绍一下自己";    Flux<String> response = dashScopeChatModel.stream(message);    printStreamResponse(response);}

执行结果:

========== 示例1:简单字符串 Prompt ==========你好!😊 我是通义千问(Qwen),阿里巴巴集团旗下的超大规模语言模型。我能够理解并生成多种语言的文本,比如中文、英文、法语、西班牙语、葡萄牙语、俄语、阿拉伯语、日语、韩语、越南语、泰语、印尼语等,支持跨语言交流与创作。我可以帮你:🔹 解答各类问题(科学、文化、生活、技术等)  🔹 创作文字(写故事、公文、邮件、剧本、诗歌、歌词等)  🔹 编程辅助(解释代码、调试建议、多语言代码生成)  🔹 逻辑推理与数学计算  🔹 多轮对话与个性化表达(比如模仿某种风格、调整语气)  🔹 文件处理(支持上传 PDF、Word、Excel、PPT、TXT 等格式,可阅读并分析其中内容)我注重准确性、安全性和实用性,也会尽力以友好、清晰、有温度的方式与你交流。不过需要说明的是:我的知识截止于2024年,无法实时获取最新网络信息(如今日天气、股市行情等),也不具备个人经历或主观意识。很高兴认识你!如果你有任何问题、想法,或者想一起写点什么、学点什么——随时告诉我吧 🌟[完成]Process finished with exit code 0

LangChain 对比实现

from langchain_openai import ChatOpenAIllm = ChatOpenAI(model="qwen-turbo", streaming=True)# 方式 1:直接字符串for chunk in llm.stream("你好,请介绍一下自己"):    print(chunk.content, end="", flush=True)# 方式 2:使用 PromptTemplate(为后续变量替换做准备)from langchain_core.prompts import PromptTemplateprompt = PromptTemplate.from_template("你好,请介绍一下自己")for chunk in llm.stream(prompt.invoke({})):    print(chunk.content, end="", flush=True)

示例 2:使用 Prompt 对象

@Testvoid demo2_PromptObject() throws InterruptedException {    System.out.println("\n========== 示例 2:Prompt 对象 ==========");    // 创建 UserMessage    UserMessage userMessage = new UserMessage("什么是人工智能?");    // 创建 Prompt 对象    Prompt prompt = new Prompt(userMessage);    Flux<ChatResponse> response = dashScopeChatModel.stream(prompt);    printStreamResponseFromChatResponse(response);}

执行结果:

========== 示例2:Prompt 对象 ==========人工智能(Artificial Intelligence,简称 AI)是指由人类设计和构建的系统或机器所展现出的、通常与人类智能相关的认知能力。这些能力包括但不限于:🔹 **感知**:如通过计算机视觉识别图像中的物体,或通过语音识别理解人类语言;  🔹 **学习**:从数据中自动发现规律与模式(如机器学习、深度学习),无需显式编程;  🔹 **推理与决策**:基于已有知识或规则进行逻辑推断、权衡利弊并做出选择(例如下棋程序AlphaGo、医疗诊断辅助系统);  🔹 **语言理解与生成**:理解自然语言含义,并能生成连贯、符合语境的文本或对话(如大语言模型ChatGPT、文心一言);  🔹 **规划与问题求解**:在复杂环境中设定目标、分解任务、制定策略(如自动驾驶路径规划、物流调度系统);  🔹 **适应与自主性**:在动态环境中持续学习、调整行为(如机器人自主导航避障)。📌 **关键说明**- AI ≠ 人类意识或通用智能:当前绝大多数AI属于“狭义AI”(Narrow AI),专精于特定任务(如翻译、人脸识别)。尚不存在具备自我意识、常识推理和跨领域泛化能力的“通用人工智能”(AGI),这仍是理论探索与长期研究目标。- AI 的实现依赖多学科交叉:包括计算机科学、数学(统计学、优化理论)、神经科学、语言学、哲学等。- 技术基础不断演进:从早期基于规则的专家系统,到以数据驱动的机器学习,再到如今以大模型为代表的生成式AI(GenAI),其能力边界正快速拓展。💡 简单类比:  > 人工智能就像为机器装上“可编程的大脑”,让它不仅能执行指令,还能从经验中学习、理解模糊信息、并完成原本需要人类智慧的任务——但它没有感受、意图或主观体验。如果你对某类AI(如大模型、AI伦理、AI如何工作)感兴趣,我可以进一步为你深入解析 😊[完成]

LangChain 对比实现

from langchain_core.prompts import ChatPromptTemplatefrom langchain_core.messages import HumanMessage# 方式 1:使用 ChatPromptTemplateprompt = ChatPromptTemplate.from_messages([    ("user""什么是人工智能?")])for chunk in llm.stream(prompt.invoke({})):    print(chunk.content, end="", flush=True)# 方式 2:直接使用消息对象human_msg = HumanMessage(content="什么是人工智能?")for chunk in llm.stream([human_msg]):    print(chunk.content, end="", flush=True)

示例 3:带系统消息的 Prompt

@Testvoid demo3_PromptWithSystemMessage() throws InterruptedException {    System.out.println("\n========== 示例 3:带系统消息的 Prompt ==========");    // 系统消息:设定 AI 的角色    SystemMessage systemMessage = new SystemMessage(        "你是一个专业的编程助手,擅长解答技术问题。" +        "请用简洁明了的方式回答问题,并提供代码示例。"    );    // 用户消息    UserMessage userMessage = new UserMessage("如何用 Java 实现单例模式?");    // 创建包含多个消息的 Prompt    Prompt prompt = new Prompt(List.of(systemMessage, userMessage));    Flux<ChatResponse> response = dashScopeChatModel.stream(prompt);    printStreamResponseFromChatResponse(response);}

执行结果:

========== 示例3:带系统消息的 Prompt ==========在 Java 中,单例模式(Singleton Pattern)确保一个类**只有一个实例**,并提供一个全局访问点。以下是几种常用、线程安全的实现方式(按推荐程度排序):---### ✅ 1. **枚举单例(最推荐 ✅)—— 简洁、线程安全、防反射/反序列化攻击**```javapublic enum Singleton {    INSTANCE;    publicvoiddoSomething() {        System.out.println("Singleton instance is working...");    }}// 使用Singleton.INSTANCE.doSomething();```> ✅ 优点:天然线程安全、防止反射破坏、防止反序列化创建新实例;简洁优雅。  > ⚠️ 注意:不能延时加载(JVM 加载类时即初始化)。---### ✅ 2. **静态内部类(推荐 ✅)—— 懒汉式 + 线程安全 + 高效**```javapublic class Singleton {    privateSingleton() {} // 私有构造器    private static class SingletonHolder {        private static final Singleton INSTANCE = new Singleton();    }    publicstatic Singleton getInstance() {        return SingletonHolder.INSTANCE;    }    publicvoiddoSomething() {        System.out.println("Lazy-loaded singleton");    }}```> ✅ 优点:懒加载(首次调用 `getInstance()` 才初始化)、线程安全(JVM 类加载机制保证)、无同步开销。---### ✅ 3. **双重检查锁定(DCL)+ volatile(经典但需谨慎)**```javapublic class Singleton {    private static volatile Singleton instance;    privateSingleton() {}    publicstatic Singleton getInstance() {        if (instance == null) {                    // 第一次检查(避免同步开销)            synchronized (Singleton.class) {                if (instance == null) {            // 第二次检查(确保只创建一次)                    instance = new Singleton();                }            }        }        return instance;    }}```> ⚠️ 注意:`volatile` 关键字**必不可少**(禁止指令重排序,保证可见性和有序性)。  > ✅ 优点:懒加载、线程安全、高性能(仅首次创建加锁)。[完成]

LangChain 对比实现

from langchain_core.prompts import ChatPromptTemplateprompt = ChatPromptTemplate.from_messages([    ("system""你是一个专业的编程助手,擅长解答技术问题。请用简洁明了的方式回答问题,并提供代码示例。"),    ("user""如何用 Java 实现单例模式?")])for chunk in llm.stream(prompt.invoke({})):    print(chunk.content, end="", flush=True)

示例 4:带聊天选项的 Prompt

@Testvoid demo4_PromptWithChatOptions() throws InterruptedException {    System.out.println("\n========== 示例 4:带聊天选项的 Prompt ==========");    UserMessage userMessage = new UserMessage("写一首关于春天的诗");    // 创建聊天选项    ChatOptions options = ChatOptions.builder()        .temperature(0.8)  // 温度:控制随机性,0-1 之间,越高越有创造性        .maxTokens(500)    // 最大 token 数:限制回答长度        .build();    // 创建带选项的 Prompt    Prompt prompt = new Prompt(userMessage, options);    Flux<ChatResponse> response = dashScopeChatModel.stream(prompt);    printStreamResponseFromChatResponse(response);}

执行结果:

========== 示例4:带聊天选项的 Prompt ==========《春笺》风在枝头试笔,写第一行新绿,  柳线垂落,蘸着溪水临摹云影。  泥土松动,蚯蚓在暗处誊抄暖意,  草尖微颤,抖落一粒粒细小的光。桃夭未落,已把粉红寄给山岗;  梨雪初凝,又将素白托付给斜阳。  蜂翅驮着蜜的邮戳,在花间往返,  而布谷的啼鸣,是大地盖下的印章。我伫立田埂,看犁沟蜿蜒如句读——  春不押韵,却自有节律;  不设伏笔,却处处伏着青翠的伏笔。  当夕照把影子拉长成一行未写完的诗,  风轻轻翻页:万物正破题。[完成]

LangChain 对比实现

from langchain_core.prompts import PromptTemplateprompt = PromptTemplate.from_template("写一首关于春天的诗")# 通过 bind 方法传递采样参数llm_with_options = llm.bind(temperature=0.8, max_tokens=500)for chunk in llm_with_options.stream(prompt.invoke({})):    print(chunk.content, end="", flush=True)

示例 5:完整的 Prompt(系统消息 + 用户消息 + 选项)

@Testvoid demo5_CompletePrompt() throws InterruptedException {    System.out.println("\n========== 示例 5:完整的 Prompt ==========");    // 系统消息:设定角色    SystemMessage systemMessage = new SystemMessage(        "你是一个经验丰富的技术面试官,擅长提出有深度的技术问题。"    );    // 用户消息    UserMessage userMessage = new UserMessage(        "请给我出 3 个 Java 中级开发者的面试问题"    );    // 聊天选项    ChatOptions options = ChatOptions.builder()        .temperature(0.7)        .maxTokens(100)        .build();    // 创建完整的 Prompt    Prompt prompt = new Prompt(        List.of(systemMessage, userMessage),        options    );    Flux<ChatResponse> response = dashScopeChatModel.stream(prompt);    printStreamResponseFromChatResponse(response);}

执行结果:

========== 示例5:完整的 Prompt ==========当然可以!以下是3个针对**Java中级开发者**(通常指有2–4年经验,熟悉核心API、JVM基础、常用框架和设计原则)的面试问题,兼顾深度、实践性和考察维度(概念理解、代码能力、问题分析与权衡意识):---**1. 【JVM & 内存模型】**  > 请解释 `String str = new String("hello")` 这行代码在JVM中会[完成]Process finished with exit code 0

LangChain 对比实现

prompt = ChatPromptTemplate.from_messages([    ("system""你是一个经验丰富的技术面试官,擅长提出有深度的技术问题。"),    ("user""请给我出 3 个 Java 中级开发者的面试问题")])llm_with_options = llm.bind(temperature=0.7, max_tokens=100)for chunk in llm_with_options.stream(prompt.invoke({})):    print(chunk.content, end="", flush=True)

示例 6:多轮对话

@Testvoid demo6_MultiTurnConversation() throws InterruptedException {    System.out.println("\n========== 示例 6:多轮对话 Prompt ==========");    // 构建对话历史    SystemMessage systemMessage = new SystemMessage("你是一个友好的助手");    UserMessage firstQuestion = new UserMessage("Java 和 Python 有什么区别?");    UserMessage followUp = new UserMessage("那在性能方面呢?");    ChatOptions chatOptions = ChatOptions.builder().maxTokens(100).build();    // 将所有消息放入 Prompt    Prompt prompt = new Prompt(List.of(        systemMessage,        firstQuestion,        followUp    ),                               chatOptions);    Flux<ChatResponse> response = dashScopeChatModel.stream(prompt);    printStreamResponseFromChatResponse(response);}

执行结果:

========== 示例6:多轮对话 Prompt ==========在性能方面,Java 通常显著优于 Python,主要原因在于它们的执行机制和设计哲学不同。以下是关键对比点:✅ **执行方式**- **Java**:编译为字节码 → 由 JVMJava 虚拟机)即时编译(JIT)为高度优化的本地机器码运行。JIT 可在运行时分析热点代码并动态优化(如方法内联、逃逸分析、锁消除等),长期运行[完成]Disconnected from the target VMaddress'127.0.0.1:54900'transport'socket'Process finished with exit code 0

LangChain 对比实现

from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder# 方式 1:直接列出所有消息prompt = ChatPromptTemplate.from_messages([    ("system""你是一个友好的助手"),    ("user""Java 和 Python 有什么区别?"),    ("user""那在性能方面呢?")])for chunk in llm.bind(max_tokens=100).stream(prompt.invoke({})):    print(chunk.content, end="", flush=True)# 方式 2:使用 MessagesPlaceholder 动态管理历史(推荐)dynamic_prompt = ChatPromptTemplate.from_messages([    ("system""你是一个友好的助手"),    MessagesPlaceholder("history"),    ("user""{question}")])# 调用时传入历史消息列表response = dynamic_prompt.invoke({    "history": [        ("user""Java 和 Python 有什么区别?"),        ("assistant""Java 是编译型语言,Python 是解释型语言...")    ],    "question""那在性能方面呢?"})for chunk in llm.stream(response.to_messages()):    print(chunk.content, end="", flush=True)

示例 7:温度参数对比

@Testvoid demo7_TemperatureComparison() throws InterruptedException {    System.out.println("\n========== 示例 7:温度参数对比 ==========");    String question = "给创业公司起一个名字";    // 低温度:更保守、确定性高    System.out.println("\n--- 低温度 (0.2) - 更保守 ---");    ChatOptions lowTemp = ChatOptions.builder().maxTokens(150).temperature(0.2).build();    Prompt prompt1 = new Prompt(new UserMessage(question), lowTemp);    printStreamResponseFromChatResponse(dashScopeChatModel.stream(prompt1));    Thread.sleep(1000);    // 高温度:更有创造性    System.out.println("\n--- 高温度 (0.9) - 更有创造性 ---");    ChatOptions highTemp = ChatOptions.builder().maxTokens(150).temperature(0.9).build();    Prompt prompt2 = new Prompt(new UserMessage(question), highTemp);    printStreamResponseFromChatResponse(dashScopeChatModel.stream(prompt2));}

LangChain 对比实现

question = "给创业公司起一个名字"prompt = PromptTemplate.from_template(question)print("\n--- 低温度 (0.2) - 更保守 ---")for chunk in llm.bind(temperature=0.2, max_tokens=150).stream(prompt.invoke({})):    print(chunk.content, end="", flush=True)print("\n\n--- 高温度 (0.9) - 更有创造性 ---")for chunk in llm.bind(temperature=0.9, max_tokens=150).stream(prompt.invoke({})):    print(chunk.content, end="", flush=True)

三、模板引擎原理与变量渲染

3.1 StTemplateRenderer 工作机制

Spring AI 默认的 PromptTemplate 使用 StTemplateRenderer,其底层基于 StringTemplate 4 引擎。渲染流程如下:

  1. 词法分析
    :扫描模板字符串,识别 {variable} 格式的占位符
  2. 语法树构建
    :将模板解析为抽象语法树(AST),支持嵌套表达式
  3. 上下文绑定
    :将传入的 Map<String, Object> 变量与 AST 节点绑定
  4. 求值渲染
    :遍历 AST,执行变量替换、条件判断、格式转换等操作
  5. 输出生成
    :拼接最终字符串结果

这种设计相比简单的字符串替换有两个关键优势:

  • 支持复杂逻辑
    :可在模板中使用条件表达式、列表迭代等(虽然多数场景不需要)
  • 安全隔离
    :模板逻辑与数据完全分离,配合自动转义可防止注入攻击

3.2 变量冲突问题与解决方案

当模板中包含代码块时,代码中的 {} 可能与模板变量语法冲突:

// 模板内容请分析以下{language}代码:```{code}```// 用户传入的 code 变量public classTest{ }  // 含 {}

Spring AI 解决方案:配置自定义分隔符

PromptTemplate promptTemplate = PromptTemplate.builder()    .renderer(StTemplateRenderer.builder()        .startDelimiterToken('<')   // 使用<var>替代{var}        .endDelimiterToken('>')        .build())    .template("请分析<language>代码:\n```<code>```")    .build();String result = promptTemplate.render(Map.of(    "language""java",    "code""public class Test { }"  // 安全,不会冲突));

LangChain 处理方式:手动转义或预处理

# LangChain 默认使用{var}语法,需手动转义代码中的{}template = "请分析{language}代码:\n```{code}```"# 方案:将代码中的{}替换为{{}}(f-string 转义规则)code_escaped = code.replace("{""{{").replace("}""}}")prompt = PromptTemplate.from_template(template)result = prompt.format(language="java", code=code_escaped)

实践建议:涉及代码分析的模板,优先使用<var>格式分隔符,或在模板设计阶段就将代码变量放在独立代码块中,减少冲突概率。


四、文件化模板管理实践

4.1 模板文件组织规范

将提示词模板从代码中抽离,推荐使用以下目录结构:

src/main/resources/└── prompts/    ├── code-review.st              # 代码审查模板    ├── expert-explanation.st       # 专家解释模板    ├── open-source-recommendation.st  # 开源项目推荐    └── README.md                   # 模板说明与版本记录

模板文件内容示例(open-source-recommendation.st):

请给我推荐几个关于{topic}的开源项目

4.2 从文件加载并渲染变量

@Testvoiddemo1_LoadSimplePromptFromFile() throws IOException, InterruptedException {    System.out.println("========== 示例 1:从文件加载简单提示词 ==========");    ChatClient chatClient = chatClientBuilder.build();    // 从 classpath 读取提示词文件    ClassPathResource resource = new ClassPathResource("prompts/open-source-recommendation.st");    String templateContent = resource.getContentAsString(StandardCharsets.UTF_8);    System.out.println("\n读取的模板内容:" + templateContent.trim());    // 创建 PromptTemplate    PromptTemplate promptTemplate = new PromptTemplate(templateContent);    System.out.println("\n--- 测试 1:Java 相关 ---");    String renderedPrompt1 = promptTemplate.render(Map.of("topic""Java"));    System.out.println("渲染后的提示词:" + renderedPrompt1);    Flux<String> response1 = chatClient.prompt()    .user(renderedPrompt1)    .stream()    .content();    printStreamResponse(response1);    Thread.sleep(500);    System.out.println("\n\n--- 测试 2:微服务相关 ---");    String renderedPrompt2 = promptTemplate.render(Map.of("topic""微服务"));    System.out.println("渲染后的提示词:" + renderedPrompt2);    Flux<String> response2 = chatClient.prompt()    .user(renderedPrompt2)    .stream()    .content();    printStreamResponse(response2);    System.out.println("\n\n💡 说明:");    System.out.println("• 提示词保存在独立的 .st 文件中");    System.out.println("• 通过 ClassPathResource 读取文件内容");    System.out.println("• 修改提示词无需重新编译代码");}

LangChain 对比实现

from langchain_core.prompts import PromptTemplatefrom pathlib import Path# 读取模板文件template_path = Path("prompts/open-source-recommendation.txt")template_content = template_path.read_text(encoding="utf-8")# 创建 PromptTemplateprompt_template = PromptTemplate.from_template(template_content)# 渲染变量(两种写法等价)rendered_1 = prompt_template.invoke({"topic""Java"})  # 返回 PromptValuerendered_2 = prompt_template.format(topic="Java")        # 返回字符串# 调用模型for chunk in llm.stream(rendered_1):    print(chunk.content, end="", flush=True)

4.3 多变量复杂模板示例

模板文件 expert-explanation.st

你是一个{role}专家。请用{language}语言,为{audience}受众解释{topic}的概念。要求:{requirements}@Testvoid demo2_LoadComplexPromptFromFile() throws IOExceptionInterruptedException {    System.out.println("\n========== 示例 2:从文件加载复杂提示词 ==========");    ChatClient chatClient = chatClientBuilder.build();    // 从 classpath 读取提示词文件    ClassPathResource resource = new ClassPathResource("prompts/expert-explanation.st");    String templateContent = resource.getContentAsString(StandardCharsets.UTF_8);    System.out.println("\n读取的模板内容:\n" + templateContent);    // 创建 PromptTemplate    PromptTemplate promptTemplate = new PromptTemplate(templateContent);    System.out.println("\n--- 场景 1:技术专家向初学者解释 ---");    Map<StringObject> variables1 = Map.of(        "role""技术",        "language""简单易懂的中文",        "audience""编程初学者",        "topic""面向对象编程",        "requirements""使用生活中的比喻,避免专业术语"    );    String renderedPrompt1 = promptTemplate.render(variables1);    System.out.println("渲染后的提示词:\n" + renderedPrompt1);    Flux<String> response1 = chatClient.prompt()            .user(renderedPrompt1)            .stream()            .content();    printStreamResponse(response1);    Thread.sleep(500);    System.out.println("\n\n--- 场景 2:教育专家向学生讲解 ---");    Map<StringObject> variables2 = Map.of(        "role""教育",        "language""生动的中文",        "audience""大学生",        "topic""机器学习",        "requirements""结合实例,深入浅出"    );    String renderedPrompt2 = promptTemplate.render(variables2);    System.out.println("渲染后的提示词:\n" + renderedPrompt2);    Flux<String> response2 = chatClient.prompt()            .user(renderedPrompt2)            .stream()            .content();    printStreamResponse(response2);    System.out.println("\n\n💡 说明:");    System.out.println("• 复杂的多变量模板也可以保存在文件中");    System.out.println("• 提示词格式更清晰,易于阅读和修改");    System.out.println("• 适合团队协作文档化");}

4.4 实际应用场景:代码审查

模板文件 code-review.st

请分析以下代码,找出其中的问题并提供改进建议:```{language}{code}

请按照以下步骤进行分析:

  1. 识别代码中的问题(bug、性能问题、安全漏洞等)
  2. 解释问题的原因和影响
  3. 提供改进后的代码示例
  4. 说明改进的理由
@Testvoiddemo3_CodeReviewPrompt() throws IOException, InterruptedException {    System.out.println("\n========== 示例 3:代码审查提示词 ==========");    ChatClient chatClient = chatClientBuilder.build();    // 从 classpath 读取提示词文件    ClassPathResource resource = new ClassPathResource("prompts/code-review.st");    String templateContent = resource.getContentAsString(StandardCharsets.UTF_8);    System.out.println("\n读取的模板内容:\n" + templateContent);    // 创建 PromptTemplate    PromptTemplate promptTemplate = new PromptTemplate(templateContent);    System.out.println("\n--- 代码审查示例 ---");    Map<String, Object> variables = Map.of(        "language""java",        "code""""            public class UserService {                public User getUserById(String id) {                    String sql = "SELECT * FROM users WHERE id = '" + id + "'";                    return jdbcTemplate.queryForObject(sql, User.class);                }            }            """    );    String renderedPrompt = promptTemplate.render(variables);    System.out.println("渲染后的提示词:\n" + renderedPrompt);    Flux<String> response = chatClient.prompt()            .user(renderedPrompt)            .stream()            .content();    printStreamResponse(response);    System.out.println("\n\n💡 说明:");    System.out.println("• 可以将常用的提示词模板统一管理");    System.out.println("• 便于维护和更新");    System.out.println("• 可以在不同项目中复用");}

五、采样参数的理论说明

5.1 Temperature 的统计学原理

Temperature 参数控制模型输出时的随机性,其本质是对模型输出的 logits 进行缩放后再应用 Softmax:

原始 logits: [2.0, 1.0, 0.1]  # token A/B/C 的偏好分数应用 Temperature:scaled = logits / T- T=0.2: [10.0, 5.0, 0.5]  → 概率分布更尖锐,输出更确定- T=1.0: [2.0, 1.0, 0.1]   → 原始分布- T=2.0: [1.0, 0.5, 0.05]  → 概率分布更平缓,输出更多样Softmax 归一化后采样下一个 token

实践建议

任务类型

推荐 Temperature

原因

事实问答、代码生成

0.0~0.3

降低随机性,提升准确性

创意写作、头脑风暴

0.7~1.0

增加多样性,激发新颖组合

对话交互、角色扮演

0.5~0.8

平衡连贯性与趣味性

多轮推理任务

0.1~0.4

保持逻辑一致性

5.2 Top-p(Nucleus Sampling)的补充作用

Top-p 参数通过动态截断概率分布来控制采样范围:

原始概率: [A:0.5, B:0.3, C:0.15, D:0.03, E:0.02]Top-p=0.9 时:1. 累加概率:A(0.5)+B(0.3)+C(0.15)=0.95 ≥ 0.92. 保留{A,B,C},重新归一化后采样3. 自动排除低概率"噪音"token

组合策略参考

  • 保守模式:temperature=0.2 + top_p=0.9 → 高确定性 + 排除极端异常
  • 创意模式:temperature=0.9 + top_p=0.95 → 高多样性 + 保留合理长尾
  • 通用模式:temperature=0.7 + top_p=0.9 → 平衡质量与多样性

六、工程实践建议

6.1 模板版本管理

为重要模板建立版本控制机制(类似你们公司项目里的SQL管理):

prompts/├── code-review-v1.0.st      # 初始版本├── code-review-v1.1.st      # 增加安全检测维度├── code-review-v2.0.st      # 适配新模型,优化 token 使用└── CHANGELOG.md             # 记录变更内容与适用场景

版本命名建议采用语义化版本:

  • MAJOR:输出格式或分析步骤变更(需下游适配)
  • MINOR:新增分析维度或优化文案(向后兼容)
  • PATCH:错别字修复或格式调整

6.2 安全注意事项

  1. 输入净化
    :对用户传入的变量值进行长度限制和特殊字符过滤
  2. 模板隔离
    :使用PromptTemplate的自动转义功能,避免变量内容被解析为指令
  3. 输出验证
    :对模型响应进行关键词检查,防止执行敏感操作
// 启用自动转义(配置自定义分隔符时)StTemplateRenderer renderer = StTemplateRenderer.builder()    .startDelimiterToken('<')    .endDelimiterToken('>')    .autoEscape(true)  // 关键配置    .build();

6.3 性能优化技巧

  1. 预编译模板
    PromptTemplate 对象可复用,避免重复解析
  2. 异步渲染
    :变量渲染与模型调用可并行执行
  3. 缓存策略
    :对相同变量组合的渲染结果进行缓存(注意变量敏感性)

七、对比总结

特性

Spring AI

LangChain

选型建议

模板引擎

StringTemplate 4(AST 解析)

f-string 风格(正则替换)

复杂逻辑选 Spring AI,简单场景选 LangChain

变量语法

{var} / 可配置<var>

{var}

Spring AI 更易处理代码块冲突

消息角色

强类型对象(SystemMessage 等)

元组列表[("role", "content")]

大型项目推荐强类型,快速原型可用元组

流式处理

Reactor Flux<T>

Python Generator

根据技术栈选择,功能等价

参数控制

ChatOptions 构建器

llm.bind(**kwargs)

设计模式不同,效果一致

历史管理

手动拼接消息列表

Memory 组件自动管理

LangChain 封装更友好

安全机制

模板引擎支持自动转义

需手动实现转义逻辑

Spring AI 默认更安全

部署集成

Spring Boot 自动配置

需自行封装配置管理

企业级项目推荐 Spring AI


参考资料

  1. Spring AI 官方文档:https://docs.springframework.org.cn/spring-ai/reference/api/prompt.html
  2. LangChain Prompt Templates:https://python.langchain.com/docs/concepts/prompt_templates/
  3. StringTemplate 引擎文档:https://www.stringtemplate.org/
基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-04-13 15:49:22 HTTP/1.1 GET : https://www.yeyulingfeng.com/a/519992.html
  2. 运行时间 : 0.168761s [ 吞吐率:5.93req/s ] 内存消耗:4,810.92kb 文件加载:145
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=38f7e4857b10496a3229e03e3fed904d
  1. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/public/index.php ( 0.79 KB )
  2. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/autoload.php ( 0.17 KB )
  3. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/composer/autoload_real.php ( 2.49 KB )
  4. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/composer/platform_check.php ( 0.90 KB )
  5. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/composer/ClassLoader.php ( 14.03 KB )
  6. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/composer/autoload_static.php ( 6.05 KB )
  7. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/helper.php ( 8.34 KB )
  8. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-validate/src/helper.php ( 2.19 KB )
  9. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/ralouphie/getallheaders/src/getallheaders.php ( 1.60 KB )
  10. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/helper.php ( 1.47 KB )
  11. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/stubs/load_stubs.php ( 0.16 KB )
  12. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Exception.php ( 1.69 KB )
  13. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-container/src/Facade.php ( 2.71 KB )
  14. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/deprecation-contracts/function.php ( 0.99 KB )
  15. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/polyfill-mbstring/bootstrap.php ( 8.26 KB )
  16. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/polyfill-mbstring/bootstrap80.php ( 9.78 KB )
  17. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/var-dumper/Resources/functions/dump.php ( 1.49 KB )
  18. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-dumper/src/helper.php ( 0.18 KB )
  19. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/var-dumper/VarDumper.php ( 4.30 KB )
  20. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/guzzlehttp/guzzle/src/functions_include.php ( 0.16 KB )
  21. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/guzzlehttp/guzzle/src/functions.php ( 5.54 KB )
  22. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/App.php ( 15.30 KB )
  23. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-container/src/Container.php ( 15.76 KB )
  24. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/psr/container/src/ContainerInterface.php ( 1.02 KB )
  25. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/provider.php ( 0.19 KB )
  26. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Http.php ( 6.04 KB )
  27. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/helper/Str.php ( 7.29 KB )
  28. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Env.php ( 4.68 KB )
  29. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/common.php ( 0.03 KB )
  30. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/helper.php ( 18.78 KB )
  31. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Config.php ( 5.54 KB )
  32. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/alipay.php ( 3.59 KB )
  33. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/facade/Env.php ( 1.67 KB )
  34. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/app.php ( 0.95 KB )
  35. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/cache.php ( 0.78 KB )
  36. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/console.php ( 0.23 KB )
  37. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/cookie.php ( 0.56 KB )
  38. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/database.php ( 2.48 KB )
  39. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/filesystem.php ( 0.61 KB )
  40. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/lang.php ( 0.91 KB )
  41. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/log.php ( 1.35 KB )
  42. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/middleware.php ( 0.19 KB )
  43. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/route.php ( 1.89 KB )
  44. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/session.php ( 0.57 KB )
  45. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/trace.php ( 0.34 KB )
  46. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/view.php ( 0.82 KB )
  47. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/event.php ( 0.25 KB )
  48. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Event.php ( 7.67 KB )
  49. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/service.php ( 0.13 KB )
  50. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/AppService.php ( 0.26 KB )
  51. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Service.php ( 1.64 KB )
  52. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Lang.php ( 7.35 KB )
  53. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/lang/zh-cn.php ( 13.70 KB )
  54. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/initializer/Error.php ( 3.31 KB )
  55. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/initializer/RegisterService.php ( 1.33 KB )
  56. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/services.php ( 0.14 KB )
  57. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/service/PaginatorService.php ( 1.52 KB )
  58. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/service/ValidateService.php ( 0.99 KB )
  59. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/service/ModelService.php ( 2.04 KB )
  60. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-trace/src/Service.php ( 0.77 KB )
  61. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Middleware.php ( 6.72 KB )
  62. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/initializer/BootService.php ( 0.77 KB )
  63. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/Paginator.php ( 11.86 KB )
  64. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-validate/src/Validate.php ( 63.20 KB )
  65. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/Model.php ( 23.55 KB )
  66. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/Attribute.php ( 21.05 KB )
  67. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/AutoWriteData.php ( 4.21 KB )
  68. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/Conversion.php ( 6.44 KB )
  69. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/DbConnect.php ( 5.16 KB )
  70. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/ModelEvent.php ( 2.33 KB )
  71. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/RelationShip.php ( 28.29 KB )
  72. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/contract/Arrayable.php ( 0.09 KB )
  73. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/contract/Jsonable.php ( 0.13 KB )
  74. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/contract/Modelable.php ( 0.09 KB )
  75. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Db.php ( 2.88 KB )
  76. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/DbManager.php ( 8.52 KB )
  77. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Log.php ( 6.28 KB )
  78. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Manager.php ( 3.92 KB )
  79. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/psr/log/src/LoggerTrait.php ( 2.69 KB )
  80. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/psr/log/src/LoggerInterface.php ( 2.71 KB )
  81. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Cache.php ( 4.92 KB )
  82. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/psr/simple-cache/src/CacheInterface.php ( 4.71 KB )
  83. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/helper/Arr.php ( 16.63 KB )
  84. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/cache/driver/File.php ( 7.84 KB )
  85. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/cache/Driver.php ( 9.03 KB )
  86. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/contract/CacheHandlerInterface.php ( 1.99 KB )
  87. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/Request.php ( 0.09 KB )
  88. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Request.php ( 55.78 KB )
  89. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/middleware.php ( 0.25 KB )
  90. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Pipeline.php ( 2.61 KB )
  91. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-trace/src/TraceDebug.php ( 3.40 KB )
  92. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/middleware/SessionInit.php ( 1.94 KB )
  93. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Session.php ( 1.80 KB )
  94. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/session/driver/File.php ( 6.27 KB )
  95. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/contract/SessionHandlerInterface.php ( 0.87 KB )
  96. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/session/Store.php ( 7.12 KB )
  97. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Route.php ( 23.73 KB )
  98. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/RuleName.php ( 5.75 KB )
  99. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/Domain.php ( 2.53 KB )
  100. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/RuleGroup.php ( 22.43 KB )
  101. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/Rule.php ( 26.95 KB )
  102. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/RuleItem.php ( 9.78 KB )
  103. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/route/app.php ( 3.94 KB )
  104. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/facade/Route.php ( 4.70 KB )
  105. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/dispatch/Controller.php ( 4.74 KB )
  106. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/Dispatch.php ( 10.44 KB )
  107. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/controller/Index.php ( 9.87 KB )
  108. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/BaseController.php ( 2.05 KB )
  109. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/facade/Db.php ( 0.93 KB )
  110. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/connector/Mysql.php ( 5.44 KB )
  111. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/PDOConnection.php ( 52.47 KB )
  112. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/Connection.php ( 8.39 KB )
  113. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/ConnectionInterface.php ( 4.57 KB )
  114. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/builder/Mysql.php ( 16.58 KB )
  115. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/Builder.php ( 24.06 KB )
  116. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/BaseBuilder.php ( 27.50 KB )
  117. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/Query.php ( 15.71 KB )
  118. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/BaseQuery.php ( 45.13 KB )
  119. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php ( 7.43 KB )
  120. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php ( 3.26 KB )
  121. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php ( 20.07 KB )
  122. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/ParamsBind.php ( 3.66 KB )
  123. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/ResultOperation.php ( 7.01 KB )
  124. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/WhereQuery.php ( 19.37 KB )
  125. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php ( 7.11 KB )
  126. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php ( 2.63 KB )
  127. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/Transaction.php ( 2.77 KB )
  128. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/log/driver/File.php ( 5.96 KB )
  129. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/contract/LogHandlerInterface.php ( 0.86 KB )
  130. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/log/Channel.php ( 3.89 KB )
  131. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/event/LogRecord.php ( 1.02 KB )
  132. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/Collection.php ( 16.47 KB )
  133. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/facade/View.php ( 1.70 KB )
  134. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/View.php ( 4.39 KB )
  135. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/controller/Es.php ( 3.30 KB )
  136. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Response.php ( 8.81 KB )
  137. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/response/View.php ( 3.29 KB )
  138. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Cookie.php ( 6.06 KB )
  139. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-view/src/Think.php ( 8.38 KB )
  140. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/contract/TemplateHandlerInterface.php ( 1.60 KB )
  141. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-template/src/Template.php ( 46.61 KB )
  142. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-template/src/template/driver/File.php ( 2.41 KB )
  143. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-template/src/template/contract/DriverInterface.php ( 0.86 KB )
  144. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/runtime/temp/c935550e3e8a3a4c27dd94e439343fdf.php ( 31.80 KB )
  145. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
  1. CONNECT:[ UseTime:0.000955s ] mysql:host=127.0.0.1;port=3306;dbname=wenku;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.000838s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.002176s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.000301s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.000507s ]
  6. SELECT * FROM `set` [ RunTime:0.000290s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.000641s ]
  8. SELECT * FROM `article` WHERE `id` = 519992 LIMIT 1 [ RunTime:0.000597s ]
  9. UPDATE `article` SET `lasttime` = 1776066562 WHERE `id` = 519992 [ RunTime:0.000853s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 64 LIMIT 1 [ RunTime:0.000231s ]
  11. SELECT * FROM `article` WHERE `id` < 519992 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.000405s ]
  12. SELECT * FROM `article` WHERE `id` > 519992 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.000526s ]
  13. SELECT * FROM `article` WHERE `id` < 519992 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.000945s ]
  14. SELECT * FROM `article` WHERE `id` < 519992 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.002268s ]
  15. SELECT * FROM `article` WHERE `id` < 519992 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.001184s ]
0.170562s