1. 什么是提示词工程 Prompt Engineering?你在项目中是怎么应用的?
考察点:Prompt 理解
参考答案:
Prompt Engineering 就是提示词工程,一门"怎么跟大模型说话"的艺术。同样一个问题,提示词不同,大模型的响应质量天差地别。
1. 角色设定
你是一个专业的播客主播,擅长把复杂的内容讲得通俗易懂。
2. 任务描述
请把下面的文章改写成适合口播的风格,要求:
- 语言口语化,避免书面语
- 加入适当的过渡语,如"那么"、"接下来"
- 控制在 500 字以内
3. 输出格式约束
请以 JSON 格式返回,包含以下字段:
- title: 标题
- content: 正文
4. 给示例
示例输入:人工智能是计算机科学的一个分支...
示例输出:大家好,今天咱们来聊聊人工智能。说白了呢,它就是...
我们的 LLM 节点支持配置 System Prompt 和 User Prompt,业务人员可以在可视化界面上编辑这些 Prompt。
这是我们最终优化后的播客生成提示词。效果就会比 把下面的内容改写成播客对话: {content}好得多。
# 角色
你是沉默王二,一个嘴上贫、心里明白的技术博主。现在你主持一档叫「王二电台」的节目,这节目嘛,主打一个——有点干货、有点废话,但绝不无聊。
# 任务
把用户提供的原始内容改编成适合单口相声或播客节目风格的逐字稿。
要像电台聊天那样自然,有节奏、有情绪、有点梗。
# 注意点
确保语言口语化,像真在跟听众唠嗑。
专业术语要用“人话”解释,越通俗越好。
整体节奏轻松点,有点幽默,有点温度,听着像朋友聊天,不像老师讲课。
保持对话的自然过渡,别让听众觉得跳。
输出时只要口播稿,不要加格式,不要写提示内容。
# 示例
欢迎收听王二电台,咱这节目啊,不讲大道理,也不装深沉。
今天这话题呢,有点意思——保证听完你会想,卧槽,原来还能这么想。
来,别磨叽,直接开整。
# 原始内容:{{input}}
2. System Prompt 和 User Prompt 有什么区别?什么时候用 System Prompt?
考察点:Prompt 设计
参考答案:
System Prompt 是给 AI 的"人设说明书",定义它是谁、该怎么表现、有什么限制。
User Prompt 是用户的具体问题或指令,是"这次要做什么"。
// 方式一:全放 User Prompt
chatClient.prompt()
.user("你是一个播客脚本作者,风格幽默。请把下面内容改写成对话:xxx")
.call();
// 方式二:分开写
chatClient.prompt()
.system("你是一个播客脚本作者,风格幽默,擅长把严肃话题讲得有趣。")
.user("请把下面内容改写成对话:xxx")
.call();
两种方式都能工作,但方式二效果会更好。因为 LLM 对 System 角色的消息有更高的权重,会更稳定地保持设定的人设和风格。
追问 1:什么时候用 System Prompt?
1. 定义角色身份
你是一位专业的程序员,写代码要严谨、要有注释。
2. 设定输出格式
所有回答必须使用 JSON 格式,包含 title 和 content 字段。
3. 规定行为边界
你只回答技术相关问题。遇到其他问题,礼貌拒绝。
4. 注入背景知识
以下是我们公司的产品介绍:[产品信息]
请基于这些信息回答用户问题。
在 PaiFlow 中,播客生成的 Prompt 结构是System 里放不变的设定,User 里放每次变化的输入:
chatClient.prompt()
.system("""
你是资深播客脚本作者,风格特点:
- 语气轻松自然,像朋友聊天
- 善于用比喻和故事解释复杂概念
- 对话有来有回,节奏明快
输出格式要求:
- 使用 A/B 标注两位主持人
- 每段对话不超过 3 句话
""")
.user("请将以下内容改写为播客对话:\n" + userContent)
.call();
在多轮对话时,System Prompt 只在开头出现一次,设定整个对话的基调,不用每轮重复。
[System] 你是一个技术助手...
[User] 什么是微服务?
[Assistant] 微服务是一种架构风格...
[User] 和单体架构有什么区别?
[Assistant] 主要区别在于...
3. 你的 VariableTemplateRender 是怎么实现 Prompt 模板渲染的?
考察点:模板引擎、正则解析
参考答案:
VariableTemplateRender 是一个轻量级的模板引擎,支持把 {{nodeId.variableName}} 格式的变量替换成实际值。
public class VariableTemplateRender {
// 预编译正则,提高性能
private static final Pattern PATTERN = Pattern.compile("\\{\\{([^}]+)\\}\\}");
public static String render(String template, Map variables) {
Matcher matcher = PATTERN.matcher(template);
StringBuilder result = new StringBuilder();
while (matcher.find()) {
String varPath = matcher.group(1); // 如 "start.input"
String[] parts = varPath.split("\\.");
// 从变量池中取值
Object value = variables.get(parts[0]);
if (parts.length > 1 && value instanceof Map) {
value = ((Map) value).get(parts[1]);
}
matcher.appendReplacement(result,
value != null ? value.toString() : "");
}
matcher.appendTail(result);
return result.toString();
}
}
模板:
请把以下内容改写成播客风格:
{{start.input}}
变量:
{
"start": {
"input": "人工智能是计算机科学的一个分支..."
}
}
渲染结果:
请把以下内容改写成播客风格:
人工智能是计算机科学的一个分支...
参考答案版本 2
VariableTemplateRender 是工作流引擎里的模板渲染组件,负责把 Prompt 模板里的变量占位符替换成实际值。
工作流里,用户可以这样写 Prompt 模板,{{node_id.variable_name}} 是变量占位符,运行时要从 VariablePool 里取对应值替换进去。
请将以下内容改写为播客风格:
标题:{{start_node.title}}
正文:{{start_node.content}}
要求风格:{{style_node.output}}
我们设计的核心是正则匹配 + 变量池查找 + 字符串替换。
-
用正则找出所有 {{xxx.yyy}} 格式的占位符
-
解析出 node_id 和 variable_name
-
从 VariablePool 取值
-
替换原文
Python 版本的工作流引擎实现。
import re
from typing import Any
class VariableTemplateRender:
# 匹配 {{node_id.variable_name}} 格式
PATTERN = re.compile(r'\{\{(\w+)\.(\w+)\}\}')
def render(self, template: str, variable_pool: VariablePool,
current_node_id: str) -> str:
def replace_match(match):
node_id = match.group(1)
var_name = ma...真诚点赞 诚不我欺
回复