大语言模型(LLM)应用开发技术预研:LangChain框架实战与Prompt Engineering最佳实践

 
更多

大语言模型(LLM)应用开发技术预研:LangChain框架实战与Prompt Engineering最佳实践

随着大语言模型(Large Language Models, LLMs)的迅速发展,其在自然语言理解、内容生成、智能对话等领域的应用日益广泛。然而,直接调用原始LLM进行应用开发存在诸多挑战,如上下文管理困难、提示工程复杂、缺乏外部知识整合能力等。为此,LangChain 框架应运而生,成为当前构建LLM应用的核心技术栈之一。

本文将深入预研大语言模型应用开发的关键技术,涵盖 LangChain 框架的实战使用Prompt Engineering 的设计原则与最佳实践RAG(Retrieval-Augmented Generation)检索增强生成技术 以及 模型微调技巧,并通过实际开发案例展示如何构建高质量、可扩展的 LLM 应用。


一、大语言模型应用开发的技术挑战

尽管 LLM 在通用语言任务上表现出色,但在实际应用开发中仍面临以下主要挑战:

  1. 上下文长度限制:大多数 LLM 的上下文窗口有限(如 GPT-3.5 为 16k tokens),难以处理长文档或复杂对话历史。
  2. 知识静态性:预训练模型的知识截止于训练数据时间,无法获取实时或私有知识。
  3. 提示工程复杂性:输出质量高度依赖输入提示(Prompt)的设计,需反复调试。
  4. 缺乏外部工具集成能力:原生模型无法直接调用数据库、API 或执行代码。
  5. 可维护性与可扩展性差:缺乏模块化设计,难以构建复杂工作流。

为应对这些挑战,LangChain 提供了一套完整的开发框架,支持链式调用、记忆管理、工具集成、检索增强等功能,极大提升了 LLM 应用的开发效率和质量。


二、LangChain 框架核心概念与架构

LangChain 是一个用于构建基于 LLM 的应用的开源框架,支持 Python 和 JavaScript,其核心设计理念是“将 LLM 作为核心推理引擎,与其他组件协同工作”。

2.1 核心组件

LangChain 的架构由以下几个核心组件构成:

组件 功能说明
Models 支持多种 LLM(如 OpenAI、Anthropic、HuggingFace)和嵌入模型
Prompts 管理提示模板、变量插值、示例选择等
Chains 将多个步骤组合成链式流程(如 LLM + 工具调用)
Memory 管理对话历史,支持短期/长期记忆机制
Indexes 构建向量索引,支持文档检索
Retrievers 从索引中检索相关文档
Agents 基于推理决定调用哪些工具完成任务
Callbacks 监控和记录链执行过程(用于调试、日志、性能分析)

2.2 安装与环境配置

pip install langchain langchain-openai langchain-community langchain-core

设置 OpenAI API 密钥:

import os
os.environ["OPENAI_API_KEY"] = "your-api-key"

三、Prompt Engineering:设计高质量提示的最佳实践

Prompt Engineering 是 LLM 应用开发的核心技能,直接影响输出的准确性、相关性和可控性。

3.1 Prompt 设计基本原则

  1. 明确任务目标:清晰定义任务类型(分类、生成、翻译等)。
  2. 提供上下文信息:补充必要的背景知识。
  3. 结构化输入格式:使用 JSON、Markdown 或 XML 等结构化格式。
  4. 使用示例(Few-shot Learning):通过输入-输出对引导模型行为。
  5. 限制输出格式:指定返回格式(如 JSON、列表、布尔值等)。
  6. 避免歧义与模糊表述:使用精确语言。

3.2 LangChain 中的 PromptTemplate

LangChain 提供 PromptTemplate 类来管理提示模板:

from langchain_core.prompts import PromptTemplate

template = """
你是一个客服助手,请根据以下订单信息回答客户问题。
订单号:{order_id}
商品名称:{product_name}
发货状态:{status}

客户问题:{question}

请用礼貌且简洁的方式回答。
"""

prompt = PromptTemplate.from_template(template)

