Sortie structurée LangChain

La plupart du temps, ce dont vous avez besoin n'est pas un texte libre, mais des données structurées—comme un objet JSON.

LangChain Structured Output permet à l'Agent de renvoyer des résultats dans le format que vous spécifiez, ce qui facilite leur utilisation directe par les programmes.


Pourquoi avez-vous besoin d'une sortie structurée ?

Supposons que vous deviez extraire un nom, un âge et une profession à partir d'une description utilisateur :

MéthodeFormat de sortieTraitement ultérieur
Réponse normaleZhang San a 28 ans et est ingénieur.Nécessite une regex ou un nouvel appel au modèle pour analyser
Sortie structurée{name: "Zhang San", age: 28, job: "Engineer"}Utilisé directement comme objet Python

La sortie structurée économise l'étape qui consiste à « analyser les données à partir du texte », ce qui permet d'utiliser directement la sortie de l'IA par les programmes.


L'utilisation la plus simple — Passer un modèle Pydantic

Il suffit de passer le modèle Pydantic au paramètre response_format :

Exemple

from dotenv import load_dotenv
load_dotenv()

from pydantic import BaseModel, Field
from langchain.agents import create_agent
from langchain.chat_models import init_chat_model
from langchain.messages import HumanMessage


# Définir la structure de sortie attendue
class CourseInfo(BaseModel):
    """Exemple de résultat d'extraction de cours de tutoriel"""
    course_name: str = Field(description=Nom du cours)
    difficulty: str = Field(description=Difficulté : Débutant/Intermédiaire/Avancé)
    estimated_hours: int = Field(description=Durée d'étude estimée (heures))
    is_free: bool = Field(description=Indique s'il est gratuit)


model = init_chat_model("deepseek:deepseek-v4-flash", temperature=0)
agent = create_agent(
    model=model,
    response_format=CourseInfo,  # Passer le modèle Pydantic
    system_prompt=Vous êtes l'assistant de cours chez Example Tutorial. Extrayez les informations sur les cours à partir des descriptions des utilisateurs.,
)

# L'utilisateur saisit une description non structurée
result = agent.invoke({
    "messages": [HumanMessage(
        content=J'ai récemment étudié le Python3 Basics Tutorial, il est de niveau débutant,
                Cela prend environ 20 heures d'étude, et c'est entièrement gratuit.
    )]
})

# Obtenir le résultat structuré à partir de structured_response
if "structured_response" in result:
    course = result["structured_response"]
    print(fNom du cours : {course.course_name})
    print(fDifficulté : {course.difficulty})
    print(fDurée estimée : {course.estimated_hours} heures)
    print(fGratuit : {'Yes' if course.is_free else 'No'})
    print(fType d'objet : {type(course)})

Résultat de l'exécution :

Course name: Python3 基础教程
Difficulty: 入门
Duration: 20 小时
Free: 是
Object type: <class '__main__.CourseInfo'>

Le structured_response retourné est une instance de modèle Pydantic, et non un simple dictionnaire. Cela signifie que vous pouvez accéder à des attributs tels que .course_name, et que l'IDE peut fournir l'autocomplétion.


Sortie structurée coexistant avec les outils

response_format et tools peuvent être utilisés ensemble—l'Agent appelle tools en cas de besoin et produit enfin des données structurées :

Exemple

from pydantic import BaseModel, Field
from langchain.agents import create_agent
from langchain.chat_models import init_chat_model
from langchain.messages import HumanMessage
from langchain.tools import tool


@tool
def search_course(keyword: str) -> str:
    """Rechercher des informations sur les cours sur Example Tutorial"""
    courses = {
        "python": Tutoriel des bases de Python3 | Débutant | Gratuit | 30 chapitres | Environ 20 heures,
        "java": Tutoriel des bases de Java | Débutant | Gratuit | 35 chapitres | Environ 25 heures,
        Analyse de données: Analyse de données avec Python | Intermédiaire | Membre | 25 chapitres | Environ 30 heures,
    }
    return courses.get(keyword.lower(), fAucun cours trouvé pour '{keyword}')


class CourseRecommendation(BaseModel):
    """Résultat de recommandation de cours"""
    course_name: str = Field(description=Nom du cours recommandé)
    reason: str = Field(description=Raison de la recommandation)
    difficulty: str = Field(description=Difficulté : Débutant/Intermédiaire/Avancé)


model = init_chat_model("deepseek:deepseek-v4-flash", temperature=0)
agent = create_agent(
    model=model,
    tools=[search_course],
    response_format=CourseRecommendation,
    system_prompt=Vous êtes le conseiller de cours chez Example Tutorial. Recherchez d'abord des cours, puis donnez des recommandations.,
)

result = agent.invoke({
    "messages": [HumanMessage(content=Je veux apprendre Python. Que recommandez-vous ?)]
})

rec = result["structured_response"]
print(fCours recommandé : {rec.course_name})
print(fRaison de la recommandation : {rec.reason})
print(fDifficulté : {rec.difficulty})

# Voir le processus complet
print("\n"=== Processus d'exécution ===")
for msg in result["messages"]:
    if msg.type == "tool":
        print(f" Appel {msg.name} : {msg.content}")

Résultat de l'exécution :

Recommended course: Python3 基础教程
Reason: 该课程免费且适合Python初学者,学习时长约20小时
Difficulty: 入门

=== 执行过程 ===
  调用 search_course: Python3 基础教程 | 入门 | 免费 | 30章 | 约20小时

Structures imbriquées complexes

Pydantic prend en charge des structures complexes telles que l'imbrication, les listes, les énumérations, etc. :

Exemple

from pydantic import BaseModel, Field
from typing import Literal
from langchain.agents import create_agent
from langchain.chat_models import init_chat_model
from langchain.messages import HumanMessage


class Topic(BaseModel):
    """Sujet"""
    name: str = Field(description=Nom du sujet)
    order: int = Field(description=Ordre d'apprentissage, à partir de 1)
    minutes: int = Field(description=Minutes d'étude recommandées)


class LearningPlan(BaseModel):
    """Plan d'étude"""
    goal: str = Field(description=Aperçu de l'objectif d'étude)
    level: Literal[Débutant, Intermédiaire, Avancé] = Field(description=Niveau de difficulté)
    total_hours: float = Field(description=Durée totale (heures))
    topics: Topic[Field] = description(Liste des sujets=Topic list)


model = init_chat_model("deepseek:deepseek-v4-flash", temperature=0)
agent = create_agent(
    model=model,
    response_format=LearningPlan,
    system_prompt=Vous êtes le planificateur d'étude chez Example Tutorial.,
)

result = agent.invoke({
    "messages": [HumanMessage(
        content=Aidez-moi à créer un plan d'étude Python pour débutant, en gardant le temps total dans les 10 heures
    )]
})

plan = result["structured_response"]
print(fObjectif : {plan.goal})
print(fDifficulté : {plan.level})
print(fDurée totale : {plan.total_hours} heures)
print(f"\n"Liste des sujets ({len(plan.topics)} éléments) :")
for topic in plan.topics:
    print(f" {topic.order}. {topic.name} ({topic.minutes} minutes)")

Résultat de l'exécution :

目标: 掌握 Python 基础语法,能够独立编写简单的 Python 程序
Difficulty: 入门
总时长: 9.5 小时

知识点列表 (6 个):
  1. 环境搭建与基础语法 (60分钟)
  2. 数据类型与变量 (90分钟)
  3. 条件判断与循环 (120分钟)
  4. 函数与模块 (120分钟)
  5. 列表与字典 (90分钟)
  6. 综合练习 (90分钟)

Obtenir une sortie structurée à partir des messages

Si vous n'avez pas besoin de la capacité d'appel d'outils de l'Agent et que vous souhaitez simplement extraire des informations structurées à partir de texte, vous pouvez utiliser le modèle directement :

Exemple

from pydantic import BaseModel, Field
from langchain.chat_models import init_chat_model


class SentimentResult(BaseModel):
    """Résultat de l'analyse de sentiment"""
    sentiment: str = Field(description=Positif/Négatif/Neutre)
    score: float = Field(description=Intensité du sentiment 0~1)
    keywords: list[str] = Field(description=Mots-clés de sentiment)


model = init_chat_model("deepseek:deepseek-v4-flash", temperature=0)

# Utiliser with_structured_output() directement sur le modèle
# Pas besoin d'un Agent
structured_model = model.with_structured_output(SentimentResult)

textes = [
    Le tutoriel d'exemple est vraiment très agréable à utiliser. Fortement recommandé !,
    Ce tutoriel a trop peu de contenu. Cela ne vaut pas le coup.,
    Le temps est agréable aujourd'hui.,
]

for text in texts:
    result = structured_model.invoke(text)
    print(fTexte : {text[:30]}...)
    print(f" Sentiment: {result.sentiment}, Intensité: {result.score}, Mots-clés: {result.keywords}")

Résultat de l'exécution :

Text: Example 真的太好用了,强烈推荐!...
  Sentiment: 积极, 强度: 0.95, 关键词: ['好用', '推荐']
Text: 这个教程内容太少了,不太值。...
  Sentiment: 消极, 强度: 0.7, 关键词: ['内容太少', '不太值']
Text: 今天天气不错。...
  Sentiment: 中性, 强度: 0.1, 关键词: ['不错']

with_structured_output() est une méthode du modèle et peut être utilisée sans Agent. Si votre scénario est « extraction d'informations » plutôt que « raisonnement en plusieurs étapes », utiliser with_structured_output() directement est plus simple et plus efficace.

Autres extensions