LangChain學習——結構化輸出和數據解析

LangChain

本指南全面介紹LangChain中結構化輸出生成和數據解析的核心功能,包括Pydantic BaseModel構造、各種輸出解析器的使用,以及高級錯誤處理機制。

詳細測試樣例和代碼可參考如下兩個鏈接:

  • test_output_parsers
  • test_pydantic_base_model

結構化輸出概述

概念定義

結構化輸出是指將大語言模型(LLM)的自然語言輸出轉換為具有明確數據類型和格式的結構化數據。這種轉換使得AI應用能夠可靠地處理和使用LLM的輸出結果。

核心優勢

  • 🎯 類型安全:確保數據符合預定義的結構和類型約束
  • 🔄 一致性:保證輸出格式的穩定性和可預測性
  • ? 可靠性:通過驗證和錯誤處理提高系統魯棒性
  • 🔧 易集成:直接獲得可在應用中使用的數據對象

技術實現方式

LangChain提供兩種主要的結構化輸出實現方式:

  1. 結構化輸出模式(Structured Output):基于約束解碼技術,確保100%格式正確
  2. 函數調用模式(Function Calling):基于工具調用機制,支持更復雜的數據結構

相關鏈接

  • 結構化輸出概念
  • 輸出解析器概念

Pydantic BaseModel 集成

概念定義

Pydantic BaseModel是Python中最強大的數據驗證和序列化庫,LangChain深度集成了Pydantic來定義和驗證結構化輸出的數據模型。

with_structured_output 方法

輸入:Pydantic模型類或JSON Schema
輸出:符合指定結構的數據對象
原理:將LLM輸出約束到預定義的數據結構中

from pydantic import BaseModel, Field
from langchain_openai import ChatOpenAIclass UserProfile(BaseModel):"""用戶檔案數據模型"""name: str = Field(description="用戶姓名")age: int = Field(description="用戶年齡", ge=0, le=150)email: str = Field(description="郵箱地址")skills: List[str] = Field(description="技能列表")# 創建結構化輸出模型
model = ChatOpenAI(model="gpt-4o-mini")
structured_llm = model.with_structured_output(UserProfile)# 使用結構化輸出
result = structured_llm.invoke("提取用戶信息:張三,25歲,郵箱zhang@example.com,擅長Python和數據分析")
# result 是 UserProfile 類型的對象
print(f"姓名: {result.name}, 年齡: {result.age}")

復雜數據結構支持

嵌套模型:支持模型之間的嵌套關系

class Address(BaseModel):"""地址信息"""street: str = Field(description="街道地址")city: str = Field(description="城市")country: str = Field(description="國家")class Company(BaseModel):"""公司信息"""name: str = Field(description="公司名稱")address: Address = Field(description="公司地址")employees: List[UserProfile] = Field(description="員工列表")# 處理復雜嵌套結構
company_llm = model.with_structured_output(Company)

枚舉類型支持

from enum import Enumclass TaskStatus(str, Enum):"""任務狀態枚舉"""PENDING = "pending"IN_PROGRESS = "in_progress"COMPLETED = "completed"CANCELLED = "cancelled"class Task(BaseModel):"""任務信息"""title: str = Field(description="任務標題")status: TaskStatus = Field(description="任務狀態")priority: int = Field(description="優先級", ge=1, le=5)task_llm = model.with_structured_output(Task)

Function Calling vs Structured Output

技術選擇指南

特性Structured OutputFunction Calling
動態字段支持? 不支持 Dict[str, Any]? 完全支持
復雜嵌套受限無限制
格式可靠性100%正確高度可靠
首次延遲有預處理開銷無額外開銷
# 包含動態字段的模型需要使用 function_calling
class FlexibleResponse(BaseModel):core_data: str = Field(description="核心數據")metadata: Dict[str, Any] = Field(description="動態元數據")# 必須指定 method="function_calling"
flexible_llm = model.with_structured_output(FlexibleResponse,method="function_calling"
)

相關鏈接

  • 如何返回結構化數據
  • Pydantic模型驗證