# 使用
formatted_prompt = prompt.format(
    order_id="12345",
    product_name="无线耳机",
    status="已发货",
    question="我的订单什么时候能收到?"
)
print(formatted_prompt)

3.3 高级提示技巧

1. Few-shot Prompting

from langchain_core.prompts import FewShotPromptTemplate, PromptTemplate

examples = [
    {"input": "2+2", "output": "4"},
    {"input": "中国的首都是哪里?", "output": "北京"},
]

example_prompt = PromptTemplate.from_template("输入: {input}\n输出: {output}\n")

few_shot_prompt = FewShotPromptTemplate(
    examples=examples,
    example_prompt=example_prompt,
    prefix="请根据以下示例回答问题:",
    suffix="输入: {query}\n输出: ",
    input_variables=["query"],
)

print(few_shot_prompt.format(query="法国的首都是?"))

2. System Message + User Message 分离

在支持 Chat 模型的场景中,使用 ChatPromptTemplate 区分系统角色和用户输入:

from langchain_core.prompts import ChatPromptTemplate

prompt = ChatPromptTemplate.from_messages([
    ("system", "你是专业的金融分析师,用简洁语言回答问题。"),
    ("human", "{question}")
])

chain = prompt | llm
response = chain.invoke({"question": "什么是通货膨胀?"})

四、LangChain Chains:构建复杂逻辑流程

Chains 是 LangChain 的核心执行单元,允许将多个组件串联成工作流。

4.1 基础链:LLMChain

from langchain_openai import ChatOpenAI
from langchain.chains import LLMChain

llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0.7)
chain = LLMChain(llm=llm, prompt=prompt)

result = chain.run({
    "order_id": "12345",
    "product_name": "智能手表",
    "status": "处理中",
    "question": "什么时候发货?"
})

4.2 顺序链(SequentialChain)

用于多步骤任务,如“摘要 → 翻译 → 情感分析”:

from langchain.chains import SimpleSequentialChain, LLMChain

# 步骤1:生成摘要
summary_prompt = PromptTemplate.from_template("请为以下文本生成摘要:{text}")
summary_chain = LLMChain(llm=llm, prompt=summary_prompt, output_key="summary")

# 步骤2:翻译成英文
translate_prompt = PromptTemplate.from_template("将以下中文翻译成英文:{summary}")
translate_chain = LLMChain(llm=llm, prompt=translate_prompt, output_key="translation")

# 组合链
overall_chain = SimpleSequentialChain(
    chains=[summary_chain, translate_chain],
    verbose=True
)

result = overall_chain.run("LangChain 是一个强大的 LLM 开发框架,支持多种功能。")
print(result)

五、RAG:检索增强生成(Retrieval-Augmented Generation)

RAG 技术通过将外部知识库与 LLM 结合,解决模型知识陈旧和幻觉问题。

5.1 RAG 基本流程

  1. 用户提问
  2. 向量化问题并检索相关文档
  3. 将检索结果作为上下文拼接到 Prompt
  4. 调用 LLM 生成答案

5.2 实战:构建基于本地文档的问答系统

步骤1:加载文档并分割

from langchain_community.document_loaders import TextLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter

loader = TextLoader("data/knowledge.txt")
docs = loader.load()

text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=500,
    chunk_overlap=50
)
split_docs = text_splitter.split_documents(docs)

步骤2:生成向量嵌入并构建索引

from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores import FAISS

embeddings = OpenAIEmbeddings()
vectorstore = FAISS.from_documents(split_docs, embeddings)

# 保存索引
vectorstore.save_local("faiss_index")

步骤3:创建检索器

retriever = vectorstore.as_retriever(search_kwargs={"k": 3})

步骤4:构建 RAG 链

from langchain_core.runnables import RunnablePassthrough
from langchain_core.output_parsers import StrOutputParser

# 定义 Prompt
rag_prompt = PromptTemplate.from_template("""
根据以下上下文回答问题:
{context}

问题:{question}
""")

