LangChain LangGraph
Module 1 Module 2 Module 3
Module 1 · Basic abilities
1 1.1a Foundation Model
2 1.1b Prompting
3 1.2a Tools
4 1.2b Web Search
5 1.3 Memory
6 1.4 Multimodal
7 1.5 Personal Chef
SUM Module Summary
HomeLangChainModule 1 · Basic abilities1.1b Prompting
📓 Notebook 📖 Explained
LANGCHAIN MODULE 1 · LESSON 1.1b

Tips on four major engineering skills
Basic · Few-shot · Structured · Structured output

Control model behavior with System Prompts, guide style with few-shot examples, and force models to output structured JSON with Pydantic—these are core skills for building reliable AI applications.

1Tip Engineering Overview: Four Progressive Techniques

Prompt Engineering is the most direct means to affect LLM output quality. This section introduces four progressive tips and techniques from the most basic to the most rigorous:

① Basic Prompting

passsystem_promptParameters define the Agent's role and behavioral guidelines. The simplest yet effective.

② Few-shot tips

Add 2-5 input/output examples to the system prompt to guide the model to imitate a specific style or format.

③ Structured prompts

Use a template in prompt to clearly define the output field names and formats to make the natural language output more regular.

④ Structured output

Use Pydantic to define the data model byresponse_formatForces LLM to output strict JSON, usable directly as a Python object.

Skill upgrade path

Reliability and parsability are improved in sequence: basic → few-shot → structured prompts → structured output. In a production environment, any scenario that requires a program to parse LLM output should be given priority.Structured output(Pydantic), it is the most reliable way.

2Basic Tip: Use system_prompt to define Agent roles

The simplest way to prompt: increate_agentwhen passed insystem_promptParameters, tell the model who it is and what it should do.

Default behavior without system_prompt

Without the system prompt, the model will give the "honest" answer - the moon has no capital:

agent = create_agent(model=deepseek_model())

question = HumanMessage(content="What's the capital of the moon?")
response = agent.invoke({"messages": [question]})
print(response['messages'][1].content)
Output (without system prompt)
The Moon does not have a capital city. It is a natural satellite with no permanent human settlements or political structures...

Add system_prompt: switch to science fiction writer role

system_prompt = "You are a science fiction writer, create a capital city at the users request."

scifi_agent = create_agent(
    model=deepseek_model(temperature=1),  # temperature=1 增加创意性
    system_prompt=system_prompt
)

response = scifi_agent.invoke({"messages": [question]})
print(response['messages'][1].content)
Output (with system prompt)
**Luna Prime** — the gleaming capital of the Moon, nestled in the Tycho Crater. Founded in 2157, it houses the Lunar Confederation's parliament beneath its great geodesic domes...
The role of the temperature parameter

temperature=1Make the model output more creative and diverse (the results of each run are different);temperature=0Make the output more certain and repeatable (the same result every time you run it). Use high temperature for creative tasks and low temperature for tasks that require consistency (such as code generation, data extraction).

3Few-shot tip: embed examples in System Prompt

Few-shot prompting is a powerful technique: give a few "input → output" examples directly in the system prompt, and LLM will imitate the style and format of these examples to generate new responses.

Add Few-shot example

system_prompt = """

You are a science fiction writer, create a space capital city at the users request.

User: What is the capital of mars?
Scifi Writer: Marsialis

User: What is the capital of Venus?
Scifi Writer: Venusovia

"""

scifi_agent = create_agent(
    model=deepseek_model(),
    system_prompt=system_prompt
)

question = HumanMessage(content="What is the capital of The Moon?")
response = scifi_agent.invoke({"messages": [question]})
print(response['messages'][1].content)
Output (few-shot style)
Scifi Writer: Lunaris

Note the change in output style: the model learned the format "Scifi Writer: [word]" in the example and gave a concise one-word answer instead of a long description.

The core principle of few-shot

LLM learned to "continue" text through training. The few-shot example is equivalent to showing the model a "conversation script", and the model will continue writing in the style of this script. The quality and consistency of the examples directly determine the few-shot effect - the examples must be representative and the format must be uniform.

4Structural tip: Use format templates to constrain output structure

Structured Prompting defines clearly field names and output formats in the system prompt, making the model's natural language output more regular and easier to parse.

Define output format template

system_prompt = """

You are a science fiction writer, create a space capital city at the users request.

Please keep to the below structure.

Name: The name of the capital city

Location: Where it is based

Vibe: 2-3 words to describe its vibe

Economy: Main industries

"""

scifi_agent = create_agent(
    model=deepseek_model(),
    system_prompt=system_prompt
)