輸出解析器系統

概念定義

**輸出解析器(Output Parsers)**是LangChain中負責將LLM的文本輸出轉換為特定數據類型的組件。它們提供了比結構化輸出更靈活的數據處理能力。

基礎解析器類型

StrOutputParser

功能:提取AI消息中的純文本內容
輸入:AIMessage對象
輸出:字符串
適用場景:簡單的文本提取和處理

from langchain_core.output_parsers import StrOutputParser# 文本提取鏈
text_chain = model | StrOutputParser()
result = text_chain.invoke("介紹一下人工智能")
# result 是純字符串
JsonOutputParser

功能:解析JSON格式的模型輸出
輸入:包含JSON的文本
輸出:Python字典或列表
適用場景:結構化數據提取

from langchain_core.output_parsers import JsonOutputParserjson_parser = JsonOutputParser()# 創建JSON解析鏈
json_chain = model | json_parser
result = json_chain.invoke("用JSON格式返回用戶信息:姓名張三,年齡25")
# result 是 Python 字典
XMLOutputParser

功能:解析XML格式的結構化數據
輸入:XML格式文本
輸出:解析后的數據結構
適用場景:處理層次化數據

from langchain_core.output_parsers import XMLOutputParserxml_parser = XMLOutputParser()
xml_chain = model | xml_parser
YAMLOutputParser

功能:解析YAML格式的配置數據
輸入:YAML格式文本
輸出:Python數據結構
適用場景:配置文件處理

from langchain_core.output_parsers import YamlOutputParseryaml_parser = YamlOutputParser()
yaml_chain = model | yaml_parser

PydanticOutputParser

功能:將文本輸出解析為Pydantic模型實例
輸入:符合模型格式的文本
輸出:Pydantic模型對象
原理:結合格式指令和數據驗證

from langchain_core.output_parsers import PydanticOutputParser# 創建解析器
parser = PydanticOutputParser(pydantic_object=UserProfile)# 獲取格式指令
format_instructions = parser.get_format_instructions()# 構建提示模板
from langchain_core.prompts import ChatPromptTemplateprompt = ChatPromptTemplate.from_template("提取用戶信息:{query}\n{format_instructions}"
).partial(format_instructions=format_instructions)# 創建完整鏈
chain = prompt | model | parser
result = chain.invoke({"query": "張三,工程師,28歲"})
# result 是 UserProfile 對象

流式解析支持

概念:支持實時處理模型的流式輸出
優勢:提供更好的用戶體驗和響應性

# 流式JSON解析
from langchain_core.output_parsers import SimpleJsonOutputParserstreaming_parser = SimpleJsonOutputParser()# 流式處理
for chunk in (model | streaming_parser).stream("生成用戶數據"):print(chunk, end="", flush=True)

相關鏈接

  • 如何解析字符串輸出
  • 如何解析JSON輸出
  • 如何解析XML輸出
  • 如何解析YAML輸出

智能錯誤處理

概念定義

智能錯誤處理是LangChain提供的高級功能,能夠自動檢測、修復和重試解析錯誤,大幅提升系統的魯棒性和可靠性。

OutputFixingParser

功能:自動修復格式錯誤的LLM輸出
輸入:可能包含格式錯誤的文本
輸出:修復后的正確數據結構
原理:使用另一個LLM理解并修復格式問題

from langchain_core.output_parsers import OutputFixingParser# 基礎解析器
base_parser = JsonOutputParser()# 包裝為自動修復解析器
fixing_parser = OutputFixingParser.from_llm(parser=base_parser,llm=ChatOpenAI(temperature=0.1)  # 使用低溫度提高修復準確性
)# 自動處理格式錯誤
broken_json = '{"name": "張三", "age": 25'  # 缺少閉合括號
fixed_result = fixing_parser.parse(broken_json)  # 自動修復成功

應用場景

  • JSON格式錯誤(缺少括號、多余逗號)
  • XML標簽不匹配
  • YAML縮進問題
  • Pydantic字段類型錯誤