# 构建链
rag_chain = (
    {"context": retriever, "question": RunnablePassthrough()}
    | rag_prompt
    | llm
    | StrOutputParser()
)

# 调用
response = rag_chain.invoke("LangChain 支持哪些功能?")
print(response)

5.3 RAG 最佳实践

  • 文档预处理:清洗噪声、去重、结构化。
  • 分块策略:根据内容语义合理分块(如按段落、章节)。
  • 嵌入模型选择:优先使用高质量嵌入模型(如 text-embedding-3-large)。
  • 重排序(Re-ranking):对检索结果使用 Cross-Encoder 进行相关性重排序。
  • 上下文压缩:使用 LLM 自身压缩无关信息,减少 token 消耗。

六、LangChain Agents:让模型自主决策

Agents 允许 LLM 根据输入决定调用哪些工具,实现“思考-行动”循环。

6.1 定义工具

from langchain.tools import tool
import requests

@tool
def get_weather(city: str) -> str:
    """获取指定城市的天气信息"""
    url = f"https://api.openweathermap.org/data/2.5/weather?q={city}&appid=your_key"
    response = requests.get(url).json()
    return f"温度: {response['main']['temp']}K, 天气: {response['weather'][0]['description']}"

@tool
def search_wikipedia(query: str) -> str:
    """在 Wikipedia 中搜索内容"""
    # 实际调用 Wikipedia API
    return f"Wikipedia 搜索结果关于 '{query}'..."

6.2 创建 Agent

from langchain import hub
from langchain.agents import create_openai_functions_agent, AgentExecutor
from langchain_openai import ChatOpenAI

tools = [get_weather, search_wikipedia]
llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)

# 使用预定义 prompt
prompt = hub.pull("hwchase17/openai-functions-agent")

agent = create_openai_functions_agent(llm, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)

# 执行
result = agent_executor.invoke({
    "input": "北京现在的天气如何?顺便查一下气候变化的定义。"
})
print(result["output"])

6.3 Agent 最佳实践

  • 工具描述清晰:确保工具的 docstring 准确描述功能和参数。
  • 限制调用次数:防止无限循环,设置 max_iterations
  • 错误处理:捕获工具执行异常并反馈给模型。
  • 审计与日志:记录每一步决策过程,便于调试。

七、模型微调(Fine-tuning)与领域适配

虽然 Prompt Engineering 和 RAG 能解决大部分问题,但对于特定领域(如法律、医疗),微调模型可显著提升性能。

7.1 微调适用场景

  • 领域术语理解(如医学术语)
  • 特定输出格式(如结构化 JSON)
  • 风格一致性(如企业客服话术)

7.2 OpenAI 微调流程(以 GPT-3.5 为例)

  1. 准备训练数据(JSONL 格式):
{"messages": [{"role": "user", "content": "什么是机器学习?"}, {"role": "assistant", "content": "机器学习是..."}]}
{"messages": [{"role": "user", "content": "解释过拟合"}, {"role": "assistant", "content": "过拟合是指..."}]}
  1. 上传文件并启动微调:
openai api fine_tunes.create -t train.jsonl -m gpt-3.5-turbo
  1. 使用微调模型:
llm = ChatOpenAI(model="ft:gpt-3.5-turbo:your-org:custom-model:abc123")

7.3 微调 vs RAG 对比

维度 微调 RAG
知识更新 需重新训练 实时更新文档即可
成本 高(训练+推理) 低(仅推理)
延迟 略高(需检索)
可解释性 好(可追溯来源)
适用场景 风格/格式定制 知识密集型任务

建议:优先使用 RAG,仅在风格一致性或格式要求极高时考虑微调。


八、实际案例:构建企业级智能客服系统

8.1 需求分析

  • 支持订单查询、退换货政策、产品咨询
  • 集成内部知识库(PDF、FAQ)
  • 支持多轮对话记忆
  • 能调用订单系统 API
  • 输出格式统一(JSON)

8.2 系统架构设计

用户输入
   ↓
