前言

这篇文章带你搞懂提示词工程到底是什么、和随便写一句 prompt 有什么区别、以及怎么用 Java + LangChain4j 把 prompt 写成可复用的代码。读完你会有一个清晰的认知框架,不再凭感觉写 prompt。

很多人觉得"提示词工程"是个玄学——不就是换着花样问 AI 吗?试几次就行了呗。

这个想法对,也不对。

对的是:prompt 确实靠"试"。不对的是:瞎试和工程化地试,效率差 10 倍

提示词工程把 prompt 当成代码来对待:有结构、有模板、有测试、有版本管理。它要解决的问题是——当你的应用里嵌入了 AI 调用,你怎么保证它稳定、可控、可维护?


一、什么是提示词工程

提示词工程是一套系统化的方法,用来设计、测试、优化 prompt,让大模型输出稳定、可控、高质量的结果。

说人话就是:你不是在"问"AI,你是在"编程"AI,只不过编程语言是自然语言。

举个例子。

普通用法:你打开 ChatGPT,打一句"帮我写个排序函数",拿到结果,完事。

工程用法:你在代码里构造一段 prompt:

你是一个资深 Java 后端工程师。
请实现一个归并排序算法,要求:
1. 时间复杂度 O(n log n),空间复杂度 O(n)
2. 使用泛型,支持 Comparable 接口
3. 包含完整的 Javadoc 注释
4. 附带 3 个 JUnit 5 测试用例
5. 输出格式:先给代码,再给复杂度分析,最后给测试

看出区别了吗?

后者给出了角色、约束、格式、验收标准。它不是"希望 AI 做好",而是"规定 AI 怎么做"。


二、和普通提示词的区别

用一张表说清楚:

+------------------+---------------------------+---------------------------------+
| 维度             | 普通提示词                 | 提示词工程                      |
+------------------+---------------------------+---------------------------------+
| 心态             | "我问个问题"              | "我设计一套指令系统"            |
| 结构             | 随口一问,无固定格式       | 角色 + 约束 + 格式 + 示例       |
| 可复现性         | 每次问法不一样,结果随机   | 模板化,结果可控可预期          |
| 迭代方式         | 不满意就换句话重来         | 加约束/拆步骤/给示例/调参数     |
| 测试             | 不测试                    | A/B 对比、批量评测、边界验证    |
| 工程化           | 聊天框里临时写             | 纳入代码仓库,版本管理,CI/CD   |
| 技术理解         | 不需要                    | 需要理解 token、上下文窗口等原理 |
+------------------+---------------------------+---------------------------------+

核心差异就一句话:普通提示词是"聊天",提示词工程是"编程"——只是编程语言变成了自然语言。

还有一个容易被忽略的点:成本意识

聊天时你不会在意 token 消耗。但在工程场景中,每个 prompt 可能被调用上万次,多 100 个 token 就多一笔真金白银。


三、核心方法论

提示词工程不是玄学,它有明确的方法论。下面四个是最基础也最好用的。

3.1 角色设定(Role Prompting)

给 AI 一个具体的身份,它会自动调整回答的知识范围、语气和专业程度。

❌ 差:解释一下 Java 的 GC 机制
✅ 好:你是一个 JVM 调优专家,请向一个有 3 年经验的 Java 开发者解释 GC 机制

为什么有效?因为大模型的训练数据里,"专家"回答的内容天然比"普通人"更专业、更有结构。

实用技巧:角色不要写得笼统,越具体越好。

❌ 你是一个程序员
✅ 你是一个有 10 年经验的 Java 后端架构师,擅长高并发系统设计,习惯用 Spring Boot + MyBatis 技术栈

3.2 Few-shot 示例

在 prompt 里塞几个输入→输出的范例,AI 会模仿你的格式和风格。

请将以下需求转为用户故事,格式参照示例:

示例 1:
输入:用户登录功能
输出:作为一个注册用户,我希望通过邮箱和密码登录系统,以便访问个人数据

示例 2:
输入:订单导出功能
输出:作为一个运营人员,我希望导出指定日期范围的订单为 Excel,以便做数据分析

现在请处理:
输入:商品搜索功能

Few-shot 是成本最低的"调参"方式——你不用动 prompt 逻辑,加两个例子效果就上来了。

3.3 思维链(Chain of Thought)

让 AI 先思考再回答,而不是一步到位。

❌ 差:这段代码有什么问题?
✅ 好:请逐步分析这段代码:
       1. 先列出所有变量的含义
       2. 追踪每个分支的执行路径
       3. 指出潜在 bug
       4. 给出修改建议

加上"逐步分析"四个字,AI 的准确率能提升 10%-30%。这是论文验证过的结论。

适用场景:推理类任务(数学、逻辑、代码审查、多步决策)。

3.4 结构化输出

要求 AI 输出 JSON、XML 或 Markdown 格式,而不是自由文本。

请分析以下代码的质量,输出 JSON:

{
  "complexity": "low|medium|high",
  "bugs": ["bug1", "bug2"],
  "suggestions": ["建议1", "建议2"],
  "score": 1-10
}

好处非常直接:下游代码可以直接 parse,不需要再做文本提取

如果 AI 的 JSON 偶尔格式不对,可以用 retry 机制或者 JSON Schema 校验兜底。


四、Java + LangChain4j 实战

光说不练不行。下面用 Java 代码演示怎么把上面四个方法论落地。

4.1 环境准备

<dependency>
    <groupId>dev.langchain4j</groupId>
    <artifactId>langchain4j</artifactId>
    <version>1.0.0-beta2</version>