RetryWithErrorOutputParser

功能:解析失敗時的智能重試機制
輸入:原始提示和錯誤信息
輸出:重新生成的正確格式數據
原理:將錯誤反饋給LLM,指導重新生成

from langchain_core.output_parsers import RetryWithErrorOutputParser# 創建重試解析器
retry_parser = RetryWithErrorOutputParser.from_llm(parser=PydanticOutputParser(pydantic_object=UserProfile),llm=ChatOpenAI(temperature=0.1),max_retries=3  # 最多重試3次
)# 自動處理解析失敗并重試
chain = prompt | model | retry_parser
result = chain.invoke({"query": "用戶信息提取"})

重試流程

  1. 初始解析嘗試失敗
  2. 將錯誤信息反饋給LLM
  3. LLM重新生成符合格式的輸出
  4. 重復直到成功或達到最大重試次數

組合錯誤處理策略

組合使用:將多種錯誤處理機制結合,實現最高可靠性

# 構建三層錯誤處理
base_parser = PydanticOutputParser(pydantic_object=ComplexModel)# 第一層:格式修復
fixing_parser = OutputFixingParser.from_llm(parser=base_parser,llm=ChatOpenAI(temperature=0.1)
)# 第二層:重試機制
ultimate_parser = RetryWithErrorOutputParser.from_llm(parser=fixing_parser,llm=ChatOpenAI(temperature=0.1),max_retries=2
)ultimate_chain = prompt | model | ultimate_parser

相關鏈接

  • 如何處理解析重試
  • 如何修復解析錯誤

高級應用模式

自定義解析器開發

概念:基于BaseOutputParser創建專用的解析邏輯
原理:繼承基類并實現parse和get_format_instructions方法

from langchain_core.output_parsers import BaseOutputParser
from typing import Listclass ListOutputParser(BaseOutputParser[List[str]]):"""列表解析器 - 分隔符解析"""def __init__(self, separator: str = ","):self.separator = separatordef parse(self, text: str) -> List[str]:"""解析分隔符分隔的列表"""return [item.strip() for item in text.split(self.separator)]def get_format_instructions(self) -> str:"""返回格式指令"""return f"請用{self.separator}分隔列表項目"# 使用自定義解析器
list_parser = ListOutputParser(separator="|")
list_chain = model | list_parser

條件解析器

功能:根據內容特征自動選擇解析策略

class ConditionalOutputParser(BaseOutputParser):"""條件解析器 - 智能格式識別"""def parse(self, text: str) -> Union[str, Dict, List]:"""根據內容特征選擇解析策略"""text = text.strip()if text.startswith('{') and text.endswith('}'):# JSON對象格式return json.loads(text)elif text.startswith('[') and text.endswith(']'):# JSON數組格式  return json.loads(text)elif ',' in text:# 逗號分隔的列表return [item.strip() for item in text.split(',')]else:# 純文本return textdef get_format_instructions(self) -> str:return "可以返回JSON、列表或純文本格式"

鏈式解析器

概念:組合多個解析器,實現復雜的數據處理流程

class ChainedOutputParser(BaseOutputParser[Dict[str, Any]]):"""鏈式解析器 - 多策略組合"""def __init__(self, parsers: List[Tuple[str, BaseOutputParser]]):self.parsers = parsersdef parse(self, text: str) -> Dict[str, Any]:"""依次應用多個解析器"""results = {"original": text}for name, parser in self.parsers:try:results[name] = parser.parse(text)except Exception as e:results[f"{name}_error"] = str(e)return results# 創建鏈式解析器
chained_parser = ChainedOutputParser([("json", JsonOutputParser()),("list", ListOutputParser()),("yaml", YamlOutputParser())
])

驗證解析器

功能:在解析后進行額外的數據驗證和清理