response = scifi_agent.invoke({"messages": [question]})
print(response['messages'][1].content)
Output (structured prompts)
Name: Selenopolis
Location: Mare Tranquillitatis, near the historic Apollo 11 landing site
Vibe: Futuristic, serene, scientific
Economy: Helium-3 extraction, space tourism, lunar research stations
The difference between structured prompts vs structured output

The output of the structured prompt is stillnatural language string, field separation is just a convention, and the model may not strictly adhere to it (occasionally adding or removing fields, or changing the order). If you need to reliably parse each field with code, you must use the following sectionStructured output (Pydantic)

5Structured output: forcing output of JSON objects with Pydantic

Structured Output is the most reliable way: usePydanticDefine the data model byresponse_formatThe parameter tells LLM that the output must be according to this schema. LangChain will automatically parse the model's JSON output into Pydantic objects under the hood.

Define the Pydantic data model

from pydantic import BaseModel

class CapitalInfo(BaseModel):
    name:     str  # 城市名称
    location: str  # 地理位置
    vibe:     str  # 氛围描述
    economy:  str  # 经济支柱

Pass in the response_format parameter

agent = create_agent(
    model=deepseek_model(),
    system_prompt="You are a science fiction writer, create a capital city at the users request.",
    response_format=CapitalInfo   # 关键:传入 Pydantic 类
)

question = HumanMessage(content="What is the capital of The Moon?")
response = agent.invoke({"messages": [question]})

# structured_response 是 Pydantic 对象,不是字符串
print(response["structured_response"])
output(Pydantic object)
CapitalInfo(
  name='Lunar Prime',
  location='Mare Imbrium, near the lunar equator',
  vibe='futuristic, serene, industrious',
  economy='Helium-3 mining, space tourism, zero-gravity manufacturing'
)

underlying working mechanism

when you pass inresponse_format=CapitalInfoWhen, LangChain will:

  1. Convert the Pydantic model to JSON Schema and inject it into the tool definition
  2. LLM received instructions: it must call theCapitalInfoTools, parameters strictly conform to the schema
  3. The model outputs tool_call (instead of ordinary text), and the parameters are structured JSON
  4. LangChain parses JSON into Pydantic objects and storesresponse["structured_response"]
Why is structured output implemented using tool calls?

Modern LLM (GPT-4, DeepSeek, Claude) are supportedFunction Calling/Tool Use, which requires that the model output strictly conforms to the parameters of JSON Schema, and the reliability is much higher than "embedding JSON in ordinary text".response_formatParameters take advantage of this mechanism.

6Reading and using structured_response

Once you have the Pydantic object, you can read each field just like accessing the properties of a normal Python object:

capital_info = response["structured_response"]

# 访问具体字段
print(capital_info.name)      # → 'Lunar Prime'
print(capital_info.location)  # → 'Mare Imbrium, near the lunar equator'
print(capital_info.vibe)      # → 'futuristic, serene, industrious'
print(capital_info.economy)   # → 'Helium-3 mining...'

# 组合使用
print(f"{capital_info.name} is located at {capital_info.location}")
Execution output
Lunar Prime
Mare Imbrium, near the lunar equator
futuristic, serene, industrious
Helium-3 mining, space tourism, zero-gravity manufacturing

Lunar Prime is located at Mare Imbrium, near the lunar equator

messages internal structure (advanced debugging)

useresponse_formathour,messagesExcept in the listHumanMessageandAIMessage, there will be one moreToolMessage

for msg in response["messages"]:
    pprint(msg)
Message history (3 items)
1. HumanMessage: "What is the capital of The Moon?"
2. AIMessage: content='' tool_calls=[{'name': 'CapitalInfo', 'args': {...}}]
   # The content of the AI ​​message is empty, and tool calls are used to carry structured data.
3. ToolMessage: "Returning structured response: name='Lunar Prime'..."
   #Tool execution results are recorded in the message history
Note: AIMessage.content is empty

When using structured output,response['messages'][-1].contentis no longer what you want (it could be an empty string or a tool call message). should passresponse["structured_response"]to get the Pydantic object insteadmessages[-1].content

7Comparison and selection guide of four techniques

SkillOutput formatreliabilityApplicable scenarios
Basic tips Natural language (free form) Low Open dialogue, creative writing, simple Q&A
Few-shot Natural language (mimicking example format) middle A specific style/format is required, and there are samples for reference.
Structured prompts Natural language (with field conventions) middle A rough structure is required, allowing for occasional deviations
Structured output Pydantic object (strict JSON) high Requires program parsing output, data pipeline, and form filling
Selection decision tree
  • Need code parsing output? → Use structured output (Pydantic + response_format)
  • Need a specific style/short format? → Use Few-shot prompts (add example in prompt)
  • Need clear structure but flexible format? → Use structured prompts (define field templates in prompt)
  • Just define roles/behaviors? → Use basic prompts (system_prompt to define roles)