news 2026/9/6 1:56:36

LLM工程化:提示工程、RAG、Agent与结构化输出实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
LLM工程化:提示工程、RAG、Agent与结构化输出实战

# LLM工程化:提示工程、RAG、Agent与结构化输出实战

## 1. 背景:从“聊天”到“生产级组件”的鸿沟

2024年以来,GPT-4o、Claude 3.5 Sonnet等模型在对话、代码生成上表现出众,但当开发人员试图将LLM集成到生产系统时,很快发现:**仅靠一条“Chat: ”指令远远不够**。

典型痛点包括:

- **幻觉**:模型回答脱离事实,尤其在缺少检索上下文时。

- **输出不可解析**:返回自由文本,下游无法用代码处理。

- **无工具调用能力**:模型无法查询数据库、执行API、发送邮件。

- **行为不可复制**:同样的输入在不同请求下结果不一致。

根源在于:生产级AI系统需要将LLM变成**可编程、可评估、可部署的软件组件**,而不仅仅是聊天机器人。这催生了现代Prompt Engineering的四个核心支柱:**系统提示(System Prompt)、RAG上下文注入、结构化输出(Structured Outputs)和Agent编排**。

截至2026年6月,主流框架(LangChain v0.3.14、OpenAI SDK v1.56、Pydantic v2.9)已将上述能力标准化。本文将以实际代码演示如何组合这些技术,构建生产就绪的LLM应用。

## 2. 技术架构:四层协同的AI工程模型

一个可靠的LLM应用通常包含以下层次:

| 层次 | 职责 | 关键组件 |

|------|------|----------|

| 系统提示层 | 定义模型角色、约束、行为红线 | 角色描述、禁止事项、输出规则 |

| 上下文层 | 注入外部知识减少幻觉 | RAG检索器、文档分块、重排序 |

| 结构与工具层 | 强制输出格式、暴露函数接口 | JSON Schema、Tool Definition |

| 编排层 | 多步推理、条件跳转、工具调用循环 | Agent循环、记忆、错误重试 |

### 2.1 系统提示:LLM的“宪法”

系统提示是每次请求都附加的指令块。它定义了模型“是什么”、“做什么”、“不能做什么”。好的系统提示应包含:

- **角色与任务**:例如“你是客户支持助手,基于文档回答”。

- **上下文注入位置**:通常用`{context}`占位符,由RAG填充。

- **输出约束**:如“如果信息不足,回答‘我不知道’”。

- **引用要求**:强制输出时附带来源文档名称。

### 2.2 RAG:让模型“知道”而非“猜对”

RAG(Retrieval-Augmented Generation)通过外部知识库注入事实。2026年,主流做法是:

1. 文档分块(chunk_size=512 tokens,overlap=20%)

2. 向量化(text-embedding-3-large,维度3072)

3. 检索(Top-K=5,使用Cohere重排序)

4. 注入到系统提示的`{retrieved_context}`位置

### 2.3 结构化输出:从“文本”到“数据”

OpenAI从2025年11月开始提供`structured_outputs=true`参数,直接返回符合JSON Schema的响应。这避免了传统“先用LLM生成文本再用正则解析”的脆弱方案。Claude 3.5同样支持`tools`模式定义输出结构。

### 2.4 Agent编排:多步推理与工具调用

Agent将LLM作为“大脑”,配合工具(如数据库查询、计算器、邮件API)执行复杂任务。典型的ReAct循环包括:思考→行动→观察→思考……直到完成。

## 3. 实践:从简单提示到生产级Agent

### 3.1 基础RAG系统提示模板

以下代码展示了使用OpenAI Python SDK v1.56构建一个带有RAG上下文的客服助手。注意系统提示中使用`{company_name}`和`{context}`占位符,并通过`messages`结构注入。

```python

import openai # v1.56.0

from typing import List

def build_rag_messages(

company_name: str,

retrieved_docs: List[str],

user_question: str

):

# 组装检索到的文档

context = "\n---\n".join(

[f"Source: {doc['source']}\n{doc['content']}"

for doc in retrieved_docs]

)

system_prompt = f"""You are a helpful support assistant for {company_name}.

Answer questions using only the documentation provided below.

If the documentation does not contain sufficient information to answer the question,

respond: "I don't have enough information from the available documentation to answer this question."

Always cite the source document name at the end of your answer.

[CONTEXT — Retrieved documentation]

{context}"""

return [

{"role": "system", "content": system_prompt},

{"role": "user", "content": user_question}

]

# 实际调用

response = openai.chat.completions.create(

model="gpt-4o", # 或 gpt-4o-2026-05

messages=build_rag_messages(

company_name="Acme Corp",

retrieved_docs=[{...}],

user_question="How to reset password?"

),

temperature=0.0,

max_tokens=512

)

```

### 3.2 结构化输出:从邮件中提取字段

生产场景中,常常需要从非结构化输入中提取结构化数据。以下代码利用Pydantic v2.9定义Schema,并通过OpenAI的`response_format`参数强制输出JSON。

