AI专栏 | Prompt Engineering实战 [新闻助手实战,这样写Prompt,你的程序能用?]

52 阅读11分钟

AI专栏 | Prompt Engineering实战 [新闻助手实战,这样写Prompt,你的程序能用?]

3 Prompt Engineering实战-黑板报.png

难度系数:★★★☆☆

本章知识:

  • 复习清单
  • 新闻助手Prompt
  • Prompt分析 [重点 ★★★★★]
  • 改造验证 [重点 ★★★★★]
  • 继续改进思路
  • 下一章预告: PromptEngineering进阶技巧

复习清单

上一章我们提到了关于PromptEngineering的8条高能建议,本章基于新闻助手的场景,带你来观察一下Prompt这样写你的程序能用么。

先来回顾一下PromptEngineering的8条高能建议有哪些?

  1. 把AI当人来看
  2. 提供单一的任务
  3. 任务描述清晰且准确
  4. 给出适量参考样例
  5. 正向描述任务信息
  6. 不要提供过长的prompt
  7. 根据任务类型切换任务角色
  8. A/B测试迭代找到最佳的prompt

接下来我们会用这份清单,逐条对照分析一个真实 Prompt 在程序中的表现。

注意 本章内容实际已涉及Agent开发,此时我们主要关注Prompt的编写问题。

新闻助手Prompt示例工程

需求描述

现在某公司要开发一个新闻助手,这个新闻助手会根据用户输入的关键词,从互联网上抓取相关的新闻,并返回给用户。

Code示例

下面是一个简单的新闻助手,基于LLM的搜索能力,实现新闻查询及格式化输出,来我们分析一下代码中所犯的问题有哪些?

# 非完整代码,主要包括关键代码,完整见gitcode仓库
# https://gitcode.com/miasdz/ai-column-code.git

sys_prompt = """
你是一个新闻助手,负责进行新闻信息查询并格式化输出。

# 输出要求
## 输出格式
以JSON格式仅输出查询结果,确保输出结果可以被python中json.loads加载不报错。
## JSON内容要求
0. json总体结构为list嵌套dict结构
1. 每个dict结构表示一个企业的新闻信息查询结果
2. 每个dict结构存在两个key,name和news
3. name key对应value为企业名称,value值类型为string
4. news key对应value值为新闻列表,value值类型为list,list的每一项值类型为dict
5. 企业新闻信息查询结果的list的每一个dict类型的值包括三个要素:date(日期)、new_type(新闻类型)、news(新闻信息)
6. new_type类型包括:
- 重大事件/战略动态类
- 产品/技术创新类
- 企业成就/荣誉认可类
- 人事与组织变动类
- 合规、风险与监管类
- 社会责任/ESG/公益类
- 日常运营与业务动态类
- 招标、采购公告类
## 示例
[
    {
      "name":"xx企业",
      "news":[
        {
            "date":"2026年1月12日",
            "new_type":"合规、风险与监管类",
            "news": "xxx公司因xxx业务违规开展被处罚1000万元。"
        },
        {
            "date":"2026年1月5日",
            "new_type":"重大事件/战略动态类",
            "news": "xxx公司与yyy公司达成战略合作。"
        },
      ]
    },
    {
      "name":"zz企业",
      "news":[
        {
            "date":"2026年1月18日",
            "new_type":"合规、风险与监管类",
            "news": "zz企业因xxx业务违规开展被行政处罚85万元。"
        },
        {
            "date":"2026年1月19日",
            "new_type":"人事与组织变动类",
            "news": "zz企业新任命总经理uu。"
        },
      ]
    }
]
"""

user_prompt = """
查询山西银行和晋商银行近期的5条新闻
"""

# 对话消息
messages = [
    {
        "role": "system",
        "content": sys_prompt
    },
    {
        "role": "user",
        "content": user_prompt
    }
]

# 调用llm接口
chat_completion = client.chat.completions.create(
    model=model,
    messages=messages,
    extra_body={
        "enable_search": True,
        "search_options": {
            "search_strategy": "max",  # 配置搜索策略为高性能模式
            "forced_search": True
        }
    }
)

...... 此处思考3分钟 ......

Prompt分析

运行结果

先看一下运行结果,看看程序是否能正常返回结果。

