侧边栏壁纸
博主头像
AI中文站

开拓MCP洪荒时代

  • 累计撰写 28 篇文章
  • 累计创建 3 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

SpringAI-Prompts

提示(Prompts) 是引导 AI 模型生成特定输出的输入。这些提示的设计和措辞显著影响模型的响应。

在 Spring AI 中与 AI 模型交互的最基础层级,处理提示的方式有些类似于在 Spring MVC 中管理"视图"(View)。这涉及创建包含占位符的扩展文本,用于动态内容。这些占位符随后会根据用户请求或应用程序中的其他代码被替换。另一个类比是包含表达式占位符的 SQL 语句。

随着 Spring AI 的发展,它将引入更高级别的抽象来与 AI 模型交互。本节描述的基础类在角色和功能上可类比于 JDBC:

  • ChatModel 类类似于 JDK 中的核心 JDBC 库

  • ChatClient 类类似于构建在 ChatModel 之上的 JdbcClient,通过 Advisor 提供更高级的结构,用于考虑与模型的过往交互、用额外上下文文档增强提示,并引入代理行为(agentic behavior)

提示结构在 AI 领域已随时间演变:

  • 最初:提示是简单字符串

  • 随后:引入特定输入的占位符(如 "USER:")

  • 当前:OpenAI 通过将多个消息字符串分类为不同角色(roles)进一步结构化提示


API 概览


Prompt 类
通常使用 ChatModelcall() 方法,它接受 Prompt 实例并返回 ChatResponse

Prompt 类充当有序 Message 对象序列和请求 ChatOptions 的容器。每个 Message 在提示中体现一个独特角色,其内容和意图各不相同。这些角色可包含多种元素:用户查询、AI 生成的响应、相关背景信息等。这种安排支持与 AI 模型的复杂交互,因为提示由多个消息构成,每个消息在对话中扮演特定角色。

以下是 Prompt 类的简化版本(为简洁省略构造函数和工具方法):

public class Prompt implements ModelRequest<List<Message>> {
    private final List<Message> messages; // 消息列表
    private ChatOptions chatOptions; // 聊天选项
}

Message 接口
Message 接口封装了提示的文本内容、元数据属性集合和称为 MessageType 的分类:

public interface Content {
    String getContent(); // 获取内容
    Map<String, Object> getMetadata(); // 获取元数据
}

public interface Message extends Content {
    MessageType getMessageType(); // 获取消息类型
}

多模态消息类型还实现 MediaContent 接口,提供媒体内容对象列表:

public interface MediaContent extends Content {
    Collection<Media> getMedia(); // 获取媒体内容
}

Message 接口的各种实现对应 AI 模型可处理的不同消息类别。模型根据对话角色区分消息类别

这些角色通过 MessageType 有效映射。

角色(Roles)
每条消息被分配特定角色,用于为 AI 模型分类消息、阐明上下文和目的。这种结构化方法增强了与 AI 沟通的细微差别和有效性:

  • 系统角色(System Role):指导 AI 的行为和响应风格,设定解释和回复输入的规则。类似于对话前向 AI 提供指令。

  • 用户角色(User Role):代表用户输入(问题、命令或陈述)。这是 AI 响应的基础。

  • 助手角色(Assistant Role):AI 对用户输入的响应。不仅是答案,对维护对话流至关重要。通过跟踪 AI 之前的响应(其 "助手角色" 消息),系统确保连贯且上下文相关的交互。助手消息可能包含函数工具调用(Function Tool Call)请求信息。

  • 工具/函数角色(Tool/Function Role):专注于响应工具调用助手消息返回额外信息。

角色在 Spring AI 中表示为枚举:

public enum MessageType {
    USER("user"),      // 用户
    ASSISTANT("assistant"), // 助手
    SYSTEM("system"),    // 系统
    TOOL("tool");       // 工具
    // ...
}

PromptTemplate 类
Spring AI 中提示模板化的关键组件是 PromptTemplate 类,旨在简化结构化提示的创建:

public class PromptTemplate implements PromptTemplateActions, PromptTemplateMessageActions {
    // 其他方法将在后面讨论
}