class ValidatingOutputParser(BaseOutputParser[Dict]):"""驗證解析器 - 數據質量保證"""def __init__(self, base_parser: BaseOutputParser, validators: List[callable]):self.base_parser = base_parserself.validators = validatorsdef parse(self, text: str) -> Dict:"""解析并驗證數據"""result = self.base_parser.parse(text)# 應用驗證規則for validator in self.validators:result = validator(result)return resultdef validate_user_age(data: Dict) -> Dict:"""驗證用戶年齡合理性"""if 'age' in data and not (0 <= data['age'] <= 150):data['age'] = max(0, min(data['age'], 150))return data# 使用驗證解析器
validating_parser = ValidatingOutputParser(base_parser=JsonOutputParser(),validators=[validate_user_age]
)

相關鏈接

  • 如何創建自定義解析器

最佳實踐指南

選擇合適的方法

決策流程圖

需要結構化輸出?
├─ 是 → 數據結構復雜(包含動態字段)?
│   ├─ 是 → 使用 with_structured_output(method="function_calling")
│   └─ 否 → 使用 with_structured_output() (默認模式)
└─ 否 → 需要格式轉換?├─ 是 → 使用合適的OutputParser (Json/XML/YAML)└─ 否 → 使用 StrOutputParser

錯誤處理最佳實踐

分層錯誤處理

  1. 預防:使用清晰的格式指令
  2. 檢測:實現數據驗證邏輯
  3. 修復:使用OutputFixingParser
  4. 重試:使用RetryWithErrorOutputParser
  5. 降級:提供備用解析策略
def robust_structured_output(query: str, model_class: BaseModel, fallback_parser=None):"""魯棒的結構化輸出處理"""try:# 主要方法:結構化輸出structured_llm = model.with_structured_output(model_class)return structured_llm.invoke(query)except Exception as e:if fallback_parser:# 降級方法:使用解析器return fallback_parser.parse(model.invoke(query).content)else:raise e

監控和調試

性能監控

import time
from typing import Anydef monitored_parse(parser: BaseOutputParser, text: str) -> Dict[str, Any]:"""監控解析性能"""start_time = time.time()try:result = parser.parse(text)success = Trueerror = Noneexcept Exception as e:result = Nonesuccess = Falseerror = str(e)end_time = time.time()return {"result": result,"success": success,"error": error,"parse_time": end_time - start_time,"input_length": len(text)}

提示工程優化

格式指令優化

def enhance_format_instructions(base_instructions: str, examples: List[str] = None) -> str:"""增強格式指令"""enhanced = base_instructionsif examples:enhanced += "\n\n示例格式:\n"for i, example in enumerate(examples, 1):enhanced += f"{i}. {example}\n"enhanced += "\n注意:嚴格按照上述格式返回,確保數據完整性。"return enhanced

類型安全增強

泛型解析器

from typing import TypeVar, GenericT = TypeVar('T')class TypedOutputParser(BaseOutputParser[T], Generic[T]):"""類型安全的解析器基類"""def __init__(self, target_type: Type[T]):self.target_type = target_typedef parse(self, text: str) -> T:# 實現類型安全的解析邏輯pass

相關資源鏈接

LangChain 官方文檔

  • 輸出解析器概述
  • 如何解析結構化輸出
  • 如何返回結構化數據
  • 如何創建自定義解析器
  • 如何處理解析重試
  • 如何修復解析錯誤

數據驗證和模型

  • Pydantic 官方文檔
  • Python Type Hints 指南

高級功能

  • 異步編程概念
  • 流式輸出指南
  • 批處理操作

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/93181.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/93181.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/93181.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

基于華為ENSP的BGP的狀態機深入淺出

本篇技術博文摘要 &#x1f31f; 本文章主要探討BGP狀態機如何控制BGP連接的建立與維護&#xff0c;以及BGP協議在運行過程中如何交換路由信息并確保網絡的穩定性 引言 &#x1f4d8; 在這個快速發展的技術時代&#xff0c;與時俱進是每個IT人的必修課。我是腎透側視攻城獅&…

Android 15中的16KB大頁有何優勢?

