<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Artificial Intelligence | Ziyang Lin</title><link>https://ziyanglin.netlify.app/en/categories/artificial-intelligence/</link><atom:link href="https://ziyanglin.netlify.app/en/categories/artificial-intelligence/index.xml" rel="self" type="application/rss+xml"/><description>Artificial Intelligence</description><generator>Source Themes Academic (https://sourcethemes.com/academic/)</generator><language>en-us</language><lastBuildDate>Mon, 30 Jun 2025 11:00:00 +0000</lastBuildDate><image><url>https://ziyanglin.netlify.app/img/icon-192.png</url><title>Artificial Intelligence</title><link>https://ziyanglin.netlify.app/en/categories/artificial-intelligence/</link></image><item><title>LLM Agent Multi-Turn Dialogue: Architecture Design and Implementation Strategies</title><link>https://ziyanglin.netlify.app/en/post/llm-agent-multi-turn-dialogue/</link><pubDate>Mon, 30 Jun 2025 11:00:00 +0000</pubDate><guid>https://ziyanglin.netlify.app/en/post/llm-agent-multi-turn-dialogue/</guid><description>&lt;h2 id="1-introduction-why-multiturn-dialogue-is-the-core-lifeline-of-agents">1. Introduction: Why Multi-Turn Dialogue is the Core Lifeline of Agents&lt;/h2>
&lt;p>In the wave of human-machine interaction, Large Language Model (LLM) driven Agents are evolving from simple &amp;ldquo;question-answer&amp;rdquo; tools into &amp;ldquo;intelligent assistants&amp;rdquo; capable of executing complex tasks with reasoning and planning abilities. The core of this evolution lies in &lt;strong>Multi-turn Dialogue&lt;/strong> capabilities.&lt;/p>
&lt;p>Single-turn dialogue resembles a one-time query, while multi-turn dialogue is a continuous, memory-driven, goal-oriented exchange. Users may not provide all information at once, requiring Agents to understand evolving needs, clarify ambiguous instructions, call external tools, and ultimately achieve the user's goals through continuous interaction.&lt;/p>
&lt;p>This document will thoroughly analyze the core challenges faced by LLM Agents in implementing efficient and reliable multi-turn dialogues, and provide a detailed explanation of current mainstream technical architectures and implementation details.&lt;/p>
&lt;h2 id="2-core-challenges-thorny-issues-in-multiturn-dialogues">2. Core Challenges: &amp;ldquo;Thorny Issues&amp;rdquo; in Multi-Turn Dialogues&lt;/h2>
&lt;p>To build a powerful multi-turn dialogue Agent, we must address several fundamental challenges:&lt;/p>
&lt;h3 id="21-context-window-limitation">2.1 Context Window Limitation&lt;/h3>
&lt;p>This is the most fundamental physical constraint. LLMs can only process a limited length of text (tokens). As conversation turns increase, the complete dialogue history quickly exceeds the model's context window.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Macro Issue&lt;/strong>: Leads to &amp;ldquo;memory loss,&amp;rdquo; where the Agent cannot recall early critical information, causing dialogue coherence to break.&lt;/li>
&lt;li>&lt;strong>Underlying Details&lt;/strong>: Directly truncating early dialogue history is the simplest but crudest method, potentially losing important premises. For example, preferences set by the user at the beginning of a conversation (&amp;ldquo;I prefer window seats&amp;rdquo;) might be forgotten during subsequent booking steps.&lt;/li>
&lt;/ul>
&lt;h3 id="22-state-maintenance-complexity">2.2 State Maintenance Complexity&lt;/h3>
&lt;p>Agents need to precisely track the dialogue state, such as: What stage is the current task at? What information has the user provided? What information is still needed?&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Macro Issue&lt;/strong>: If the state is confused, the Agent appears &amp;ldquo;muddled,&amp;rdquo; repeatedly asking for known information or getting &amp;ldquo;lost&amp;rdquo; in the task flow.&lt;/li>
&lt;li>&lt;strong>Underlying Details&lt;/strong>: State is more than just dialogue history. It's a structured data collection that may include user intent, extracted entities (like dates, locations), API call results, current task nodes, etc. Designing a robust, scalable state management mechanism is a significant engineering challenge.&lt;/li>
&lt;/ul>
&lt;h3 id="23-intent-drifting--goal-forgetting">2.3 Intent Drifting &amp;amp; Goal Forgetting&lt;/h3>
&lt;p>In long conversations, user intent may change, or a large goal may be broken down into multiple subtasks.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Macro Issue&lt;/strong>: Agents need to understand and adapt to these dynamic changes rather than rigidly adhering to the initial goal. If a user checks the weather and then says, &amp;ldquo;Book me a flight there,&amp;rdquo; the Agent must recognize this as a new, related intent.&lt;/li>
&lt;li>&lt;strong>Underlying Details&lt;/strong>: This requires the Agent to have strong intent recognition and reasoning capabilities to determine whether the current user input is continuing, modifying, or starting a completely new task.&lt;/li>
&lt;/ul>
&lt;h3 id="24-error-handling--selfcorrection">2.4 Error Handling &amp;amp; Self-Correction&lt;/h3>
&lt;p>When tool calls fail (e.g., API timeout), information extraction errors occur, or understanding deviates, the Agent cannot simply crash or give up.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Macro Issue&lt;/strong>: A reliable Agent should be able to identify failures and proactively initiate correction processes, such as retrying, clarifying with the user, or finding alternatives.&lt;/li>
&lt;li>&lt;strong>Underlying Details&lt;/strong>: This requires designing fault tolerance and retry mechanisms at the architectural level. The Agent needs to &amp;ldquo;understand&amp;rdquo; error messages returned by tools and generate new &amp;ldquo;thoughts&amp;rdquo; based on these to plan the next corrective action.&lt;/li>
&lt;/ul>
&lt;h2 id="3-technical-architecture-evolution-and-analysis">3. Technical Architecture Evolution and Analysis&lt;/h2>
&lt;p>To address the above challenges, the industry has explored various solutions, from simple history compression to complex Agentic architectures.&lt;/p>
&lt;h3 id="31-early-attempts-dialogue-history-compression">3.1 Early Attempts: Dialogue History Compression&lt;/h3>
&lt;p>This is the most direct approach to solving context window limitations.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Summary Memory&lt;/strong>: After each round of dialogue, or when the history length approaches a threshold, another LLM call summarizes the existing conversation.
&lt;ul>
&lt;li>&lt;strong>Advantage&lt;/strong>: Effectively reduces length.&lt;/li>
&lt;li>&lt;strong>Disadvantage&lt;/strong>: The summarization process may lose details and adds additional LLM call costs and latency.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h3 id="32-react-architecture-giving-agents-the-ability-to-think">3.2 ReAct Architecture: Giving Agents the Ability to &amp;ldquo;Think&amp;rdquo;&lt;/h3>
&lt;p>ReAct (Reason + Act) is the cornerstone of today's mainstream Agent architectures. Through an elegant &amp;ldquo;think-act-observe&amp;rdquo; cycle, it transforms an LLM from a mere text generator into an entity with reasoning and execution capabilities.&lt;/p>
&lt;ul>
&lt;li>
&lt;p>&lt;strong>Macro Concept&lt;/strong>: Mimics the human problem-solving pattern—first analyze (Reason), then take action (Act), and finally observe results (Observation) and adjust approach.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Underlying Implementation&lt;/strong>: Through carefully designed prompts, guides the LLM to generate text with specific markers.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Thought&lt;/strong>: The LLM performs an &amp;ldquo;inner monologue&amp;rdquo; at this step, analyzing the current situation and planning the next action. This content is invisible to users.&lt;/li>
&lt;li>&lt;strong>Action&lt;/strong>: The LLM decides which tool to call and what parameters to pass. For example, &lt;code>search(&amp;quot;Beijing weather today&amp;quot;)&lt;/code>.&lt;/li>
&lt;li>&lt;strong>Observation&lt;/strong>: Feeds back the results of tool execution (such as API returned data, database query results) to the LLM.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;p>This cycle repeats until the Agent considers the task complete.&lt;/p>
&lt;h4 id="react-work-cycle">ReAct Work Cycle&lt;/h4>
&lt;pre>&lt;code class="language-mermaid">graph TD
A[&amp;quot;User Input&amp;quot;] --&amp;gt; B{&amp;quot;LLM Generates Thought and Action&amp;quot;};
B -- Thought --&amp;gt; C[&amp;quot;Inner Monologue: What should I do?&amp;quot;];
C --&amp;gt; D{&amp;quot;Action: Call Tool&amp;quot;};
D -- &amp;quot;Tool Input&amp;quot; --&amp;gt; E[&amp;quot;External Tool (API, DB)&amp;quot;];
E -- &amp;quot;Tool Output&amp;quot; --&amp;gt; F[&amp;quot;Observation: Get Result&amp;quot;];
F --&amp;gt; G{&amp;quot;LLM Generates New Thought Based on Observation&amp;quot;};
G -- &amp;quot;Thought&amp;quot; --&amp;gt; H[&amp;quot;Inner Monologue: ...&amp;quot;];
H --&amp;gt; I{&amp;quot;Is Task Complete?&amp;quot;};
I -- &amp;quot;No&amp;quot; --&amp;gt; D;
I -- &amp;quot;Yes&amp;quot; --&amp;gt; J[&amp;quot;Final Answer&amp;quot;];
J --&amp;gt; K[&amp;quot;Respond to User&amp;quot;];
&lt;/code>&lt;/pre>
&lt;h3 id="33-finite-state-machine-fsm-building-tracks-for-dialogue-flow">3.3 Finite State Machine (FSM): Building &amp;ldquo;Tracks&amp;rdquo; for Dialogue Flow&lt;/h3>
&lt;p>For tasks with clear goals and relatively fixed processes (such as food ordering, customer service), Finite State Machines (FSM) are an extremely powerful and reliable architecture.&lt;/p>
&lt;ul>
&lt;li>
&lt;p>&lt;strong>Macro Concept&lt;/strong>: Abstract complex dialogue processes into a series of discrete &amp;ldquo;states&amp;rdquo; and &amp;ldquo;transition conditions&amp;rdquo; between these states. The Agent is in a clear state at any moment and can only transition to the next state through predefined paths.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Underlying Implementation&lt;/strong>:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>States&lt;/strong>: Define possible nodes in the dialogue, such as &lt;code>AskLocation&lt;/code>, &lt;code>AskCuisine&lt;/code>, &lt;code>ConfirmOrder&lt;/code>, &lt;code>OrderPlaced&lt;/code>.&lt;/li>
&lt;li>&lt;strong>Transitions&lt;/strong>: Define rules for state switching, typically triggered by user input or tool output. For example, in the &lt;code>AskLocation&lt;/code> state, if location information is successfully extracted from user input, transition to the &lt;code>AskCuisine&lt;/code> state.&lt;/li>
&lt;li>&lt;strong>State Handler&lt;/strong>: Each state is associated with a handler function responsible for executing specific logic in that state (such as asking the user questions, calling APIs).&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h4 id="a-simple-food-ordering-agent">A Simple Food Ordering Agent&lt;/h4>
&lt;pre>&lt;code class="language-mermaid">stateDiagram-v2
[*] --&amp;gt; Awaiting_Order
Awaiting_Order: User initiates food order
Awaiting_Order --&amp;gt; Collect_Cuisine: Identify ordering intent
Collect_Cuisine: &amp;quot;What cuisine would you like?&amp;quot;
Collect_Cuisine --&amp;gt; Collect_Headcount: User provides cuisine
Collect_Headcount: &amp;quot;How many people dining?&amp;quot;
Collect_Headcount --&amp;gt; Confirmation: User provides headcount
state Confirmation {
direction LR
[*] --&amp;gt; Show_Summary
Show_Summary: &amp;quot;Booking [headcount] for [cuisine], confirm?&amp;quot;
Show_Summary --&amp;gt; Finalize: User confirms
Finalize --&amp;gt; [*]
}
Confirmation --&amp;gt; Collect_Cuisine: User modifies
&lt;/code>&lt;/pre>
&lt;h4 id="modern-evolution-of-fsm-dynamic-and-hierarchical">Modern Evolution of FSM: Dynamic and Hierarchical&lt;/h4>
&lt;p>Traditional FSMs rely on hardcoded rules for state transitions, which can be rigid when facing complex, changing real-world scenarios. Modern Agent design deeply integrates FSM with LLM capabilities, giving rise to more intelligent and flexible architectures.&lt;/p>
&lt;ul>
&lt;li>
&lt;p>&lt;strong>LLM-Driven State Transitions&lt;/strong>: Rather than using fixed &lt;code>if-else&lt;/code> rules to determine state changes, let the LLM make decisions. In each cycle, pass the dialogue history, current user input, and a list of all possible target states to the LLM, allowing it to determine the most appropriate next state based on its powerful context understanding. This upgrades state transitions from &amp;ldquo;rule-driven&amp;rdquo; to &amp;ldquo;intelligence-driven.&amp;rdquo;&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>State-Specific Prompts&lt;/strong>: This is a powerful application of dynamic prompting. For each core state node in the FSM, a highly optimized set of dedicated prompts can be pre-designed. When the Agent enters a certain state (such as &lt;code>Collect_Cuisine&lt;/code>), the system immediately activates the prompt corresponding to that state. This prompt not only guides the LLM on how to interact with users at that node but can also define tools that can be called in that state, rules to follow, etc. This allows the Agent to &amp;ldquo;wear different hats&amp;rdquo; at different task stages, exhibiting high professionalism and task relevance.&lt;/p>
&lt;/li>
&lt;/ul>
&lt;h5 id="example-statespecific-prompt-for-queryflights-state-in-flight-booking-subprocess">Example: State-Specific Prompt for &lt;code>Query_Flights&lt;/code> State in Flight Booking Sub-Process&lt;/h5>
&lt;pre>&lt;code># IDENTITY
You are a world-class flight booking assistant AI.
# STATE &amp;amp; GOAL
You are currently in the &amp;quot;Query_Flights&amp;quot; state.
Your SOLE GOAL is to collect the necessary information to search for flights.
The necessary information is: origin city, destination city, and departure date.
# AVAILABLE TOOLS
- `flight_search_api(origin: str, destination: str, date: str)`: Use this tool to search for flights.
# CONTEXT
- Conversation History:
{conversation_history}
- User Profile:
{user_profile}
- Current State Data:
{state_data} # e.g., {&amp;quot;origin&amp;quot;: &amp;quot;Shanghai&amp;quot;, &amp;quot;destination&amp;quot;: &amp;quot;Beijing&amp;quot;, &amp;quot;date&amp;quot;: null}
# RULES
1. Analyze the Current State Data first.
2. If any necessary information (origin, destination, date) is missing, you MUST ask the user for it clearly.
3. Phrase your questions to sound helpful and natural.
4. Once all information is collected, your FINAL ACTION MUST be to call the `flight_search_api` tool with the correct parameters.
5. Do not make up information. Do not ask for information that is not required (e.g., return date, unless specified by the user).
# OUTPUT FORMAT
Your output must be a single JSON object.
- To ask a question: {&amp;quot;action&amp;quot;: &amp;quot;ask_user&amp;quot;, &amp;quot;question&amp;quot;: &amp;quot;Your question here.&amp;quot;}
- To call a tool: {&amp;quot;action&amp;quot;: &amp;quot;call_tool&amp;quot;, &amp;quot;tool_name&amp;quot;: &amp;quot;flight_search_api&amp;quot;, &amp;quot;tool_params&amp;quot;: {&amp;quot;origin&amp;quot;: &amp;quot;...&amp;quot;, &amp;quot;destination&amp;quot;: &amp;quot;...&amp;quot;, &amp;quot;date&amp;quot;: &amp;quot;...&amp;quot;}}
&lt;/code>&lt;/pre>
&lt;ul>
&lt;li>&lt;strong>Hierarchical FSM&lt;/strong>: For large complex tasks, a single flat state diagram is difficult to manage. Hierarchical FSMs introduce the concept of &amp;ldquo;SOP nesting&amp;rdquo; or &amp;ldquo;sub-state diagrams.&amp;rdquo; A high-level FSM (main SOP) is responsible for planning the macro business process (such as &amp;ldquo;complete a travel booking&amp;rdquo;), and when the process reaches a certain macro state (such as &amp;ldquo;book flight&amp;rdquo;), it can activate an embedded, more detailed sub-FSM (sub-SOP) that specifically handles a series of refined operations like &amp;ldquo;query flights -&amp;gt; select seats -&amp;gt; confirm payment.&amp;rdquo; This pattern greatly enhances the modularity and manageability of task decomposition.&lt;/li>
&lt;/ul>
&lt;h5 id="hierarchical-state-machine-sop-nesting-example">Hierarchical State Machine (SOP Nesting) Example&lt;/h5>
&lt;pre>&lt;code class="language-mermaid">stateDiagram-v2
direction LR
[*] --&amp;gt; MainSOP
state &amp;quot;Main Process: Travel Planning (Main SOP)&amp;quot; as MainSOP {
[*] --&amp;gt; Collect_Trip_Info
note right of Collect_Trip_Info
User: &amp;quot;Help me plan a trip to Beijing&amp;quot;
end note
Collect_Trip_Info --&amp;gt; Book_Flight_Sub_SOP : &amp;quot;OK, let's book flights first&amp;quot;
state &amp;quot;Sub-Process: Flight Booking&amp;quot; as Book_Flight_Sub_SOP {
direction LR
[*] --&amp;gt; Query_Flights: &amp;quot;When do you want to depart?&amp;quot;
Query_Flights --&amp;gt; Select_Seat: &amp;quot;Found flights, please select seat&amp;quot;
Select_Seat --&amp;gt; Confirm_Payment: &amp;quot;Seat selected, please pay&amp;quot;
Confirm_Payment --&amp;gt; [*]: Payment successful
}
Book_Flight_Sub_SOP --&amp;gt; Book_Hotel: &amp;quot;Flight booked, now for hotel&amp;quot;
Book_Hotel --&amp;gt; Finalize_Trip: &amp;quot;Hotel booked, final confirmation&amp;quot;
Finalize_Trip --&amp;gt; [*]
}
&lt;/code>&lt;/pre>
&lt;p>&lt;strong>FSM vs. ReAct&lt;/strong>: FSM is structured, predictable, and easy to debug, making it very suitable for task-oriented dialogues. ReAct is more flexible and versatile, suitable for handling open-ended tasks requiring complex reasoning and dynamic planning. In practice, the two are often combined (for example, using ReAct to handle an open-ended subtask within an FSM state, or as mentioned above, using an LLM to drive FSM state transitions).&lt;/p>
&lt;h2 id="4-core-components-agents-memory-system">4. Core Components: Agent's &amp;ldquo;Memory&amp;rdquo; System&lt;/h2>
&lt;p>Regardless of the architecture used, a powerful memory system is the cornerstone of effective multi-turn dialogue.&lt;/p>
&lt;h3 id="41-shortterm-memory">4.1 Short-term Memory&lt;/h3>
&lt;p>Also known as working memory, primarily responsible for storing recent dialogue history.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Typical Implementation&lt;/strong>: &lt;code>ConversationBufferMemory&lt;/code> or &lt;code>ConversationBufferWindowMemory&lt;/code>.&lt;/li>
&lt;li>&lt;strong>Underlying Details&lt;/strong>:
&lt;ul>
&lt;li>&lt;code>ConversationBufferMemory&lt;/code>: Stores complete dialogue history. Simple and direct, but quickly exhausts the context window in long conversations.&lt;/li>
&lt;li>&lt;code>ConversationBufferWindowMemory&lt;/code>: Only keeps the most recent &lt;code>k&lt;/code> turns of dialogue. This sliding window mechanism effectively controls length but risks losing important early information.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h3 id="42-longterm-memory">4.2 Long-term Memory&lt;/h3>
&lt;p>Responsible for storing cross-dialogue, persistent knowledge and information.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Typical Implementation&lt;/strong>: Retrieval-Augmented Generation (RAG) based on &lt;strong>vector databases&lt;/strong>.&lt;/li>
&lt;li>&lt;strong>Underlying Details&lt;/strong>:
&lt;ol>
&lt;li>Chunk external documents (such as product manuals, knowledge base articles) or key information from past conversations.&lt;/li>
&lt;li>Use an Embedding model to convert text blocks into vectors.&lt;/li>
&lt;li>Store vectors in a vector database (such as Chroma, Pinecone, FAISS).&lt;/li>
&lt;li>When a user asks a question, convert their question into a vector as well.&lt;/li>
&lt;li>Perform similarity search in the vector database to find the most relevant text blocks.&lt;/li>
&lt;li>Inject these text blocks as context along with the user's question into the LLM's prompt, guiding it to generate more precise answers.&lt;/li>
&lt;/ol>
&lt;/li>
&lt;/ul>
&lt;h3 id="43-structured-memory">4.3 Structured Memory&lt;/h3>
&lt;p>Stores and retrieves information in a structured way, especially key entities and their relationships from conversations.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Typical Implementation&lt;/strong>: Entity-relationship storage based on knowledge graphs, such as the &lt;code>Graphiti&lt;/code> project using Neo4j.&lt;/li>
&lt;li>&lt;strong>Underlying Details&lt;/strong>:
&lt;ul>
&lt;li>
&lt;p>&lt;strong>Knowledge Graph Advantages&lt;/strong>: Unlike simple key-value storage, knowledge graphs can capture complex relationship networks between entities. For example, not just recording a person named &amp;ldquo;John,&amp;rdquo; but also recording &amp;ldquo;John is Mary's manager,&amp;rdquo; &amp;ldquo;John is responsible for Project A,&amp;rdquo; and other relationship information.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Graphiti Project Analysis&lt;/strong>: &lt;a href="https://github.com/getzep/graphiti">Graphiti&lt;/a> is a knowledge graph memory system designed specifically for LLM Agents, seamlessly integrating Neo4j's graph database capabilities with LLM's natural language processing abilities.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Core Workflow&lt;/strong>:
&lt;ol>
&lt;li>&lt;strong>Entity and Relationship Extraction&lt;/strong>: LLM analyzes conversation content, identifying key entities and their relationships&lt;/li>
&lt;li>&lt;strong>Graph Construction&lt;/strong>: Transforms identified entities and relationships into Cypher query statements, dynamically updating the Neo4j graph database&lt;/li>
&lt;li>&lt;strong>Context Enhancement&lt;/strong>: In subsequent conversations, retrieves relevant entity networks through graph queries, injecting them as context into the LLM's prompt&lt;/li>
&lt;/ol>
&lt;/li>
&lt;li>&lt;strong>Technical Highlights&lt;/strong>:
&lt;ul>
&lt;li>&lt;strong>Automatic Schema Inference&lt;/strong>: No need to predefine entity types and relationships; the system can automatically infer appropriate graph structures from conversations&lt;/li>
&lt;li>&lt;strong>Incremental Updates&lt;/strong>: As conversations progress, the graph is continuously enriched and corrected, forming an increasingly complete knowledge network&lt;/li>
&lt;li>&lt;strong>Relationship Reasoning&lt;/strong>: Supports multi-hop queries, able to discover indirectly associated information (e.g., &amp;ldquo;Who are the colleagues of John's manager?&amp;quot;)&lt;/li>
&lt;li>&lt;strong>Temporal Awareness&lt;/strong>: Graphiti/Zep's core feature is its Temporal Knowledge Graph architecture, where each node and relationship carries timestamp attributes, enabling the system to:
&lt;ul>
&lt;li>Track how entity states change over time (e.g., &amp;ldquo;John was a developer last year, promoted to project manager this year&amp;rdquo;)&lt;/li>
&lt;li>Perform temporal reasoning (e.g., &amp;ldquo;What was B's status before event A occurred?&amp;quot;)&lt;/li>
&lt;li>Resolve time-related queries (e.g., &amp;ldquo;How is the project mentioned last month progressing now?&amp;quot;)&lt;/li>
&lt;li>Automatically identify and handle outdated information, ensuring answers are based on the latest factual state&lt;/li>
&lt;li>Build event timelines, helping the Agent understand causal relationships and event sequences&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Practical Application Example&lt;/strong>:&lt;/p>
&lt;pre>&lt;code class="language-python">from graphiti import GraphMemory
# Initialize graph memory
graph_memory = GraphMemory(
neo4j_uri=&amp;quot;neo4j://localhost:7687&amp;quot;,
neo4j_user=&amp;quot;neo4j&amp;quot;,
neo4j_password=&amp;quot;password&amp;quot;
)
# Update graph in conversation
user_message = &amp;quot;My project manager John said we're starting a new project next week&amp;quot;
graph_memory.update_from_text(user_message)
# Retrieve relevant information in subsequent conversations
query = &amp;quot;Who is the project manager?&amp;quot;
context = graph_memory.retrieve_relevant_context(query)
# Returns: &amp;quot;John is the project manager, responsible for a new project starting next week.&amp;quot;
&lt;/code>&lt;/pre>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Comparison with Traditional Entity Memory&lt;/strong>: Traditional methods can only store flat entity-attribute pairs, while knowledge graph methods can express and query complex multi-level relationship networks, providing Agents with richer, more insightful contextual information.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Essentially a Form of Long-term Memory&lt;/strong>: Although we discuss structured memory as a separate category, knowledge graph systems like Graphiti/Zep are essentially an advanced form of long-term memory. They not only persistently store information across conversations but also organize this information in a more structured, queryable, and reasoning-friendly way. Compared to semantic similarity retrieval in vector databases, knowledge graphs provide more precise relationship navigation and reasoning capabilities.&lt;/p>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h4 id="graphitizep-temporal-knowledge-graph-architecture-and-workflow">Graphiti/Zep Temporal Knowledge Graph Architecture and Workflow&lt;/h4>
&lt;pre>&lt;code class="language-mermaid">graph TD
subgraph &amp;quot;User Conversation History&amp;quot;
A1[&amp;quot;Conversation 1: 'I'm John, a software engineer'&amp;quot;] --&amp;gt; A2[&amp;quot;Conversation 2: 'I'm responsible for Project A'&amp;quot;]
A2 --&amp;gt; A3[&amp;quot;Conversation 3: 'I was a developer last year, promoted to project manager this year'&amp;quot;]
A3 --&amp;gt; A4[&amp;quot;Conversation 4: 'Mary is a member of my team'&amp;quot;]
end
subgraph &amp;quot;Entity and Relationship Extraction&amp;quot;
B[&amp;quot;LLM Analyzer&amp;quot;] --&amp;gt; C[&amp;quot;Entity Recognition: John, Project A, Mary&amp;quot;]
B --&amp;gt; D[&amp;quot;Relationship Extraction: John-responsible for-Project A, John-manages-Mary&amp;quot;]
B --&amp;gt; E[&amp;quot;Temporal Attributes: John.role(2024)=project manager, John.role(2023)=developer&amp;quot;]
end
subgraph &amp;quot;Temporal Knowledge Graph&amp;quot;
F[&amp;quot;John (Person)&amp;quot;] -- &amp;quot;role(2023)&amp;quot; --&amp;gt; G[&amp;quot;Developer&amp;quot;]
F -- &amp;quot;role(2024)&amp;quot; --&amp;gt; H[&amp;quot;Project Manager&amp;quot;]
F -- &amp;quot;responsible for(2024)&amp;quot; --&amp;gt; I[&amp;quot;Project A&amp;quot;]
F -- &amp;quot;manages(2024)&amp;quot; --&amp;gt; J[&amp;quot;Mary (Person)&amp;quot;]
end
subgraph &amp;quot;Query and Reasoning&amp;quot;
K[&amp;quot;User Question: 'What was John's position last year?'&amp;quot;]
L[&amp;quot;Graph Query: MATCH (p:Person {name:'John'})-[r:role {year:2023}]-&amp;gt;(role) RETURN role&amp;quot;]
M[&amp;quot;Result: 'Developer'&amp;quot;]
N[&amp;quot;Temporal Reasoning: 'John's career progression is from developer to project manager'&amp;quot;]
end
A4 --&amp;gt; B
E --&amp;gt; F
K --&amp;gt; L
L --&amp;gt; M
M --&amp;gt; N
style F fill:#f9f,stroke:#333,stroke-width:2px
style I fill:#bbf,stroke:#333,stroke-width:2px
style J fill:#f9f,stroke:#333,stroke-width:2px
style G fill:#bfb,stroke:#333,stroke-width:2px
style H fill:#bfb,stroke:#333,stroke-width:2px
&lt;/code>&lt;/pre>
&lt;p>This diagram shows how Graphiti/Zep transforms conversation history into a knowledge graph with a temporal dimension, supporting time-based queries and reasoning. Timestamps enable the system to track the evolution of entity attributes and relationships, answering &amp;ldquo;when&amp;rdquo; and &amp;ldquo;how changed&amp;rdquo; types of questions, capabilities that traditional knowledge graphs and vector stores struggle to achieve.&lt;/p>
&lt;h3 id="44-summary-memory">4.4 Summary Memory&lt;/h3>
&lt;p>As mentioned earlier, saves space by creating rolling summaries of dialogue history.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Typical Implementation&lt;/strong>: &lt;code>ConversationSummaryMemory&lt;/code> or &lt;code>ConversationSummaryBufferMemory&lt;/code>.&lt;/li>
&lt;li>&lt;strong>Underlying Details&lt;/strong>:
&lt;ul>
&lt;li>&lt;code>ConversationSummaryMemory&lt;/code>: Summarizes the entire dialogue history each time, which is costly.&lt;/li>
&lt;li>&lt;code>ConversationSummaryBufferMemory&lt;/code>: A hybrid strategy. It keeps the most recent &lt;code>k&lt;/code> turns of complete dialogue while maintaining a rolling summary of earlier conversations. This achieves a good balance between cost and information fidelity.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h3 id="45-user-profile-memory">4.5 User Profile Memory&lt;/h3>
&lt;p>This is a more proactive, advanced form of structured memory, aimed at going beyond single conversations to establish a persistent, dynamically updated &amp;ldquo;profile&amp;rdquo; for users. The Agent not only remembers conversation content but also &amp;ldquo;who you are.&amp;rdquo;&lt;/p>
&lt;ul>
&lt;li>
&lt;p>&lt;strong>Macro Concept&lt;/strong>: Structurally store user preferences, habits, historical choices, and even demographic information (with user authorization). In each interaction, inject this &amp;ldquo;user profile&amp;rdquo; as key context directly into the prompt, allowing the LLM to &amp;ldquo;understand&amp;rdquo; its conversation partner from the start.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Underlying Implementation&lt;/strong>:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Data Structure&lt;/strong>: Typically maintains user metadata in the form of key-value pairs (such as JSON objects). For example: &lt;code>{&amp;quot;user_id&amp;quot;: &amp;quot;123&amp;quot;, &amp;quot;preferred_language&amp;quot;: &amp;quot;English&amp;quot;, &amp;quot;dietary_restrictions&amp;quot;: [&amp;quot;vegetarian&amp;quot;], &amp;quot;home_city&amp;quot;: &amp;quot;Shanghai&amp;quot;}&lt;/code>.&lt;/li>
&lt;li>&lt;strong>Prompt Injection&lt;/strong>: When building the final prompt, include the serialized user profile string (such as &lt;code>[UserProfile]...[/UserProfile]&lt;/code>) as a fixed part of the context.&lt;/li>
&lt;li>&lt;strong>Dynamic Maintenance&lt;/strong>: This is the core of the mechanism. After a conversation ends, the Agent or a background process analyzes the interaction to determine if the user profile needs updating. For example, when a user says &amp;ldquo;I recently moved to Beijing,&amp;rdquo; the system needs a mechanism to update the &lt;code>home_city&lt;/code> field. This update process itself may require a separate LLM call for information extraction and decision-making.&lt;/li>
&lt;/ol>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Advantages&lt;/strong>:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>High Personalization&lt;/strong>: The Agent can provide forward-looking, highly customized services.&lt;/li>
&lt;li>&lt;strong>Conversation Efficiency&lt;/strong>: Avoids repeatedly asking users for basic preferences, making interactions smoother.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Challenges&lt;/strong>:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Update Mechanism Complexity&lt;/strong>: How to accurately and safely update user profiles is a technical challenge.&lt;/li>
&lt;li>&lt;strong>Token Consumption&lt;/strong>: User profiles occupy valuable context window space.&lt;/li>
&lt;li>&lt;strong>Data Privacy&lt;/strong>: Must strictly adhere to user privacy policies.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h2 id="5-summary-and-outlook">5. Summary and Outlook&lt;/h2>
&lt;p>Building an LLM Agent capable of smooth, intelligent multi-turn dialogue is a complex system engineering task. It requires us to:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Face Physical Limitations&lt;/strong>: Overcome context window bottlenecks through clever &lt;strong>memory management mechanisms&lt;/strong> (such as summaries, RAG).&lt;/li>
&lt;li>&lt;strong>Choose Appropriate Architecture&lt;/strong>: Balance &lt;strong>flexibility (ReAct)&lt;/strong> and &lt;strong>structure (FSM)&lt;/strong> based on task complexity, or even combine both.&lt;/li>
&lt;li>&lt;strong>Design Robust Processes&lt;/strong>: Build in &lt;strong>state tracking&lt;/strong>, &lt;strong>intent recognition&lt;/strong>, and &lt;strong>error correction&lt;/strong> capabilities to keep the Agent stable and reliable in complex interactions.&lt;/li>
&lt;/ol>
&lt;p>Future development will focus more on the Agent's autonomous learning and evolution capabilities. Agents will not only execute tasks but also learn new skills from interactions with users, optimize their tool calling strategies, and dynamically adjust their conversation style, ultimately becoming truly personalized intelligent partners.&lt;/p></description></item><item><title>Retrieval-Augmented Generation (RAG): A Comprehensive Technical Analysis</title><link>https://ziyanglin.netlify.app/en/post/rag-technical-documentation/</link><pubDate>Mon, 30 Jun 2025 10:00:00 +0000</pubDate><guid>https://ziyanglin.netlify.app/en/post/rag-technical-documentation/</guid><description>&lt;h2 id="1-macro-overview-why-rag">1. Macro Overview: Why RAG?&lt;/h2>
&lt;h3 id="11-what-is-rag">1.1 What is RAG?&lt;/h3>
&lt;p>RAG, or Retrieval-Augmented Generation, is a technical framework that combines information retrieval from external knowledge bases with the powerful generative capabilities of large language models (LLMs). In simple terms, when a user asks a question, a RAG system first retrieves the most relevant information snippets from a vast, updatable knowledge base (such as company internal documents, product manuals, or the latest web information), and then &amp;ldquo;feeds&amp;rdquo; this information along with the original question to the language model, enabling it to generate answers based on precise, up-to-date context.&lt;/p>
&lt;p>To use an analogy: Imagine a student taking an open-book exam. This student (the LLM) has already learned a lot of knowledge (pre-training data), but when answering very specific questions or those involving the latest information, they can refer to reference books (external knowledge base). RAG is this &amp;ldquo;open-book&amp;rdquo; process, allowing the LLM to consult the most recent and authoritative materials when answering questions, thus providing more accurate and comprehensive answers.&lt;/p>
&lt;h3 id="12-rags-core-value-solving-llms-inherent-limitations">1.2 RAG's Core Value: Solving LLM's Inherent Limitations&lt;/h3>
&lt;p>Despite their power, large language models have several inherent limitations that RAG technology specifically addresses.&lt;/p>
&lt;p>&lt;strong>Limitation 1: Knowledge Cut-off&lt;/strong>&lt;/p>
&lt;p>An LLM's knowledge is frozen at the time of its last training. For example, a model completed in early 2023 cannot answer questions about events that occurred after that point. RAG completely solves this problem by introducing an external knowledge base that can be updated at any time. Companies can update their knowledge bases with the latest product information, financial reports, market dynamics, etc., and the RAG system can immediately leverage this new knowledge to answer questions.&lt;/p>
&lt;p>&lt;strong>Limitation 2: Hallucination&lt;/strong>&lt;/p>
&lt;p>When LLMs encounter questions outside their knowledge domain or with uncertain answers, they sometimes &amp;ldquo;confidently make things up,&amp;rdquo; fabricating facts and producing what are known as &amp;ldquo;hallucinations.&amp;rdquo; RAG greatly constrains model output by providing clear, fact-based reference materials. The model is required to answer based on the retrieved context, which effectively defines the scope of its response, significantly reducing the probability of hallucinations.&lt;/p>
&lt;p>&lt;strong>Limitation 3: Lack of Domain-Specific Knowledge&lt;/strong>&lt;/p>
&lt;p>General-purpose LLMs often perform poorly when handling specialized questions in specific industries or enterprises. For example, they don't understand a company's internal processes or the technical specifications of particular products. Through RAG, enterprises can build a specialized knowledge base containing internal regulations, technical documentation, customer support records, and more. This equips the LLM with domain expert knowledge, enabling it to handle highly specialized Q&amp;amp;A tasks.&lt;/p>
&lt;p>&lt;strong>Limitation 4: Lack of Transparency &amp;amp; Interpretability&lt;/strong>&lt;/p>
&lt;p>The answer generation process of traditional LLMs is a &amp;ldquo;black box&amp;rdquo; - we cannot know what information they based their conclusions on. This is fatal in fields requiring high credibility, such as finance, healthcare, and law. The RAG architecture naturally enhances transparency because the system can clearly show &amp;ldquo;I derived this answer based on these documents (Source 1, Source 2&amp;hellip;)&amp;quot;. Users can trace and verify the sources of information, greatly enhancing trust in the answers.&lt;/p>
&lt;h3 id="13-rags-macro-workflow">1.3 RAG's Macro Workflow&lt;/h3>
&lt;p>At the highest level, RAG's workflow can be depicted as a simple yet elegant architecture.&lt;/p>
&lt;pre>&lt;code class="language-mermaid">graph TD
A[&amp;quot;User Query&amp;quot;] --&amp;gt; B{RAG System};
B --&amp;gt; C[&amp;quot;Retrieve&amp;quot;];
C --&amp;gt; D[&amp;quot;External Knowledge Base&amp;quot;];
D --&amp;gt; C;
C --&amp;gt; E[&amp;quot;Augment&amp;quot;];
A --&amp;gt; E;
E --&amp;gt; F[&amp;quot;Generate&amp;quot;];
F --&amp;gt; G[LLM];
G --&amp;gt; F;
F --&amp;gt; H[&amp;quot;Final Answer with Sources&amp;quot;];
&lt;/code>&lt;/pre>
&lt;p>This workflow can be interpreted as:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Retrieve&lt;/strong>: After receiving a user's question, the system first converts it into a format suitable for searching (such as a vector), then quickly matches and retrieves the most relevant information snippets from the knowledge base.&lt;/li>
&lt;li>&lt;strong>Augment&lt;/strong>: The system integrates the retrieved information snippets with the user's original question into a richer &amp;ldquo;prompt.&amp;rdquo;&lt;/li>
&lt;li>&lt;strong>Generate&lt;/strong>: This enhanced prompt is sent to the LLM, guiding it to generate a content-rich and accurate answer based on the provided context, along with sources of information.&lt;/li>
&lt;/ol>
&lt;p>Through this process, RAG successfully transforms the LLM from a &amp;ldquo;closed-world scholar&amp;rdquo; into an &amp;ldquo;open-world, verifiable expert.&amp;rdquo;&lt;/p>
&lt;h2 id="2-rag-core-architecture-dual-process-analysis">2. RAG Core Architecture: Dual Process Analysis&lt;/h2>
&lt;p>The lifecycle of a RAG system can be clearly divided into two core processes:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Offline Process: Indexing&lt;/strong>: This is a preprocessing stage responsible for transforming raw data sources into a knowledge base ready for quick retrieval. This process typically runs in the background and is triggered whenever the knowledge base content needs updating.&lt;/li>
&lt;li>&lt;strong>Online Process: Retrieval &amp;amp; Generation&lt;/strong>: This is the real-time process of user interaction with the system, responsible for retrieving information from the index based on user input and generating answers.&lt;/li>
&lt;/ol>
&lt;p>Below, we'll analyze these two processes through detailed diagrams and explanations.&lt;/p>
&lt;h3 id="21-offline-process-indexing">2.1 Offline Process: Indexing&lt;/h3>
&lt;p>The goal of this process is to transform unstructured or semi-structured raw data into structured, easily queryable indices.&lt;/p>
&lt;pre>&lt;code class="language-mermaid">graph TD
subgraph &amp;quot;Offline Indexing Pipeline&amp;quot;
A[&amp;quot;Data Sources&amp;quot;] --&amp;gt; B[&amp;quot;Load&amp;quot;];
B --&amp;gt; C[&amp;quot;Split/Chunk&amp;quot;];
C --&amp;gt; D[&amp;quot;Embed&amp;quot;];
D --&amp;gt; E[&amp;quot;Store/Index&amp;quot;];
end
A --&amp;gt; A_Details(&amp;quot;e.g.: PDFs, .txt, .md, Notion, Confluence, databases&amp;quot;);
B --&amp;gt; B_Details(&amp;quot;Using data loaders, e.g., LlamaIndex Readers&amp;quot;);
C --&amp;gt; C_Details(&amp;quot;Strategies: fixed size, recursive splitting, semantic chunking&amp;quot;);
D --&amp;gt; D_Details(&amp;quot;Using Embedding models, e.g., BERT, Sentence-BERT, a-e-5-large-v2&amp;quot;);
E --&amp;gt; E_Details(&amp;quot;Store in vector databases, e.g., Chroma, Pinecone, FAISS&amp;quot;);
&lt;/code>&lt;/pre>
&lt;p>&lt;strong>Process Details:&lt;/strong>&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Load&lt;/strong>: The system first needs to load original documents from various specified data sources. These sources can be diverse, such as PDF files, Markdown documents, web pages, Notion pages, database records, etc. Modern RAG frameworks (like LlamaIndex, LangChain) provide rich data loader ecosystems to simplify this process.&lt;/li>
&lt;li>&lt;strong>Split/Chunk&lt;/strong>: Due to the limited context window of language models, directly embedding a long document (like a PDF with hundreds of pages) as a single vector performs poorly and loses many details. Therefore, it's essential to split long texts into smaller, semantically complete chunks. The chunking strategy is crucial and directly affects retrieval precision.&lt;/li>
&lt;li>&lt;strong>Embed&lt;/strong>: This is the core step of transforming textual information into machine-understandable mathematical representations. The system uses a pre-trained embedding model to map each text chunk to a high-dimensional vector. This vector captures the semantic information of the text, with semantically similar text chunks being closer to each other in the vector space.&lt;/li>
&lt;li>&lt;strong>Store/Index&lt;/strong>: Finally, the system stores the vector representations of all text chunks along with their metadata (such as source document, chapter, page number, etc.) in a specialized database, typically a vector database. Vector databases are specially optimized to support efficient similarity searches across massive-scale vector data.&lt;/li>
&lt;/ol>
&lt;h3 id="22-online-process-retrieval--generation">2.2 Online Process: Retrieval &amp;amp; Generation&lt;/h3>
&lt;p>This process is triggered when a user submits a query, with the goal of generating precise, evidence-based answers in real-time.&lt;/p>
&lt;pre>&lt;code class="language-mermaid">graph TD
A[&amp;quot;User Query&amp;quot;] --&amp;gt; B[&amp;quot;Embed Query&amp;quot;];
B --&amp;gt; C[&amp;quot;Vector Search&amp;quot;];
C &amp;lt;--&amp;gt; D[&amp;quot;Vector Database&amp;quot;];
C --&amp;gt; E[&amp;quot;Get Top-K Chunks&amp;quot;];
E --&amp;gt; F[&amp;quot;(Optional) Re-ranking&amp;quot;];
A &amp;amp; F --&amp;gt; G[&amp;quot;Build Prompt&amp;quot;];
G --&amp;gt; H[&amp;quot;LLM Generation&amp;quot;];
H --&amp;gt; I[&amp;quot;Final Answer&amp;quot;];
&lt;/code>&lt;/pre>
&lt;p>&lt;strong>Process Details:&lt;/strong>&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Embed Query&lt;/strong>: When a user inputs a question, the system uses the &lt;strong>same embedding model&lt;/strong> as in the indexing phase to convert this question into a query vector.&lt;/li>
&lt;li>&lt;strong>Vector Search&lt;/strong>: The system takes this query vector and performs a similarity search in the vector database. The most common algorithm is &amp;ldquo;K-Nearest Neighbors&amp;rdquo; (KNN), aiming to find the K text chunk vectors closest to the query vector in the vector space.&lt;/li>
&lt;li>&lt;strong>Get Top-K Chunks&lt;/strong>: Based on the search results, the system retrieves the original content of these K most relevant text chunks from the database. These K text chunks form the core context for answering the question.&lt;/li>
&lt;li>&lt;strong>Re-ranking (Optional)&lt;/strong>: In some advanced RAG systems, there's an additional re-ranking step. This is because high vector similarity doesn't always equate to high relevance to the question. A re-ranker is a lighter-weight model that re-examines the relevance of these Top-K text chunks to the original question and reorders them, selecting the highest quality ones as the final context.&lt;/li>
&lt;li>&lt;strong>Build Prompt&lt;/strong>: The system combines the original question and the filtered context information according to a predefined template into a complete prompt. This prompt typically includes instructions like: &amp;ldquo;Please answer this question based on the following context information. Question: [&amp;hellip;] Context: [&amp;hellip;]&amp;quot;.&lt;/li>
&lt;li>&lt;strong>LLM Generation&lt;/strong>: Finally, this enhanced prompt is sent to the large language model (LLM). The LLM, following the instructions, comprehensively utilizes its internal knowledge and the provided context to generate a fluent, accurate, and information-rich answer. The system can also cite the sources of the context, enhancing the credibility of the answer.&lt;/li>
&lt;/ol>
&lt;h2 id="3-indexing-deep-dive">3. Indexing Deep Dive&lt;/h2>
&lt;p>Indexing is the cornerstone of RAG systems. The quality of this process directly determines the effectiveness of subsequent retrieval and generation phases. A well-designed indexing process ensures that information in the knowledge base is accurately and completely transformed into retrievable units. Let's explore each component in depth.&lt;/p>
&lt;h3 id="31-data-loading">3.1 Data Loading&lt;/h3>
&lt;p>The first step is to load raw data from various sources into the processing pipeline.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Loaders&lt;/strong>: Modern RAG frameworks provide powerful loader ecosystems. For example, LangChain's &lt;code>Document Loaders&lt;/code> support loading data from over 100 different sources, including:
&lt;ul>
&lt;li>&lt;strong>Files&lt;/strong>: &lt;code>TextLoader&lt;/code> (plain text), &lt;code>PyPDFLoader&lt;/code> (PDF), &lt;code>JSONLoader&lt;/code>, &lt;code>CSVLoader&lt;/code>, &lt;code>UnstructuredFileLoader&lt;/code> (capable of processing Word, PowerPoint, HTML, XML, and other formats).&lt;/li>
&lt;li>&lt;strong>Web Content&lt;/strong>: &lt;code>WebBaseLoader&lt;/code> (web scraping), &lt;code>YoutubeLoader&lt;/code> (loading YouTube video captions).&lt;/li>
&lt;li>&lt;strong>Collaboration Platforms&lt;/strong>: &lt;code>NotionDirectoryLoader&lt;/code>, &lt;code>ConfluenceLoader&lt;/code>.&lt;/li>
&lt;li>&lt;strong>Databases&lt;/strong>: &lt;code>AzureCosmosDBLoader&lt;/code>, &lt;code>PostgresLoader&lt;/code>.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;p>Choosing the right loader allows enterprises to easily integrate their existing knowledge assets into RAG systems without complex data format conversions.&lt;/p>
&lt;h3 id="32-text-splitting--chunking">3.2 Text Splitting / Chunking&lt;/h3>
&lt;p>&lt;strong>Why is chunking necessary?&lt;/strong>
Directly vectorizing an entire document (like a PDF with hundreds of pages) is impractical for three reasons:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Context Length Limitations&lt;/strong>: Most embedding models and LLMs have token input limits.&lt;/li>
&lt;li>&lt;strong>Noise Issues&lt;/strong>: A single vector representing a lengthy document contains too many topics and details, diluting the semantic information and making it difficult to precisely match specific user questions during retrieval.&lt;/li>
&lt;li>&lt;strong>Retrieval Cost&lt;/strong>: Feeding an entire document as context to an LLM consumes substantial computational resources and costs.&lt;/li>
&lt;/ol>
&lt;p>Therefore, splitting documents into semantically related chunks is a crucial step. &lt;strong>The quality of chunks determines the ceiling of RAG performance.&lt;/strong>&lt;/p>
&lt;h4 id="321-core-parameters-chunksize-and-chunkoverlap">3.2.1 Core Parameters: &lt;code>chunk_size&lt;/code> and &lt;code>chunk_overlap&lt;/code>&lt;/h4>
&lt;ul>
&lt;li>&lt;code>chunk_size&lt;/code>: Defines the size of each text block, typically calculated in character count or token count. Choosing this value requires balancing &amp;ldquo;information density&amp;rdquo; and &amp;ldquo;context completeness.&amp;rdquo; Too small may fragment complete semantics; too large may introduce excessive noise.&lt;/li>
&lt;li>&lt;code>chunk_overlap&lt;/code>: Defines the number of characters (or tokens) that overlap between adjacent text blocks. Setting overlap can effectively prevent cutting off a complete sentence or paragraph at block boundaries, ensuring semantic continuity.&lt;/li>
&lt;/ul>
&lt;h4 id="322-mainstream-chunking-strategies">3.2.2 Mainstream Chunking Strategies&lt;/h4>
&lt;p>The choice of chunking strategy depends on the structure and content of the document.&lt;/p>
&lt;p>&lt;strong>Strategy 1: Character Splitting&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Representative&lt;/strong>: &lt;code>CharacterTextSplitter&lt;/code>&lt;/li>
&lt;li>&lt;strong>Principle&lt;/strong>: This is the simplest direct method. It splits text based on a fixed character (like &lt;code>\n\n&lt;/code> newline) and then forcibly chunks according to the preset &lt;code>chunk_size&lt;/code>.&lt;/li>
&lt;li>&lt;strong>Advantages&lt;/strong>: Simple, fast, low computational cost.&lt;/li>
&lt;li>&lt;strong>Disadvantages&lt;/strong>: Completely ignores the semantics and logical structure of the text, easily breaking sentences in the middle or abruptly cutting off complete concept descriptions.&lt;/li>
&lt;li>&lt;strong>Applicable Scenarios&lt;/strong>: Suitable for texts with no obvious structure or where semantic coherence is not a high requirement.&lt;/li>
&lt;/ul>
&lt;pre>&lt;code class="language-python"># Example: CharacterTextSplitter
from langchain_text_splitters import CharacterTextSplitter
text_splitter = CharacterTextSplitter(
separator=&amp;quot;\n\n&amp;quot;,
chunk_size=1000,
chunk_overlap=200,
length_function=len,
)
&lt;/code>&lt;/pre>
&lt;p>&lt;strong>Strategy 2: Recursive Character Splitting&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Representative&lt;/strong>: &lt;code>RecursiveCharacterTextSplitter&lt;/code>&lt;/li>
&lt;li>&lt;strong>Principle&lt;/strong>: This is currently the most commonly used and recommended strategy. It attempts to split recursively according to a set of preset separators (like &lt;code>[&amp;quot;\n\n&amp;quot;, &amp;quot;\n&amp;quot;, &amp;quot; &amp;quot;, &amp;quot;&amp;quot;]&lt;/code>). It first tries to split using the first separator (&lt;code>\n\n&lt;/code>, paragraph); if the resulting blocks are still larger than &lt;code>chunk_size&lt;/code>, it continues using the next separator (&lt;code>\n&lt;/code>, line) to split these large blocks, and so on until the block size meets requirements.&lt;/li>
&lt;li>&lt;strong>Advantages&lt;/strong>: Makes the greatest effort to maintain the integrity of paragraphs, sentences, and other semantic units, striking a good balance between universality and effectiveness.&lt;/li>
&lt;li>&lt;strong>Disadvantages&lt;/strong>: Still based on character rules rather than true semantic understanding.&lt;/li>
&lt;li>&lt;strong>Applicable Scenarios&lt;/strong>: The preferred strategy for the vast majority of scenarios.&lt;/li>
&lt;/ul>
&lt;pre>&lt;code class="language-python"># Example: RecursiveCharacterTextSplitter
from langchain_text_splitters import RecursiveCharacterTextSplitter
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=1000,
chunk_overlap=200,
)
&lt;/code>&lt;/pre>
&lt;p>&lt;strong>Strategy 3: Token-Based Splitting&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Representative&lt;/strong>: &lt;code>TokenTextSplitter&lt;/code>, &lt;code>CharacterTextSplitter.from_tiktoken_encoder&lt;/code>&lt;/li>
&lt;li>&lt;strong>Principle&lt;/strong>: It calculates &lt;code>chunk_size&lt;/code> by token count rather than character count. This is more consistent with how language models process text and allows for more precise control over the length of content input to the model.&lt;/li>
&lt;li>&lt;strong>Advantages&lt;/strong>: More precise control over cost and input length for model API calls.&lt;/li>
&lt;li>&lt;strong>Disadvantages&lt;/strong>: Computation is slightly more complex than character splitting.&lt;/li>
&lt;li>&lt;strong>Applicable Scenarios&lt;/strong>: When strict control over costs and API call input lengths is needed.&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>Strategy 4: Semantic Chunking&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Principle&lt;/strong>: This is a more advanced experimental method. Instead of being based on fixed rules, it's based on understanding the semantics of the text. The splitter calculates embedding similarity between sentences and splits when it detects that the semantic difference between adjacent sentences exceeds a threshold.&lt;/li>
&lt;li>&lt;strong>Advantages&lt;/strong>: Can generate highly semantically consistent text blocks, theoretically the best splitting method.&lt;/li>
&lt;li>&lt;strong>Disadvantages&lt;/strong>: Very high computational cost, as it requires multiple embedding calculations during the splitting phase.&lt;/li>
&lt;li>&lt;strong>Applicable Scenarios&lt;/strong>: Scenarios requiring extremely high retrieval quality, regardless of computational cost.&lt;/li>
&lt;/ul>
&lt;h3 id="33-embedding">3.3 Embedding&lt;/h3>
&lt;p>Embedding is the process of transforming text chunks into high-dimensional numerical vectors, which serve as mathematical representations of the text's semantics.&lt;/p>
&lt;h4 id="331-embedding-model-selection">3.3.1 Embedding Model Selection&lt;/h4>
&lt;p>The choice of embedding model directly affects retrieval quality and system cost.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Closed-Source Commercial Models (e.g., OpenAI)&lt;/strong>:
&lt;ul>
&lt;li>&lt;strong>Representatives&lt;/strong>: &lt;code>text-embedding-ada-002&lt;/code>, &lt;code>text-embedding-3-small&lt;/code>, &lt;code>text-embedding-3-large&lt;/code>&lt;/li>
&lt;li>&lt;strong>Advantages&lt;/strong>: Powerful performance, typically ranking high in various evaluation benchmarks, simple to use (API calls).&lt;/li>
&lt;li>&lt;strong>Disadvantages&lt;/strong>: Requires payment, data must be sent to third-party servers, privacy risks exist.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;pre>&lt;code class="language-python"># Example: Using OpenAI Embeddings
from langchain_openai import OpenAIEmbeddings
embeddings_model = OpenAIEmbeddings(model=&amp;quot;text-embedding-3-small&amp;quot;)
&lt;/code>&lt;/pre>
&lt;ul>
&lt;li>&lt;strong>Open-Source Models (e.g., Hugging Face)&lt;/strong>:
&lt;ul>
&lt;li>&lt;strong>Representatives&lt;/strong>: &lt;code>sentence-transformers/all-mpnet-base-v2&lt;/code> (English general), &lt;code>bge-large-zh-v1.5&lt;/code> (Chinese), &lt;code>m3e-large&lt;/code> (Chinese-English) etc.&lt;/li>
&lt;li>&lt;strong>Advantages&lt;/strong>: Free, can be deployed locally, no data privacy leakage risk, numerous fine-tuned models available for specific languages or domains.&lt;/li>
&lt;li>&lt;strong>Disadvantages&lt;/strong>: Requires self-management of model deployment and computational resources, performance may have some gap compared to top commercial models.&lt;/li>
&lt;li>&lt;strong>MTEB Leaderboard&lt;/strong>: The Massive Text Embedding Benchmark (MTEB) is a public leaderboard for evaluating and comparing the performance of different embedding models, an important reference for selecting open-source models.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;pre>&lt;code class="language-python"># Example: Using open-source models from Hugging Face
from langchain_huggingface import HuggingFaceEmbeddings
model_name = &amp;quot;sentence-transformers/all-mpnet-base-v2&amp;quot;
embeddings_model = HuggingFaceEmbeddings(model_name=model_name)
&lt;/code>&lt;/pre>
&lt;p>&lt;strong>Core Principle&lt;/strong>: Throughout the entire RAG process, &lt;strong>the same embedding model must be used in both the indexing phase and the online retrieval phase&lt;/strong>. Otherwise, the query vectors and document vectors will exist in different vector spaces, making meaningful similarity comparisons impossible.&lt;/p>
&lt;h2 id="4-retrieval-technology-deep-dive">4. Retrieval Technology Deep Dive&lt;/h2>
&lt;p>Retrieval is the &amp;ldquo;heart&amp;rdquo; of RAG systems. Finding the most relevant contextual information is the prerequisite for generating high-quality answers. If the retrieved content is irrelevant or inaccurate, even the most powerful LLM will be ineffective - this is the so-called &amp;ldquo;Garbage In, Garbage Out&amp;rdquo; principle.&lt;/p>
&lt;p>Retrieval technology has evolved from traditional keyword matching to modern semantic vector search, and has now developed various advanced strategies to address complex challenges in different scenarios.&lt;/p>
&lt;h3 id="41-traditional-foundation-sparse-retrieval">4.1 Traditional Foundation: Sparse Retrieval&lt;/h3>
&lt;p>Sparse retrieval is a classic information retrieval method based on word frequency statistics, independent of deep learning models. Its core idea is that the more times a word appears in a specific document and the fewer times it appears across all documents, the more representative that word is for that document.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Representative Algorithms&lt;/strong>: &lt;strong>TF-IDF&lt;/strong> &amp;amp; &lt;strong>BM25 (Best Match 25)&lt;/strong>&lt;/li>
&lt;li>&lt;strong>Principle Brief (using BM25 as an example)&lt;/strong>:
&lt;ol>
&lt;li>&lt;strong>Term Frequency (TF)&lt;/strong>: Calculate the frequency of each query term in the document.&lt;/li>
&lt;li>&lt;strong>Inverse Document Frequency (IDF)&lt;/strong>: Measure the &amp;ldquo;rarity&amp;rdquo; of a term. Rarer terms have higher weights.&lt;/li>
&lt;li>&lt;strong>Document Length Penalty&lt;/strong>: Penalize overly long documents to prevent them from getting artificially high scores just because they contain more words.&lt;/li>
&lt;/ol>
&lt;/li>
&lt;li>&lt;strong>Advantages&lt;/strong>:
&lt;ul>
&lt;li>&lt;strong>Precise Keyword Matching&lt;/strong>: Performs excellently for queries containing specific terms, abbreviations, or product models (like &amp;ldquo;iPhone 15 Pro&amp;rdquo;).&lt;/li>
&lt;li>&lt;strong>Strong Interpretability&lt;/strong>: Score calculation logic is clear, easy to understand and debug.&lt;/li>
&lt;li>&lt;strong>Fast Computation&lt;/strong>: No complex model inference required.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>Disadvantages&lt;/strong>:
&lt;ul>
&lt;li>&lt;strong>Cannot Understand Semantics&lt;/strong>: Unable to handle synonyms, near-synonyms, or conceptual relevance. For example, searching for &amp;ldquo;Apple phone&amp;rdquo; won't match documents containing &amp;ldquo;iPhone&amp;rdquo;.&lt;/li>
&lt;li>&lt;strong>&amp;ldquo;Vocabulary Gap&amp;rdquo; Problem&lt;/strong>: Relies on literal matching between queries and documents.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>Applicable Scenarios&lt;/strong>: As part of hybrid retrieval, handling keyword and proper noun matching.&lt;/li>
&lt;/ul>
&lt;h3 id="42-modern-core-dense-retrieval--vector-search">4.2 Modern Core: Dense Retrieval / Vector Search&lt;/h3>
&lt;p>Dense retrieval is the mainstream technology in current RAG systems. It uses deep learning models (the embedding models we discussed earlier) to encode the semantic information of text into dense vectors, enabling retrieval based on &amp;ldquo;semantic similarity&amp;rdquo; rather than &amp;ldquo;literal similarity&amp;rdquo;.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Core Idea&lt;/strong>: Semantically similar texts have vectors that are close to each other in multidimensional space.&lt;/li>
&lt;li>&lt;strong>Workflow&lt;/strong>:
&lt;ol>
&lt;li>Offline: Vectorize all document chunks and store them in a vector database.&lt;/li>
&lt;li>Online: Vectorize the user query.&lt;/li>
&lt;li>In the vector database, calculate the distance/similarity between the query vector and all document vectors (such as cosine similarity, Euclidean distance).&lt;/li>
&lt;li>Return the Top-K document chunks with the closest distances.&lt;/li>
&lt;/ol>
&lt;/li>
&lt;/ul>
&lt;h4 id="421-approximate-nearest-neighbor-ann-search">4.2.1 Approximate Nearest Neighbor (ANN) Search&lt;/h4>
&lt;p>Since performing exact &amp;ldquo;nearest neighbor&amp;rdquo; searches among millions or even billions of vectors is extremely computationally expensive, the industry widely adopts &lt;strong>Approximate Nearest Neighbor (ANN)&lt;/strong> algorithms. ANN sacrifices minimal precision in exchange for query speed improvements of several orders of magnitude.&lt;/p>
&lt;ul>
&lt;li>
&lt;p>&lt;strong>Mainstream ANN Algorithm&lt;/strong>: &lt;strong>HNSW (Hierarchical Navigable Small World)&lt;/strong>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>HNSW Principle Brief&lt;/strong>: It constructs a hierarchical graph structure. In the higher-level graph, it performs rough, large-step searches to quickly locate the target area; then in the lower-level graph, it performs fine, small-step searches to finally find the nearest neighbor vectors. This is like finding an address in a city - first determining which district (higher level), then which street (lower level).&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Advantages&lt;/strong>:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Powerful Semantic Understanding&lt;/strong>: Can cross literal barriers to understand concepts and intentions.&lt;/li>
&lt;li>&lt;strong>High Recall Rate&lt;/strong>: Can retrieve more semantically relevant documents with different wording.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Disadvantages&lt;/strong>:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Keyword Insensitivity&lt;/strong>: Sometimes less effective than sparse retrieval for matching specific keywords or proper nouns.&lt;/li>
&lt;li>&lt;strong>Strong Dependence on Embedding Models&lt;/strong>: Effectiveness completely depends on the quality of the embedding model.&lt;/li>
&lt;li>&lt;strong>&amp;ldquo;Black Box&amp;rdquo; Problem&lt;/strong>: The process of generating and matching vectors is less intuitive than sparse retrieval.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h3 id="43-powerful-combination-hybrid-search">4.3 Powerful Combination: Hybrid Search&lt;/h3>
&lt;p>Since sparse retrieval and dense retrieval each have their own strengths and weaknesses, the most natural idea is to combine them to leverage their respective advantages. Hybrid search was born for this purpose.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Implementation Method&lt;/strong>:
&lt;ol>
&lt;li>&lt;strong>Parallel Execution&lt;/strong>: Simultaneously process user queries using sparse retrieval (like BM25) and dense retrieval (vector search).&lt;/li>
&lt;li>&lt;strong>Score Fusion&lt;/strong>: Obtain two sets of results and their corresponding scores.&lt;/li>
&lt;li>&lt;strong>Result Re-ranking&lt;/strong>: Use a fusion algorithm (such as &lt;strong>Reciprocal Rank Fusion, RRF&lt;/strong>) to merge the two sets of results and re-rank them based on the fused scores to get the final Top-K results. The RRF algorithm gives higher weight to documents that rank high in different retrieval methods.&lt;/li>
&lt;/ol>
&lt;/li>
&lt;/ul>
&lt;pre>&lt;code class="language-mermaid">graph TD
subgraph &amp;quot;Hybrid Search&amp;quot;
A[&amp;quot;User Query&amp;quot;] --&amp;gt; B[&amp;quot;BM25 Retriever&amp;quot;];
A --&amp;gt; C[&amp;quot;Vector Retriever&amp;quot;];
B --&amp;gt; D[&amp;quot;Sparse Results (Top-K)&amp;quot;];
C --&amp;gt; E[&amp;quot;Dense Results (Top-K)&amp;quot;];
D &amp;amp; E --&amp;gt; F{&amp;quot;Fusion &amp;amp; Reranking (e.g., RRF)&amp;quot;};
F --&amp;gt; G[&amp;quot;Final Ranked Results&amp;quot;];
end
&lt;/code>&lt;/pre>
&lt;ul>
&lt;li>&lt;strong>Advantages&lt;/strong>: Balances the precision of keyword matching and the breadth of semantic understanding, achieving better results than single retrieval methods in most scenarios.&lt;/li>
&lt;li>&lt;strong>Applicable Scenarios&lt;/strong>: Almost all RAG applications requiring high-quality retrieval.&lt;/li>
&lt;/ul>
&lt;h3 id="44-frontier-exploration-advanced-retrieval-strategies">4.4 Frontier Exploration: Advanced Retrieval Strategies&lt;/h3>
&lt;p>To address more complex query intentions and data structures, academia and industry have developed a series of advanced retrieval strategies.&lt;/p>
&lt;h4 id="441-contextual-compression--reranking">4.4.1 Contextual Compression &amp;amp; Re-ranking&lt;/h4>
&lt;p>&lt;strong>Problem&lt;/strong>: The Top-K document chunks returned by vector search may only partially contain content truly relevant to the question, and some high-ranking blocks might actually be &amp;ldquo;false positives.&amp;rdquo; Directly feeding this redundant or irrelevant information to the LLM increases noise and cost.&lt;/p>
&lt;p>&lt;strong>Solution&lt;/strong>: Add an intermediate &amp;ldquo;filtering&amp;rdquo; and &amp;ldquo;sorting&amp;rdquo; layer between retrieval and generation.&lt;/p>
&lt;pre>&lt;code class="language-mermaid">graph TD
A[&amp;quot;Initial Retrieval&amp;quot;] --&amp;gt; B[&amp;quot;Top-K Documents&amp;quot;];
B --&amp;gt; C{&amp;quot;Compressor / Re-ranker&amp;quot;};
UserQuery --&amp;gt; C;
C --&amp;gt; D[&amp;quot;Filtered &amp;amp; Re-ranked Documents&amp;quot;];
D --&amp;gt; E[&amp;quot;LLM Generation&amp;quot;];
&lt;/code>&lt;/pre>
&lt;ul>
&lt;li>&lt;strong>Implementation Method&lt;/strong>: Using LangChain's &lt;code>ContextualCompressionRetriever&lt;/code>.
&lt;ul>
&lt;li>&lt;strong>&lt;code>LLMChainExtractor&lt;/code>&lt;/strong>: Uses an LLM to judge whether each document chunk is relevant to the query and only extracts relevant sentences.&lt;/li>
&lt;li>&lt;strong>&lt;code>EmbeddingsFilter&lt;/code>&lt;/strong>: Recalculates the similarity between query vectors and document chunk vectors, filtering out documents below a certain threshold.&lt;/li>
&lt;li>&lt;strong>Re-ranker&lt;/strong>: This is currently the most effective and commonly used approach. It uses a lighter-weight &lt;strong>cross-encoder&lt;/strong> model specifically trained to calculate relevance scores. Unlike the bi-encoder used in the retrieval phase (which encodes queries and documents separately), a cross-encoder receives both the query and document chunk as input simultaneously, enabling more fine-grained relevance judgment. Common re-rankers include &lt;code>Cohere Rerank&lt;/code>, &lt;code>BAAI/bge-reranker-*&lt;/code>, and models provided by open-source or cloud service vendors.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h4 id="442-selfquerying-retriever">4.4.2 Self-Querying Retriever&lt;/h4>
&lt;p>&lt;strong>Problem&lt;/strong>: User queries are typically in natural language but may contain filtering requirements for &lt;strong>metadata&lt;/strong>. For example: &amp;ldquo;Recommend some science fiction movies released after 2000 with ratings above 8.5?&amp;rdquo;&lt;/p>
&lt;p>&lt;strong>Solution&lt;/strong>: Let the LLM itself &amp;ldquo;translate&amp;rdquo; natural language queries into structured query statements containing metadata filtering conditions.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Workflow&lt;/strong>:
&lt;ol>
&lt;li>User inputs a natural language query.&lt;/li>
&lt;li>&lt;code>SelfQueryingRetriever&lt;/code> sends the query to the LLM.&lt;/li>
&lt;li>Based on predefined metadata field information (such as &lt;code>year&lt;/code>, &lt;code>rating&lt;/code>, &lt;code>genre&lt;/code>), the LLM generates a structured query containing:
&lt;ul>
&lt;li>&lt;code>query&lt;/code>: The keyword part for vector search (&amp;ldquo;science fiction movies&amp;rdquo;).&lt;/li>
&lt;li>&lt;code>filter&lt;/code>: Conditions for metadata filtering (&lt;code>year &amp;gt; 2000 AND rating &amp;gt; 8.5&lt;/code>).&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>The retriever uses this structured query to perform a &amp;ldquo;filter first, then search&amp;rdquo; operation on the vector database, greatly narrowing the search scope and improving precision.&lt;/li>
&lt;/ol>
&lt;/li>
&lt;/ul>
&lt;pre>&lt;code class="language-python"># Core settings for Self-Querying in LangChain
metadata_field_info = [
AttributeInfo(name=&amp;quot;genre&amp;quot;, ...),
AttributeInfo(name=&amp;quot;year&amp;quot;, ...),
AttributeInfo(name=&amp;quot;rating&amp;quot;, ...),
]
retriever = SelfQueryRetriever.from_llm(
llm,
vectorstore,
document_content_description,
metadata_field_info,
)
&lt;/code>&lt;/pre>
&lt;h4 id="443-multivector-retriever">4.4.3 Multi-Vector Retriever&lt;/h4>
&lt;p>&lt;strong>Problem&lt;/strong>: A single vector struggles to perfectly summarize a longer document chunk, especially when the chunk contains multiple subtopics.&lt;/p>
&lt;p>&lt;strong>Solution&lt;/strong>: Generate &lt;strong>multiple&lt;/strong> vectors representing different aspects for each document chunk, rather than a single vector.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Implementation Methods&lt;/strong>:
&lt;ol>
&lt;li>&lt;strong>Smaller Sub-chunks&lt;/strong>: Further split the original document chunk into smaller sentences or paragraphs, and generate vectors for these small chunks.&lt;/li>
&lt;li>&lt;strong>Summary Vectors&lt;/strong>: Use an LLM to generate a summary for each document chunk, then vectorize the summary.&lt;/li>
&lt;li>&lt;strong>Hypothetical Question Vectors&lt;/strong>: Use an LLM to pose several possible questions about each document chunk, then vectorize these questions.&lt;/li>
&lt;/ol>
&lt;/li>
&lt;/ul>
&lt;p>During querying, the query vector matches with all these sub-vectors (sub-chunks, summaries, questions). Once a match is successful, what's returned is the &lt;strong>complete original document chunk&lt;/strong> it belongs to. This leverages both the precision of fine-grained matching and ensures that the context provided to the final LLM is complete.&lt;/p>
&lt;h4 id="444-parent-document-retriever">4.4.4 Parent Document Retriever&lt;/h4>
&lt;p>This is a common implementation of the multi-vector retriever. It splits documents into &amp;ldquo;parent chunks&amp;rdquo; and &amp;ldquo;child chunks.&amp;rdquo; Indexing and retrieval happen on the smaller &amp;ldquo;child chunks,&amp;rdquo; but what's ultimately returned to the LLM is the larger &amp;ldquo;parent chunk&amp;rdquo; that the child belongs to. This solves the &amp;ldquo;context loss&amp;rdquo; problem, ensuring that the LLM sees a more complete linguistic context when generating answers.&lt;/p>
&lt;h4 id="445-graph-rag">4.4.5 Graph RAG&lt;/h4>
&lt;p>&lt;strong>Problem&lt;/strong>: Traditional RAG views knowledge as independent text blocks, ignoring the complex, web-like relationships between knowledge points.&lt;/p>
&lt;p>&lt;strong>Solution&lt;/strong>: Build the knowledge base into a &lt;strong>Knowledge Graph&lt;/strong>, where entities are nodes and relationships are edges.&lt;/p>
&lt;ul>
&lt;li>
&lt;p>&lt;strong>Workflow&lt;/strong>:&lt;/p>
&lt;ol>
&lt;li>During querying, the system first identifies the core entities in the query.&lt;/li>
&lt;li>It then explores neighboring nodes and relationships related to these entities in the graph, forming a subgraph containing rich structured information.&lt;/li>
&lt;li>This subgraph information is linearized (converted to text) and provided to the LLM as context.&lt;/li>
&lt;/ol>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Advantages&lt;/strong>: Can answer more complex questions requiring multi-hop reasoning (e.g., &amp;ldquo;Who is A's boss's wife?&amp;quot;), providing deeper context than &amp;ldquo;text blocks.&amp;rdquo;&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Implementation Case: Graphiti/Zep&lt;/strong>:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Introduction&lt;/strong>: &lt;a href="https://github.com/getzep/graphiti">Graphiti&lt;/a> is a temporal knowledge graph architecture designed specifically for LLM Agents, seamlessly integrating Neo4j's graph database capabilities with LLM's natural language processing abilities.&lt;/li>
&lt;li>&lt;strong>Core Features&lt;/strong>:
&lt;ul>
&lt;li>&lt;strong>Temporal Awareness&lt;/strong>: Each node and relationship carries timestamp attributes, enabling tracking of how entity states change over time.&lt;/li>
&lt;li>&lt;strong>Automatic Schema Inference&lt;/strong>: No need to predefine entity types and relationships; the system can automatically infer appropriate graph structures from conversations.&lt;/li>
&lt;li>&lt;strong>Multi-hop Reasoning&lt;/strong>: Supports complex relationship path queries, capable of discovering indirectly associated information.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>Application Scenarios&lt;/strong>: Particularly suitable for multi-turn dialogue systems requiring long-term memory and temporal reasoning, such as customer support, personal assistants, and other scenarios needing to &amp;ldquo;remember&amp;rdquo; user historical interactions.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h4 id="446-agentic-rag--adaptive-rag">4.4.6 Agentic RAG / Adaptive RAG&lt;/h4>
&lt;p>This is the latest evolutionary direction of RAG, endowing RAG systems with certain &amp;ldquo;thinking&amp;rdquo; and &amp;ldquo;decision-making&amp;rdquo; capabilities, allowing them to adaptively select the best retrieval strategy based on the complexity of the question.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Core Idea&lt;/strong>: Transform the traditional linear RAG process into a dynamic process driven by an LLM Agent that can loop and iterate.&lt;/li>
&lt;li>&lt;strong>Possible Workflow&lt;/strong>:
&lt;ol>
&lt;li>&lt;strong>Question Analysis&lt;/strong>: The Agent first analyzes the user's question. Is this a simple question or a complex one? Does it need keyword matching or semantic search?&lt;/li>
&lt;li>&lt;strong>Strategy Selection&lt;/strong>:
&lt;ul>
&lt;li>If the question is simple, directly perform vector search.&lt;/li>
&lt;li>If the question contains metadata, switch to Self-Querying.&lt;/li>
&lt;li>If the question is ambiguous, the Agent might first rewrite the question (Query Rewriting), generating several different query variants and executing them separately.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>Result Reflection &amp;amp; Iteration&lt;/strong>: The Agent examines the preliminary retrieved results. If the results are not ideal (e.g., low relevance or conflicting information), it can decide to:
&lt;ul>
&lt;li>&lt;strong>Query Again&lt;/strong>: Use different keywords or strategies to retrieve again.&lt;/li>
&lt;li>&lt;strong>Web Search&lt;/strong>: If the internal knowledge base doesn't have an answer, it can call search engine tools to find information online.&lt;/li>
&lt;li>&lt;strong>Multi-step Reasoning&lt;/strong>: Break down complex questions into several sub-questions, retrieving and answering step by step.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ol>
&lt;/li>
&lt;/ul>
&lt;p>Agentic RAG is no longer a fixed pipeline but a flexible, intelligent framework, representing the future direction of RAG development.&lt;/p>
&lt;h2 id="5-generation-phase-the-final-touch">5. Generation Phase: The Final Touch&lt;/h2>
&lt;p>The generation phase is the endpoint of the RAG process and the ultimate manifestation of its value. In this phase, the system combines the &amp;ldquo;essence&amp;rdquo; context obtained from previous retrieval, filtering, and re-ranking with the user's original question to form a final prompt, which is then sent to the large language model (LLM) to generate an answer.&lt;/p>
&lt;h3 id="51-core-task-effective-prompt-engineering">5.1 Core Task: Effective Prompt Engineering&lt;/h3>
&lt;p>The core task of this phase is &lt;strong>Prompt Engineering&lt;/strong>. A well-designed prompt template can clearly instruct the LLM on its task, ensuring it thinks and answers along the right track.&lt;/p>
&lt;p>A typical RAG prompt template structure is as follows:&lt;/p>
&lt;pre>&lt;code class="language-text">You are a professional, rigorous Q&amp;amp;A assistant. Please answer the user's question based on the context information provided below.
Your answer must be completely based on the given context, and you are prohibited from using your internal knowledge for any supplementation or imagination.
If there is not enough information in the context to answer the question, please clearly state &amp;quot;Based on the available information, I cannot answer this question.&amp;quot;
At the end of your answer, please list all the context source IDs you referenced.
---
[Context Information]
{context}
---
[User Question]
{question}
---
[Your Answer]
&lt;/code>&lt;/pre>
&lt;h4 id="511-template-key-elements-analysis">5.1.1 Template Key Elements Analysis&lt;/h4>
&lt;ul>
&lt;li>&lt;strong>Persona&lt;/strong>: &amp;ldquo;You are a professional, rigorous Q&amp;amp;A assistant.&amp;rdquo; This helps set the tone and style of the LLM's output.&lt;/li>
&lt;li>&lt;strong>Core Instruction&lt;/strong>: &amp;ldquo;Please answer the user's question based on the context information provided below.&amp;rdquo; This is the most critical task instruction.&lt;/li>
&lt;li>&lt;strong>Constraints &amp;amp; Guardrails&lt;/strong>:
&lt;ul>
&lt;li>&amp;ldquo;Must be completely based on the given context, prohibited from&amp;hellip; supplementation or imagination.&amp;rdquo; -&amp;gt; This is key to suppressing model hallucinations.&lt;/li>
&lt;li>&amp;ldquo;If there is not enough information, please clearly state&amp;hellip;&amp;rdquo; -&amp;gt; This defines the model's &amp;ldquo;escape route&amp;rdquo; when information is insufficient, preventing it from guessing.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>Attribution/Citation&lt;/strong>: &amp;ldquo;Please list all the context source IDs you referenced.&amp;rdquo; -&amp;gt; This is the foundation for answer explainability and credibility.&lt;/li>
&lt;li>&lt;strong>Placeholders&lt;/strong>:
&lt;ul>
&lt;li>&lt;code>{context}&lt;/code>: This will be filled with the content of multiple document chunks (chunks) obtained from the retrieval phase, after processing.&lt;/li>
&lt;li>&lt;code>{question}&lt;/code>: This will be filled with the user's original question.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h3 id="52-context-and-question-fusion">5.2 Context and Question Fusion&lt;/h3>
&lt;p>When the system fills multiple document chunks (e.g., Top-5 chunks) into the &lt;code>{context}&lt;/code> placeholder, these chunks are packaged together with the original question and sent to the LLM. The LLM reads the entire enhanced prompt and then:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Understands the Question&lt;/strong>: Clarifies the user's query intent.&lt;/li>
&lt;li>&lt;strong>Locates Information&lt;/strong>: Searches for sentences and paragraphs directly related to the question within the provided multiple context blocks.&lt;/li>
&lt;li>&lt;strong>Synthesizes &amp;amp; Refines&lt;/strong>: Integrates, understands, and refines scattered information points found from different context blocks.&lt;/li>
&lt;li>&lt;strong>Generates an Answer&lt;/strong>: Based on the refined information, generates a final answer using fluent, coherent natural language.&lt;/li>
&lt;li>&lt;strong>Cites Sources&lt;/strong>: According to instructions, includes the document sources that the answer is based on.&lt;/li>
&lt;/ol>
&lt;p>Through this carefully designed &amp;ldquo;open-book exam&amp;rdquo; process, the RAG system ultimately generates a high-quality answer that combines both the LLM's powerful language capabilities and fact-based information.&lt;/p>
&lt;h2 id="6-rag-evaluation-framework-how-to-measure-system-quality">6. RAG Evaluation Framework: How to Measure System Quality?&lt;/h2>
&lt;p>Building a RAG system is just the first step. Scientifically and quantitatively evaluating its performance, and continuously iterating and optimizing based on this evaluation, is equally important. A good evaluation framework can help us diagnose whether the system's bottleneck is in the retrieval module (&amp;ldquo;not found&amp;rdquo;) or in the generation module (&amp;ldquo;not well expressed&amp;rdquo;).&lt;/p>
&lt;p>Industry-leading RAG evaluation frameworks, such as &lt;strong>RAGAS (RAG Assessment)&lt;/strong> and &lt;strong>TruLens&lt;/strong>, provide a series of metrics to score RAG system performance from different dimensions.&lt;/p>
&lt;h3 id="61-core-evaluation-dimensions">6.1 Core Evaluation Dimensions&lt;/h3>
&lt;p>RAG evaluation can be divided into two levels: &lt;strong>component level&lt;/strong> (evaluating retrieval and generation separately) and &lt;strong>end-to-end level&lt;/strong> (evaluating the quality of the final answer).&lt;/p>
&lt;pre>&lt;code class="language-mermaid">graph TD
subgraph &amp;quot;RAG Evaluation Dimensions&amp;quot;
A(&amp;quot;Evaluation&amp;quot;) --&amp;gt; B[&amp;quot;Component-Level Evaluation&amp;quot;];
A --&amp;gt; C[&amp;quot;End-to-End Evaluation&amp;quot;];
B --&amp;gt; B1[&amp;quot;Retriever Quality Evaluation&amp;quot;];
B --&amp;gt; B2[&amp;quot;Generator Quality Evaluation&amp;quot;];
B1 --&amp;gt; B1_Metrics(&amp;quot;Context Precision, Context Recall&amp;quot;);
B2 --&amp;gt; B2_Metrics(&amp;quot;Faithfulness&amp;quot;);
C --&amp;gt; C_Metrics(&amp;quot;Answer Relevancy, Answer Correctness&amp;quot;);
end
&lt;/code>&lt;/pre>
&lt;h3 id="62-key-evaluation-metrics-using-ragas-as-an-example">6.2 Key Evaluation Metrics (Using RAGAS as an Example)&lt;/h3>
&lt;p>Below we explain in detail several core metrics in the RAGAS framework. These metrics do not require manually annotated reference answers (Reference-Free), greatly reducing evaluation costs.&lt;/p>
&lt;h4 id="621-evaluating-generation-quality">6.2.1 Evaluating Generation Quality&lt;/h4>
&lt;p>&lt;strong>Metric 1: Faithfulness&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Definition&lt;/strong>: Measures the extent to which the generated answer is completely based on the provided context. High faithfulness means that every statement in the answer can find evidence in the context.&lt;/li>
&lt;li>&lt;strong>Evaluation Method&lt;/strong>: RAGAS uses an LLM to analyze the answer, breaking it down into a series of statements. Then, for each statement, it verifies in the context whether there is evidence supporting that statement. The final score is (number of statements supported by the context) / (total number of statements).&lt;/li>
&lt;li>&lt;strong>Problem Diagnosed&lt;/strong>: This metric is the &lt;strong>core indicator for measuring &amp;ldquo;model hallucination&amp;rdquo;&lt;/strong>. A low score means the generator (LLM) is freely making up information that doesn't exist in the context.&lt;/li>
&lt;li>&lt;strong>Data Required&lt;/strong>: &lt;code>question&lt;/code>, &lt;code>answer&lt;/code>, &lt;code>context&lt;/code>.&lt;/li>
&lt;/ul>
&lt;h4 id="622-evaluating-both-retrieval-and-generation-quality">6.2.2 Evaluating Both Retrieval and Generation Quality&lt;/h4>
&lt;p>&lt;strong>Metric 2: Answer Relevancy&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Definition&lt;/strong>: Measures the relevance of the generated answer to the user's original question. An answer faithful to the context might still be off-topic.&lt;/li>
&lt;li>&lt;strong>Evaluation Method&lt;/strong>: RAGAS uses an Embedding model to measure the semantic similarity between the question and answer. It also uses an LLM to identify &amp;ldquo;noise&amp;rdquo; or irrelevant sentences in the answer and penalizes them.&lt;/li>
&lt;li>&lt;strong>Problem Diagnosed&lt;/strong>: A low score means that although the answer may be based on the context, it doesn't directly or effectively answer the user's question, or it contains too much irrelevant information.&lt;/li>
&lt;li>&lt;strong>Data Required&lt;/strong>: &lt;code>question&lt;/code>, &lt;code>answer&lt;/code>.&lt;/li>
&lt;/ul>
&lt;h4 id="623-evaluating-retrieval-quality">6.2.3 Evaluating Retrieval Quality&lt;/h4>
&lt;p>&lt;strong>Metric 3: Context Precision&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Definition&lt;/strong>: Measures how much of the retrieved context is truly relevant to the question - the &amp;ldquo;signal-to-noise ratio.&amp;rdquo;&lt;/li>
&lt;li>&lt;strong>Evaluation Method&lt;/strong>: RAGAS analyzes the context sentence by sentence and has an LLM judge whether each sentence is necessary for answering the user's question. The final score is (number of sentences deemed useful) / (total number of sentences in the context).&lt;/li>
&lt;li>&lt;strong>Problem Diagnosed&lt;/strong>: A low score (high &lt;code>1 - Context Precision&lt;/code> value) indicates that the retriever returned many irrelevant &amp;ldquo;noise&amp;rdquo; documents, which interferes with the generator's judgment and increases costs. This suggests that the &lt;strong>retrieval algorithm needs optimization&lt;/strong>.&lt;/li>
&lt;li>&lt;strong>Data Required&lt;/strong>: &lt;code>question&lt;/code>, &lt;code>context&lt;/code>.&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>Metric 4: Context Recall&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Definition&lt;/strong>: Measures whether the retrieved context contains all the necessary information to answer the question.&lt;/li>
&lt;li>&lt;strong>Evaluation Method&lt;/strong>: This metric requires a &lt;strong>manually annotated reference answer (Ground Truth)&lt;/strong> as a benchmark. RAGAS has an LLM analyze this reference answer and judge whether each sentence in it can find support in the retrieved context.&lt;/li>
&lt;li>&lt;strong>Problem Diagnosed&lt;/strong>: A low score means the retriever &lt;strong>failed to find&lt;/strong> key information needed to answer the question, indicating &amp;ldquo;missed retrievals.&amp;rdquo; This might suggest that the document chunking strategy is unreasonable, or the Embedding model cannot understand the query well.&lt;/li>
&lt;li>&lt;strong>Data Required&lt;/strong>: &lt;code>question&lt;/code>, &lt;code>ground_truth&lt;/code> (reference answer), &lt;code>context&lt;/code>.&lt;/li>
&lt;/ul>
&lt;h3 id="63-using-evaluation-to-guide-iteration">6.3 Using Evaluation to Guide Iteration&lt;/h3>
&lt;p>By comprehensively evaluating a RAG system using the above metrics, we can get a clear performance profile and make targeted optimizations:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Low Faithfulness Score&lt;/strong>: The problem is in the &lt;strong>generator&lt;/strong>. Need to optimize the Prompt, add stronger constraints, or switch to an LLM with stronger instruction-following capabilities.&lt;/li>
&lt;li>&lt;strong>Low Answer Relevancy Score&lt;/strong>: The problem could be in either the generator or retriever. Need to check if the Prompt is guiding the model off-topic, or if the retrieved content is of poor quality.&lt;/li>
&lt;li>&lt;strong>Low Context Precision Score&lt;/strong>: The problem is in the &lt;strong>retriever&lt;/strong>. Indicates that the recalled documents are of poor quality with much noise. Can try better retrieval strategies, such as adding a Re-ranker to filter irrelevant documents.&lt;/li>
&lt;li>&lt;strong>Low Context Recall Score&lt;/strong>: The problem is in the &lt;strong>retriever&lt;/strong>. Indicates that key information wasn't found. Need to check if the Chunking strategy is fragmenting key information, or try methods like Multi-Query to expand the retrieval scope.&lt;/li>
&lt;/ul>
&lt;p>Through the &amp;ldquo;evaluate-diagnose-optimize&amp;rdquo; closed loop, we can continuously improve the overall performance of the RAG system.&lt;/p>
&lt;h2 id="7-challenges-and-future-outlook">7. Challenges and Future Outlook&lt;/h2>
&lt;p>Although RAG has greatly expanded the capabilities of large language models and has become the de facto standard for building knowledge-intensive applications, it still faces some challenges while also pointing to exciting future development directions.&lt;/p>
&lt;h3 id="71-current-challenges">7.1 Current Challenges&lt;/h3>
&lt;ol>
&lt;li>&lt;strong>&amp;ldquo;Needle-in-a-Haystack&amp;rdquo; Problem&lt;/strong>: As LLM context windows grow larger (e.g., million-level tokens), precisely finding and utilizing key information in lengthy, noisy contexts becomes increasingly difficult. Research shows that LLM performance when processing long contexts is affected by the position of information within them, with issues like &amp;ldquo;middle neglect.&amp;rdquo;&lt;/li>
&lt;li>&lt;strong>Imperfect Chunking&lt;/strong>: How to optimally split documents remains an open question. Existing rule-based or simple semantic splitting methods may damage information integrity or introduce irrelevant context, affecting retrieval and generation quality.&lt;/li>
&lt;li>&lt;strong>Evaluation Complexity and Cost&lt;/strong>: Although frameworks like RAGAS provide automated evaluation metrics, building a comprehensive, reliable evaluation set still requires significant human effort. Especially in domains requiring fine judgment, machine evaluation results may differ from human perception.&lt;/li>
&lt;li>&lt;strong>Integration of Structured and Multimodal Data&lt;/strong>: Knowledge in the real world isn't just text. How to efficiently integrate tables, charts, images, audio, and other multimodal information, and enable RAG systems to understand and utilize them, is an actively explored area.&lt;/li>
&lt;li>&lt;strong>Production Environment Complexity&lt;/strong>: Deploying a RAG prototype to a production environment requires considering data updates, permission management, version control, cost monitoring, low-latency responses, and a series of engineering challenges.&lt;/li>
&lt;/ol>
&lt;h3 id="72-future-outlook">7.2 Future Outlook&lt;/h3>
&lt;ol>
&lt;li>&lt;strong>Smarter Indexing&lt;/strong>: Future indexing processes will no longer be simple &amp;ldquo;split-vectorize&amp;rdquo; operations. They will more deeply understand document structures, automatically build knowledge graphs, identify entities and relationships, generate multi-level, multi-perspective representations (such as summaries, questions), creating a richer, more queryable knowledge network.&lt;/li>
&lt;li>&lt;strong>Adaptive Retrieval&lt;/strong>: As demonstrated by Agentic RAG, future RAG systems will have stronger autonomy. They can dynamically decide whether to perform simple vector searches or execute complex multi-step queries, or even call external tools (such as search engines, calculators, APIs) to obtain information based on the specific situation of the question. Retrieval will evolve from a fixed step to a flexible, agent-driven process.&lt;/li>
&lt;li>&lt;strong>LLM as Part of RAG&lt;/strong>: As LLM capabilities strengthen, they will participate more deeply in every aspect of RAG. Not just in the generation phase, but also in indexing (generating metadata, summaries), querying (query rewriting, expansion), retrieval (as a re-ranker), and other phases, playing a core role.&lt;/li>
&lt;li>&lt;strong>End-to-End Optimization&lt;/strong>: Future frameworks may allow end-to-end joint fine-tuning of various RAG components (Embedding models, LLM generators, etc.), making the entire system highly optimized for a specific task or domain, rather than simply piecing together individual components.&lt;/li>
&lt;li>&lt;strong>Native Multimodal RAG&lt;/strong>: RAG will natively support understanding and retrieving content like images, audio, and video. Users can ask questions like &amp;ldquo;Find me that picture of &amp;lsquo;a cat playing piano&amp;rsquo;&amp;rdquo; and the system can directly perform semantic retrieval in multimedia databases and return results.&lt;/li>
&lt;/ol>
&lt;p>In summary, RAG is evolving from a relatively fixed &amp;ldquo;retrieve-augment-generate&amp;rdquo; pipeline to a more dynamic, intelligent, adaptive knowledge processing framework. It will continue to serve as the key bridge connecting large language models with the vast external world, continuously unleashing AI's application potential across various industries in the foreseeable future.&lt;/p></description></item><item><title>Model Context Protocol (MCP): A Standardized Framework for AI Capability Extension</title><link>https://ziyanglin.netlify.app/en/post/mcp-documentation/</link><pubDate>Mon, 30 Jun 2025 08:00:00 +0000</pubDate><guid>https://ziyanglin.netlify.app/en/post/mcp-documentation/</guid><description>&lt;h2 id="1-macro-introduction-why-do-we-need-mcp-beyond-tool-calling">1. Macro Introduction: Why Do We Need MCP Beyond Tool Calling?&lt;/h2>
&lt;p>In our previous document on general LLM tool calling, we revealed how LLMs can break their knowledge boundaries by calling external functions. This is a powerful &lt;strong>programming paradigm&lt;/strong>, but it doesn't define a &lt;strong>standardized set of communication rules&lt;/strong>. Each developer must decide for themselves how to organize APIs, manage tools, and handle data formats, leading to ecosystem fragmentation.&lt;/p>
&lt;p>The &lt;strong>Model Context Protocol (MCP)&lt;/strong> was born precisely to solve this problem. It doesn't aim to replace the general concept of tool calling, but rather builds a layer of &lt;strong>standardized, pluggable, service-oriented protocol&lt;/strong> on top of it.&lt;/p>
&lt;p>If &amp;ldquo;tool calling&amp;rdquo; is teaching a car how to &amp;ldquo;refuel&amp;rdquo; (use external capabilities), then MCP establishes &lt;strong>standardized gas stations and fuel nozzle interfaces&lt;/strong> for the world. No matter what car you drive (different LLMs) or what fuel you need (different tools), as long as you follow the MCP standard, you can connect seamlessly and plug-and-play.&lt;/p>
&lt;p>The core value of MCP lies in:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Standardization&lt;/strong>: Defines unified message formats and interaction patterns for communication between models and external tool services. Developers no longer need to customize tool integration solutions for each model or application.&lt;/li>
&lt;li>&lt;strong>Decoupling&lt;/strong>: Completely separates the &lt;strong>implementation&lt;/strong> of tools (running on MCP servers) from their &lt;strong>use&lt;/strong> (initiated by LLMs). Models don't need to know the internal code of tools, only how to communicate with them through the protocol.&lt;/li>
&lt;li>&lt;strong>Reusability&lt;/strong>: Once a tool or data source is encapsulated as an MCP server, it can be easily reused by any model or application that supports the MCP protocol, greatly improving development efficiency.&lt;/li>
&lt;li>&lt;strong>Discoverability&lt;/strong>: MCP makes tools service-oriented, laying the foundation for building tool marketplaces and enabling automatic discovery and orchestration of tools in the future.&lt;/li>
&lt;/ul>
&lt;p>In simple terms, MCP elevates scattered &amp;ldquo;function calls&amp;rdquo; to the level of &amp;ldquo;distributed service calls,&amp;rdquo; serving as a key infrastructure for building scalable, interoperable AI Agent ecosystems.&lt;/p>
&lt;h2 id="2-mcp-core-architecture-a-trinity-collaboration-model">2. MCP Core Architecture: A Trinity Collaboration Model&lt;/h2>
&lt;p>The MCP architecture consists of three core components that interact through clearly defined protocols, forming a solid &amp;ldquo;trinity&amp;rdquo; collaboration model.&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Model/Agent&lt;/strong>: The decision core. It is responsible for understanding user intent and generating requests that follow the MCP format to call external tools or access external resources.&lt;/li>
&lt;li>&lt;strong>MCP Client&lt;/strong>: The communication hub. It serves as a bridge between the model and MCP servers, parsing MCP requests generated by the model, communicating with the corresponding MCP servers through standardized transmission methods (such as Stdio, HTTP SSE), and handling returned results.&lt;/li>
&lt;li>&lt;strong>MCP Server&lt;/strong>: The capability provider. This is a separate process or service that encapsulates one or more tools or data sources and provides standardized access interfaces through the MCP protocol.&lt;/li>
&lt;/ol>
&lt;p>Below is a visual explanation of this architecture:&lt;/p>
&lt;pre>&lt;code class="language-mermaid">graph TD
subgraph Agent [Model/Agent]
A[LLM] -- Generates Request --&amp;gt; B(MCP XML Request);
end
subgraph Client [MCP Client]
C{Request Parser};
B -- Parse Request --&amp;gt; C;
end
subgraph LocalServer [MCP Server - Local]
D[Stdio Communication];
end
subgraph RemoteServer [MCP Server - Remote]
E[HTTP SSE Communication];
end
subgraph ServerCore [MCP Server Internal]
F[Protocol Processor] -- Execute Tool --&amp;gt; G[Tool/Resource Implementation];
end
C -- Route to Local --&amp;gt; D;
C -- Route to Remote --&amp;gt; E;
D -- Local Transport --&amp;gt; F;
E -- Remote Transport --&amp;gt; F;
G -- Return Result --&amp;gt; F;
F -- Protocol Return --&amp;gt; C;
C -- Submit Result --&amp;gt; A;
style A fill:#cde4ff,stroke:#333;
style B fill:#e6ffc2,stroke:#333;
style C fill:#fce8b2,stroke:#333;
style D fill:#f9c5b4,stroke:#333;
style E fill:#f9c5b4,stroke:#333;
style F fill:#d4a8e3,stroke:#333;
style G fill:#b4f9f2,stroke:#333;
&lt;/code>&lt;/pre>
&lt;h3 id="detailed-architecture-responsibilities">Detailed Architecture Responsibilities:&lt;/h3>
&lt;ol>
&lt;li>&lt;strong>Model Generates Request&lt;/strong>: When an LLM needs external capabilities, it no longer generates JSON for specific APIs, but instead generates an XML message that conforms to the MCP specification, such as &lt;code>&amp;lt;use_mcp_tool&amp;gt;&lt;/code>. This message clearly specifies which &lt;code>server_name&lt;/code> to communicate with and which &lt;code>tool_name&lt;/code> to call.&lt;/li>
&lt;li>&lt;strong>Client Parsing and Routing&lt;/strong>: The MCP client (typically part of the model's runtime environment) captures and parses this XML request. It queries a service registry based on the &lt;code>server_name&lt;/code> to determine whether the target server is a local process or a remote service.&lt;/li>
&lt;li>&lt;strong>Selecting Communication Channel&lt;/strong>:
&lt;ul>
&lt;li>If the target is a &lt;strong>local MCP server&lt;/strong> (e.g., a locally running Python script), the client will communicate with that server process through &lt;strong>standard input/output (stdio)&lt;/strong>.&lt;/li>
&lt;li>If the target is a &lt;strong>remote MCP server&lt;/strong> (e.g., a service deployed in the cloud), the client will establish a connection with it through the &lt;strong>HTTP Server-Sent Events (SSE)&lt;/strong> protocol.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>Server Processing Request&lt;/strong>: After receiving the request, the protocol processor on the MCP server calls the specific tool function or resource handler that has been registered internally based on the &lt;code>tool_name&lt;/code> or &lt;code>uri&lt;/code>.&lt;/li>
&lt;li>&lt;strong>Execution and Return&lt;/strong>: The server executes the specific logic (calling APIs, querying databases, etc.) and encapsulates the results in the MCP standard format, returning them to the client through the same route.&lt;/li>
&lt;li>&lt;strong>Result Feedback to Model&lt;/strong>: After receiving the server's response, the client organizes and formats it as the execution result of the external tool, and submits it back to the LLM for the LLM to generate the final natural language reply, completing the entire interaction loop.&lt;/li>
&lt;/ol>
&lt;p>The brilliance of this architecture lies in the fact that the LLM itself is completely decoupled from the physical location and network implementation details of the tools. It only needs to learn to &amp;ldquo;speak&amp;rdquo; the MCP &amp;ldquo;common language&amp;rdquo; to interact with any service in the entire MCP ecosystem.&lt;/p>
&lt;h2 id="3-communication-protocol-deep-dive-mcps-neural-network">3. Communication Protocol Deep Dive: MCP's Neural Network&lt;/h2>
&lt;p>The power of MCP lies in its standardized communication methods. It primarily connects clients and servers through two distinctly different protocols to accommodate different deployment scenarios.&lt;/p>
&lt;h3 id="31-local-communication-standard-inputoutput-stdio">3.1. Local Communication: Standard Input/Output (Stdio)&lt;/h3>
&lt;p>When the MCP server is a local executable file or script (e.g., a Python script, a Go program), the MCP client uses &lt;strong>Standard Input/Output (Stdio)&lt;/strong> for communication. This is a classic and efficient form of inter-process communication (IPC).&lt;/p>
&lt;p>&lt;strong>Workflow Breakdown&lt;/strong>:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Launch Subprocess&lt;/strong>: The MCP client (such as a VS Code extension) launches the MCP server program as a &lt;strong>subprocess&lt;/strong> (e.g., executing &lt;code>python mcp_server.py&lt;/code>).&lt;/li>
&lt;li>&lt;strong>Pipe Establishment&lt;/strong>: The operating system automatically establishes three pipes between the parent process (client) and child process (server):
&lt;ul>
&lt;li>&lt;code>stdin&lt;/code> (standard input): The channel for the client to send data to the server.&lt;/li>
&lt;li>&lt;code>stdout&lt;/code> (standard output): The channel for the server to send successful results to the client.&lt;/li>
&lt;li>&lt;code>stderr&lt;/code> (standard error): The channel for the server to send error messages to the client.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>Message Exchange&lt;/strong>:
&lt;ul>
&lt;li>The client writes the MCP request (e.g., an XML string like &lt;code>&amp;lt;use_mcp_tool&amp;gt;...&lt;/code>) to the server process's &lt;code>stdin&lt;/code>. To handle packet sticking issues, messages are typically delimited by specific separators (such as newline &lt;code>\n&lt;/code>) or length prefixes.&lt;/li>
&lt;li>The server reads and parses the request from its &lt;code>stdout&lt;/code> and executes the corresponding logic.&lt;/li>
&lt;li>The server writes the execution result (also an XML string in MCP format) to its own &lt;code>stdout&lt;/code>.&lt;/li>
&lt;li>If any errors occur during the process, error details are written to &lt;code>stderr&lt;/code>.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>Lifecycle Management&lt;/strong>: The client is responsible for monitoring the lifecycle of the server subprocess and can terminate it when it's no longer needed.&lt;/li>
&lt;/ol>
&lt;p>&lt;strong>Advantages&lt;/strong>:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Extremely Low Latency&lt;/strong>: Since it's local inter-process communication, there's almost no network overhead.&lt;/li>
&lt;li>&lt;strong>Simple and Reliable&lt;/strong>: Simple implementation, not dependent on the network stack.&lt;/li>
&lt;li>&lt;strong>High Security&lt;/strong>: Data doesn't leave the machine, providing natural isolation.&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>Applicable Scenarios&lt;/strong>:&lt;/p>
&lt;ul>
&lt;li>Local tools requiring high performance and high-frequency calls.&lt;/li>
&lt;li>Tools that directly operate on the local file system or hardware.&lt;/li>
&lt;li>Development and debugging environments.&lt;/li>
&lt;/ul>
&lt;h3 id="32-remote-communication-serversent-events-http-sse">3.2. Remote Communication: Server-Sent Events (HTTP SSE)&lt;/h3>
&lt;p>When the MCP server is deployed on a remote host or in the cloud, communication is done through the HTTP-based &lt;strong>Server-Sent Events (SSE)&lt;/strong> protocol. SSE is a web technology that allows servers to push events to clients in a one-way fashion.&lt;/p>
&lt;p>&lt;strong>Workflow Breakdown&lt;/strong>:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>HTTP Connection&lt;/strong>: The MCP client initiates a regular HTTP GET request to a specific endpoint of the MCP server (e.g., &lt;code>https://api.my-mcp-server.com/v1/mcp&lt;/code>). The key is that the client includes &lt;code>Accept: text/event-stream&lt;/code> in the request header, indicating it wants to establish an SSE connection.&lt;/li>
&lt;li>&lt;strong>Long Connection Maintenance&lt;/strong>: Upon receiving the request, the server doesn't immediately close the connection but keeps it open, forming a &lt;strong>long connection&lt;/strong>. The &lt;code>Content-Type&lt;/code> header of the response is set to &lt;code>text/event-stream&lt;/code>.&lt;/li>
&lt;li>&lt;strong>Event Pushing&lt;/strong>:
&lt;ul>
&lt;li>The client sends the MCP request (XML string) as part of the HTTP POST request body to another endpoint of the server through this long connection.&lt;/li>
&lt;li>After processing the request, the server encapsulates the response data in the SSE event format and &lt;strong>pushes&lt;/strong> it back to the client through the previously established long connection. Each event consists of fields such as &lt;code>event: &amp;lt;event_name&amp;gt;&lt;/code> and &lt;code>data: &amp;lt;event_data&amp;gt;&lt;/code>.&lt;/li>
&lt;li>MCP typically defines different types of events, such as &lt;code>result&lt;/code> for success, &lt;code>error&lt;/code> for failure, and &lt;code>log&lt;/code> for transmitting logs.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ol>
&lt;p>&lt;strong>Advantages&lt;/strong>:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Cross-Network Communication&lt;/strong>: Can easily connect to servers anywhere.&lt;/li>
&lt;li>&lt;strong>Firewall Penetration&lt;/strong>: Based on standard HTTP(S) protocol, with good network compatibility.&lt;/li>
&lt;li>&lt;strong>Server-Side Push&lt;/strong>: Suitable for scenarios requiring server-initiated notifications.&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>Applicable Scenarios&lt;/strong>:&lt;/p>
&lt;ul>
&lt;li>Encapsulating third-party cloud service APIs (such as weather, maps, payments).&lt;/li>
&lt;li>Shared tools that need centralized management and deployment.&lt;/li>
&lt;li>Building publicly accessible tool service ecosystems.&lt;/li>
&lt;/ul>
&lt;h2 id="4-mcp-message-format-breakdown-the-protocols-common-language">4. MCP Message Format Breakdown: The Protocol's &amp;ldquo;Common Language&amp;rdquo;&lt;/h2>
&lt;p>The core of MCP is its XML-based message format that is both human-readable and machine-parsable. Models express their intentions by generating XML fragments in these specific formats.&lt;/p>
&lt;h3 id="41-usemcptool-calling-a-tool">4.1. &lt;code>&amp;lt;use_mcp_tool&amp;gt;&lt;/code>: Calling a Tool&lt;/h3>
&lt;p>This is the most core message, used to request the execution of a defined tool.&lt;/p>
&lt;p>&lt;strong>Structure Example&lt;/strong>:&lt;/p>
&lt;pre>&lt;code class="language-xml">&amp;lt;use_mcp_tool&amp;gt;
&amp;lt;server_name&amp;gt;weather-server&amp;lt;/server_name&amp;gt;
&amp;lt;tool_name&amp;gt;get_forecast&amp;lt;/tool_name&amp;gt;
&amp;lt;arguments&amp;gt;
{
&amp;quot;city&amp;quot;: &amp;quot;San Francisco&amp;quot;,
&amp;quot;days&amp;quot;: 5
}
&amp;lt;/arguments&amp;gt;
&amp;lt;/use_mcp_tool&amp;gt;
&lt;/code>&lt;/pre>
&lt;p>&lt;strong>Field Details&lt;/strong>:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>&lt;code>&amp;lt;server_name&amp;gt;&lt;/code> (Required)&lt;/strong>:
&lt;ul>
&lt;li>&lt;strong>Purpose&lt;/strong>: Unique identifier of the MCP server.&lt;/li>
&lt;li>&lt;strong>Underlying Details&lt;/strong>: The client uses this name to look up corresponding server information (whether it's a local process or remote URL) in its internal service registry, deciding whether to use Stdio or SSE for communication. This is key to implementing routing.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>&lt;code>&amp;lt;tool_name&amp;gt;&lt;/code> (Required)&lt;/strong>:
&lt;ul>
&lt;li>&lt;strong>Purpose&lt;/strong>: Name of the tool to call.&lt;/li>
&lt;li>&lt;strong>Underlying Details&lt;/strong>: After receiving the request, the MCP server uses this name to find and execute the corresponding function in its internal tool mapping table.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>&lt;code>&amp;lt;arguments&amp;gt;&lt;/code> (Required)&lt;/strong>:
&lt;ul>
&lt;li>&lt;strong>Purpose&lt;/strong>: Parameters needed to call the tool.&lt;/li>
&lt;li>&lt;strong>Underlying Details&lt;/strong>: The content is typically a &lt;strong>JSON string&lt;/strong>. The server needs to first parse this string, convert it to a language-native object or dictionary, and then pass it to the specific tool function. This design leverages JSON's powerful data expression capabilities and cross-language universality.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h3 id="42-accessmcpresource-accessing-a-resource">4.2. &lt;code>&amp;lt;access_mcp_resource&amp;gt;&lt;/code>: Accessing a Resource&lt;/h3>
&lt;p>In addition to actively &amp;ldquo;executing&amp;rdquo; tools, MCP also supports passively &amp;ldquo;accessing&amp;rdquo; data sources.&lt;/p>
&lt;p>&lt;strong>Structure Example&lt;/strong>:&lt;/p>
&lt;pre>&lt;code class="language-xml">&amp;lt;access_mcp_resource&amp;gt;
&amp;lt;server_name&amp;gt;internal-docs&amp;lt;/server_name&amp;gt;
&amp;lt;uri&amp;gt;doc://product/specs/version-3.md&amp;lt;/uri&amp;gt;
&amp;lt;/access_mcp_resource&amp;gt;
&lt;/code>&lt;/pre>
&lt;p>&lt;strong>Field Details&lt;/strong>:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>&lt;code>&amp;lt;server_name&amp;gt;&lt;/code> (Required)&lt;/strong>: Same as above, used for routing.&lt;/li>
&lt;li>&lt;strong>&lt;code>&amp;lt;uri&amp;gt;&lt;/code> (Required)&lt;/strong>:
&lt;ul>
&lt;li>&lt;strong>Purpose&lt;/strong>: Uniform Resource Identifier for the resource.&lt;/li>
&lt;li>&lt;strong>Underlying Details&lt;/strong>: The format of the URI (&lt;code>scheme://path&lt;/code>) is defined and interpreted by the server itself. For example:
&lt;ul>
&lt;li>&lt;code>file:///path/to/local/file&lt;/code>: Access a local file.&lt;/li>
&lt;li>&lt;code>db://customers/id/123&lt;/code>: Query a database.&lt;/li>
&lt;li>&lt;code>api://v1/users?active=true&lt;/code>: Access a REST API endpoint.
The server needs to parse this URI and execute the appropriate resource retrieval logic based on its scheme and path.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h2 id="5-building-an-mcp-server-from-concept-to-code-skeleton">5. Building an MCP Server: From Concept to Code Skeleton&lt;/h2>
&lt;p>To make the concept more concrete, below is a minimalist Python pseudocode skeleton showing how to implement an MCP server that responds to Stdio communication.&lt;/p>
&lt;pre>&lt;code class="language-python">import sys
import json
import xml.etree.ElementTree as ET
# 1. Define specific tool functions
def get_weather(city: str, days: int = 1):
&amp;quot;&amp;quot;&amp;quot;A simulated weather tool&amp;quot;&amp;quot;&amp;quot;
# In the real world, this would call a weather API
return {&amp;quot;city&amp;quot;: city, &amp;quot;forecast&amp;quot;: f&amp;quot;Sunny for the next {days} days&amp;quot;}
# Map tool names to function objects
AVAILABLE_TOOLS = {
&amp;quot;get_weather&amp;quot;: get_weather
}
# 2. MCP protocol processing main loop
def main_loop():
&amp;quot;&amp;quot;&amp;quot;Read requests from stdin, process them, and write results to stdout&amp;quot;&amp;quot;&amp;quot;
for line in sys.stdin:
request_xml = line.strip()
if not request_xml:
continue
try:
# 3. Parse MCP request
root = ET.fromstring(request_xml)
if root.tag == &amp;quot;use_mcp_tool&amp;quot;:
tool_name = root.find(&amp;quot;tool_name&amp;quot;).text
args_str = root.find(&amp;quot;arguments&amp;quot;).text
args = json.loads(args_str)
# 4. Find and execute the tool
tool_function = AVAILABLE_TOOLS.get(tool_name)
if tool_function:
result = tool_function(**args)
# 5. Encapsulate successful result and write back to stdout
response = {&amp;quot;status&amp;quot;: &amp;quot;success&amp;quot;, &amp;quot;data&amp;quot;: result}
sys.stdout.write(json.dumps(response) + &amp;quot;\n&amp;quot;)
else:
raise ValueError(f&amp;quot;Tool '{tool_name}' not found.&amp;quot;)
# (Logic for handling access_mcp_resource can be added here)
except Exception as e:
# 6. Write error information back to stderr
error_response = {&amp;quot;status&amp;quot;: &amp;quot;error&amp;quot;, &amp;quot;message&amp;quot;: str(e)}
sys.stderr.write(json.dumps(error_response) + &amp;quot;\n&amp;quot;)
# Flush buffers in real-time to ensure the client receives immediately
sys.stdout.flush()
sys.stderr.flush()
if __name__ == &amp;quot;__main__&amp;quot;:
main_loop()
&lt;/code>&lt;/pre>
&lt;p>This skeleton clearly demonstrates the core responsibilities of an MCP server: listening for input, parsing the protocol, executing logic, and returning results.&lt;/p>
&lt;h2 id="6-practical-exercise-using-the-mcpdriven-context7-server-to-answer-technical-questions">6. Practical Exercise: Using the MCP-Driven context7 Server to Answer Technical Questions&lt;/h2>
&lt;p>After theory and skeleton, let's look at a real, end-to-end example to see how MCP works in practical applications.&lt;/p>
&lt;p>&lt;strong>Scenario&lt;/strong>: We're building an AI programming assistant. When a user asks a specific programming question, we want the AI to provide the most authoritative and accurate answer by querying the latest official documentation, rather than relying on its potentially outdated internal knowledge.&lt;/p>
&lt;p>In this scenario, the &lt;code>context7&lt;/code> MCP server is our &amp;ldquo;external document library.&amp;rdquo;&lt;/p>
&lt;p>Here's the complete interaction flow:&lt;/p>
&lt;pre>&lt;code class="language-mermaid">sequenceDiagram
participant User
participant Agent as AI Programming Assistant (Model+Client)
participant Context7 as context7 MCP Server
User-&amp;gt;&amp;gt;+Agent: Ask about React Hooks differences
Note over Agent: 1. Analyze question, decide to call tool
Agent--&amp;gt;&amp;gt;+Context7: 2. Send MCP request (get-library-docs)
Note over Context7: 3. Query document library
Context7--&amp;gt;&amp;gt;-Agent: 4. Return document summary (key differences)
Note over Agent: 5. Understand and summarize authoritative material
Agent--&amp;gt;&amp;gt;-User: 6. Generate final answer based on documentation
&lt;/code>&lt;/pre>
&lt;h3 id="process-breakdown-and-mcp-value-demonstration">Process Breakdown and MCP Value Demonstration&lt;/h3>
&lt;ol>
&lt;li>
&lt;p>&lt;strong>Intent to Protocol Conversion&lt;/strong>: The model (LLM) successfully converts the user's natural language question into a structured, standardized MCP request. It not only identifies the need to call a tool but also accurately fills in the &lt;code>server_name&lt;/code>, &lt;code>tool_name&lt;/code>, and &lt;code>arguments&lt;/code>, which is the core capability of an MCP-driven Agent.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Decoupling Advantage&lt;/strong>: The AI programming assistant (client) doesn't need to know at all how the &lt;code>context7&lt;/code> server is implemented. It could be a complex system connected to multiple data sources. But for the assistant, it's just a service endpoint that follows the MCP protocol and can be accessed through the name &lt;code>context7&lt;/code>. This decoupling makes replacing or upgrading the document source extremely simple without needing to modify the Agent's core logic.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Scalability from Standardization&lt;/strong>: Now, if we want to add the ability to query NPM package dependencies to this AI assistant, we just need to develop or integrate another MCP server named &lt;code>npm-analyzer&lt;/code>. The learning cost for the Agent is almost zero because it only needs to learn to generate a new &lt;code>&amp;lt;use_mcp_tool&amp;gt;&lt;/code> request pointing to the new &lt;code>server_name&lt;/code>. The entire system's capabilities can be infinitely expanded like building with Lego blocks.&lt;/p>
&lt;/li>
&lt;/ol>
&lt;p>This example clearly demonstrates how MCP evolves from a simple &amp;ldquo;function call&amp;rdquo; concept to a powerful, scalable service-oriented architecture, providing a solid foundation for building complex AI applications.&lt;/p>
&lt;h2 id="7-conclusion-mcps-value-and-futurebuilding-the-internet-of-ai">7. Conclusion: MCP's Value and Future—Building the &amp;ldquo;Internet&amp;rdquo; of AI&lt;/h2>
&lt;p>General tool calling gives LLMs the ability to &amp;ldquo;speak&amp;rdquo; and &amp;ldquo;act,&amp;rdquo; while the &lt;strong>Model Context Protocol (MCP) defines the grammar and traffic rules for these abilities&lt;/strong>. Through standardization, decoupling, and service-oriented design principles, MCP transforms isolated AI applications and tools into a potential, interoperable massive network.&lt;/p>
&lt;p>The true value of MCP isn't that it defines another type of RPC (Remote Procedure Call), but that it's specifically tailored for the unique scenario of &lt;strong>AI Agent interaction with the external world&lt;/strong>. It's simple enough for LLMs to easily generate protocol messages, yet powerful enough to support complex, distributed application ecosystems.&lt;/p>
&lt;p>In the future, as the MCP ecosystem matures, we can envision an &amp;ldquo;Internet of AI tools&amp;rdquo;:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Tool Marketplace&lt;/strong>: Developers can publish and sell standardized MCP servers, and other applications can purchase and integrate them as needed.&lt;/li>
&lt;li>&lt;strong>Agent Interoperability&lt;/strong>: Intelligent agents developed by different companies based on different underlying models can call each other's capabilities and collaborate on more complex tasks as long as they all &amp;ldquo;speak&amp;rdquo; the MCP language.&lt;/li>
&lt;li>&lt;strong>Dynamic Service Discovery&lt;/strong>: More advanced Agents might be able to dynamically discover and learn new MCP services, continuously expanding their capability boundaries without requiring reprogramming.&lt;/li>
&lt;/ul>
&lt;p>Therefore, understanding and mastering MCP is not just about learning a specific technology, but a key step in gaining insight into and planning for the next generation of AI application architecture.&lt;/p></description></item><item><title>LLM Tool Calling: The Key Technology Breaking AI Capability Boundaries</title><link>https://ziyanglin.netlify.app/en/post/llm-tool-calling/</link><pubDate>Mon, 30 Jun 2025 07:00:00 +0000</pubDate><guid>https://ziyanglin.netlify.app/en/post/llm-tool-calling/</guid><description>&lt;h2 id="1-macro-overview-why-tool-calling-is-llms-super-plugin">1. Macro Overview: Why Tool Calling is LLM's &amp;ldquo;Super Plugin&amp;rdquo;&lt;/h2>
&lt;p>The emergence of Large Language Models (LLMs) has fundamentally changed how we interact with machines. However, LLMs have an inherent, unavoidable &amp;ldquo;ceiling&amp;rdquo;: they are essentially &amp;ldquo;probability prediction machines&amp;rdquo; trained on massive text data, with their knowledge frozen at the time their training data ends. This means an LLM cannot know &amp;ldquo;what's the weather like today?&amp;quot;, cannot access your company's internal database, and cannot book a flight ticket for you.&lt;/p>
&lt;p>The &lt;strong>LLM Tool Calling / Function Calling&lt;/strong> mechanism emerged precisely to break through this ceiling. It gives LLMs an unprecedented ability: &lt;strong>calling external tools (APIs, functions, databases, etc.) to obtain real-time information, perform specific tasks, or interact with the external world&lt;/strong> when needed.&lt;/p>
&lt;p>In simple terms, the tool calling mechanism upgrades LLMs from &amp;ldquo;knowledgeable conversationalists&amp;rdquo; to capable &amp;ldquo;intelligent agents.&amp;rdquo; It allows LLMs to:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Obtain real-time information&lt;/strong>: By calling weather APIs, news APIs, search engines, etc., to get the latest information beyond the model's training data.&lt;/li>
&lt;li>&lt;strong>Operate external systems&lt;/strong>: Connect to enterprise CRM/ERP systems to query data, or connect to IoT devices to control smart home appliances.&lt;/li>
&lt;li>&lt;strong>Execute complex tasks&lt;/strong>: Break down complex user instructions (like &amp;ldquo;help me find and book a cheap flight to Shanghai next week&amp;rdquo;) and complete them by calling multiple APIs in combination.&lt;/li>
&lt;li>&lt;strong>Provide more precise, verifiable answers&lt;/strong>: For queries requiring exact calculations or structured data, LLMs can call calculators or databases instead of relying on their potentially inaccurate internal knowledge.&lt;/li>
&lt;/ul>
&lt;p>Therefore, tool calling is not just a simple extension of LLM functionality, but a core foundation for building truly powerful AI applications that deeply integrate with both the physical and digital worlds.&lt;/p>
&lt;h2 id="2-core-concepts-and-workflow-how-do-llms-learn-to-use-tools">2. Core Concepts and Workflow: How Do LLMs &amp;ldquo;Learn&amp;rdquo; to Use Tools?&lt;/h2>
&lt;p>To understand the underlying logic of tool calling, we need to view it as an elegant process involving three core roles working together:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Large Language Model (LLM)&lt;/strong>: The brain and decision-maker.&lt;/li>
&lt;li>&lt;strong>Tool Definitions&lt;/strong>: A detailed &amp;ldquo;tool instruction manual.&amp;rdquo;&lt;/li>
&lt;li>&lt;strong>Developer/Client-side Code&lt;/strong>: The ultimate &amp;ldquo;executor.&amp;rdquo;&lt;/li>
&lt;/ol>
&lt;p>The LLM itself &lt;strong>never actually executes any code&lt;/strong>. Its only task, after understanding the user's intent and the &amp;ldquo;tool manual&amp;rdquo; it has, is to &lt;strong>generate a JSON data structure that precisely describes which tool should be called and with what parameters&lt;/strong>.&lt;/p>
&lt;p>Below is a visual explanation of this process:&lt;/p>
&lt;pre>&lt;code class="language-mermaid">sequenceDiagram
participant User
participant Client as Client/Application Layer
participant LLM as Large Language Model
participant Tools as External Tools/APIs
User-&amp;gt;&amp;gt;+Client: &amp;quot;What's the weather in Beijing today?&amp;quot;
Client-&amp;gt;&amp;gt;+LLM: Submit user request + Tool Definitions
Note over LLM: 1. Understand user intent&amp;lt;br/&amp;gt;2. Match most appropriate tool (get_weather)&amp;lt;br/&amp;gt;3. Extract required parameters (location: &amp;quot;Beijing&amp;quot;)
LLM--&amp;gt;&amp;gt;-Client: Return JSON: {&amp;quot;tool_calls&amp;quot;: [{&amp;quot;function&amp;quot;: {&amp;quot;name&amp;quot;: &amp;quot;get_weather&amp;quot;, &amp;quot;arguments&amp;quot;: &amp;quot;{\&amp;quot;location\&amp;quot;: \&amp;quot;Beijing\&amp;quot;}&amp;quot;}}]}
Client-&amp;gt;&amp;gt;+Tools: 2. Based on LLM's JSON, call the actual get_weather(&amp;quot;Beijing&amp;quot;) function
Tools--&amp;gt;&amp;gt;-Client: Return weather data (e.g.: {&amp;quot;temperature&amp;quot;: &amp;quot;25°C&amp;quot;, &amp;quot;condition&amp;quot;: &amp;quot;sunny&amp;quot;})
Client-&amp;gt;&amp;gt;+LLM: 3. Submit tool execution result back to LLM
Note over LLM: 4. Understand the data returned by the tool
LLM--&amp;gt;&amp;gt;-Client: 5. Generate user-friendly natural language response
Client-&amp;gt;&amp;gt;-User: &amp;quot;The weather in Beijing today is sunny with a temperature of 25 degrees Celsius.&amp;quot;
&lt;/code>&lt;/pre>
&lt;h3 id="process-breakdown">Process Breakdown:&lt;/h3>
&lt;ol>
&lt;li>
&lt;p>&lt;strong>Define &amp;amp; Describe&lt;/strong>:&lt;/p>
&lt;ul>
&lt;li>Developers first need to define available tools in a structured way (typically using JSON Schema). This &amp;ldquo;manual&amp;rdquo; is crucial to the entire process and must clearly tell the LLM:
&lt;ul>
&lt;li>&lt;strong>Tool name&lt;/strong> (&lt;code>name&lt;/code>): For example, &lt;code>get_weather&lt;/code>.&lt;/li>
&lt;li>&lt;strong>Tool function description&lt;/strong> (&lt;code>description&lt;/code>): For example, &amp;ldquo;Get real-time weather information for a specified city.&amp;rdquo; This is the most important basis for the LLM to understand the tool's purpose.&lt;/li>
&lt;li>&lt;strong>Tool parameters&lt;/strong> (&lt;code>parameters&lt;/code>): Detailed definition of what inputs the tool needs, including each input's name, type (string, number, boolean, etc.), whether it's required, and parameter descriptions.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Intent Recognition &amp;amp; Parameter Extraction&lt;/strong>:&lt;/p>
&lt;ul>
&lt;li>When a user makes a request (e.g., &amp;ldquo;Check the weather in Beijing&amp;rdquo;), the developer's application sends the user's original request &lt;strong>along with all the tool definitions from step 1&lt;/strong> to the LLM.&lt;/li>
&lt;li>The LLM's core task is to do two things:
&lt;ul>
&lt;li>&lt;strong>Intent Recognition&lt;/strong>: Among all available tools, determine which tool's function description best matches the user's request. In this example, it would match &lt;code>get_weather&lt;/code>.&lt;/li>
&lt;li>&lt;strong>Parameter Extraction&lt;/strong>: From the user's request, identify and extract values that satisfy the tool's parameter requirements. Here, it would recognize that the &lt;code>location&lt;/code> parameter value is &amp;ldquo;Beijing&amp;rdquo;.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>After completing these two steps, the LLM generates one or more &lt;code>tool_calls&lt;/code> objects, essentially saying &amp;ldquo;I suggest you call the function named &lt;code>get_weather&lt;/code> and pass in the parameter &lt;code>{ &amp;quot;location&amp;quot;: &amp;quot;Beijing&amp;quot; }&lt;/code>&amp;rdquo;.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Execute &amp;amp; Observe&lt;/strong>:&lt;/p>
&lt;ul>
&lt;li>The developer's application code receives the JSON returned by the LLM and parses this &amp;ldquo;call suggestion.&amp;rdquo;&lt;/li>
&lt;li>The application code &lt;strong>actually executes&lt;/strong> the &lt;code>get_weather(&amp;quot;Beijing&amp;quot;)&lt;/code> function locally or on the server side.&lt;/li>
&lt;li>After execution, it gets a real return result, such as a JSON object containing weather information.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Summarize &amp;amp; Respond&lt;/strong>:&lt;/p>
&lt;ul>
&lt;li>To complete the loop, the application layer needs to submit the actual execution result from the previous step back to the LLM.&lt;/li>
&lt;li>This time, the LLM's task is to understand this raw data returned by the tool (e.g., &lt;code>{&amp;quot;temperature&amp;quot;: &amp;quot;25°C&amp;quot;, &amp;quot;condition&amp;quot;: &amp;quot;sunny&amp;quot;}&lt;/code>) and convert it into a fluent, natural, user-friendly response.&lt;/li>
&lt;li>Finally, the user receives the reply &amp;ldquo;The weather in Beijing today is sunny with a temperature of 25 degrees Celsius,&amp;rdquo; and the entire process is complete.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ol>
&lt;p>This process elegantly combines the LLM's powerful natural language understanding ability with the external tool's powerful functional execution capability, achieving a 1+1&amp;gt;2 effect.&lt;/p>
&lt;h2 id="3-technical-deep-dive-analyzing-the-industry-standard-openai-tool-calling">3. Technical Deep Dive: Analyzing the Industry Standard (OpenAI Tool Calling)&lt;/h2>
&lt;p>OpenAI's API is currently the de facto standard in the field of LLM tool calling, and its design is widely emulated. Understanding its implementation details is crucial for any developer looking to integrate LLM tool calling into their applications.&lt;/p>
&lt;h3 id="31-core-api-parameters">3.1. Core API Parameters&lt;/h3>
&lt;p>When calling OpenAI's Chat Completions API, there are two main parameters related to tool calling: &lt;code>tools&lt;/code> and &lt;code>tool_choice&lt;/code>.&lt;/p>
&lt;h4 id="tools-parameter-your-toolbox">&lt;code>tools&lt;/code> Parameter: Your &amp;ldquo;Toolbox&amp;rdquo;&lt;/h4>
&lt;p>The &lt;code>tools&lt;/code> parameter is an array where you can define one or more tools. Each tool follows a fixed structure, with the core being a &lt;code>function&lt;/code> object defined based on the &lt;strong>JSON Schema&lt;/strong> specification.&lt;/p>
&lt;p>&lt;strong>Example: Defining a weather tool and a flight booking tool&lt;/strong>&lt;/p>
&lt;pre>&lt;code class="language-json">[
{
&amp;quot;type&amp;quot;: &amp;quot;function&amp;quot;,
&amp;quot;function&amp;quot;: {
&amp;quot;name&amp;quot;: &amp;quot;get_current_weather&amp;quot;,
&amp;quot;description&amp;quot;: &amp;quot;Get real-time weather information for a specified location&amp;quot;,
&amp;quot;parameters&amp;quot;: {
&amp;quot;type&amp;quot;: &amp;quot;object&amp;quot;,
&amp;quot;properties&amp;quot;: {
&amp;quot;location&amp;quot;: {
&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;,
&amp;quot;description&amp;quot;: &amp;quot;City and state/province name, e.g., 'San Francisco, CA'&amp;quot;
},
&amp;quot;unit&amp;quot;: {
&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;,
&amp;quot;enum&amp;quot;: [&amp;quot;celsius&amp;quot;, &amp;quot;fahrenheit&amp;quot;],
&amp;quot;description&amp;quot;: &amp;quot;Temperature unit&amp;quot;
}
},
&amp;quot;required&amp;quot;: [&amp;quot;location&amp;quot;]
}
}
},
{
&amp;quot;type&amp;quot;: &amp;quot;function&amp;quot;,
&amp;quot;function&amp;quot;: {
&amp;quot;name&amp;quot;: &amp;quot;book_flight&amp;quot;,
&amp;quot;description&amp;quot;: &amp;quot;Book a flight ticket for the user from departure to destination&amp;quot;,
&amp;quot;parameters&amp;quot;: {
&amp;quot;type&amp;quot;: &amp;quot;object&amp;quot;,
&amp;quot;properties&amp;quot;: {
&amp;quot;departure&amp;quot;: {
&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;,
&amp;quot;description&amp;quot;: &amp;quot;Departure airport or city&amp;quot;
},
&amp;quot;destination&amp;quot;: {
&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;,
&amp;quot;description&amp;quot;: &amp;quot;Destination airport or city&amp;quot;
},
&amp;quot;date&amp;quot;: {
&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;,
&amp;quot;description&amp;quot;: &amp;quot;Desired departure date in YYYY-MM-DD format&amp;quot;
}
},
&amp;quot;required&amp;quot;: [&amp;quot;departure&amp;quot;, &amp;quot;destination&amp;quot;, &amp;quot;date&amp;quot;]
}
}
}
]
&lt;/code>&lt;/pre>
&lt;p>&lt;strong>Key Points Analysis&lt;/strong>:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>&lt;code>type&lt;/code>&lt;/strong>: Currently fixed as &lt;code>&amp;quot;function&amp;quot;&lt;/code>.&lt;/li>
&lt;li>&lt;strong>&lt;code>function.name&lt;/code>&lt;/strong>: Function name. Must be a combination of letters, numbers, and underscores, not exceeding 64 characters. This is the key for your code to identify which function to call.&lt;/li>
&lt;li>&lt;strong>&lt;code>function.description&lt;/code>&lt;/strong>: &lt;strong>Critically important&lt;/strong>. This is the main basis for the LLM to decide whether to select this tool. The description should clearly, accurately, and unambiguously explain what the function does. A good description can greatly improve the LLM's call accuracy.&lt;/li>
&lt;li>&lt;strong>&lt;code>function.parameters&lt;/code>&lt;/strong>: A standard JSON Schema object.
&lt;ul>
&lt;li>&lt;strong>&lt;code>type&lt;/code>&lt;/strong>: Must be &lt;code>&amp;quot;object&amp;quot;&lt;/code>.&lt;/li>
&lt;li>&lt;strong>&lt;code>properties&lt;/code>&lt;/strong>: Defines each parameter's name, type (&lt;code>string&lt;/code>, &lt;code>number&lt;/code>, &lt;code>boolean&lt;/code>, &lt;code>array&lt;/code>, &lt;code>object&lt;/code>), and description. The parameter description is equally important as it helps the LLM understand what information to extract from user input to fill this parameter.&lt;/li>
&lt;li>&lt;strong>&lt;code>required&lt;/code>&lt;/strong>: An array of strings listing which parameters are mandatory. If the user request lacks necessary information, the LLM might ask follow-up questions or choose not to call the tool.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h4 id="toolchoice-parameter-controlling-the-llms-choice">&lt;code>tool_choice&lt;/code> Parameter: Controlling the LLM's Choice&lt;/h4>
&lt;p>By default, the LLM decides on its own whether to respond with text or call one or more tools based on the user's input. The &lt;code>tool_choice&lt;/code> parameter allows you to control this behavior more precisely.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>&lt;code>&amp;quot;none&amp;quot;&lt;/code>&lt;/strong>: Forces the LLM not to call any tools and directly return a text response.&lt;/li>
&lt;li>&lt;strong>&lt;code>&amp;quot;auto&amp;quot;&lt;/code>&lt;/strong> (default): The LLM can freely choose whether to respond with text or call tools.&lt;/li>
&lt;li>&lt;strong>&lt;code>{&amp;quot;type&amp;quot;: &amp;quot;function&amp;quot;, &amp;quot;function&amp;quot;: {&amp;quot;name&amp;quot;: &amp;quot;my_function&amp;quot;}}&lt;/code>&lt;/strong>: Forces the LLM to call this specific tool named &lt;code>my_function&lt;/code>.&lt;/li>
&lt;/ul>
&lt;p>This parameter is very useful in scenarios where you need to enforce a specific process or limit the LLM's capabilities.&lt;/p>
&lt;h3 id="32-requestresponse-lifecycle">3.2. Request-Response Lifecycle&lt;/h3>
&lt;p>A complete tool calling interaction involves at least two API requests.&lt;/p>
&lt;p>&lt;strong>First Request: From User to LLM&lt;/strong>&lt;/p>
&lt;pre>&lt;code class="language-python"># request
response = client.chat.completions.create(
model=&amp;quot;gpt-4o&amp;quot;,
messages=[{&amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;, &amp;quot;content&amp;quot;: &amp;quot;Please book me a flight from New York to London tomorrow&amp;quot;}],
tools=my_tools, # The tool list defined above
tool_choice=&amp;quot;auto&amp;quot;
)
&lt;/code>&lt;/pre>
&lt;p>&lt;strong>First Response: LLM's &amp;ldquo;Call Suggestion&amp;rdquo;&lt;/strong>&lt;/p>
&lt;p>If the LLM decides to call a tool, the API response's &lt;code>finish_reason&lt;/code> will be &lt;code>tool_calls&lt;/code>, and the &lt;code>message&lt;/code> object will contain a &lt;code>tool_calls&lt;/code> array.&lt;/p>
&lt;pre>&lt;code class="language-json">{
&amp;quot;choices&amp;quot;: [
{
&amp;quot;finish_reason&amp;quot;: &amp;quot;tool_calls&amp;quot;,
&amp;quot;message&amp;quot;: {
&amp;quot;role&amp;quot;: &amp;quot;assistant&amp;quot;,
&amp;quot;content&amp;quot;: null,
&amp;quot;tool_calls&amp;quot;: [
{
&amp;quot;id&amp;quot;: &amp;quot;call_abc123&amp;quot;,
&amp;quot;type&amp;quot;: &amp;quot;function&amp;quot;,
&amp;quot;function&amp;quot;: {
&amp;quot;name&amp;quot;: &amp;quot;book_flight&amp;quot;,
&amp;quot;arguments&amp;quot;: &amp;quot;{\&amp;quot;departure\&amp;quot;:\&amp;quot;New York\&amp;quot;,\&amp;quot;destination\&amp;quot;:\&amp;quot;London\&amp;quot;,\&amp;quot;date\&amp;quot;:\&amp;quot;2025-07-01\&amp;quot;}&amp;quot;
}
}
]
}
}
],
...
}
&lt;/code>&lt;/pre>
&lt;p>&lt;strong>Key Points Analysis&lt;/strong>:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>&lt;code>finish_reason&lt;/code>&lt;/strong>: A value of &lt;code>&amp;quot;tool_calls&amp;quot;&lt;/code> indicates that the LLM wants you to execute a tool call, rather than ending the conversation.&lt;/li>
&lt;li>&lt;strong>&lt;code>message.role&lt;/code>&lt;/strong>: &lt;code>assistant&lt;/code>.&lt;/li>
&lt;li>&lt;strong>&lt;code>message.tool_calls&lt;/code>&lt;/strong>: This is an array, meaning the LLM can request multiple tool calls at once.
&lt;ul>
&lt;li>&lt;strong>&lt;code>id&lt;/code>&lt;/strong>: A unique call ID. In subsequent requests, you'll need to use this ID to associate the tool's execution results.&lt;/li>
&lt;li>&lt;strong>&lt;code>function.name&lt;/code>&lt;/strong>: The function name the LLM suggests calling.&lt;/li>
&lt;li>&lt;strong>&lt;code>function.arguments&lt;/code>&lt;/strong>: &lt;strong>A JSON object in string form&lt;/strong>. You need to parse this string to get the specific parameters needed to call the function.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>Second Request: Returning Tool Results to the LLM&lt;/strong>&lt;/p>
&lt;p>After executing the tool in your code, you need to send the results back to the LLM to complete the conversation. At this point, you need to construct a new &lt;code>messages&lt;/code> list that includes:&lt;/p>
&lt;ol>
&lt;li>The original user message.&lt;/li>
&lt;li>The &lt;code>assistant&lt;/code> message returned by the LLM in the previous step (containing &lt;code>tool_calls&lt;/code>).&lt;/li>
&lt;li>A new message with the &lt;code>tool&lt;/code> role, containing the tool's execution results.&lt;/li>
&lt;/ol>
&lt;pre>&lt;code class="language-python"># message history
messages = [
{&amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;, &amp;quot;content&amp;quot;: &amp;quot;Please book me a flight from New York to London tomorrow&amp;quot;},
response.choices[0].message, # Assistant's 'tool_calls' message
{
&amp;quot;tool_call_id&amp;quot;: &amp;quot;call_abc123&amp;quot;, # Must match the ID from the previous step
&amp;quot;role&amp;quot;: &amp;quot;tool&amp;quot;,
&amp;quot;name&amp;quot;: &amp;quot;book_flight&amp;quot;,
&amp;quot;content&amp;quot;: &amp;quot;{\&amp;quot;status\&amp;quot;: \&amp;quot;success\&amp;quot;, \&amp;quot;ticket_id\&amp;quot;: \&amp;quot;TICKET-45678\&amp;quot;}&amp;quot; # Actual return value from the tool
}
]
# second request
second_response = client.chat.completions.create(
model=&amp;quot;gpt-4o&amp;quot;,
messages=messages
)
&lt;/code>&lt;/pre>
&lt;p>&lt;strong>Second Response: LLM's Final Reply&lt;/strong>&lt;/p>
&lt;p>This time, the LLM will generate a natural language response for the user based on the tool's returned results.&lt;/p>
&lt;pre>&lt;code class="language-json">{
&amp;quot;choices&amp;quot;: [
{
&amp;quot;finish_reason&amp;quot;: &amp;quot;stop&amp;quot;,
&amp;quot;message&amp;quot;: {
&amp;quot;role&amp;quot;: &amp;quot;assistant&amp;quot;,
&amp;quot;content&amp;quot;: &amp;quot;Great! I've booked your flight from New York to London for tomorrow. Your ticket ID is TICKET-45678.&amp;quot;
}
}
],
...
}
&lt;/code>&lt;/pre>
&lt;p>With this, a complete tool calling cycle is finished.&lt;/p>
&lt;h2 id="4-code-implementation-a-complete-python-example">4. Code Implementation: A Complete Python Example&lt;/h2>
&lt;p>Below is an end-to-end Python example using OpenAI's Python library to demonstrate how to implement a weather query feature.&lt;/p>
&lt;pre>&lt;code class="language-python">import os
import json
from openai import OpenAI
from dotenv import load_dotenv
# --- 1. Initial Setup ---
load_dotenv() # Load environment variables from .env file
client = OpenAI(api_key=os.getenv(&amp;quot;OPENAI_API_KEY&amp;quot;))
# --- 2. Define Our Local Tool Functions ---
# This is a mock function; in a real application, it would call an actual weather API
def get_current_weather(location, unit=&amp;quot;celsius&amp;quot;):
&amp;quot;&amp;quot;&amp;quot;Get real-time weather information for a specified location&amp;quot;&amp;quot;&amp;quot;
if &amp;quot;New York&amp;quot; in location:
return json.dumps({
&amp;quot;location&amp;quot;: &amp;quot;New York&amp;quot;,
&amp;quot;temperature&amp;quot;: &amp;quot;10&amp;quot;,
&amp;quot;unit&amp;quot;: unit,
&amp;quot;forecast&amp;quot;: [&amp;quot;sunny&amp;quot;, &amp;quot;light breeze&amp;quot;]
})
elif &amp;quot;London&amp;quot; in location:
return json.dumps({
&amp;quot;location&amp;quot;: &amp;quot;London&amp;quot;,
&amp;quot;temperature&amp;quot;: &amp;quot;15&amp;quot;,
&amp;quot;unit&amp;quot;: unit,
&amp;quot;forecast&amp;quot;: [&amp;quot;light rain&amp;quot;, &amp;quot;northeast wind&amp;quot;]
})
else:
return json.dumps({&amp;quot;location&amp;quot;: location, &amp;quot;temperature&amp;quot;: &amp;quot;unknown&amp;quot;})
# --- 3. Main Execution Flow ---
def run_conversation(user_prompt: str):
print(f&amp;quot;👤 User: {user_prompt}&amp;quot;)
# Step 1: Send the user's message and tool definitions to the LLM
messages = [{&amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;, &amp;quot;content&amp;quot;: user_prompt}]
tools = [
{
&amp;quot;type&amp;quot;: &amp;quot;function&amp;quot;,
&amp;quot;function&amp;quot;: {
&amp;quot;name&amp;quot;: &amp;quot;get_current_weather&amp;quot;,
&amp;quot;description&amp;quot;: &amp;quot;Get real-time weather information for a specified city&amp;quot;,
&amp;quot;parameters&amp;quot;: {
&amp;quot;type&amp;quot;: &amp;quot;object&amp;quot;,
&amp;quot;properties&amp;quot;: {
&amp;quot;location&amp;quot;: {
&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;,
&amp;quot;description&amp;quot;: &amp;quot;City name, e.g., New York City&amp;quot;,
},
&amp;quot;unit&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;, &amp;quot;enum&amp;quot;: [&amp;quot;celsius&amp;quot;, &amp;quot;fahrenheit&amp;quot;]},
},
&amp;quot;required&amp;quot;: [&amp;quot;location&amp;quot;],
},
},
}
]
response = client.chat.completions.create(
model=&amp;quot;gpt-4o&amp;quot;,
messages=messages,
tools=tools,
tool_choice=&amp;quot;auto&amp;quot;,
)
response_message = response.choices[0].message
tool_calls = response_message.tool_calls
# Step 2: Check if the LLM decided to call a tool
if tool_calls:
print(f&amp;quot;🤖 LLM decided to call tool: {tool_calls[0].function.name}&amp;quot;)
# Add the LLM's reply to the message history
messages.append(response_message)
# Step 3: Execute the tool call
# Note: This example only handles the first tool call
tool_call = tool_calls[0]
function_name = tool_call.function.name
function_to_call = globals().get(function_name) # Get the function from the global scope
if not function_to_call:
print(f&amp;quot;❌ Error: Function {function_name} is not defined&amp;quot;)
return
function_args = json.loads(tool_call.function.arguments)
# Call the function and get the result
function_response = function_to_call(
location=function_args.get(&amp;quot;location&amp;quot;),
unit=function_args.get(&amp;quot;unit&amp;quot;),
)
print(f&amp;quot;🛠️ Tool '{function_name}' returned: {function_response}&amp;quot;)
# Step 4: Return the tool's execution result to the LLM
messages.append(
{
&amp;quot;tool_call_id&amp;quot;: tool_call.id,
&amp;quot;role&amp;quot;: &amp;quot;tool&amp;quot;,
&amp;quot;name&amp;quot;: function_name,
&amp;quot;content&amp;quot;: function_response,
}
)
print(&amp;quot;🗣️ Submitting tool result back to LLM, generating final response...&amp;quot;)
second_response = client.chat.completions.create(
model=&amp;quot;gpt-4o&amp;quot;,
messages=messages,
)
final_response = second_response.choices[0].message.content
print(f&amp;quot;🤖 LLM final response: {final_response}&amp;quot;)
return final_response
else:
# If the LLM didn't call any tools, directly return its text content
final_response = response_message.content
print(f&amp;quot;🤖 LLM direct response: {final_response}&amp;quot;)
return final_response
# --- Run Examples ---
if __name__ == &amp;quot;__main__&amp;quot;:
run_conversation(&amp;quot;What's the weather like in London today?&amp;quot;)
print(&amp;quot;\n&amp;quot; + &amp;quot;=&amp;quot;*50 + &amp;quot;\n&amp;quot;)
run_conversation(&amp;quot;How are you?&amp;quot;)
&lt;/code>&lt;/pre>
&lt;p>This example clearly demonstrates the entire process from defining tools, sending requests, handling &lt;code>tool_calls&lt;/code>, executing local functions, to sending results back to the model to get the final answer.&lt;/p>
&lt;h2 id="5-advanced-topics-and-best-practices">5. Advanced Topics and Best Practices&lt;/h2>
&lt;p>After mastering the basic process, we need to understand some advanced usage and design principles to build more robust and reliable tool calling systems.&lt;/p>
&lt;h3 id="51-parallel-tool-calling">5.1. Parallel Tool Calling&lt;/h3>
&lt;p>Newer models (like &lt;code>gpt-4o&lt;/code>) support parallel tool calling. This means the model can request multiple different, independent tools to be called in a single response.&lt;/p>
&lt;p>&lt;strong>Scenario Example&lt;/strong>: User asks: &amp;ldquo;What's the weather like in New York and London today?&amp;rdquo;&lt;/p>
&lt;p>The model might return a response containing two &lt;code>tool_calls&lt;/code>:&lt;/p>
&lt;ol>
&lt;li>&lt;code>get_current_weather(location=&amp;quot;New York&amp;quot;)&lt;/code>&lt;/li>
&lt;li>&lt;code>get_current_weather(location=&amp;quot;London&amp;quot;)&lt;/code>&lt;/li>
&lt;/ol>
&lt;p>Your code needs to be able to iterate through each &lt;code>tool_call&lt;/code> object in the &lt;code>message.tool_calls&lt;/code> array, execute them separately, collect all results, and then submit these results together in a new request to the model.&lt;/p>
&lt;p>&lt;strong>Code Handling Logic&lt;/strong>:&lt;/p>
&lt;pre>&lt;code class="language-python"># ... (received response_message containing multiple tool_calls)
messages.append(response_message) # Add assistant's reply to messages
# Execute functions for each tool call and collect results
tool_outputs = []
for tool_call in tool_calls:
function_name = tool_call.function.name
function_to_call = available_functions[function_name]
function_args = json.loads(tool_call.function.arguments)
output = function_to_call(**function_args)
tool_outputs.append({
&amp;quot;tool_call_id&amp;quot;: tool_call.id,
&amp;quot;role&amp;quot;: &amp;quot;tool&amp;quot;,
&amp;quot;name&amp;quot;: function_name,
&amp;quot;content&amp;quot;: output,
})
# Add all tool outputs to the message history
messages.extend(tool_outputs)
# Call the model again
second_response = client.chat.completions.create(
model=&amp;quot;gpt-4o&amp;quot;,
messages=messages
)
&lt;/code>&lt;/pre>
&lt;h3 id="52-error-handling">5.2. Error Handling&lt;/h3>
&lt;p>Tool calls are not always successful. APIs might time out, databases might be unreachable, or the function execution itself might throw exceptions. Gracefully handling these errors is crucial.&lt;/p>
&lt;p>When a tool execution fails, you should catch the exception and return structured information describing the error as the result of the tool call to the LLM.&lt;/p>
&lt;p>&lt;strong>Example&lt;/strong>:&lt;/p>
&lt;pre>&lt;code class="language-python">try:
# Try to call the API
result = some_flaky_api()
content = json.dumps({&amp;quot;status&amp;quot;: &amp;quot;success&amp;quot;, &amp;quot;data&amp;quot;: result})
except Exception as e:
# If it fails, return error information
content = json.dumps({&amp;quot;status&amp;quot;: &amp;quot;error&amp;quot;, &amp;quot;message&amp;quot;: f&amp;quot;API call failed: {str(e)}&amp;quot;})
# Return the result (whether successful or failed) to the LLM
messages.append({
&amp;quot;tool_call_id&amp;quot;: tool_call.id,
&amp;quot;role&amp;quot;: &amp;quot;tool&amp;quot;,
&amp;quot;name&amp;quot;: function_name,
&amp;quot;content&amp;quot;: content,
})
&lt;/code>&lt;/pre>
&lt;p>When the LLM receives error information, it typically responds to the user with an apologetic answer that reflects the problem (e.g., &amp;ldquo;Sorry, I'm currently unable to retrieve weather information. Please try again later.&amp;quot;) rather than causing the entire application to crash.&lt;/p>
&lt;h3 id="53-designing-effective-tool-descriptions">5.3. Designing Effective Tool Descriptions&lt;/h3>
&lt;p>&lt;strong>The quality of the tool description (&lt;code>description&lt;/code>) directly determines the LLM's call accuracy.&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Clear and Specific&lt;/strong>: Avoid using vague terms.
&lt;ul>
&lt;li>&lt;strong>Bad&lt;/strong>: &amp;ldquo;Get data&amp;rdquo;&lt;/li>
&lt;li>&lt;strong>Good&lt;/strong>: &amp;ldquo;Query the user's order history from the company's CRM system based on user ID&amp;rdquo;&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>Include Key Information and Limitations&lt;/strong>: If the tool has specific limitations, be sure to mention them in the description.
&lt;ul>
&lt;li>&lt;strong>Example&lt;/strong>: &amp;ldquo;Query flight information. Note: This tool can only query flights within the next 30 days and cannot query historical flights.&amp;rdquo;&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>Start with a Verb&lt;/strong>: Use a clear verb to describe the core functionality of the function.&lt;/li>
&lt;li>&lt;strong>Clear Parameter Descriptions&lt;/strong>: The &lt;code>description&lt;/code> of parameters is equally important; it guides the LLM on how to correctly extract information from user conversations.
&lt;ul>
&lt;li>&lt;strong>Bad&lt;/strong>: &lt;code>&amp;quot;date&amp;quot;: &amp;quot;A date&amp;quot;&lt;/code>&lt;/li>
&lt;li>&lt;strong>Good&lt;/strong>: &lt;code>&amp;quot;date&amp;quot;: &amp;quot;Booking date, must be a string in YYYY-MM-DD format&amp;quot;&lt;/code>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h3 id="54-security-considerations">5.4. Security Considerations&lt;/h3>
&lt;p>Giving LLMs the ability to call code is a double-edged sword and must be handled with caution.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Never Execute Code Generated by LLMs&lt;/strong>: The LLM's output is a &amp;ldquo;call suggestion,&amp;rdquo; not executable code. Never use &lt;code>eval()&lt;/code> or similar methods to directly execute strings generated by LLMs. You should parse the suggested function name and parameters, then call your pre-defined, safe, and trusted local functions.&lt;/li>
&lt;li>&lt;strong>Confirmation and Authorization&lt;/strong>: For operations with serious consequences (like deleting data, sending emails, making payments), implement a confirmation mechanism before execution. This could be forcing user confirmation at the code level or having the LLM generate a confirmation message after generating the call suggestion.&lt;/li>
&lt;li>&lt;strong>Principle of Least Privilege&lt;/strong>: Only provide the LLM with the minimum tools necessary to complete its task. Don't expose your entire codebase or irrelevant APIs.&lt;/li>
&lt;/ul>
&lt;h2 id="6-conclusion-and-future-outlook">6. Conclusion and Future Outlook&lt;/h2>
&lt;p>LLM tool calling is one of the most breakthrough advances in artificial intelligence in recent years. It transforms LLMs from closed &amp;ldquo;language brains&amp;rdquo; into open, extensible &amp;ldquo;intelligent agent&amp;rdquo; cores capable of interacting with the world. By combining the powerful natural language understanding capabilities of LLMs with the unlimited functionality of external tools, we can build unprecedented intelligent applications.&lt;/p>
&lt;p>From querying weather and booking hotels to controlling smart homes, analyzing corporate financial reports, and automating software development processes, tool calling is unlocking countless possibilities. As model capabilities continue to strengthen, tool description understanding will become more precise, multi-tool coordination will become more complex and intelligent, and error handling and self-correction capabilities will become stronger.&lt;/p>
&lt;p>In the future, we may see more complex Agentic architectures where LLMs not only call tools but can dynamically create, combine, and even optimize tools. Mastering the principles and practices of LLM tool calling is not only an essential skill to keep up with the current AI technology wave but also a key to future intelligent application development.&lt;/p></description></item><item><title>TensorRT In-Depth: High-Performance Deep Learning Inference Engine</title><link>https://ziyanglin.netlify.app/en/post/tensorrt-documentation/</link><pubDate>Mon, 30 Jun 2025 06:00:00 +0000</pubDate><guid>https://ziyanglin.netlify.app/en/post/tensorrt-documentation/</guid><description>&lt;h2 id="1-introduction">1. Introduction&lt;/h2>
&lt;p>NVIDIA® TensorRT™ is a software development kit (SDK) for high-performance deep learning inference on NVIDIA GPUs. It is designed to optimize and accelerate trained neural networks, enabling them to run in production environments with low latency and high throughput. TensorRT takes models from mainstream deep learning frameworks (such as TensorFlow, PyTorch, ONNX, etc.), applies a series of sophisticated optimization techniques, and generates a highly optimized runtime engine.&lt;/p>
&lt;p>This document will provide an in-depth yet accessible introduction to TensorRT's core concepts, key features, workflow, and latest functionalities (including TensorRT-LLM specifically designed for accelerating large language models), helping developers fully leverage its powerful performance advantages.&lt;/p>
&lt;h2 id="2-core-concepts">2. Core Concepts&lt;/h2>
&lt;p>Understanding TensorRT's core components is the first step to using it effectively.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Engine&lt;/strong>: The core of TensorRT. It is an optimized model representation that includes a computation graph and weights generated for a specific GPU architecture and configuration (such as batch size, precision). The Engine is immutable and is the final product for deployment.&lt;/li>
&lt;li>&lt;strong>Builder (&lt;code>IBuilder&lt;/code>)&lt;/strong>: This is the main interface for creating an Engine. The Builder takes a network definition and applies various optimizations, ultimately generating an optimized plan for the target GPU, which can be serialized into an Engine.&lt;/li>
&lt;li>&lt;strong>Network Definition (&lt;code>INetworkDefinition&lt;/code>)&lt;/strong>: This is where you define the model structure. You can build the network manually from scratch or import it from a model file using a Parser.&lt;/li>
&lt;li>&lt;strong>Parser&lt;/strong>: Used to parse models from different frameworks (primarily ONNX format) and convert them into TensorRT's network definition. TensorRT provides a powerful ONNX parser.&lt;/li>
&lt;li>&lt;strong>Profiler (&lt;code>IProfiler&lt;/code>)&lt;/strong>: An optional interface that allows you to collect and query information about layer performance during the build process. This helps with debugging and understanding which layers are performance bottlenecks.&lt;/li>
&lt;li>&lt;strong>Execution Context (&lt;code>IExecutionContext&lt;/code>)&lt;/strong>: This is the main interface for executing inference. An Engine can have multiple Execution Contexts, allowing concurrent execution of inference tasks. Each context maintains its own inputs, outputs, and state.&lt;/li>
&lt;/ul>
&lt;pre>&lt;code class="language-mermaid">graph TD;
subgraph &amp;quot;Model Building Offline&amp;quot;
A[Original Model&amp;lt;br&amp;gt;TensorFlow/PyTorch] --&amp;gt; B{ONNX Parser};
B --&amp;gt; C[Network Definition];
C --&amp;gt; D[Builder];
D -- Optimization Config --&amp;gt; E[Optimized Plan];
E --&amp;gt; F((Engine));
end
subgraph &amp;quot;Inference Deployment Online&amp;quot;
F --&amp;gt; G[Execution Context];
H[Input Data] --&amp;gt; G;
G --&amp;gt; I[Output Results];
end
style F fill:#f9f,stroke:#333,stroke-width:2px
style G fill:#ccf,stroke:#333,stroke-width:2px
&lt;/code>&lt;/pre>
&lt;h2 id="3-key-features-and-optimization-techniques">3. Key Features and Optimization Techniques&lt;/h2>
&lt;p>TensorRT's high performance stems from its advanced optimization techniques.&lt;/p>
&lt;h3 id="31-precision-calibration--quantization">3.1. Precision Calibration &amp;amp; Quantization&lt;/h3>
&lt;p>TensorRT supports multiple precisions for inference, including FP32, FP16, INT8, and the latest FP8. Among these, INT8 quantization is a key technology for improving performance and reducing memory usage.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Post-Training Quantization (PTQ)&lt;/strong>: Determines the scaling factors needed to convert FP32 weights and activation values to INT8 through a calibration dataset, without retraining the model.&lt;/li>
&lt;li>&lt;strong>Quantization-Aware Training (QAT)&lt;/strong>: Simulates quantization operations during training, making the model more robust to quantization errors, thus achieving higher accuracy when converted to INT8.&lt;/li>
&lt;/ul>
&lt;p>You can use &lt;code>QuantizationSpec&lt;/code> to precisely control which layers or types of layers need to be quantized.&lt;/p>
&lt;pre>&lt;code class="language-python"># Example: Only quantize 'Conv2D' type layers
q_spec = QuantizationSpec()
q_spec.add(name='Conv2D', is_keras_class=True)
q_model = quantize_model(model, quantization_mode='partial', quantization_spec=q_spec)
&lt;/code>&lt;/pre>
&lt;h3 id="32-layer--tensor-fusion">3.2. Layer &amp;amp; Tensor Fusion&lt;/h3>
&lt;p>TensorRT intelligently merges multiple independent layers into a single, more complex layer. This reduces the number of CUDA kernel launches and memory reads/writes, significantly lowering latency.&lt;/p>
&lt;ul>
&lt;li>
&lt;p>&lt;strong>Vertical Fusion&lt;/strong>: Merges consecutive layers with the same data dependencies (such as Conv, Bias, ReLU) into a single CBR layer.&lt;/p>
&lt;pre>&lt;code class="language-mermaid">graph TD;
subgraph &amp;quot;Before Fusion&amp;quot;
A[Input] --&amp;gt; B(Conv);
B --&amp;gt; C(Bias);
C --&amp;gt; D(ReLU);
D --&amp;gt; E[Output];
end
subgraph &amp;quot;After Fusion&amp;quot;
A2[Input] --&amp;gt; F((Conv + Bias + ReLU));
F --&amp;gt; E2[Output];
end
&lt;/code>&lt;/pre>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Horizontal Fusion&lt;/strong>: Merges parallel layers that have the same input but perform different operations.&lt;/p>
&lt;pre>&lt;code class="language-mermaid">graph TD;
subgraph &amp;quot;Before Fusion&amp;quot;
A[Input] --&amp;gt; B(Conv A);
A --&amp;gt; C(Conv B);
B --&amp;gt; D[Output A];
C --&amp;gt; E[Output B];
end
subgraph &amp;quot;After Fusion&amp;quot;
A2[Input] --&amp;gt; F((Conv A + Conv B));
F --&amp;gt; D2[Output A];
F --&amp;gt; E2[Output B];
end
&lt;/code>&lt;/pre>
&lt;/li>
&lt;/ul>
&lt;h3 id="33-kernel-autotuning">3.3. Kernel Auto-Tuning&lt;/h3>
&lt;p>For specific target GPU architectures, TensorRT selects the optimal CUDA kernel for each layer from a library containing multiple implementations. It tests different algorithms and implementations based on the current batch size, input dimensions, and parameters to find the fastest one.&lt;/p>
&lt;h3 id="34-dynamic-shapes">3.4. Dynamic Shapes&lt;/h3>
&lt;p>TensorRT can handle models with input tensor dimensions that vary at runtime. When building an Engine, you can specify an optimization profile that includes minimum, optimal, and maximum dimensions for inputs. TensorRT will generate an Engine that can efficiently handle any input dimensions within the specified range.&lt;/p>
&lt;h3 id="35-plugins">3.5. Plugins&lt;/h3>
&lt;p>For custom or special layers not natively supported by TensorRT, you can implement your own logic through the plugin API (&lt;code>IPluginV2&lt;/code>). This provides great extensibility for TensorRT.&lt;/p>
&lt;p>The latest versions of TensorRT have greatly simplified the plugin registration process through decorators, especially for the Python API.&lt;/p>
&lt;pre>&lt;code class="language-python"># Example: Register a simple element-wise addition plugin
import tensorrt.plugin as trtp
@trtp.register(&amp;quot;sample::elemwise_add_plugin&amp;quot;)
def add_plugin_desc(inp0: trtp.TensorDesc, block_size: int) -&amp;gt; trtp.TensorDesc:
return inp0.like()
&lt;/code>&lt;/pre>
&lt;h3 id="36-sparsity">3.6. Sparsity&lt;/h3>
&lt;p>TensorRT supports leveraging structured sparsity features on NVIDIA Ampere and higher architecture GPUs. If your model weights have a 2:4 sparsity pattern, TensorRT can utilize sparse tensor cores to further accelerate computation, nearly doubling performance.&lt;/p>
&lt;h2 id="4-workflow">4. Workflow&lt;/h2>
&lt;p>A typical TensorRT deployment workflow is as follows:&lt;/p>
&lt;pre>&lt;code class="language-mermaid">sequenceDiagram
participant D as Developer
participant TF as TensorFlow/PyTorch
participant ONNX
participant Poly as Polygraphy
participant TRT as TensorRT (trtexec/API)
participant App as Application
D-&amp;gt;&amp;gt;TF: Train Model
TF--&amp;gt;&amp;gt;D: Generate Trained Model
D-&amp;gt;&amp;gt;ONNX: Export to ONNX Format
ONNX--&amp;gt;&amp;gt;D: .onnx File
D-&amp;gt;&amp;gt;Poly: Use Polygraphy to Check and Optimize
Poly--&amp;gt;&amp;gt;D: Optimized .onnx File
D-&amp;gt;&amp;gt;TRT: Build Engine (FP16/INT8)
TRT--&amp;gt;&amp;gt;D: Generate .engine File
D-&amp;gt;&amp;gt;App: Deploy Engine
App-&amp;gt;&amp;gt;App: Load Engine and Create Execution Context
loop Inference Loop
App-&amp;gt;&amp;gt;App: Prepare Input Data
App-&amp;gt;&amp;gt;App: Execute Inference
App-&amp;gt;&amp;gt;App: Get Output Results
end
&lt;/code>&lt;/pre>
&lt;ol>
&lt;li>
&lt;p>&lt;strong>Model Export&lt;/strong>: Export your trained model from your training framework (such as PyTorch or TensorFlow) to ONNX format. ONNX is an open model exchange format that serves as a bridge between training and inference.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Model Inspection and Optimization (Polygraphy)&lt;/strong>: Before building an Engine, it is strongly recommended to use the &lt;strong>Polygraphy&lt;/strong> toolkit to inspect, modify, and optimize your ONNX model. Polygraphy is a powerful tool that can:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Inspect Models&lt;/strong>: Display information about the model's layers, inputs, outputs, etc.&lt;/li>
&lt;li>&lt;strong>Constant Folding&lt;/strong>: Pre-compute constant expressions in the model, simplifying the computation graph.
&lt;pre>&lt;code class="language-bash">polygraphy surgeon sanitize model.onnx -o folded.onnx --fold-constants
&lt;/code>&lt;/pre>
&lt;/li>
&lt;li>&lt;strong>Compare Outputs from Different Frameworks&lt;/strong>: Verify that TensorRT's output is consistent with the original framework (such as ONNX Runtime) to troubleshoot precision issues.
&lt;pre>&lt;code class="language-bash">polygraphy run model.onnx --trt --onnxrt
&lt;/code>&lt;/pre>
&lt;/li>
&lt;li>&lt;strong>Handle Data-Dependent Shapes (DDS)&lt;/strong>: Identify and set upper bounds for tensors with data-dependent shapes.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Build Engine&lt;/strong>: Use the &lt;code>trtexec&lt;/code> command-line tool or TensorRT's C++/Python API to build an Engine.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>&lt;code>trtexec&lt;/code>&lt;/strong>: A convenient command-line tool for quickly building an Engine from an ONNX file and conducting performance benchmarking.
&lt;pre>&lt;code class="language-bash">trtexec --onnx=model.onnx --saveEngine=model.engine --fp16
&lt;/code>&lt;/pre>
&lt;/li>
&lt;li>&lt;strong>API&lt;/strong>: Provides more flexible control, such as defining optimization profiles for dynamic shapes, configuring plugins, etc.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Deployment and Inference&lt;/strong>: Load the serialized Engine file into your application and use an Execution Context to perform inference.&lt;/p>
&lt;pre>&lt;code class="language-python"># Using Polygraphy's TrtRunner for inference
from polygraphy.backend.trt import TrtRunner, EngineFromBytes
# Load Engine
engine = EngineFromBytes(open(&amp;quot;model.engine&amp;quot;, &amp;quot;rb&amp;quot;).read())
with TrtRunner(engine) as runner:
# Prepare input data
feed_dict = {&amp;quot;input_name&amp;quot;: input_data}
# Execute inference
outputs = runner.infer(feed_dict=feed_dict)
&lt;/code>&lt;/pre>
&lt;/li>
&lt;/ol>
&lt;h2 id="5-latest-feature-highlights">5. Latest Feature Highlights&lt;/h2>
&lt;p>TensorRT is rapidly iterating, and here are some of the latest important features:&lt;/p>
&lt;ul>
&lt;li>
&lt;p>&lt;strong>Polygraphy Tool Enhancements&lt;/strong>:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Simplified CLI Syntax&lt;/strong>: Allows specifying both script and function name in a single parameter (&lt;code>my_script.py:my_func&lt;/code>).&lt;/li>
&lt;li>&lt;strong>Improved Input Specification&lt;/strong>: Uses a new list-style syntax (&lt;code>--input-shapes input0:[x,y,z]&lt;/code>) to avoid ambiguity.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Quickly Deployable Plugins&lt;/strong>:&lt;/p>
&lt;ul>
&lt;li>The Python API has introduced &lt;a href="mailto:%60@trtp.register">`@trtp.register&lt;/a>&lt;code>and&lt;/code>@trt.plugin.autotune` decorators, making it unprecedentedly simple to define, register, and auto-tune plugins without writing C++ code.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>CUDA Graphs&lt;/strong>:&lt;/p>
&lt;ul>
&lt;li>Through the &lt;code>--use-cuda-graph&lt;/code> flag, TensorRT can leverage CUDA Graphs to capture the entire inference process, further reducing CPU overhead and kernel launch latency, particularly suitable for scenarios with fixed model structures.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>FP8 Support&lt;/strong>:&lt;/p>
&lt;ul>
&lt;li>On Hopper and higher architecture GPUs, TensorRT supports FP8 inference, providing higher performance and lower memory usage for large language models and other applications.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h2 id="6-appendix-common-commands">6. Appendix: Common Commands&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>Install Polygraphy&lt;/strong>:
&lt;pre>&lt;code class="language-bash">python3 -m pip install polygraphy --extra-index-url https://pypi.ngc.nvidia.com
&lt;/code>&lt;/pre>
&lt;/li>
&lt;li>&lt;strong>Build and Install TensorRT Open Source Components&lt;/strong>:
&lt;pre>&lt;code class="language-bash"># From source directory
make install
&lt;/code>&lt;/pre>
&lt;/li>
&lt;li>&lt;strong>Run pytest Tests&lt;/strong>:
&lt;pre>&lt;code class="language-bash">pytest --verbose
&lt;/code>&lt;/pre>
&lt;/li>
&lt;/ul>
&lt;h2 id="7-tensorrtllm-born-for-large-language-model-inference">7. TensorRT-LLM: Born for Large Language Model Inference&lt;/h2>
&lt;p>As the scale and complexity of large language models (LLMs) grow exponentially, traditional inference optimization methods face unprecedented challenges. To address these challenges, NVIDIA has introduced TensorRT-LLM, an open-source library specifically designed to accelerate and optimize LLM inference. It is built on top of TensorRT and encapsulates a series of cutting-edge optimization techniques for LLMs.&lt;/p>
&lt;h3 id="71-what-is-tensorrtllm">7.1. What is TensorRT-LLM?&lt;/h3>
&lt;p>TensorRT-LLM can be thought of as an &amp;ldquo;LLM expert version&amp;rdquo; of TensorRT. It provides a Python API that allows developers to easily define LLM models and automatically apply various state-of-the-art optimizations. Ultimately, it generates a high-performance TensorRT engine that can be directly deployed.&lt;/p>
&lt;p>Unlike general TensorRT which mainly handles static graphs, TensorRT-LLM specifically addresses the dynamic characteristics in LLM inference, such as:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Autoregressive Generation&lt;/strong>: Each newly generated token depends on the previous tokens, resulting in dynamically changing input sequence lengths.&lt;/li>
&lt;li>&lt;strong>Enormous Model Scale&lt;/strong>: Model parameters often number in the billions or even hundreds of billions, making it impossible to deploy on a single GPU.&lt;/li>
&lt;li>&lt;strong>Massive KV Cache&lt;/strong>: The inference process requires storing a large number of key-value pairs (Key-Value Cache), placing extremely high demands on memory bandwidth and capacity.&lt;/li>
&lt;/ul>
&lt;h3 id="72-core-architecture-and-components">7.2. Core Architecture and Components&lt;/h3>
&lt;p>TensorRT-LLM's architecture is divided into frontend and backend:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Python API (&lt;code>tensorrt_llm&lt;/code>)&lt;/strong>: This is the main interface for user interaction. It defines models in a declarative way (similar to PyTorch), allowing developers to avoid dealing with the complex underlying TensorRT C++ API.&lt;/li>
&lt;li>&lt;strong>C++ Backend&lt;/strong>: This is the core that actually performs the optimization, containing pre-written, highly optimized CUDA kernels, LLM-specific optimization passes, and a runtime that can efficiently handle LLM tasks.&lt;/li>
&lt;/ul>
&lt;pre>&lt;code class="language-mermaid">graph TD;
subgraph &amp;quot;Frontend (Python API)&amp;quot;
A[Hugging Face / Custom Model] --&amp;gt;|Weights| B(Model Definition&amp;lt;br&amp;gt;tensorrt_llm.Module);
B --&amp;gt; C{Builder};
C -- Generate Network and Config --&amp;gt; D[Network Definition];
end
subgraph &amp;quot;Backend (C++ Runtime)&amp;quot;
D --&amp;gt; E[TensorRT-LLM Optimization];
E --&amp;gt; F((LLM Optimized Engine));
end
subgraph &amp;quot;Inference&amp;quot;
F --&amp;gt; G[C++/Python Runtime];
H[Input Prompts] --&amp;gt; G;
G --&amp;gt; I[Output Tokens];
end
style F fill:#c9f,stroke:#333,stroke-width:2px
&lt;/code>&lt;/pre>
&lt;h3 id="73-key-optimization-techniques-llmspecific">7.3. Key Optimization Techniques (LLM-Specific)&lt;/h3>
&lt;p>The magic of TensorRT-LLM lies in its optimization techniques specifically designed for LLMs.&lt;/p>
&lt;h4 id="731-inflight-batching-also-known-as-continuous-batching">7.3.1. In-Flight Batching (also known as Continuous Batching)&lt;/h4>
&lt;p>&lt;strong>Problem&lt;/strong>: Traditional static batching requires all requests to wait until a batch is formed before processing them together. Due to the varying generation lengths of each request, this leads to significant GPU idle time (&amp;ldquo;bubbles&amp;rdquo;), as the batch must wait for the slowest request to complete.&lt;/p>
&lt;p>&lt;strong>Solution&lt;/strong>: In-Flight Batching allows the server to dynamically add new requests while the GPU is running. Once a request completes, its computational resources are immediately released and allocated to new requests in the waiting queue. This greatly improves GPU utilization and overall system throughput.&lt;/p>
&lt;pre>&lt;code class="language-mermaid">gantt
title GPU Utilization Comparison
dateFormat X
axisFormat %S
section Static Batching
Request A: 0, 6
Request B: 0, 3
Request C: 0, 5
GPU Waiting : 3, 3
GPU Waiting : 5, 1
section In-Flight Batching
Request A : 0, 6
Request B : 0, 3
Request C : 0, 5
New Request D : 3, 4
&lt;/code>&lt;/pre>
&lt;h4 id="732-paged-kv-cache--attention">7.3.2. Paged KV Cache &amp;amp; Attention&lt;/h4>
&lt;p>&lt;strong>Problem&lt;/strong>: In the autoregressive generation process, the KV cache grows linearly with sequence length, consuming large amounts of GPU memory. The traditional approach is to pre-allocate a continuous memory block for each request that can accommodate the maximum sequence length, leading to severe memory fragmentation and waste.&lt;/p>
&lt;p>&lt;strong>Solution&lt;/strong>: Inspired by operating system virtual memory paging, TensorRT-LLM introduced Paged KV Cache. It divides the KV cache into fixed-size &amp;ldquo;blocks&amp;rdquo; and allocates them as needed.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Non-contiguous Storage&lt;/strong>: KV caches for logically continuous tokens can be stored in physically non-contiguous blocks.&lt;/li>
&lt;li>&lt;strong>Memory Sharing&lt;/strong>: For complex scenarios (such as parallel sampling, Beam Search), different sequences can share the same KV cache blocks (e.g., sharing the cache for the prompt portion), significantly saving memory.&lt;/li>
&lt;li>&lt;strong>Optimized Attention Kernels&lt;/strong>: TensorRT-LLM uses specially optimized Attention kernels such as FlashAttention and MQA/GQA that can directly operate on these non-contiguous cache blocks, avoiding data copy overhead.&lt;/li>
&lt;/ul>
&lt;h4 id="733-tensor--pipeline-parallelism">7.3.3. Tensor &amp;amp; Pipeline Parallelism&lt;/h4>
&lt;p>For large models that cannot fit on a single GPU, TensorRT-LLM has built-in seamless support for tensor parallelism and pipeline parallelism. Developers only need to specify the parallelism degree (&lt;code>tp_size&lt;/code>, &lt;code>pp_size&lt;/code>) during building, and TensorRT-LLM will automatically handle model splitting and cross-GPU communication.&lt;/p>
&lt;pre>&lt;code class="language-bash"># Example: Build a Llama model with 2-way tensor parallelism
python3 examples/llama/convert_checkpoint.py \
--model_dir ./llama-7b-hf \
--output_dir ./tllm_checkpoint_tp2 \
--dtype float16 \
--tp_size 2
&lt;/code>&lt;/pre>
&lt;h4 id="734-advanced-quantization-support-fp8int4int8">7.3.4. Advanced Quantization Support (FP8/INT4/INT8)&lt;/h4>
&lt;p>The enormous parameter count of LLMs makes them ideal candidates for quantization. TensorRT-LLM supports various advanced quantization schemes:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>FP8&lt;/strong>: On NVIDIA Hopper and higher architecture GPUs, FP8 provides precision close to FP16 while significantly improving performance and reducing memory usage.&lt;/li>
&lt;li>&lt;strong>INT8 SmoothQuant&lt;/strong>: A technique that quantizes both activations and weights, achieving INT8 acceleration while maintaining high precision.&lt;/li>
&lt;li>&lt;strong>INT4/INT8 Weight-Only Quantization (W4A16/W8A16)&lt;/strong>: This is a very popular technique that only quantizes model weights (the largest part of parameters) to INT4 or INT8, while keeping activations in FP16. This greatly reduces memory usage with minimal impact on accuracy.&lt;/li>
&lt;/ul>
&lt;pre>&lt;code class="language-bash"># Example: Build a model with INT4 weight-only quantization
python convert_checkpoint.py --model_dir ./gpt-j-6b \
--dtype float16 \
--use_weight_only \
--weight_only_precision int4 \
--output_dir ./trt_ckpt/gptj_int4wo_tp1/
&lt;/code>&lt;/pre>
&lt;h3 id="74-tensorrtllm-workflow">7.4. TensorRT-LLM Workflow&lt;/h3>
&lt;p>A typical TensorRT-LLM workflow is as follows:&lt;/p>
&lt;pre>&lt;code class="language-mermaid">sequenceDiagram
participant D as Developer
participant HF as Hugging Face Hub
participant Conv as convert_checkpoint.py
participant Build as trtllm-build
participant App as Inference Application (Python/C++)
D-&amp;gt;&amp;gt;HF: Download Model Weights
HF--&amp;gt;&amp;gt;D: model_dir
D-&amp;gt;&amp;gt;Conv: Run Conversion Script (Specify Precision, Parallelism, etc.)
Conv--&amp;gt;&amp;gt;D: Generate TensorRT-LLM Checkpoint
D-&amp;gt;&amp;gt;Build: Run Build Command (Specify Plugins, BatchSize, etc.)
Build--&amp;gt;&amp;gt;D: Generate Optimized .engine File
D-&amp;gt;&amp;gt;App: Load Engine and Run Inference
App--&amp;gt;&amp;gt;D: Return Generation Results
&lt;/code>&lt;/pre>
&lt;p>&lt;strong>End-to-End Example (Using Llama-7B)&lt;/strong>:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Convert Weights&lt;/strong>:
&lt;pre>&lt;code class="language-bash">git clone https://huggingface.co/meta-llama/Llama-2-7b-hf
python3 examples/llama/convert_checkpoint.py \
--model_dir ./Llama-2-7b-hf \
--output_dir ./tllm_checkpoint_1gpu \
--dtype float16
&lt;/code>&lt;/pre>
&lt;/li>
&lt;li>&lt;strong>Build Engine&lt;/strong>:
&lt;pre>&lt;code class="language-bash">trtllm-build --checkpoint_dir ./tllm_checkpoint_1gpu \
--output_dir ./trt_engines/llama_7b \
--gpt_attention_plugin float16 \
--gemm_plugin float16
&lt;/code>&lt;/pre>
&lt;/li>
&lt;li>&lt;strong>Run Inference&lt;/strong>:
&lt;pre>&lt;code class="language-bash">python3 examples/run.py --max_output_len=100 \
--tokenizer_dir ./Llama-2-7b-hf \
--engine_dir=./trt_engines/llama_7b
&lt;/code>&lt;/pre>
&lt;/li>
&lt;/ol>
&lt;h3 id="75-convenient-highlevel-api-llm">7.5. Convenient High-Level API (&lt;code>LLM&lt;/code>)&lt;/h3>
&lt;p>To further simplify the development process, TensorRT-LLM provides a high-level API called &lt;code>LLM&lt;/code>. This interface encapsulates model loading, building, saving, and inference into a simple class, allowing developers to complete all operations in just a few lines of code.&lt;/p>
&lt;pre>&lt;code class="language-python">from tensorrt_llm import LLM
# 1. Initialize LLM object, if the engine doesn't exist, it will automatically build from HuggingFace model
# All optimizations like In-Flight Batching, Paged KV-Cache will be applied here
llm = LLM(
model=&amp;quot;meta-llama/Llama-2-7b-hf&amp;quot;,
tensor_parallel_size=1,
)
# 2. (Optional) Save the built engine for later use
llm.save(&amp;quot;llama_engine_dir&amp;quot;)
# 3. Run inference
prompt = &amp;quot;NVIDIA TensorRT-LLM is&amp;quot;
for output in llm.generate([prompt], max_new_tokens=50):
print(output)
&lt;/code>&lt;/pre>
&lt;p>This high-level API is ideal for rapid prototyping and deployment.&lt;/p>
&lt;h3 id="76-conclusion">7.6. Conclusion&lt;/h3>
&lt;p>TensorRT-LLM is not simply applying TensorRT to LLMs, but a comprehensive solution fundamentally redesigned for LLM inference, containing multiple state-of-the-art optimizations. Through In-Flight Batching, Paged KV-Cache, native parallel support, and advanced quantization schemes, it can maximize the hardware performance of NVIDIA GPUs, providing a solid foundation for deploying high-performance, high-throughput LLM services.&lt;/p></description></item><item><title>RAG Data Augmentation Techniques: Key Methods for Bridging the Semantic Gap</title><link>https://ziyanglin.netlify.app/en/post/rag-data-augmentation/</link><pubDate>Sat, 28 Jun 2025 16:00:00 +0000</pubDate><guid>https://ziyanglin.netlify.app/en/post/rag-data-augmentation/</guid><description>&lt;h2 id="1-introduction-why-rag-needs-data-augmentation">1. Introduction: Why RAG Needs Data Augmentation?&lt;/h2>
&lt;h3 id="11-understanding-the-semantic-gap">1.1 Understanding the &amp;ldquo;Semantic Gap&amp;rdquo;&lt;/h3>
&lt;p>The core of Retrieval-Augmented Generation (RAG) lies in the &amp;ldquo;retrieval&amp;rdquo; component. However, in practical applications, the retrieval step often becomes the bottleneck of the entire system. The root cause is the &lt;strong>&amp;ldquo;Semantic Gap&amp;rdquo;&lt;/strong> or &lt;strong>&amp;ldquo;Retrieval Mismatch&amp;rdquo;&lt;/strong>.&lt;/p>
&lt;p>Specifically, this problem manifests in:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Diversity and Uncertainty of User Queries&lt;/strong>: Users ask questions in countless ways, potentially using colloquial language, abbreviations, typos, or describing the same issue from different angles.&lt;/li>
&lt;li>&lt;strong>Fixed and Formal Nature of Knowledge Base Documents&lt;/strong>: Documents in knowledge bases are typically structured and formal, with relatively fixed terminology.&lt;/li>
&lt;/ul>
&lt;p>This leads to a situation where the user's query vector and the document chunk vectors in the knowledge base may be far apart in vector space, even when they are semantically related.&lt;/p>
&lt;p>&lt;strong>For example:&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Knowledge Base Document&lt;/strong>: &lt;code># ThinkPad X1 Carbon Cooling Guide\n\nIf your ThinkPad X1 Carbon is experiencing overheating issues, you can try cleaning the fan, updating the BIOS, or selecting balanced mode in power management...&lt;/code>&lt;/li>
&lt;li>&lt;strong>Possible User Queries&lt;/strong>:
&lt;ul>
&lt;li>&amp;ldquo;My laptop is too hot, what should I do?&amp;rdquo;&lt;/li>
&lt;li>&amp;ldquo;Is my Lenovo laptop fan noise due to overheating?&amp;rdquo; (Even though the brand doesn't exactly match, the issue is essentially similar)&lt;/li>
&lt;li>&amp;ldquo;Computer gets very hot, games are lagging&amp;rdquo;&lt;/li>
&lt;li>&amp;ldquo;How can I cool down my ThinkPad?&amp;rdquo;&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;p>In a standard RAG workflow, these queries might fail to accurately retrieve the cooling guide mentioned above because their literal expressions and vector representations are too different.&lt;/p>
&lt;h3 id="12-standard-rag-workflow">1.2 Standard RAG Workflow&lt;/h3>
&lt;p>To better understand the problem, let's first look at the standard RAG workflow.&lt;/p>
&lt;pre>&lt;code class="language-mermaid">graph TD
A[User Input Query] --&amp;gt; B{Encoder};
B --&amp;gt; C[Query Vector];
C --&amp;gt; D{Vector Database};
E[Knowledge Base Documents] --&amp;gt; F{Encoder};
F --&amp;gt; G[Document Chunk Vectors];
G --&amp;gt; D;
D -- Vector Similarity Search --&amp;gt; H[Top-K Relevant Document Chunks];
A --&amp;gt; I((LLM));
H --&amp;gt; I;
I --&amp;gt; J[Generate Final Answer];
style A fill:#f9f,stroke:#333,stroke-width:2px
style J fill:#ccf,stroke:#333,stroke-width:2px
&lt;/code>&lt;/pre>
&lt;p>&lt;em>Figure 1: Standard RAG System Workflow&lt;/em>&lt;/p>
&lt;p>As shown above, the entire retrieval process heavily relies on the similarity between the &lt;code>Query Vector&lt;/code> and &lt;code>Chunk Vectors&lt;/code>. If there is a &amp;ldquo;semantic gap&amp;rdquo; between them, the retrieval effectiveness will be significantly reduced.&lt;/p>
&lt;p>The core objective of &lt;strong>Data Augmentation/Generalization&lt;/strong> is to proactively generate a large number of potential, semantically equivalent but expressively diverse &amp;ldquo;virtual queries&amp;rdquo; or &amp;ldquo;equivalent descriptions&amp;rdquo; for each document chunk in the knowledge base, thereby preemptively bridging this gap on the knowledge base side.&lt;/p>
&lt;h2 id="2-llmbased-data-augmentationgeneralization-techniques-deep-dive-into-details">2. LLM-Based Data Augmentation/Generalization Techniques: Deep Dive into Details&lt;/h2>
&lt;p>Leveraging the powerful language understanding and generation capabilities of Large Language Models (LLMs) is the most efficient and mainstream approach to data augmentation/generalization. The core idea is: &lt;strong>Let the LLM play the role of users and generate various possible questions and expressions for each knowledge chunk.&lt;/strong>&lt;/p>
&lt;p>There are two main technical implementation paths: &lt;strong>Hypothetical Questions Generation&lt;/strong> and &lt;strong>Summarization &amp;amp; Paraphrasing&lt;/strong>.&lt;/p>
&lt;h3 id="21-technical-path-one-hypothetical-questions-generation">2.1 Technical Path One: Hypothetical Questions Generation&lt;/h3>
&lt;p>This is the most direct and effective method. For each document chunk in the knowledge base, we have the LLM generate a set of questions that can be answered by this document chunk.&lt;/p>
&lt;h4 id="technical-implementation-details">Technical Implementation Details:&lt;/h4>
&lt;ol>
&lt;li>&lt;strong>Document Chunking&lt;/strong>: First, split the original document into meaningful, appropriately sized knowledge chunks. This is the foundation of all RAG systems.&lt;/li>
&lt;li>&lt;strong>Generate Questions for Each Chunk&lt;/strong>:
&lt;ul>
&lt;li>Iterate through each chunk.&lt;/li>
&lt;li>Feed the content of the chunk as context to an LLM.&lt;/li>
&lt;li>Use a carefully designed prompt (see Chapter 3) to instruct the LLM to generate N questions closely related to the chunk's content.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>Data Organization and Indexing&lt;/strong>:
&lt;ul>
&lt;li>&lt;strong>Key Step&lt;/strong>: Associate the N generated questions with the original chunk. When vectorizing, &lt;strong>don't vectorize the questions themselves&lt;/strong>, but process each generated &amp;ldquo;question-original text pair&amp;rdquo;. A common approach is to concatenate the question and original text when vectorizing, or associate the question as metadata with the original chunk's vector during indexing.&lt;/li>
&lt;li>A more common practice is to store &lt;strong>both the vectors of the generated questions&lt;/strong> and &lt;strong>the vector of the original chunk&lt;/strong> in the vector database, all pointing to the same original chunk ID. This way, when a user queries, whether they match the original chunk or one of the generated questions, they can ultimately locate the correct original text.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>Store in Vector Database&lt;/strong>: Store the processed data (original chunk vectors, generated question vectors) and their metadata (such as original ID) in a vector database (like ChromaDB, Milvus, Qdrant, etc.).&lt;/li>
&lt;/ol>
&lt;h4 id="workflow-diagram">Workflow Diagram:&lt;/h4>
&lt;pre>&lt;code class="language-mermaid">graph TD
subgraph &amp;quot;Offline Processing&amp;quot;
A[Original Document] --&amp;gt; B(Chunking);
B --&amp;gt; C{Iterate Each Chunk};
C --&amp;gt; D[LLM Generator];
D -- &amp;quot;Generate for Chunk n&amp;quot; --&amp;gt; E[Generated Multiple Questions];
Chunk_n --&amp;gt; F{Encoder};
F --&amp;gt; G[Vector of Chunk_n];
G -- &amp;quot;Points to Chunk_n ID&amp;quot; --&amp;gt; H((Vector Database));
E --&amp;gt; I{Encoder};
I --&amp;gt; J[Vectors of All Generated Questions];
J -- &amp;quot;All Point to Chunk_n ID&amp;quot; --&amp;gt; H;
subgraph &amp;quot;Original Knowledge&amp;quot;
direction LR
Chunk_n(Chunk n);
end
end
subgraph &amp;quot;Online Retrieval&amp;quot;
K[User Query] --&amp;gt; L{Encoder};
L --&amp;gt; M[Query Vector];
M --&amp;gt; H;
H -- &amp;quot;Vector Retrieval&amp;quot; --&amp;gt; N{Top-K Results};
N --&amp;gt; O[Get Original Chunk by ID];
end
style D fill:#c7f4c8,stroke:#333,stroke-width:2px;
style H fill:#f8d7da,stroke:#333,stroke-width:2px;
style E fill:#f9e79f,stroke:#333,stroke-width:2px;
&lt;/code>&lt;/pre>
&lt;p>&lt;em>Figure 2: Data-Augmented RAG Workflow with Hypothetical Questions Generation&lt;/em>&lt;/p>
&lt;p>This method greatly enriches the &amp;ldquo;retrievability&amp;rdquo; of each knowledge chunk, essentially creating multiple different &amp;ldquo;entry points&amp;rdquo; for each piece of knowledge.&lt;/p>
&lt;h3 id="22-technical-path-two-summarization--paraphrasing">2.2 Technical Path Two: Summarization &amp;amp; Paraphrasing&lt;/h3>
&lt;p>Besides generating questions, we can also generate summaries of knowledge chunks or rewrite them in different ways.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Summarization&lt;/strong>: For a relatively long knowledge chunk, an LLM can generate a concise core summary. This summary can serve as a &amp;ldquo;coarse-grained&amp;rdquo; retrieval entry point. When a user's query is relatively broad, it might more easily match with the summary.&lt;/li>
&lt;li>&lt;strong>Paraphrasing&lt;/strong>: Have the LLM rewrite the core content of the same knowledge chunk using different sentence structures and vocabulary. This also creates new vectors that are different from the original text vector but semantically consistent.&lt;/li>
&lt;/ul>
&lt;h4 id="technical-implementation-details1">Technical Implementation Details:&lt;/h4>
&lt;p>The implementation method is similar to hypothetical question generation, except that the prompt's goal changes from &amp;ldquo;generating questions&amp;rdquo; to &amp;ldquo;generating summaries&amp;rdquo; or &amp;ldquo;paraphrasing&amp;rdquo;. The generated data is similarly associated with the original chunk, and its vector is stored in the database.&lt;/p>
&lt;p>In practice, &lt;strong>hypothetical question generation is usually more popular than summarization/paraphrasing&lt;/strong> because it more directly simulates the user's &amp;ldquo;questioning&amp;rdquo; behavior, aligning better with the essence of the retrieval task.&lt;/p>
&lt;h2 id="3-prompt-engineering-for-data-generalization-an-excellent-example">3. Prompt Engineering for Data Generalization: An Excellent Example&lt;/h2>
&lt;p>The quality of the prompt directly determines the quality of the generated data. A good prompt should be like a precise scalpel, guiding the LLM to generate the data we want.&lt;/p>
&lt;p>Below is a well-considered prompt example designed for the &amp;ldquo;hypothetical questions generation&amp;rdquo; task:&lt;/p>
&lt;pre>&lt;code class="language-text">### Role and Goal
You are an advanced AI assistant tasked with generating a set of high-quality, diverse questions for a given knowledge text (Context). These questions should be fully answerable by the provided text. Your goal is to help build a smarter Q&amp;amp;A system that can find answers regardless of how users phrase their questions, as long as they relate to the text content.
### Instructions
Based on the `[Original Text]` provided below, please generate **5** different questions.
### Requirements
1. **Diversity**: The generated questions must differ in sentence structure, wording, and intent. Try to ask from different angles, for example:
* **How-to type**: How to operate...?
* **Why type**: Why does...happen?
* **What is type**: What does...mean?
* **Comparison type**: What's the difference between...and...?
* **What-if type**: What if...?
2. **Persona**: Imagine you are different types of users asking questions:
* A **Beginner** who knows nothing about this field.
* An **Expert** seeking in-depth technical details.
* A **Student** looking for answers for an assignment.
3. **Fully Answerable**: Ensure each generated question can be fully and only answered using information from the `[Original Text]`. Don't ask questions that require external knowledge.
4. **Language Style**: Questions should be natural, clear, and conform to conversational English.
### Output Format
Please output strictly in the following JSON format, without any additional explanations or text:
```json
{
&amp;quot;generated_questions&amp;quot;: [
{
&amp;quot;persona&amp;quot;: &amp;quot;beginner&amp;quot;,
&amp;quot;question&amp;quot;: &amp;quot;First question here&amp;quot;
},
{
&amp;quot;persona&amp;quot;: &amp;quot;expert&amp;quot;,
&amp;quot;question&amp;quot;: &amp;quot;Second question here&amp;quot;
},
{
&amp;quot;persona&amp;quot;: &amp;quot;student&amp;quot;,
&amp;quot;question&amp;quot;: &amp;quot;Third question here&amp;quot;
},
// ... more questions
]
}
&lt;/code>&lt;/pre>
&lt;h3 id="original-text">[Original Text]&lt;/h3>
&lt;p>{context_chunk}&lt;/p>
&lt;pre>&lt;code>
#### Prompt Design Analysis:
* **Role and Goal**: Gives the LLM a clear positioning, helping it understand the significance of the task, rather than just mechanically executing it.
* **Diversity Requirements**: This is the most critical part. It guides the LLM to think from different dimensions, avoiding generating a large number of homogeneous questions (e.g., simply turning statements into questions).
* **Persona Role-Playing**: This instruction greatly enriches the diversity of questions. A beginner's questions might be broader and more colloquial, while an expert's questions might be more specific and technical.
* **Fully Answerable**: This is an important constraint, ensuring the strong relevance of generated questions to the original text, avoiding introducing noise.
* **JSON Output Format**: Forced structured output makes the LLM's return results easily parsable and processable by programs, an essential element in automated workflows.
## 4. Effect Validation: How to Measure the Effectiveness of Data Augmentation?
Data augmentation is not a process that is &amp;quot;automatically good once done&amp;quot;; a scientific evaluation system must be established to verify its effectiveness. Evaluation should be conducted from two aspects: **recall rate** and **final answer quality**.
### 4.1 Retrieval Evaluation
This is the core metric for evaluating improvements in the retrieval component.
#### Steps:
1. **Build an Evaluation Dataset**: This is the most critical step. You need to create a test set containing `(question, corresponding correct original Chunk_ID)` pairs. The questions in this test set should be as diverse as possible, simulating real user queries.
2. **Conduct Two Tests**:
* **Experimental Group A (Without Data Augmentation)**: Use the standard RAG process to retrieve with questions from the test set, recording the Top-K Chunk IDs recalled.
* **Experimental Group B (With Data Augmentation)**: Use a knowledge base integrated with data augmentation, retrieve with the same questions, and record the Top-K Chunk IDs recalled.
3. **Calculate Evaluation Metrics**:
* **Recall@K**: What proportion of questions in the test set had their corresponding correct Chunk_ID appear in the top K of the recall results? This is the most important metric. `Recall@K = (Number of correctly recalled questions) / (Total number of questions)`.
* **Precision@K**: How many of the top K results recalled are correct? For a single question, if there is only one correct answer, then Precision@K is either 1/K or 0.
* **MRR (Mean Reciprocal Rank)**: The average of the reciprocal of the rank of the correct answer in the recall list. This metric not only cares about whether it was recalled but also how high it was ranked. The higher the ranking, the higher the score. `MRR = (1/N) * Σ(1 / rank_i)`, where `N` is the total number of questions, and `rank_i` is the rank of the correct answer for the i-th question.
By comparing the `Recall@K` and `MRR` metrics of experimental groups A and B, you can quantitatively determine whether data augmentation has improved recall performance.
### 4.2 Generation Quality Evaluation
Improved recall rate is a prerequisite, but it doesn't completely equate to improved user experience. We also need to evaluate the final answers generated by the RAG system end-to-end.
#### Method One: Human Evaluation
This is the most reliable but most costly method.
1. **Design Evaluation Dimensions**:
* **Relevance**: Does the generated answer get to the point and address the user's question?
* **Accuracy/Factuality**: Is the information in the answer accurate and based on the retrieved knowledge?
* **Fluency**: Is the language of the answer natural and smooth?
2. **Conduct Blind Evaluation**: Have evaluators score (e.g., 1-5 points) or compare (A is better/B is better/tie) two sets of answers without knowing which answer comes from which system (before/after enhancement).
3. **Statistical Analysis**: Determine whether data augmentation has a positive impact on the final answer quality through statistical scores or win rates.
#### Method Two: LLM-based Automatic Evaluation
This is a more efficient alternative, using a more powerful, advanced LLM (such as GPT-4o, Claude 3.5 Sonnet) as a &amp;quot;judge&amp;quot;.
1. **Design Evaluation Prompt**: Create a prompt asking the judge LLM to compare answers generated by different systems.
* **Input**: User question, retrieved context, System A's answer, System B's answer.
* **Instructions**: Ask the LLM to analyze from dimensions such as relevance and accuracy, determine which answer is better, and output scores and reasons in JSON format.
2. **Batch Execution and Analysis**: Run this evaluation process for all questions in the test set, then calculate win rates.
This method allows for large-scale, low-cost evaluation, making rapid iteration possible.
## 5. Conclusion and Future Outlook
**In summary, LLM-based data augmentation/generalization is a key technology for enhancing RAG system performance, especially for solving the &amp;quot;semantic gap&amp;quot; problem.** By pre-generating a large number of &amp;quot;virtual questions&amp;quot; or equivalent descriptions in the offline phase, it greatly enriches the retrievability of the knowledge base, making the system more adaptable to the diversity of user queries in the real world.
**Practical Considerations:**
* **Balance Between Cost and Quality**: Generating data incurs LLM API call costs and index storage costs. The number of data to generate for each chunk needs to be decided based on budget and performance improvement needs.
* **Cleaning Generated Data**: LLM generation is not 100% perfect and may produce low-quality or irrelevant questions. Consider adding a validation step to filter out poor-quality data.
**Future Outlook:**
* **Combination with Rerankers**: Data augmentation aims to improve &amp;quot;recall,&amp;quot; while reranker models aim to optimize &amp;quot;ranking.&amp;quot; Combining the two—ensuring relevant content is recalled through data augmentation, then fine-ranking through reranker models—is the golden combination for RAG optimization.
* **Multimodal Data Augmentation**: With the development of multimodal large models, future RAG will process more than just text. How to perform data augmentation for image and audio/video knowledge (e.g., generating text questions about image content) will be an interesting research direction.
* **Adaptive Data Augmentation**: Future systems might automatically discover recall failure cases based on real user queries online, and perform targeted data augmentation for relevant knowledge chunks, forming a continuously optimizing closed loop.&lt;/code>&lt;/pre></description></item><item><title>Ollama Practical Guide: Local Deployment and Management of Large Language Models</title><link>https://ziyanglin.netlify.app/en/post/ollama-documentation/</link><pubDate>Fri, 27 Jun 2025 02:00:00 +0000</pubDate><guid>https://ziyanglin.netlify.app/en/post/ollama-documentation/</guid><description>&lt;h2 id="1-introduction">1. Introduction&lt;/h2>
&lt;p>Ollama is a powerful open-source tool designed to allow users to easily download, run, and manage large language models (LLMs) in local environments. Its core advantage lies in simplifying the deployment and use of complex models, enabling developers, researchers, and enthusiasts to experience and utilize state-of-the-art artificial intelligence technology on personal computers without specialized hardware or complex configurations.&lt;/p>
&lt;p>&lt;strong>Key Advantages:&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Ease of Use:&lt;/strong> Complete model download, running, and interaction through simple command-line instructions.&lt;/li>
&lt;li>&lt;strong>Cross-Platform Support:&lt;/strong> Supports macOS, Windows, and Linux.&lt;/li>
&lt;li>&lt;strong>Rich Model Library:&lt;/strong> Supports numerous popular open-source models such as Llama 3, Mistral, Gemma, Phi-3, and more.&lt;/li>
&lt;li>&lt;strong>Highly Customizable:&lt;/strong> Through &lt;code>Modelfile&lt;/code>, users can easily customize model behavior, system prompts, and parameters.&lt;/li>
&lt;li>&lt;strong>API-Driven:&lt;/strong> Provides a REST API for easy integration with other applications and services.&lt;/li>
&lt;li>&lt;strong>Open Source Community:&lt;/strong> Has an active community continuously contributing new models and features.&lt;/li>
&lt;/ul>
&lt;p>This document will provide a comprehensive introduction to Ollama's various features, from basic fundamentals to advanced applications, helping you fully master this powerful tool.&lt;/p>
&lt;hr>
&lt;h2 id="2-quick-start">2. Quick Start&lt;/h2>
&lt;p>This section will guide you through installing and basic usage of Ollama.&lt;/p>
&lt;h3 id="21-installation">2.1 Installation&lt;/h3>
&lt;p>Visit the &lt;a href="https://ollama.com/">Ollama official website&lt;/a> to download and install the package suitable for your operating system.&lt;/p>
&lt;h3 id="22-running-your-first-model">2.2 Running Your First Model&lt;/h3>
&lt;p>After installation, open a terminal (or command prompt) and use the &lt;code>ollama run&lt;/code> command to download and run a model. For example, to run the Llama 3 model:&lt;/p>
&lt;pre>&lt;code class="language-shell">ollama run llama3
&lt;/code>&lt;/pre>
&lt;p>On first run, Ollama will automatically download the required model files from the model library. Once the download is complete, you can directly converse with the model in the terminal.&lt;/p>
&lt;h3 id="23-managing-local-models">2.3 Managing Local Models&lt;/h3>
&lt;p>You can use the following commands to manage locally downloaded models:&lt;/p>
&lt;ul>
&lt;li>
&lt;p>&lt;strong>List Local Models:&lt;/strong>&lt;/p>
&lt;pre>&lt;code class="language-shell">ollama list
&lt;/code>&lt;/pre>
&lt;p>This command displays the name, ID, size, and modification time of all downloaded models.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Remove Local Models:&lt;/strong>&lt;/p>
&lt;pre>&lt;code class="language-shell">ollama rm &amp;lt;model_name&amp;gt;
&lt;/code>&lt;/pre>
&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h2 id="3-core-concepts">3. Core Concepts&lt;/h2>
&lt;h3 id="31-modelfile">3.1 Modelfile&lt;/h3>
&lt;p>&lt;code>Modelfile&lt;/code> is one of Ollama's core features. It's a configuration file similar to &lt;code>Dockerfile&lt;/code> that allows you to define and create custom models. Through &lt;code>Modelfile&lt;/code>, you can:&lt;/p>
&lt;ul>
&lt;li>Specify a base model.&lt;/li>
&lt;li>Set model parameters (such as temperature, top_p, etc.).&lt;/li>
&lt;li>Define the model's system prompt.&lt;/li>
&lt;li>Customize the model's interaction template.&lt;/li>
&lt;li>Apply LoRA adapters.&lt;/li>
&lt;/ul>
&lt;p>A simple &lt;code>Modelfile&lt;/code> example:&lt;/p>
&lt;pre>&lt;code class="language-Modelfile"># Specify base model
FROM llama3
# Set model temperature
PARAMETER temperature 0.8
# Set system prompt
SYSTEM &amp;quot;&amp;quot;&amp;quot;
You are a helpful AI assistant. Your name is Roo.
&amp;quot;&amp;quot;&amp;quot;
&lt;/code>&lt;/pre>
&lt;p>Use the &lt;code>ollama create&lt;/code> command to create a new model based on a &lt;code>Modelfile&lt;/code>:&lt;/p>
&lt;pre>&lt;code class="language-shell">ollama create my-custom-model -f ./Modelfile
&lt;/code>&lt;/pre>
&lt;h3 id="32-model-import">3.2 Model Import&lt;/h3>
&lt;p>Ollama supports importing models from external file systems, particularly from &lt;code>Safetensors&lt;/code> format weight files.&lt;/p>
&lt;p>In a &lt;code>Modelfile&lt;/code>, use the &lt;code>FROM&lt;/code> directive and provide the directory path containing &lt;code>safetensors&lt;/code> files:&lt;/p>
&lt;pre>&lt;code class="language-Modelfile">FROM /path/to/safetensors/directory
&lt;/code>&lt;/pre>
&lt;p>Then use the &lt;code>ollama create&lt;/code> command to create the model.&lt;/p>
&lt;h3 id="33-multimodal-models">3.3 Multimodal Models&lt;/h3>
&lt;p>Ollama supports multimodal models (such as LLaVA) that can process both text and image inputs simultaneously.&lt;/p>
&lt;pre>&lt;code class="language-shell">ollama run llava &amp;quot;What's in this image? /path/to/image.png&amp;quot;
&lt;/code>&lt;/pre>
&lt;hr>
&lt;h2 id="4-api-reference">4. API Reference&lt;/h2>
&lt;p>Ollama provides a set of REST APIs for programmatically interacting with models. The default service address is &lt;code>http://localhost:11434&lt;/code>.&lt;/p>
&lt;h3 id="41-apigenerate">4.1 &lt;code>/api/generate&lt;/code>&lt;/h3>
&lt;p>Generate text.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Request (Streaming):&lt;/strong>
&lt;pre>&lt;code class="language-shell">curl http://localhost:11434/api/generate -d '{
&amp;quot;model&amp;quot;: &amp;quot;llama3&amp;quot;,
&amp;quot;prompt&amp;quot;: &amp;quot;Why is the sky blue?&amp;quot;
}'
&lt;/code>&lt;/pre>
&lt;/li>
&lt;li>&lt;strong>Request (Non-streaming):&lt;/strong>
&lt;pre>&lt;code class="language-shell">curl http://localhost:11434/api/generate -d '{
&amp;quot;model&amp;quot;: &amp;quot;llama3&amp;quot;,
&amp;quot;prompt&amp;quot;: &amp;quot;Why is the sky blue?&amp;quot;,
&amp;quot;stream&amp;quot;: false
}'
&lt;/code>&lt;/pre>
&lt;/li>
&lt;/ul>
&lt;h3 id="42-apichat">4.2 &lt;code>/api/chat&lt;/code>&lt;/h3>
&lt;p>Conduct multi-turn conversations.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Request:&lt;/strong>
&lt;pre>&lt;code class="language-shell">curl http://localhost:11434/api/chat -d '{
&amp;quot;model&amp;quot;: &amp;quot;llama3&amp;quot;,
&amp;quot;messages&amp;quot;: [
{
&amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;,
&amp;quot;content&amp;quot;: &amp;quot;why is the sky blue?&amp;quot;
}
],
&amp;quot;stream&amp;quot;: false
}'
&lt;/code>&lt;/pre>
&lt;/li>
&lt;/ul>
&lt;h3 id="43-apiembed">4.3 &lt;code>/api/embed&lt;/code>&lt;/h3>
&lt;p>Generate embedding vectors for text.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Request:&lt;/strong>
&lt;pre>&lt;code class="language-shell">curl http://localhost:11434/api/embed -d '{
&amp;quot;model&amp;quot;: &amp;quot;all-minilm&amp;quot;,
&amp;quot;input&amp;quot;: [&amp;quot;Why is the sky blue?&amp;quot;, &amp;quot;Why is the grass green?&amp;quot;]
}'
&lt;/code>&lt;/pre>
&lt;/li>
&lt;/ul>
&lt;h3 id="44-apitags">4.4 &lt;code>/api/tags&lt;/code>&lt;/h3>
&lt;p>List all locally available models.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Request:&lt;/strong>
&lt;pre>&lt;code class="language-shell">curl http://localhost:11434/api/tags
&lt;/code>&lt;/pre>
&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h2 id="5-command-line-tools-cli">5. Command Line Tools (CLI)&lt;/h2>
&lt;p>Ollama provides a rich set of command-line tools for managing models and interacting with the service.&lt;/p>
&lt;ul>
&lt;li>&lt;code>ollama run &amp;lt;model&amp;gt;&lt;/code>: Run a model.&lt;/li>
&lt;li>&lt;code>ollama create &amp;lt;model&amp;gt; -f &amp;lt;Modelfile&amp;gt;&lt;/code>: Create a model from a Modelfile.&lt;/li>
&lt;li>&lt;code>ollama pull &amp;lt;model&amp;gt;&lt;/code>: Pull a model from a remote repository.&lt;/li>
&lt;li>&lt;code>ollama push &amp;lt;model&amp;gt;&lt;/code>: Push a model to a remote repository.&lt;/li>
&lt;li>&lt;code>ollama list&lt;/code>: List local models.&lt;/li>
&lt;li>&lt;code>ollama cp &amp;lt;source_model&amp;gt; &amp;lt;dest_model&amp;gt;&lt;/code>: Copy a model.&lt;/li>
&lt;li>&lt;code>ollama rm &amp;lt;model&amp;gt;&lt;/code>: Delete a model.&lt;/li>
&lt;li>&lt;code>ollama ps&lt;/code>: View running models and their resource usage.&lt;/li>
&lt;li>&lt;code>ollama stop &amp;lt;model&amp;gt;&lt;/code>: Stop a running model and unload it from memory.&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h2 id="6-advanced-features">6. Advanced Features&lt;/h2>
&lt;h3 id="61-openai-api-compatibility">6.1 OpenAI API Compatibility&lt;/h3>
&lt;p>Ollama provides an endpoint compatible with the OpenAI API, allowing you to seamlessly migrate existing OpenAI applications to Ollama. The default address is &lt;code>http://localhost:11434/v1&lt;/code>.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>List Models (Python):&lt;/strong>
&lt;pre>&lt;code class="language-python">from openai import OpenAI
client = OpenAI(
base_url='http://localhost:11434/v1',
api_key='ollama', # required, but unused
)
response = client.models.list()
print(response)
&lt;/code>&lt;/pre>
&lt;/li>
&lt;/ul>
&lt;h3 id="62-structured-output">6.2 Structured Output&lt;/h3>
&lt;p>By combining the OpenAI-compatible API with Pydantic, you can force the model to output JSON with a specific structure.&lt;/p>
&lt;pre>&lt;code class="language-python">from pydantic import BaseModel
from openai import OpenAI
client = OpenAI(base_url=&amp;quot;http://localhost:11434/v1&amp;quot;, api_key=&amp;quot;ollama&amp;quot;)
class UserInfo(BaseModel):
name: str
age: int
try:
completion = client.beta.chat.completions.parse(
model=&amp;quot;llama3.1:8b&amp;quot;,
messages=[{&amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;, &amp;quot;content&amp;quot;: &amp;quot;My name is John and I am 30 years old.&amp;quot;}],
response_format=UserInfo,
)
print(completion.choices[0].message.parsed)
except Exception as e:
print(f&amp;quot;Error: {e}&amp;quot;)
&lt;/code>&lt;/pre>
&lt;h3 id="63-performance-tuning">6.3 Performance Tuning&lt;/h3>
&lt;p>You can adjust Ollama's performance and resource management through environment variables:&lt;/p>
&lt;ul>
&lt;li>&lt;code>OLLAMA_KEEP_ALIVE&lt;/code>: Set how long models remain active in memory. For example, &lt;code>10m&lt;/code>, &lt;code>24h&lt;/code>, or &lt;code>-1&lt;/code> (permanent).&lt;/li>
&lt;li>&lt;code>OLLAMA_MAX_LOADED_MODELS&lt;/code>: Maximum number of models loaded into memory simultaneously.&lt;/li>
&lt;li>&lt;code>OLLAMA_NUM_PARALLEL&lt;/code>: Number of requests each model can process in parallel.&lt;/li>
&lt;/ul>
&lt;h3 id="64-lora-adapters">6.4 LoRA Adapters&lt;/h3>
&lt;p>Use the &lt;code>ADAPTER&lt;/code> directive in a &lt;code>Modelfile&lt;/code> to apply a LoRA (Low-Rank Adaptation) adapter, changing the model's behavior without modifying the base model weights.&lt;/p>
&lt;pre>&lt;code class="language-Modelfile">FROM llama3
ADAPTER /path/to/your-lora-adapter.safetensors
&lt;/code>&lt;/pre>
&lt;hr>
&lt;h2 id="7-appendix">7. Appendix&lt;/h2>
&lt;h3 id="71-troubleshooting">7.1 Troubleshooting&lt;/h3>
&lt;ul>
&lt;li>&lt;strong>Check CPU Features:&lt;/strong> On Linux, you can use the following command to check if your CPU supports instruction sets like AVX, which are crucial for the performance of certain models.
&lt;pre>&lt;code class="language-shell">cat /proc/cpuinfo | grep flags | head -1
&lt;/code>&lt;/pre>
&lt;/li>
&lt;/ul>
&lt;h3 id="72-contribution-guidelines">7.2 Contribution Guidelines&lt;/h3>
&lt;p>Ollama is an open-source project, and community contributions are welcome. When submitting code, please follow good commit message formats, for example:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Good:&lt;/strong> &lt;code>llm/backend/mlx: support the llama architecture&lt;/code>&lt;/li>
&lt;li>&lt;strong>Bad:&lt;/strong> &lt;code>feat: add more emoji&lt;/code>&lt;/li>
&lt;/ul>
&lt;h3 id="73-related-links">7.3 Related Links&lt;/h3>
&lt;ul>
&lt;li>&lt;strong>Official Website:&lt;/strong> &lt;a href="https://ollama.com/">&lt;a href="https://ollama.com/">https://ollama.com/&lt;/a>&lt;/a>&lt;/li>
&lt;li>&lt;strong>GitHub Repository:&lt;/strong> &lt;a href="https://github.com/ollama/ollama">&lt;a href="https://github.com/ollama/ollama">https://github.com/ollama/ollama&lt;/a>&lt;/a>&lt;/li>
&lt;li>&lt;strong>Model Library:&lt;/strong> &lt;a href="https://ollama.com/library">&lt;a href="https://ollama.com/library">https://ollama.com/library&lt;/a>&lt;/a>&lt;/li>
&lt;/ul></description></item></channel></rss>