```python

from pydantic import BaseModel, Field # v2.9.0

import openai

class EmailExtract(BaseModel):

sender_name: str = Field(description="Name of the person sending the email")

company: str = Field(description="Company name")

team_size: int = Field(description="Number of team members")

deadline: str = Field(description="Deadline date (format: YYYY-MM-DD)")

budget: str = Field(description="Budget amount and currency")

contact_email: str = Field(description="Contact email address")

# 使用结构化输出(OpenAI v1.56+)

def extract_email_info(email_text: str) -> EmailExtract:

response = openai.beta.chat.completions.parse(

model="gpt-4o",

messages=[

{"role": "system", "content": "Extract fields from the email and return as structured JSON."},

{"role": "user", "content": email_text}

],

response_format=EmailExtract, # OpenAI自动转换为JSON Schema

temperature=0.0

)

return response.choices[0].message.parsed # 直接返回Pydantic对象

# 测试

email = """

Hi, I'm Sarah from Acme Corp. We need a data analytics platform for our team of 12 by September 2026. Budget: ₹8 lakhs. Please contact sarah@acme.co

"""

result = extract_email_info(email)

print(result.model_dump_json(indent=2))

# 输出: {"sender_name":"Sarah","company":"Acme Corp","team_size":12,...}

```

**关键数据**:在LangSmith的基准测试中,使用`response_format`的结构化输出比传统`temperature=0 + 正则解析`模式,字段提取准确率从76%提升至99.4%,且解析耗时降低50%。

### 3.3 Agent编排:结合RAG与工具

真实场景往往需要将以上技术组合。例如一个“销售线索生成Agent”:收到邮件后,先调用结构化提取,再RAG查询公司背景,然后调用CRM API创建记录。以下是使用LangChain v0.3.14的简化实现。

```python

from langchain_openai import ChatOpenAI # v0.3.14

from langchain.agents import create_tool_calling_agent, AgentExecutor

from langchain.tools import tool

from langchain.memory import ConversationBufferMemory

@tool

def search_company_info(company_name: str) -> str:

"""搜索公司信息(模拟RAG)"""

return f"Contoso: AI startup, 50 employees, founded 2022"

@tool

def create_crm_lead(name: str, company: str, email: str) -> str:

"""在CRM中创建销售线索"""

# 实际调用CRM API

return f"Lead created: {name} from {company}"

llm = ChatOpenAI(model="gpt-4o", temperature=0.0)

agent = create_tool_calling_agent(

llm=llm,

tools=[search_company_info, create_crm_lead],

system_message="你是销售线索处理助手。首先从邮件中提取字段,然后搜索公司信息,最后创建CRM线索。按步骤执行。"

)

agent_executor = AgentExecutor(agent=agent, tools=[search_company_info, create_crm_lead], verbose=True)

# 运行

agent_executor.invoke({"input": email})

# 可见到多步推理与工具调用

```

## 4. 总结与展望

从2024到2026年,LLM应用开发已经从“写提示”进化到“编排系统”。核心三点:

- **结构化**:用Schema代替自然语言输出,使结果可编程。

- **可评估**:每个组件(RAG召回、工具调用、输出格式)均应有自动化评估。

- **可部署**:利用LangChain等框架将提示、RAG、Agent封装为模块,便于CI/CD。

未来趋势:**多模型协同**(如用小模型做路由、大模型做推理)和**自修复Agent**(Agent检错后自动重试)将进一步降低幻觉风险。对于工程师,掌握上述四层技术栈,是构建可靠LLM产品的必修课。

**参考**:本文示例代码兼容OpenAI API 2025-11以后版本、LangChain v0.3.14、Pydantic v2.9。建议在LangSmith平台上进行生产级评估与监控。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/6 1:55:44

普通BM和验证BM到底有什么区别?Facebook广告投放必看的资产避坑指南

做Facebook投放的朋友,应该都听过两个词:普通BM、验证BM。很多人对它们的理解特别简单——普通BM就是没验证的,验证BM就是验证过的。这话没错,但如果你真的在做Facebook投放,光知道这个还不够。因为不少人会进一步认为…

作者头像 李华
网站建设 2026/9/6 1:55:35

CEH v12认证备考全攻略:从资料筛选到靶场实战一次讲透

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/6 1:54:47

线吸附算法实现

本文提出的线线吸附算法的核心思路是:以参考线为基准,将待吸附线的线段投影到参考线上,并截取对应长度的一段作为结果。具体流程如下:数据预处理与坐标统一:将所有输入图层统一转换到EPSG:4498,该坐标系是上…

作者头像 李华
网站建设 2026/9/6 1:54:30

从语音交互到AI Agent:300美元AI设备背后的技术架构与应用边界

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/6 1:54:05

YOLOv8+PyQt5非机动车头盔检测系统设计:从模型训练到GUI部署全流程

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华