deepseek回答&#xff1a; Android 15引入的16KB大內存頁是系統性能優化的關鍵變革&#xff0c;其核心優勢體現在以下方面&#xff1a; ? 一、性能全面提升 系統整體加速 配置16KB頁面的設備整體性能提升5%-10%&#xff0c;通過減少內存管理開銷釋放更多資源用于應用運行。…

Gis數據的A*算法規劃航線

1.1 用到的技術棧geotools JTSJgrapht1.2 實現思路// 定義柵格網格參數private static final double CELL_SIZE_DEGREES 0.005;private static int gridWidth 0;//格子高度 index 1private static int gridHeight 0;//格子寬度// 1. 讀取GeoJSON文件File geoJsonFile new …

Spring Boot 默認使用 CGLIB,但CGLIB 無法代理 final 類或 final 方法

那么當這兩件事沖突時&#xff0c;Spring Boot 是怎么“解決”的呢&#xff1f;答案是&#xff1a;它不解決&#xff0c;也無法解決。當這種情況發生時&#xff0c;你的應用程序會直接啟動失敗。這不是 Spring Boot 的疏忽&#xff0c;而是由 CGLIB 的底層原理和 Java 語言的規…

cuda編程筆記(10)--memory access 優化

全局內存訪問優化&#xff08;Coalesced Access&#xff09; 什么是 Coalesced Access&#xff1f; 定義&#xff1a;一個 warp&#xff08;32 個線程&#xff09;在同一指令中訪問全局內存時&#xff0c;如果這些訪問請求可以合并成盡可能少的內存事務&#xff08;通常是 32…

閑庭信步使用圖像驗證平臺加速FPGA的開發:第三十一課——車牌識別的FPGA實現(3)車牌字符分割預處理

&#xff08;本系列只需要modelsim即可完成數字圖像的處理&#xff0c;每個工程都搭建了全自動化的仿真環境&#xff0c;只需要雙擊top_tb.bat文件就可以完成整個的仿真&#xff0c;大大降低了初學者的門檻&#xff01;&#xff01;&#xff01;&#xff01;如需要該系列的工程…

電子電氣架構 --- 汽車軟件全生命周期

我是穿拖鞋的漢子,魔都中堅持長期主義的汽車電子工程師。 老規矩,分享一段喜歡的文字,避免自己成為高知識低文化的工程師: 簡單,單純,喜歡獨處,獨來獨往,不易合同頻過著接地氣的生活,除了生存溫飽問題之外,沒有什么過多的欲望,表面看起來很高冷,內心熱情,如果你身…

力扣面試150(41/150)

7.25 56. 合并區間 以數組 intervals 表示若干個區間的集合&#xff0c;其中單個區間為 intervals[i] [starti, endi] 。請你合并所有重疊的區間&#xff0c;并返回 一個不重疊的區間數組&#xff0c;該數組需恰好覆蓋輸入中的所有區間 。 我的思路&#xff1a; 左端點升序…

【隧道篇 / IPsec】(7.6) ? 01. 利用向導快速建立IPsec安全隧道 (點對點) ? FortiGate 防火墻

【簡介】相信很多人已經習慣利用導向快速創建VPN了&#xff0c;而且已經有部分嘗鮮者已經用上了FortiOS 7.6&#xff0c;但是會發現FortiOS 7.6下的VPN向導改變了很多&#xff0c;一時無法下手&#xff0c;下面我們來看看最常見的點對點是如何配置的。環境介紹在配置IPsec VPN之…

PLLIP核

。1 號紅色框內的速度等級代表著設備的速度 等級&#xff0c;保存默認就好&#xff1b;2 號紅色框內設置輸入頻率&#xff1b;3 號紅色框選擇 PLL 的工作模式。我們 開發板用的晶振是 50MHz 的&#xff0c;故在 2 號紅色框內我們填寫 50MHz&#xff1b;我們在 3 號紅色框內選正…

1.1 Deep learning?pytorch ?深度學習訓練出來的模型通常有效但無法解釋合理性? 如何 解釋?

