
1. “Humanising LLM Outputs Is Dumb”到底在批评什么近年来大语言模型LLM的对话能力越来越强很多产品在设计时也刻意让模型输出贴近真人口吻比如加语气词、带表情、用口语化表达甚至模拟人类的犹豫和重复。这种“人性化处理”在聊天机器人、写作助手、娱乐陪伴类应用里确实能提升体验用户也更愿意和“像真人”的AI多聊几句。但如果你把 LLM 用在工单自动分类、数据抽取、SQL 生成、代码补全、客服话术审核这类工程任务里“太像人写的”反而会变成灾难。先说几个最常见的副产物格式不稳定。上一轮还输出 JSON下一轮突然变成 Markdown 表格或者前缀了一段“好的我来帮你处理”。语气词污染业务数据。最终存入数据库的文本里混入“嗯呢”“亲”“~”这类字符。模型“脑补”严重。为了让语气更像人会在不确定的信息上用自然语言模糊带过而不是直接说“不知道”。Token 成本上升。同样的信息量人性化输出可能多消耗 30% 以上的 token响应时间也更长。下游程序解析困难。正则、JSON.parse、query 模板都假设输入是稳定的而“人性化”恰恰破坏了这种稳定性。所以 “Humanising LLM Outputs Is Dumb” 这句话并不是说 LLM 不应该有自然语言能力而是在批评一种工程上的懒惰不分场景地追求“像人说话”把生成式模型的灵活性当成了默认选项却忽略了系统稳定性和可维护性。本文围绕“LLM 输出的人性化程度控制”展开先讲清楚人性化输出来自哪些因素再结合代码演示如何通过 Prompt、采样参数、结构化输出和后处理让 LLM 在工程场景中变得“可靠”而不是“像人”。同时也会说明哪些业务场景确实需要保留人性化哪些场景必须做规范化处理。2. LLM 输出的“人性化程度”由哪些因素决定在讨论怎么控制之前需要先理解 LLM 输出的风格到底受哪些因素影响。很多人以为只要在 Prompt 里写一句“请简洁回复”就够了实际上影响输出风格的因素至少包括四个层面。2.1 采样参数采样参数直接决定模型生成文本时的随机性和重复倾向。和风格最相关的是下面几个参数作用对“人性化”的影响temperature控制生成结果的随机性值越大输出越发散值越高越容易出现口语化表达、语气词、跳跃性转折top_p控制候选词的概率累积范围调低后输出更保守更不容易出现“出人意料的话”presence_penalty对已经出现过的词进行惩罚调高后模型会避免重复但可能引入更多新词frequency_penalty对高频出现的词进行惩罚调高后口头禅和重复句式会减少但表达可能变得生硬如果你希望输出更接近“标准书面语”通常会把 temperature 调到 0.1 到 0.3top_p 调到 0.8 到 0.9。这里需要注意这些参数不是越大或越小越好而是要根据任务风险来判断聊天场景可以接受较高的随机性而数据提取、SQL 生成这类场景需要尽可能稳定。2.2 System PromptSystem Prompt 是约束模型行为最直接的手段。它的作用不是“魔法”而是给模型设定一个角色和输出规范。举例你是一个严谨的数据处理助手。你的输出必须简洁、规范、口语化程度为零。 不使用任何语气词、表情符号、感叹句。 只输出最终结果不解释过程。和简单地在用户消息末尾追加“请简洁”相比System Prompt 在大多数模型上的约束效果更强因为它位于对话的开头且对整个会话都有影响。2.3 模型本身不同模型的“人性化倾向”差异很大。有些模型在预训练和微调阶段被刻意优化成“乐于助人的聊天助手”默认输出就会带很多解释性、鼓励性的内容。另一些模型则更偏向指令遵循输出相对克制。这个因素在工程选型时需要格外关注。如果你的应用定位是数据清洗或结构化抽取优先选择指令遵循能力强的模型而不是对话风格强的模型。2.4 输出后处理最后一道防线是程序层面的后处理。无论 Prompt 写得多好、参数调得多准LLM 始终存在输出不稳定的小概率情况。这时候就需要在代码里做规则清洗、格式校验、甚至二次调用。后处理这个概念常常被忽略但它是“去人性化”最可控的一环。后面会给出具体的代码示例。3. 业务场景判断需要人性化还是需要规范化在开始写代码之前先建立一个场景判断框架。很多开发者在项目初期没有想清楚这个问题导致系统上线后频繁修修补补。3.1 需要保留人性化的场景适合保留人性话的场景通常是“用户感知型交互”情感陪伴类聊天机器人内容创作灵感助手口语陪练游戏 NPC 对话这些场景里用户的核心诉求是“愿意继续聊下去”而不是“信息绝对准确”。此时就可以用较高的 temperature甚至在 Prompt 里明确要求使用轻松口语风格。3.2 需要规范化的场景适合强制规范化的场景通常是“下游系统消费型”场景期望输出推荐温度客服工单自动摘要固定模板的短文本0.2 以下邮件分类只输出类别标签0.1 以下自然语言转 SQL可执行的 SQL 语句0 或极小值信息抽取JSON 格式结果0.1 以下代码生成可直接运行的代码0.1 以下一个简单的判断标准如果 LLM 的输出会被另一个程序直接消费而不是直接展示给用户那就需要做规范化。反过来如果输出是给用户阅读的人性化才有价值。3.3 混合场景怎么处理现实项目中很多任务同时存在“给人看”和“给机器用”的需求。一个典型的场景是智能客服系统对话回复需要自然流畅但对话结束后的会话摘要必须结构化存储。这种情况下更推荐的做法是拆成两条独立链路一条面向用户使用高温度参数和口语化 Prompt另一条面向系统使用低温度参数和结构化 Prompt。不要让同一个 Prompt 完成两个目标否则两边都无法做好。4. 实战把 LLM 输出从“感性”拉回“理性”下面通过一个具体项目演示如何让 LLM 的输出更规范。例子是输入一段客户反馈要求 LLM 判断问题类别并生成本地化摘要。项目使用 Python 语言假设你已经有基本的 Python 环境。示例会保持简单重点演示思路和完整代码。4.1 环境准备需要安装两个库openai和python-dotenv。如果你使用的是 OpenAI 兼容接口代码逻辑类似只需要调整 base_url 和 api_key。pip install openai python-dotenv在项目目录下创建.env文件OPENAI_API_KEYyour_api_key_here OPENAI_BASE_URLhttps://api.openai.com/v1这里需要注意不同厂商的 API 在模型名、接口路径上可能有差异请以实际使用的服务为准。示例中的代码不绑定某个具体服务商你可以按自己项目对接的 LLM 接口调整。4.2 基础版本直接调用 LLM先写一个最普通的调用版本仅仅把用户反馈传给模型不做任何额外约束。# 文件路径llm_demo/basic_call.py import os from openai import OpenAI from dotenv import load_dotenv load_dotenv() client OpenAI( api_keyos.getenv(OPENAI_API_KEY), base_urlos.getenv(OPENAI_BASE_URL), ) def analyze_feedback(content: str) - str: response client.chat.completions.create( modelgpt-4o-mini, messages[ { role: user, content: f请分析以下客户反馈\n{content}, } ], temperature0.7, ) return response.choices[0].message.content if __name__ __main__: feedback 我上周买的鼠标今天居然双击没反应了客服态度还很差气死我了 print(analyze_feedback(feedback))temperature 设置为 0.7模型的输出可能类似好的呢我来帮您分析一下这条反馈~ 从描述来看这位客户遇到了鼠标质量问题左键单击时没有反应。另外从客户情绪来看他对客服的态度也非常不满应该是在沟通过程中感受到了不好的体验。建议商家尽快联系客户处理退换货问题这段回复单独看并没有问题甚至可以说“很有人情味”。但如果你的目标是生成工单摘要这段文本到处都是坑有表情符号、有语气词、有非结构化描述、有冗余解释直接存入数据库会对后续统计和检索造成麻烦。4.3 通过 System Prompt 约束表达现在加入 System Prompt明确要求输出简洁、规范、禁止语气词和表情。# 文件路径llm_demo/system_prompt_version.py import os from openai import OpenAI from dotenv import load_dotenv load_dotenv() client OpenAI( api_keyos.getenv(OPENAI_API_KEY), base_urlos.getenv(OPENAI_BASE_URL), ) SYSTEM_PROMPT 你是一个严谨的工单分析助手。你只输出结构化结果不使用任何口语化表达。 具体要求 1. 不使用“好的呢”“亲”“嗯呢”“哈哈”等语气词。 2. 不使用表情符号。 3. 不输出任何解释性开场白。 4. 一句话概括问题一句话概括建议。 .strip() def analyze_feedback(content: str) - str: response client.chat.completions.create( modelgpt-4o-mini, messages[ {role: system, content: SYSTEM_PROMPT}, {role: user, content: f请分析以下客户反馈\n{content}}, ], temperature0.2, ) return response.choices[0].message.content if __name__ __main__: feedback 我上周买的鼠标今天居然双击没反应了客服态度还很差气死我了 print(analyze_feedback(feedback))这次输出大概率会变成问题鼠标左键双击无效属于硬件故障客户同时投诉客服态度差。 建议联系客户退换货并调查客服沟通记录。可以看到仅仅通过 System Prompt 和调整 temperature输出质量就有了明显提升。4.4 输出后处理规则清洗与格式校验依赖模型自控力仍然存在风险。为了进一步保证一致性增加一个后处理函数做三件事去除首尾空白和多余换行移除表情符号移除“好的”“好的呢”“我来帮您”这类常见前缀# 文件路径llm_demo/post_process.py import re PATTERNS_TO_REMOVE [ r好的呢[,、\s]*, r好的[!。.\s]*, r我来帮[您你][,、\s]*, r亲[,、\s]*, r[\U0001F300-\U0001FAFF\U0001F600-\U0001F64F], ] def clean_llm_output(text: str) - str: cleaned text.strip() for pattern in PATTERNS_TO_REMOVE: cleaned re.sub(pattern, , cleaned) return re.sub(r\n{2,}, \n, cleaned) def validate_output(text: str) - bool: 简单校验不能为空不能包含表情符号。 if not text: return False if re.search(r[\U0001F300-\U0001FAFF], text): return False return True这段代码的价值在于即使某次模型输出了不规范内容程序层也能兜底。上面这个项目示例想说明的核心思路是Prompt 定“风格基调”参数定“随机边界”后处理定“最终兜底”。三者缺一不可。5. 进阶用结构化输出彻底切断“废话文学”如果只是想让 LLM 输出少一点废话上述方案已经足够。但工程实践中还有一种更稳妥的思路不让 LLM 自由输出而是强制它输出特定格式。5.1 JSON Mode 示例现在的 LLM API 大多支持 JSON 输出模式。你可以在消息中要求模型只输出合法 JSON部分接口还支持response_format参数。# 文件路径llm_demo/json_mode.py import json import os from openai import OpenAI from dotenv import load_dotenv load_dotenv() client OpenAI( api_keyos.getenv(OPENAI_API_KEY), base_urlos.getenv(OPENAI_BASE_URL), ) SYSTEM_PROMPT 你是一个数据抽取助手。用户会提供一段文本你需要从中抽取指定字段。 输出格式必须为 JSON不允许包含任何其他文字。 字段说明 - category: 问题类别只能是 [硬件故障, 服务态度, 物流问题, 其他] 中的一个 - summary: 一句话摘要不超过30个字 - suggestion: 处理建议不超过20个字 .strip() def extract_feedback(content: str) - dict: response client.chat.completions.create( modelgpt-4o-mini, response_format{type: json_object}, messages[ {role: system, content: SYSTEM_PROMPT}, {role: user, content: content}, ], temperature0.1, ) raw response.choices[0].message.content try: result json.loads(raw) except json.JSONDecodeError: # 解析失败时进行最小清理后尝试二次解析 cleaned raw.strip().removeprefix(json).removesuffix().strip() result json.loads(cleaned) return result if __name__ __main__: feedback 我上周买的鼠标今天居然双击没反应了客服态度还很差气死我了 result extract_feedback(feedback) print(json.dumps(result, ensure_asciiFalse, indent2))输出示例{ category: 硬件故障, summary: 鼠标双击无反应同时投诉客服态度差, suggestion: 退换货并核查客服服务记录 }注意JSON Mode 并不是 100% 保证合法 JSON个别情况下仍可能输出额外的逗号或转义错误所以在代码里仍然需要try-except兜底。5.2 把 LLM 输出当成“数据通道”而不是“对话对象”这个思维方式很重要。如果你把 LLM 当成一个人去看待你会接受它偶尔啰嗦、偶尔跑题但当你把 LLM 当成一个“带噪声的数据转换通道”时你自然就会为它设计校验、重试、降级方案。结构化输出方案本质上就是把“人性化”选项关到最小同时把错误暴露给程序去检测和处理而不是等着用户去“感受语气”。另外有一点值得提LLM 的后处理链路并不要求和模型部署在同一台机器上。实际项目中模型服务通常部署在云端或独立 GPU 服务器后处理的规则引擎、解析服务、业务数据库可以部署在另一台应用服务器。两者通过 API 通信即可。很多开发者会误以为“AI 项目必须所有服务都在同一台机器上”这其实要看场景。模型推理和后处理是两套独立的计算资源需求完全可以根据各自负载单独部署。6. 常见问题与排查思路在控制 LLM 输出规范化的过程中有不少高频问题。下面整理成一张表格方便排查。问题现象常见原因解决思路System Prompt 写了禁止语气词输出里仍有“好的呢”模型本身风格偏好强单轮约束不够在用户消息里再次强调降低 temperature增加后处理规则temperature 调到 0 后输出变慢或结果异常极低温度会降低模型的多样性部分任务反而表现不好不要追求 0通常 0.1~0.3 是工程上的安全区间JSON 解析偶尔失败LLM 输出包含 Markdown 代码块标记或前后多余文本使用 response_format 参数解析前清理 markdown 标记增加二次解析后处理正则误删正常内容规则写得太宽泛先做小样本测试规则尽量精确到具体高频语气词同一个 Prompt 效果不稳定模型版本更新或动态采样参数差异固定模型版本记录每次调用的参数建立回归用例结构化抽取字段缺失Prompt 对字段说明不清晰在 Prompt 中明确枚举值范围提供示例输入输出Token 消耗远超预期Prompt 里塞了太多示例精简 few-shot 示例静态内容合并只保留必要约束模型输出速度慢输入文本太长或模型参数量太大缩短输入、使用更小模型、开启流式输出、后处理服务与模型服务分离部署排查时建议遵循一个顺序先看原始输出判断是“模型没做好”还是“后处理没兜住”。如果是模型问题优先改 Prompt其次是调参数。如果改了 Prompt 仍然不稳定再增加后处理和重试机制。最后才考虑换模型或换服务商。7. 最佳实践与工程建议下面这些建议来自多个 LLM 项目的落地经验不一定每条都适合你的场景但可以作为系统设计的检查清单。7.1 建立双 Prompt 体系建议在项目中维护两套 Prompt面向用户展示的 Prompt允许口语化、有温度。面向系统消费的 Prompt要求结构化、简洁、无冗余。这两套 Prompt 分开维护不要混用一个。可以在代码中用配置文件管理例如prompts/chat.yaml和prompts/extract.yaml。7.2 把参数配置纳入版本管理temperature、top_p、模型名等参数不要散落在业务代码里。把它们集中到配置文件中并纳入 Git 管理。这样每次调参都能回溯也方便团队评审。# 文件路径config/extract_config.yaml model: gpt-4o-mini temperature: 0.1 top_p: 0.9 max_tokens: 200 response_format: json_object7.3 对输出做结构化校验而不是只做文本清洗文本清洗能解决语气词问题但解决不了字段缺失或格式错误。建议对关键字段做类型校验例如ALLOWED_CATEGORIES [硬件故障, 服务态度, 物流问题, 其他] def validate_extract_result(data: dict) - bool: if category not in data or summary not in data: return False if data[category] not in ALLOWED_CATEGORIES: return False if len(data[summary]) 50: return False return True7.4 记录原始输出与后处理结果不要只存最终结果。把模型原始输出、清洗后结果、校验是否通过都记录下来。这在排查问题时非常有用。很多“莫名其妙”的问题只有拿到原始输出才能定位根因。可以采用简单的 JSON 日志{ input: 客户原文, raw_output: 模型原始输出, processed_output: 后处理结果, is_valid: true, model: gpt-4o-mini, temperature: 0.1, latency_ms: 562 }7.5 建立回归用例集LLM 应用和传统软件的最大区别是同一个输入每次输出可能不一样。所以必须准备一个固定的小规模测试集每次修改 Prompt 或升级模型后都跑一遍确认输出格式和内容没有劣化。测试集不需要很大10 到 20 条有代表性的样本即可。关键是要覆盖不同类型正常输入、异常输入、空输入、超长输入、带辱骂词的输入、多种语言混合输入。7.6 不要把所有逻辑都押在 Prompt 上Prompt 确实是控制 LLM 输出最灵活的方式但它也是脆弱的方式。如果你的业务对正确性要求很高例如生成 SQL、计算金额、判断风控规则建议用规则引擎对输出做二次校验。涉及关键操作时让 LLM 只输出“建议动作”由代码决定是否执行。不要直接执行模型生成的代码或数据库操作。8. 结尾与下一步“Humanising LLM Outputs Is Dumb”这句话真正想提醒开发者的是人性化是一种产品选择而不是 LLM 默认应该具备的能力。如果你做的产品需要机器与人自然交流那就要大胆地做人性化如果你做的是数据管道、工单系统、代码生成器那就应该想办法让输出变得可控、可校验、可追溯。技术上的控制手段其实并不复杂System Prompt 约束风格采样参数约束随机性JSON Mode 约束结构后处理规则兜底回归用例集保证长期稳定。这五层设好之后LLM 在工程场景中的表现会稳定很多。下一步可以继续深入的方向是结构化输出与 function calling 的完整实战、LLM 应用的可观测性与评估体系设计、以及如何把上面的方案应用到 RAG 场景中。建议先拿自己项目里最让团队头疼的一个 LLM 输出场景按上面五个层次排查一遍很快就能看到改进效果。