一、从一次深夜调试说起

上周三凌晨两点,我在调试一个智能客服的对话接口。原本预期模型能返回结构化的JSON,结果它给我吐回来一大段散文式的回答,里面还夹着几句“我觉得用户可能想问的是……”。当时我就对着屏幕苦笑——这模型太“热心”了,热心得让我解析代码直接崩溃。

问题就出在提示词上。我写了“请分析用户意图”,却没告诉它“用JSON格式输出”。这个教训让我意识到,调用大模型API和调用传统API完全是两码事。传统API是精确的机械指令,而大模型更像是一个需要明确引导的聪明实习生。


二、API调用:别把它当普通HTTP请求

很多人第一次用LLM API时,容易犯一个错误:把提示词随便一塞,然后抱怨结果不稳定。下面这个例子是我早期踩过的坑:

# 错误示范:过于随意的调用
response = openai.ChatCompletion.create(
    model="gpt-3.5-turbo",
    messages=[{"role": "user", "content": "介绍一下杭州"}]
)
# 结果可能是一段导游词、一篇历史文章,或者突然开始写诗——完全看模型当天心情

问题在于缺乏上下文和约束。大模型需要明确的“对话背景”和“身份设定”。改进后的版本:

# 正确姿势:给模型明确的角色和格式要求
messages = [
    {"role": "system", "content": "你是一个专注于技术城市的百科助手,回答简洁,不超过100字。"},
    {"role": "user", "content": "请用三个关键词概括杭州的科技产业特点"}
]
# 现在输出稳定多了,而且不会突然开始背古诗

关键点:system消息是你的指挥棒。它决定了模型的回答风格、专业领域和输出边界。我习惯把system消息写成项目需求文档的风格,越具体越好。


三、提示工程:不是魔法,是工程规范

提示工程听起来高大上,其实核心就一条:用人类能懂的方式,告诉模型你想要什么。下面分享几个实战中总结的模板。

1. 结构化输出模板

template = """
请分析以下用户问题,并严格按照JSON格式输出:

用户问题:{question}

输出要求:
- category: 问题分类(技术/产品/售后)
- keywords: 提取3个核心关键词
- response: 生成简短回答(50字内)

JSON格式:
"""
# 注意:在提示词里明确写“JSON格式”四个字有奇效,模型会主动约束输出结构

2. 分步思考模板(Chain-of-Thought)

template = """
请按步骤思考:

用户查询:“如何快速学习Python?”

第一步:识别用户身份(新手/转行/学生?)
第二步:分析真实需求(找工作/做项目/考试?)
第三步:给出针对性建议

请用“【步骤】”开头回答:
"""
# 这个技巧能让模型把思考过程外化,特别适合需要推理的场景

3. 少样本学习(Few-Shot)模板

template = """
请根据示例格式回答问题:

示例1:
问:苹果的营养价值
答:{"fruit": "苹果", "vitamins": ["C", "K"], "calories": 52}

示例2:
问:香蕉的产地
答:{"fruit": "香蕉", "origin": ["热带地区"], "calories": 89}

现在请回答:
问:橙子的主要功效
答:
"""
# 给一两个例子,模型就能迅速get到你想要的格式和深度,比写长篇大论的要求管用

四、温度参数:别小看这个滑块

temperature参数可能是最被低估的设置。早期我总用默认值0.7,直到有一次生成产品描述时,同一提示词跑出“优雅奢华”“性价比之王”“小众精品”三种完全不同的人设。

# 产品描述场景
high_temp = 0.9  # 创意营销文案,每次都有新花样
mid_temp = 0.3   # 技术文档,稳定但略有变化
low_temp = 0.1   # 法律条款,几乎一字不差

# 经验法则:
# - 创意类:0.7~0.9
# - 分析类:0.3~0.5  
# - 标准化输出:0.1~0.2
# 重要:生产环境一定要测试不同温度下的输出稳定性

五、错误处理:模型会“说谎”

这是我用血泪换来的经验:永远不要假设模型的输出是正确的。特别是涉及数字、日期、专业术语时。

# 危险代码:
answer = response.choices[0].message.content
db.execute(f"INSERT INTO table VALUES ('{answer}')")  
# 如果模型突然在回答里夹带引号或分号,SQL注入就来了

# 安全做法:
import json
import re

def safe_parse(response_text):
    # 先尝试提取JSON
    json_match = re.search(r'\{.*\}', response_text, re.DOTALL)
    if json_match:
        try:
            return json.loads(json_match.group())
        except:
            pass
    
    # 非结构化文本的清洗
    cleaned = response_text.strip().replace('```', '')
    # 关键:设置默认值和长度限制
    return {"content": cleaned[:500]}  # 硬性截断,防止数据库字段溢出

模型可能会生成看似合理但完全错误的信息(业内叫“幻觉”)。重要数据一定要有二次校验,或者让模型提供引用来源。


六、个人经验包

  1. 提示词要迭代开发:别指望一次写对。我习惯建个prompt_version.txt文件,记录每次调整和效果,像写实验日志一样。

  2. 系统消息放最后调:先搞定用户消息的格式和内容,等主体逻辑跑通了,再回头精修system消息。反过来做很容易浪费时间。

  3. 给模型“思考时间”:复杂任务在提示词里加上“请逐步思考”“让我们一步步分析”,效果立竿见影。这相当于给了模型更多的计算步骤。

  4. 长度限制写在明处:在提示词里明确写“不超过50字”“用一句话回答”,比在代码里截断更自然。模型会自己组织语言适应长度。

  5. 生产环境加降级方案:当API返回异常或内容不符合预期时,要有fallback逻辑。我常用的方案是缓存几个高质量模板答案,关键时刻直接替换。

  6. 成本意识:每次调用前估算token数。长文档处理时,先做摘要再提问,比直接扔全文进去便宜得多。记住:输入token通常比输出token便宜,但两者都计费。


最后说点实在的

大模型API调用,上手容易,精通难。最大的门槛不是技术,而是思维转换——从“指令式编程”切换到“引导式沟通”。刚开始你会觉得模型不听话,慢慢你会发现,问题往往出在自己没表达清楚。

最好的学习方法是建个测试脚本,固定一个任务(比如商品描述生成),用不同的提示词、温度参数、格式要求反复跑。跑上几十次,你自然就能摸到模型的脾气。我电脑里现在还留着三个月前的对比测试记录,翻看时能清晰看到自己提示工程的进化轨迹。

记住,模型不是魔法黑盒,它是个有固定模式的聪明学生。你的提示词,就是给这个学生的考卷题目。题目出得清晰,答案才能漂亮。

Logo

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

更多推荐