DL 是什么&#xff0c;你如何理解DL模型&#xff1f; DL 對于我而言&#xff0c;就是人類試圖想通過數學語言描述人類學習過程的一門技術&#xff0c;或者說學科。 因此 DL 模型 相當于 數學 的 一個 funciton &#xff0c;有輸入&#xff0c;通過function處理&#xff0c;得…

java實現在工具類中注入其他對象方式

方案1&#xff1a; Slf4j Component public class ChatdocApiClient {Value("${chatdoc.app-id}")private String appId;Value("${chatdoc.secret}")private String secret;Value("${chatdoc.domain}")private String domain;private final Rest…

electron中IPC 渲染進程與主進程通信方法解析

electron中ipcRenderer.invoke、ipcRenderer.on、ipcRenderer.send、ipcRenderer.sendSync作用與區別 IPC 渲染進程與主進程通信方法解析 ipcRenderer 的這幾個方法作用不完全相同&#xff0c;它們適用于不同的通信場景&#xff0c;核心區別在于通信方向、是否需要響應以及同步…

epoll_event 事件類型詳解

epoll_event 事件類型詳解 epoll_event 是 Linux epoll I/O 多路復用機制的核心結構體&#xff0c;其中的事件類型決定了 epoll 監控的行為和觸發條件。以下是各種事件類型的詳細解析&#xff1a; epoll_event 結構體 #include <sys/epoll.h>typedef union epoll_data {v…

設計自己的小傳輸協議 導論與概念

設計自己的小傳輸協議 導論與概念 1&#xff1a;聊一聊協議頭設計 ? 早在《TCP/IP詳解》中的第一句話中&#xff0c;我們就知道協議的含義是這樣的&#xff1a;協議是通信雙方共同遵守的一套規則&#xff0c;提供格式定義、語義解釋等&#xff0c;使不同設備或軟件能夠正確交…

iOS —— 天氣預報仿寫總結

在iOS中&#xff0c;最常見的網絡請求方式是NSURLSession&#xff0c;它是蘋果推薦的現代API&#xff0c;簡單安全且易于拓展。一次完整的網絡請求流程&#xff1a;構造 NSURL 對象創建 NSURLSessionDataTask發起請求&#xff08;resume&#xff09;在回調中解析數據回到主線程…

MySQL 8.4 Windows 版安裝記錄與步驟參考

導語&#xff1a; MySQL 作為廣泛使用的開源數據庫管理系統&#xff0c;是許多開發者和學習者的必備工具。最近有朋友詢問安裝過程&#xff0c;正好整理了 MySQL 8.4 在 Windows 系統下的安裝步驟和一些注意事項&#xff0c;分享給有需要的朋友做個參考。關于 MySQL&#xff1a…

七、搭建springCloudAlibaba2021.1版本分布式微服務-skywalking9.0鏈路追蹤

前言鏈路追蹤介紹 對于一個大型的幾十個&#xff0c;幾百個微服務構成的微服務架構系統&#xff0c;通常會遇到下面的一系列問題。 如何串聯整個調用鏈路&#xff0c;快速定位問題&#xff1f;如何澄清各個微服務之間的依賴關系&#xff1f;如何進行各個微服務接口的性能分析&a…

深入理解大語言模型生成參數:temperature、top\_k、top\_p 等全解析

在使用大語言模型&#xff08;如 GPT-4、LLaMA、ChatGLM 等&#xff09;進行文本生成任務時&#xff0c;很多開發者會面對各種“生成參數”&#xff0c;如 temperature、top_k、top_p、repetition_penalty 等。這些參數雖然看起來抽象&#xff0c;但掌握它們的意義和配置技巧&a…

vulhub Web Machine(N7)靶場攻略

下載地址&#xff1a; https://download.vulnhub.com/webmachine/Web-Machine-N7.ova 使用方法&#xff1a; 靶場下載好以后不用解壓&#xff0c;需要使用Oracle VirtualBox虛擬機打開&#xff0c;用VMware會報錯。安裝Oracle VirtualBox虛擬機時安裝地址不能隨便選擇&#…