此类使用 TemplateRenderer API 渲染模板。默认情况下,Spring AI 使用基于 Terence Parr 开发的开源 StringTemplate 引擎的 StTemplateRenderer 实现。模板变量由 {} 语法标识,但也可配置其他分隔符。

public interface TemplateRenderer extends BiFunction<String, Map<String, Object>, String> {
    @Override
    String apply(String template, Map<String, Object> variables); // 应用模板和变量
}

Spring AI 使用 TemplateRenderer 接口处理变量代入模板字符串的实际替换。默认实现使用 [StringTemplate]。如需自定义逻辑,可实现自己的 TemplateRenderer。对于不需要模板渲染的场景(如模板字符串已完整),可使用提供的 NoOpTemplateRenderer

使用自定义分隔符的示例

PromptTemplate promptTemplate = PromptTemplate.builder()
    .renderer(StTemplateRenderer.builder()
        .startDelimiterToken('<')  // 起始分隔符
        .endDelimiterToken('>')    // 结束分隔符
        .build())
    .template("""
            Tell me the names of 5 movies whose soundtrack was composed by <composer>.
            """)
    .build();

String prompt = promptTemplate.render(Map.of("composer", "John Williams")); // 渲染结果

实现接口
此类实现的接口支持提示创建的不同方面:

PromptTemplateStringActions

  • 专注于创建和渲染提示字符串(最基本的提示生成形式)

public interface PromptTemplateStringActions {
    String render(); // 无外部输入的渲染
    String render(Map<String, Object> model); // 带动态内容的渲染
}

PromptTemplateMessageActions

  • 专为通过生成和操作 Message 对象创建提示

public interface PromptTemplateMessageActions {
    Message createMessage(); // 创建无数据的消息
    Message createMessage(List<Media> mediaList); // 创建带媒体内容的消息
    Message createMessage(Map<String, Object> model); // 创建带动态内容的消息
}

PromptTemplateActions

  • 设计用于返回可传递给 ChatModel 生成响应的 Prompt 对象

public interface PromptTemplateActions extends PromptTemplateStringActions {
    Prompt create(); // 创建无输入的提示
    Prompt create(ChatOptions modelOptions); // 创建带聊天选项的提示
    Prompt create(Map<String, Object> model); // 创建带动态内容的提示
    Prompt create(Map<String, Object> model, ChatOptions modelOptions); // 创建带内容和选项的提示
}

使用示例


基础示例(来自 AI Workshop)

PromptTemplate promptTemplate = new PromptTemplate("Tell me a {adjective} joke about {topic}");
Prompt prompt = promptTemplate.create(Map.of("adjective", adjective, "topic", topic));
return chatModel.call(prompt).getResult(); // 调用模型获取结果

角色使用示例(来自 AI Workshop)

// 用户消息
String userText = """
    Tell me about three famous pirates from the Golden Age of Piracy and why they did.
    Write at least a sentence for each pirate.
    """;
Message userMessage = new UserMessage(userText); // 用户角色消息

// 系统消息模板
String systemText = """
  You are a helpful AI assistant that helps people find information.
  Your name is {name}
  You should reply to the user's request with your name and also in the style of a {voice}.
  """;
SystemPromptTemplate systemPromptTemplate = new SystemPromptTemplate(systemText);
// 创建系统角色消息(带动态参数)
Message systemMessage = systemPromptTemplate.createMessage(Map.of("name", name, "voice", voice)); 

// 组合提示
Prompt prompt = new Prompt(List.of(userMessage, systemMessage)); 

// 获取生成结果
List<Generation> response = chatModel.call(prompt).getResults(); 

使用自定义模板渲染器
可通过实现 TemplateRenderer 接口并将其传递给 PromptTemplate 构造函数来使用自定义渲染器。也可继续使用默认的 StTemplateRenderer 但自定义配置:

PromptTemplate promptTemplate = PromptTemplate.builder()
    .renderer(StTemplateRenderer.builder()
        .startDelimiterToken('<')
        .endDelimiterToken('>')
        .build())
    .template("Tell me the names of 5 movies whose soundtrack was composed by <composer>.")
    .build();
String prompt = promptTemplate.render(Map.of("composer", "John Williams"));