注意 下述运行结果代码实测结果截取,再次执行无法保证完全一致。

[
    {
        "name": "山西银行",
        "news": [
            {
                "date": "2026年1月7日",
                "new_type": "日常运营与业务动态类",
                "news": "山西银行发布‘晋晟理财’理财产品净值公告。"
            },
            {
                "date": "2025年12月31日",
                "new_type": "日常运营与业务动态类",
                "news": "山西银行发布‘晋晟理财’理财产品净值公告。"
            },
            {
                "date": "2025年12月24日",
                "new_type": "日常运营与业务动态类",
                "news": "山西银行发布‘晋晟理财’理财产品净值公告。"
            },
            {
                "date": "2025年12月18日",
                "new_type": "重大事件/战略动态类",
                "news": "任凯与临汾市长王延峰座谈。"
            },
            {
                "date": "2025年12月12日",
                "new_type": "重大事件/战略动态类",
                "news": "邢毅赴省内金融同业拜访交流。"
            }
        ]
    },
    {
        "name": "晋商银行",
        "news": [
            {
                "date": "2025年12月15日",
                "new_type": "合规、风险与监管类",
                "news": "晋商消费金融成被执行人第一大股东为晋商银行。"
            },
            {
                "date": "2025年12月10日",
                "new_type": "合规、风险与监管类",
                "news": "山西最新批复!多家金融机构高管任职获批。"
            },
            {
                "date": "2025年11月30日",
                "new_type": "人事与组织变动类",
                "news": "山西银行党委副书记、行长(代)邢毅带队赴太重集团开展专项调研。"
            },
            {
                "date": "2025年11月30日",
                "new_type": "人事与组织变动类",
                "news": "山西银行党委副书记、副董事长、行长李颖耀拟进一步使用。"
            },
            {
                "date": "2025年11月28日",
                "new_type": "重大事件/战略动态类",
                "news": "山西银行新增高管人事变动引关注。"
            }
        ]
    }
]

json校验

观察上述结果,prompt要求的json格式是正确的。但是从内容上分析会发现明显的错误:

  1. 同一个人的名字出现在了两家企业内,稍微了解一下是错误新闻
  2. 我要求的是近期新闻,截至我写作时间2026年1月19日,返回的新闻几乎全都是25年末的,近期目标效果差
  3. 新闻与公司关联错误,A公司新闻归类到B公司
  4. 从news字段中看不出来企业与这条新闻的关系
  5. 新闻类型错误,如“重大事件/战略动态类”

问题分析

基于前面的建议,我们逐条分析一下这段乍一看还不错的prompt,存在什么问题

1. 提供单一的任务

问题指数: ★★★★★

基于上一章节对单一任务的理解,我们再看Prompt:

SystemPrompt逻辑点:

  • 新闻信息查询
  • 新闻归类
  • 数据格式化

根据单一任务理解,system prompt已经违反单一任务的限制,不做认知的切换,新闻信息查询和归类属于两类任务 信息提取分类决策任务,不满足单一任务定义。

UserPrompt逻辑点:

  • 查询山西银行近期新闻
  • 查询晋商银行近期新闻
  • 近期是什么时候[隐性任务]
  • 新闻筛选

对于UserPrompt,要求同时查询两个企业的信息,涉及了两个信息聚合主题,也不符合单一任务定义。

根据执行结果,综合SystemPrompt和UserPrompt,经过A/B测试,主要问题体现在UserPrompt中存在两个信息实体,具体见新Prompt运行效果。

2. 任务描述清晰且准确

从程序运行结果看,主要的prompt用于描述数据格式,返回符合预期要求,从描述层面足够清晰,满足该项。

3. 给出适量参考样例

JSON格式正确,demo中给了明确的示例,满足该项。

4. 正向描述任务信息

问题指数: ★☆☆☆☆☆

确保输出结果可以被python中json.loads加载不报错。非正面描述,不过问题不大,大模型实测是没问题的,也可以改为更合理的描述如"符合标准 RFC 8259 规范的 JSON 字符串"。

5. 不要提供过长的prompt

使用openai的tokenizer计算约在gpt4模型下约600,从模型容量角度看不多,该条满足。

token统计

可参考OpenAI官方tokenizer计算结果(不同模型结算结果不同,仅供参考)

platform.openai.com/tokenizer