</dependency>
<dependency>
    <groupId>dev.langchain4j</groupId>
    <artifactId>langchain4j-open-ai</artifactId>
    <version>1.0.0-beta2</version>
</dependency>

4.2 Prompt 模板化:角色设定 + 结构化输出

import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.openai.OpenAiChatModel;
import dev.langchain4j.service.*;

public class PromptEngineeringDemo {

    // 定义结构化输出的 Java Bean
    static class CodeReview {
        String complexity;
        List<String> bugs;
        List<String> suggestions;
        int score;
    }

    // 定义 AI Service 接口——prompt 模板直接写在注解里
    interface CodeReviewer {
        @SystemMessage("""
            你是一个资深 Java 代码审查专家,有 10 年经验。
            你擅长发现并发安全问题和性能瓶颈。
            你必须严格输出 JSON 格式,不要加任何额外说明。
            """)
        @UserMessage("""
            请审查以下 Java 代码:
            {{code}}
            
            输出 JSON:
            {
              "complexity": "low|medium|high",
              "bugs": ["问题描述"],
              "suggestions": ["改进建议"],
              "score": 1-10
            }
            """)
        CodeReview review(String code);
    }

    public static void main(String[] args) {
        ChatLanguageModel model = OpenAiChatModel.builder()
            .apiKey(System.getenv("OPENAI_API_KEY"))
            .modelName("gpt-4o")
            .build();

        CodeReviewer reviewer = AiServices.create(CodeReviewer.class, model);

        String code = """
            public class Counter {
                private int count = 0;
                public void increment() { count++; }
                public int get() { return count; }
            }
            """;

        CodeReview result = reviewer.review(code);
        System.out.println("复杂度: " + result.complexity);
        System.out.println("Bug 数: " + result.bugs.size());
        System.out.println("评分: " + result.score);
    }
}

要点解读

  • @SystemMessage角色设定——告诉 AI 你是谁、怎么说话
  • @UserMessage 里的 {{code}}模板变量——prompt 参数化,不硬编码
  • 返回类型 CodeReview结构化输出——LangChain4j 自动把 JSON 映射成 Java 对象

4.3 思维链 + Few-shot

interface SqlGenerator {
    @SystemMessage("""
        你是一个 SQL 优化专家。
        生成 SQL 前,你必须先说明你的思考过程,然后再给出 SQL。
        思考过程用「分析:」开头,SQL 用「SQL:」开头。
        """)
    @UserMessage("""
        参考示例:
        
        需求:查询过去 30 天每个用户的订单总额
        分析:需要 users 表和 orders 表做 join,
              按 user_id 分组,用 sum 聚合金额,
              时间过滤用 orders.created_at >= 当前日期 - 30 天
        SQL:SELECT u.name, SUM(o.amount) AS total
             FROM users u JOIN orders o ON u.id = o.user_id
             WHERE o.created_at >= DATE_SUB(NOW(), INTERVAL 30 DAY)
             GROUP BY u.id, u.name
             ORDER BY total DESC
        
        现在请处理:
        需求:{{requirement}}
        """)
    String generateSql(String requirement);
}

这里 Few-shot 示例让 AI 模仿思考格式,思维链提示让 AI 展示推理过程——两个方法叠加,质量更稳。

4.4 多轮对话 + 上下文管理

工程场景里经常需要多轮交互。LangChain4j 提供了 ChatMemory 来管理上下文:

ChatMemory memory = MessageWindowChatMemory.withMaxMessages(10);

ConversationalChain chain = ConversationalChain.builder()
    .chatLanguageModel(model)
    .chatMemory(memory)
    .build();

String answer1 = chain.execute("我要设计一个秒杀系统");
String answer2 = chain.execute("你刚才说的方案,第三点展开讲讲");
// AI 记得上一轮的"方案"指的是什么

五、常见误区

5.1 以为 prompt 越长越好

错。prompt 是给 AI 的有效信息密度,不是字数。废话多反而稀释关键指令。

原则:每句话都应该在"约束行为"或"提供信息",否则就删掉。

5.2 角色设定写得像招聘 JD

“你是一个精通 Java、Python、Go、Rust,熟悉 K8s、Docker、Terraform 的全栈工程师”——这种角色等于没说。

角色越聚焦,回答越精准。

5.3 不测试就直接上线

很多人 prompt 调好了,自己试了两次觉得不错,就提交代码了。

工程化的做法是:准备 20-50 条测试用例,每次改 prompt 跑一遍,看通过率变化。

// 简单的批量测试框架
List<TestCase> cases = List.of(
    new TestCase("input1", "expectedOutput1"),
    new TestCase("input2", "expectedOutput2")
);

int pass = 0;
for (TestCase tc : cases) {
    String actual = agent.process(tc.input);
    if (matches(actual, tc.expected)) pass++;
}
System.out.println("通过率: " + pass + "/" + cases.size());

5.4 忽视 token 成本

一个 prompt 多 200 个 token,调用 10 万次就多花几十美金。工程里要养成精简 prompt 的习惯。

5.5 把 prompt 写在代码字符串里不管理

prompt 是代码的一部分,该和代码一起进 Git。更好的做法是外部化管理——放在配置文件或数据库里,改 prompt 不用重新部署。


结尾

提示词工程不是玄学,是一门把自然语言当编程语言用的工程实践。

你不需要一次写出完美的 prompt。你需要的是:

  1. 掌握四个核心方法(角色、示例、思维链、结构化输出)
  2. 用模板和参数化把 prompt 变成可复用的"函数"
  3. 写出测试用例,持续迭代

最后记住一句话:

你不是在跟 AI 聊天,你是在给一个极其聪明但没有任何常识的实习生写需求文档。

需要多具体,就写多具体。


Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