[Agent Router]
   ├──→ [RAG Chain] → 知识库问答
   ├──→ [Order API Tool] → 订单查询
   └──→ [Policy Classifier] → 退换货判断
   ↓
格式化输出(JSON)

8.3 核心代码实现

from langchain.agents import AgentExecutor, create_openai_functions_agent
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder

# 系统 Prompt
system_prompt = """
你是一个企业客服助手,根据用户问题选择合适的工具或知识库回答。
必须以 JSON 格式返回:{"answer": "...", "source": "knowledge/api"}
"""

prompt = ChatPromptTemplate.from_messages([
    ("system", system_prompt),
    MessagesPlaceholder(variable_name="chat_history"),
    ("human", "{input}"),
    MessagesPlaceholder(variable_name="agent_scratchpad")
])

# 工具列表
tools = [get_order_status, search_knowledge_base]

# 创建 Agent
agent = create_openai_functions_agent(llm, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)

# 添加记忆
from langchain_core.messages import HumanMessage, AIMessage
from langchain_community.chat_message_histories import ChatMessageHistory

history = ChatMessageHistory()
history.add_user_message("我的订单12345状态?")
history.add_ai_message("正在查询...")

# 调用
response = agent_executor.invoke({
    "input": "这个产品支持7天无理由退货吗?",
    "chat_history": history.messages
})

8.4 部署建议

  • 使用 FastAPI 封装为 REST API
  • 添加缓存层(Redis)缓存常见问答
  • 使用 LangSmith 进行链路监控与调试
  • 设置限流与鉴权机制

九、性能优化与成本控制

9.1 Token 优化策略

  • 使用 token_counter 监控输入输出长度
  • 启用流式输出(stream=True)提升用户体验
  • 对长上下文使用 map-reducerefine 摘要链

9.2 缓存机制

from langchain.globals import set_llm_cache
from langchain_community.cache import InMemoryCache

set_llm_cache(InMemoryCache())

9.3 成本监控

  • 使用 LangChain 的 CallbackHandler 记录 token 使用
  • 定期分析高频 Prompt 并优化
  • 对非关键任务使用较小模型(如 gpt-3.5-turbo)

十、总结与展望

本文系统性地介绍了基于 LangChain 框架的大语言模型应用开发技术体系,涵盖 Prompt EngineeringRAGAgents模型微调 等核心技术,并通过实际案例展示了如何构建企业级 LLM 应用。

核心要点回顾:

  1. LangChain 提供了模块化、可扩展的 LLM 应用开发框架,极大提升了开发效率。
  2. Prompt Engineering 是基础技能,需结合 Few-shot、结构化输入等技巧。
  3. RAG 是解决知识局限性的首选方案,适用于大多数知识密集型场景。
  4. Agents 适用于需要动态决策的任务,但需谨慎控制调用复杂度。
  5. 微调适用于风格/格式定制,但成本高,应优先考虑 RAG。

未来趋势

  • 多模态 Agent:结合图像、语音等输入形式
  • 自动化 Prompt 优化:使用 LLM 自身优化提示
  • 轻量化本地模型 + LangChain:在边缘设备部署
  • AI 编程助手深度集成:自动生成和调试 LangChain 链

LangChain 正在成为 LLM 应用开发的“操作系统”,掌握其核心技术栈,将为构建下一代智能应用奠定坚实基础。


标签:大语言模型, LangChain, Prompt Engineering, RAG, AI应用开发

打赏

本文固定链接: https://www.cxy163.net/archives/10622 | 绝缘体

该日志由 绝缘体.. 于 2016年05月12日 发表在 未分类 分类下, 你可以发表评论,并在保留原文地址及作者的情况下引用到你的网站或博客。
原创文章转载请注明: 大语言模型(LLM)应用开发技术预研:LangChain框架实战与Prompt Engineering最佳实践 | 绝缘体
关键字: , , , ,

大语言模型(LLM)应用开发技术预研:LangChain框架实战与Prompt Engineering最佳实践:等您坐沙发呢!

发表评论


快捷键:Ctrl+Enter