使用资源代替原始字符串
Spring AI 支持 org.springframework.core.io.Resource 抽象,可将提示数据放入文件中直接使用:

@Value("classpath:/prompts/system-message.st") // 注入资源
private Resource systemResource;

// 直接使用资源创建系统提示模板
SystemPromptTemplate systemPromptTemplate = new SystemPromptTemplate(systemResource);

提示工程(Prompt Engineering)


在生成式 AI 中,创建提示对开发者至关重要。提示的质量和结构显著影响 AI 输出的效果。投入时间设计周到的提示可极大改善 AI 结果。

创建有效提示的关键要素
开发提示时需整合多个关键组件以确保清晰有效:

  1. 指令(Instructions)

    • 向 AI 提供清晰直接的指令(类似于与人沟通)

    • 明确性对帮助 AI "理解" 期望至关重要

  2. 外部上下文(External Context)

    • 必要时包含相关背景信息或对 AI 响应的具体指导

    • 为提示提供框架,帮助 AI 掌握整体场景

  3. 用户输入(User Input)

    • 用户直接请求或问题(构成提示的核心)

  4. 输出指示符(Output Indicator)

    • 指定 AI 响应的期望格式(如 JSON)

    • 注意:AI 可能不严格遵守格式(例如在 JSON 前添加 "here is your JSON")

    • 提供问答格式的示例对 AI "理解" 查询结构和意图非常有益

提示工程技术分类
基础技术

  • 文本摘要(Text Summarization)

    • 将冗长文本压缩为简明摘要,捕捉要点和主要思想,省略次要细节

  • 问答(Question Answering)

    • 根据用户问题从提供文本中提取具体答案,精确定位相关信息

  • 文本分类(Text Classification)

    • 系统地将文本分类到预定义类别,基于内容分配最合适类别

  • 对话(Conversation)

    • 创建交互式对话,使 AI 能与用户进行自然流畅的交流

  • 代码生成(Code Generation)

    • 根据特定需求生成功能代码片段,将自然语言指令转化为可执行代码

高级技术

  • 零样本/少样本学习(Zero-shot, Few-shot Learning)

    • 模型在极少或没有特定问题类型示例的情况下做出准确预测

    • 利用学习到的泛化能力理解新任务

  • 思维链(Chain-of-Thought)

    • 链接多个 AI 响应以创建连贯且上下文感知的对话

    • 帮助 AI 保持讨论主线,确保相关性和连续性

  • ReAct(推理+行动,Reason + Act)

    • AI 先分析(推理)输入,再确定最合适的行动或响应

    • 结合理解与决策

  • Microsoft Guidance 框架

    • 用于创建和优化提示的结构化方法

    • 指导用户构建能引发 AI 模型期望响应的有效提示

令牌(Tokens)


令牌在 AI 模型处理文本的方式中至关重要,充当将单词转换为 AI 可处理格式的桥梁:

  • 输入阶段:单词被转换为令牌

  • 处理阶段:AI 模型使用令牌化格式理解和响应

  • 输出阶段:令牌被转换回单词

令牌化(Tokenization) 是将文本分解为令牌的过程,是 AI 模型理解和处理语言的基础。通常:

  • 1 个令牌 ≈ 3/4 个单词

  • 示例:莎士比亚全集(约 90 万字)≈ 120 万令牌

实际意义

  • 计费(Billing)

    • AI 模型服务通常基于令牌使用量计费

    • 输入(提示)和输出(响应)均计入总令牌数(更短的提示更具成本效益)

  • 模型限制(Model Limits)

    • 不同 AI 模型有不同令牌限制(定义其"上下文窗口")

    • 示例限制:

      • GPT-3:4K 令牌

      • Claude 2 / Llama 2:100K 令牌

      • 研究模型:最高 100 万令牌

  • 上下文窗口(Context Window)

    • 模型的令牌限制决定其上下文窗口

    • 超过此限制的输入不会被处理

    • 关键:仅发送处理所需的最少有效信息集(例如询问《哈姆雷特》时无需包含莎士比亚所有作品)

  • 响应元数据(Response Metadata)

    • AI 模型响应的元数据包含使用的令牌数

    • 这是管理使用量和成本的重要信息

0

评论区