6. 根据任务类型切换任务角色

Systmem Prompt首行定义了任务角色,该条满足。

7. A/B测试迭代找到最佳的prompt

A/B测试迭代属于持续优化的过程,接下来我们继续修改prompt测试的过程满足此条。

改造验证

新版Prompt

sys_prompt = """
你是一个新闻助手,负责进行新闻信息查询并格式化输出。

# 输出要求
## 输出格式
以JSON格式仅输出查询结果,确保输出结果符合标准 RFC 8259 规范的 JSON 字符串。
## JSON内容要求
1. JSON结构存在两个key,name和news
2. name key对应value为企业名称,value值类型为string
3. news key对应value值为新闻列表,value值类型为list,list的每一项值类型为dict
4. 企业新闻信息查询结果的list的每一个dict类型的值包括三个要素:date(日期)、new_type(新闻类型)、new_info(新闻信息)
5. new_type类型包括:
- 重大事件/战略动态类
- 产品/技术创新类
- 企业成就/荣誉认可类
- 人事与组织变动类
- 合规、风险与监管类
- 社会责任/ESG/公益类
- 日常运营与业务动态类
- 招标、采购公告类
## 示例
{
  "name":"xx企业",
  "news":[
    {
        "date":"2026年1月12日",
        "new_type":"合规、风险与监管类",
        "news": "xxx公司因xxx业务违规开展被处罚1000万元。"
    },
    {
        "date":"2026年1月5日",
        "new_type":"重大事件/战略动态类",
        "news": "xxx公司与yyy公司达成战略合作。"
    },
  ]
}
# 约束
当未检索到可验证的有效新闻时,news 字段应返回一个空数组 []
"""

user_prompt = """
查询晋商银行近期的5条新闻
"""

实测结果

再看新prompt测试结果,在单一信息主体下,结果可用。

{
  "name": "晋商银行",
  "news": [
    {
      "date": "2026年1月16日",
      "new_type": "日常运营与业务动态类",
      "news": "晋商银行股份有限公司2026年第006期同业存单发行情况公告。"
    },
    {
      "date": "2026年1月14日",
      "new_type": "日常运营与业务动态类",
      "news": "晋商银行股份有限公司2026年第004期同业存单即日起开始在银行间债券市场交易流通。"
    },
    {
      "date": "2026年1月6日",
      "new_type": "合规、风险与监管类",
      "news": "晋商银行发布《关于加强个人银行账户安全管理的公告》。"
    },
    {
      "date": "2025年11月28日",
      "new_type": "日常运营与业务动态类",
      "news": "晋商银行召开2025年四季度经营工作会。"
    },
    {
      "date": "2025年10月29日",
      "new_type": "人事与组织变动类",
      "news": "晋商银行启动2026年度校园招聘,计划招聘11人。"
    }
  ]
}

继续改进思路

初始需求如何满足?

再翻回来看user_prompt,要求查询两个信息主体的新闻,上述优化后的prompt仅查询一个主体好用,那多个怎么办?

这就涉及工作流的开发:

  1. 用户意图识别:通过用户prompt摘取在新闻查询场景下的查询主体有几个
  2. 根据获取出的查询主体,多次调用新闻查询服务
  3. 聚合结果

查询质量不满足、新闻总结不满足怎么办

现在使用的是大模型提供的查询服务,如果需要相对稳定的查询数据源,那就需要依赖外部服务了,比如秘塔搜索API、百度搜索API甚至是外部稳定数据源的数据采购等方式来提升数据质量。

此时做法就变成了:

  1. 用户意图识别获取查询主体
  2. FuncationCalling获取外部数据
  3. 通过LLM进行新闻总结及归类
  4. 基于新闻总结及归类结果进行信息提取为JSON结构
  5. 多轮查询的信息聚合

这些流程的窜连完成一个完整的新闻领域查询服务,详情查看gitcode源码。

gitcode.com/miasdz/ai-c…

针对LLM单一任务,靠人识别可能因经验不足或者思维定式无法准确分析,后续将开发Prompt单一分析器Agent,用于优化Agent的Prompt准备。

下一章预告

下一章节将通过介绍PromptEngineering中思维链、思维树、自洽性等进阶技巧。


关注本专栏,让我们一起掌握方法、实践落地、共同发展。