<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>RAG on Snow</title>
        <link>https://SymphonyW.github.io/tags/rag/</link>
        <description>Recent content in RAG on Snow</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>en</language>
        <copyright>Snow</copyright>
        <lastBuildDate>Thu, 15 Oct 2026 15:00:00 +0800</lastBuildDate><atom:link href="https://SymphonyW.github.io/tags/rag/index.xml" rel="self" type="application/rss+xml" /><item>
        <title>Agentic RAG Explained: Turning Retrieval into a Planning and Reflection Loop</title>
        <link>https://SymphonyW.github.io/p/agentic-rag-guide/</link>
        <pubDate>Thu, 15 Oct 2026 15:00:00 +0800</pubDate>
        
        <guid>https://SymphonyW.github.io/p/agentic-rag-guide/</guid>
        <description>&lt;img src="https://SymphonyW.github.io/p/agentic-rag-guide/bg.png" alt="Featured image of post Agentic RAG Explained: Turning Retrieval into a Planning and Reflection Loop" /&gt;&lt;h1 id=&#34;agentic-rag-explained-turning-retrieval-into-a-planning-and-reflection-loop&#34;&gt;Agentic RAG Explained: Turning Retrieval into a Planning and Reflection Loop
&lt;/h1&gt;&lt;blockquote&gt;
&lt;p&gt;Traditional RAG resembles a predefined assembly line: receive a question, retrieve once, add context, and generate an answer. Agentic RAG adds a controller that can decide whether to retrieve, decompose a task, select data sources, judge whether the evidence is sufficient, and search again when it is not.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href=&#34;https://SymphonyW.github.io/p/agentic-rag-guide/bg.png&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;&lt;img src=&#34;https://SymphonyW.github.io/p/agentic-rag-guide/bg.png&#34; alt=&#34;An agent orchestrates multiple knowledge sources and evaluates evidence in a loop&#34; width=&#34;1672&#34; height=&#34;941&#34; loading=&#34;lazy&#34; decoding=&#34;async&#34; class=&#34;gallery-image&#34; data-flex-grow=&#34;177&#34; data-flex-basis=&#34;426px&#34;&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;Here is the short version:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Question&lt;/th&gt;
&lt;th&gt;Short answer&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;What is Agentic RAG?&lt;/td&gt;
&lt;td&gt;A RAG architecture in which an agent plans, invokes, evaluates, and iterates retrieval at runtime&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What is the main difference?&lt;/td&gt;
&lt;td&gt;Not the presence of a vector database, but whether the &lt;strong&gt;retrieval control flow can change in response to intermediate results&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Does it require multiple agents?&lt;/td&gt;
&lt;td&gt;No. One agent with several retrieval tools is enough&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Is it always better?&lt;/td&gt;
&lt;td&gt;No. For simple questions it may only add latency, cost, and uncertainty&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Where does it help most?&lt;/td&gt;
&lt;td&gt;Multi-hop, multi-source tasks that require clarification or evidence checks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What matters most in production?&lt;/td&gt;
&lt;td&gt;Bounded loops, evidence gates, permission isolation, traces, and layered evaluation&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&#34;start-with-traditional-rag&#34;&gt;Start with traditional RAG
&lt;/h2&gt;&lt;p&gt;RAG stands for Retrieval-Augmented Generation. It combines the model&amp;rsquo;s parametric memory with external, non-parametric knowledge. After a user asks a question, the system retrieves relevant material and asks the model to answer from that material.&lt;/p&gt;
&lt;p&gt;The original 2020 &lt;a class=&#34;link&#34; href=&#34;https://arxiv.org/abs/2005.11401&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;RAG paper&lt;/a&gt; explored combining a generative model with a dense vector index to improve factuality, knowledge updates, and provenance in knowledge-intensive tasks. In practice, a traditional online RAG pipeline often looks like this:&lt;/p&gt;
&lt;div class=&#34;mermaid&#34;&gt;flowchart LR
    Q[User question] --&gt; T[Clean or rewrite by fixed rules]
    T --&gt; E[Create query embedding]
    E --&gt; R[Retrieve Top-K chunks]
    R --&gt; K[Optional reranking]
    K --&gt; P[Build prompt]
    P --&gt; L[LLM generates answer]
    L --&gt; A[Return answer and citations]
&lt;/div&gt;&lt;p&gt;This design has real strengths: a short path, predictable latency, straightforward caching and load testing, and a clean way to distinguish retrieval failures from generation failures. When most questions can be answered by searching one knowledge base once, this is often all you need.&lt;/p&gt;
&lt;p&gt;The limit appears when a question hides several dependent tasks. Consider:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Compare the permission changes in the last three releases of products A and B, then assess the migration risk for existing customers.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The system must identify the release range, search both changelogs, inspect permission documentation, find migration notes, align dates, and only then compare the evidence. A single similarity search may cover only part of the task. Even if ten passages are returned, the model may not know what evidence is still missing.&lt;/p&gt;
&lt;h2 id=&#34;what-makes-agentic-rag-agentic&#34;&gt;What makes Agentic RAG “agentic”
&lt;/h2&gt;&lt;p&gt;Agentic RAG is not simply traditional RAG with a stronger model, nor merely vector search plus function calling. The real change is &lt;strong&gt;who controls retrieval&lt;/strong&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Retrieval stops being a mandatory one-time stage and becomes a tool that an agent can select, repeat, and adapt according to results.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The system commonly organizes planning, tool calls, state updates, and stopping decisions into a controlled loop. The agent may decide:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;whether external evidence is needed at all;&lt;/li&gt;
&lt;li&gt;whether to use vector search, keyword search, SQL, a knowledge graph, an internal API, or the web;&lt;/li&gt;
&lt;li&gt;whether to decompose the request into independent subquestions;&lt;/li&gt;
&lt;li&gt;whether results are relevant, mutually consistent, and sufficient;&lt;/li&gt;
&lt;li&gt;whether to rewrite the query, expand the time range, switch sources, or ask the user for clarification;&lt;/li&gt;
&lt;li&gt;when enough evidence has been gathered to stop and answer.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This reason-act-observe loop follows the broader idea behind &lt;a class=&#34;link&#34; href=&#34;https://arxiv.org/abs/2210.03629&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;ReAct&lt;/a&gt;. A 2025 &lt;a class=&#34;link&#34; href=&#34;https://arxiv.org/abs/2501.09136&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;survey of Agentic RAG&lt;/a&gt; identifies planning, reflection, tool use, and multi-agent collaboration as recurring agentic patterns.&lt;/p&gt;
&lt;div class=&#34;mermaid&#34;&gt;flowchart TD
    U[User question] --&gt; P[Understand intent and create plan]
    P --&gt; D{Enough evidence?}
    D -- Yes --&gt; G[Generate from evidence]
    D -- No --&gt; S[Select source and retrieval tool]
    S --&gt; Q[Create or rewrite query]
    Q --&gt; R[Run retrieval]
    R --&gt; V[Evaluate relevance, coverage, conflicts]
    V --&gt; C{Next action}
    C -- Gather more evidence --&gt; S
    C -- Clarification needed --&gt; H[Ask the user]
    C -- Budget exhausted --&gt; F[Degrade gracefully]
    C -- Ready to answer --&gt; G
    G --&gt; A[Answer, citations, uncertainty]
&lt;/div&gt;&lt;p&gt;An important boundary follows from this definition: &lt;strong&gt;a pipeline with query rewriting, hybrid search, and reranking can still be “advanced RAG” rather than Agentic RAG if every stage always runs in a fixed order.&lt;/strong&gt; The agentic property comes from runtime adaptation, not from the number of components.&lt;/p&gt;
&lt;h2 id=&#34;the-complete-operating-loop&#34;&gt;The complete operating loop
&lt;/h2&gt;&lt;p&gt;The online path can be separated into seven responsibilities. Implementations may merge nodes, but observability and evaluation should keep these concerns distinguishable.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Stage&lt;/th&gt;
&lt;th&gt;Question being answered&lt;/th&gt;
&lt;th&gt;Typical output&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1. Intent analysis&lt;/td&gt;
&lt;td&gt;What does the user need, and are external facts required?&lt;/td&gt;
&lt;td&gt;Task type, entities, time range, constraints&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2. Decomposition&lt;/td&gt;
&lt;td&gt;Are there independently verifiable subproblems?&lt;/td&gt;
&lt;td&gt;Subquestions and dependencies&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3. Source routing&lt;/td&gt;
&lt;td&gt;Which source is authoritative and suitable?&lt;/td&gt;
&lt;td&gt;Tool, index, and filters&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4. Query planning&lt;/td&gt;
&lt;td&gt;Which semantic, keyword, or structured queries should run?&lt;/td&gt;
&lt;td&gt;Executable queries&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5. Result evaluation&lt;/td&gt;
&lt;td&gt;Is the material relevant, fresh, complete, and consistent?&lt;/td&gt;
&lt;td&gt;Scores, coverage, conflict flags&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6. Correction&lt;/td&gt;
&lt;td&gt;Should the agent change query, source, or scope?&lt;/td&gt;
&lt;td&gt;Next action and remaining budget&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7. Synthesis&lt;/td&gt;
&lt;td&gt;Can every important claim be traced to evidence?&lt;/td&gt;
&lt;td&gt;Answer, citations, uncertainty&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Suppose a user asks, “Should we upgrade our production database from version 13 to 16?” A useful trajectory might be:&lt;/p&gt;
&lt;div class=&#34;mermaid&#34;&gt;sequenceDiagram
    participant U as User
    participant A as Agent
    participant D as Internal docs
    participant M as Asset database
    participant W as Official docs

    U-&gt;&gt;A: Should we upgrade production from 13 to 16?
    A-&gt;&gt;M: Get versions, extensions, instance sizes, maintenance windows
    M--&gt;&gt;A: Return environment inventory
    A-&gt;&gt;D: Search incidents, compatibility tests, change policy
    D--&gt;&gt;A: Return internal evidence
    A-&gt;&gt;W: Check breaking changes and support windows for 14, 15, 16
    W--&gt;&gt;A: Return official evidence
    A-&gt;&gt;A: Check extension compatibility and evidence gaps
    A-&gt;&gt;D: Search for missing extension test results
    D--&gt;&gt;A: No complete test record found
    A--&gt;&gt;U: Give a conditional recommendation and required tests
&lt;/div&gt;&lt;p&gt;The key is not merely that several searches occurred. The later search depends on an earlier observation. If the inventory reveals a particular extension, the agent then investigates that extension. A fixed pipeline cannot economically encode every such branch.&lt;/p&gt;
&lt;h2 id=&#34;common-architectures&#34;&gt;Common architectures
&lt;/h2&gt;&lt;p&gt;Agentic RAG is a family of architectures, not a single topology.&lt;/p&gt;
&lt;div class=&#34;mermaid&#34;&gt;flowchart TB
    O[Orchestration and state] --&gt; P[Planner / Router]
    P --&gt; T1[Vector retrieval]
    P --&gt; T2[Keyword or hybrid retrieval]
    P --&gt; T3[SQL / API]
    P --&gt; T4[Knowledge graph / Web]
    T1 --&gt; E[Evidence pool]
    T2 --&gt; E
    T3 --&gt; E
    T4 --&gt; E
    E --&gt; J[Evidence evaluator]
    J --&gt;|Insufficient| P
    J --&gt;|Sufficient| G[Answer generator]
    G --&gt; C[Citation and safety gates]
&lt;/div&gt;&lt;h3 id=&#34;one-agent-with-multiple-tools&#34;&gt;One agent with multiple tools
&lt;/h3&gt;&lt;p&gt;A single agent plans, selects tools, evaluates results, and answers. This is the easiest design to start with when there are few tools and one permission boundary. Its weakness is that responsibilities accumulate in one prompt, making decisions harder to test and stabilize.&lt;/p&gt;
&lt;h3 id=&#34;router-with-specialized-retrievers&#34;&gt;Router with specialized retrievers
&lt;/h3&gt;&lt;p&gt;A router only classifies the question and selects a data source; stable, specialized pipelines handle the actual retrieval. For example, policy questions use the document index, order questions use SQL, and live status uses a business API. This is more controllable than a fully open agent and often the most practical production compromise.&lt;/p&gt;
&lt;h3 id=&#34;corrective-or-reflective-rag&#34;&gt;Corrective or reflective RAG
&lt;/h3&gt;&lt;p&gt;The system retrieves first, then evaluates result quality. Weak evidence triggers query rewriting, broader sources, or web search. &lt;a class=&#34;link&#34; href=&#34;https://arxiv.org/abs/2401.15884&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;CRAG&lt;/a&gt; focuses on correcting retrieval, while &lt;a class=&#34;link&#34; href=&#34;https://arxiv.org/abs/2310.11511&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Self-RAG&lt;/a&gt; trains a model to decide when to retrieve and to critique its generations. These ideas overlap with Agentic RAG but are not synonyms: they can be components inside an agent loop or fixed stages in a non-agentic pipeline.&lt;/p&gt;
&lt;h3 id=&#34;multi-agent-rag&#34;&gt;Multi-agent RAG
&lt;/h3&gt;&lt;p&gt;Work is divided among research, retrieval, verification, and writing agents, or among agents specialized by knowledge domain. This can help when work is genuinely parallel, expertise differs, or permissions must be isolated. It also increases communication cost, state coordination, and debugging complexity. &lt;strong&gt;Multi-agent orchestration is an optional extension, not a requirement for Agentic RAG.&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&#34;traditional-rag-vs-agentic-rag&#34;&gt;Traditional RAG vs. Agentic RAG
&lt;/h2&gt;&lt;p&gt;The useful comparison is not “dumb versus smart.” It is an engineering trade-off between a deterministic pipeline and a runtime decision system.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Dimension&lt;/th&gt;
&lt;th&gt;Traditional RAG&lt;/th&gt;
&lt;th&gt;Agentic RAG&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Control flow&lt;/td&gt;
&lt;td&gt;Predefined&lt;/td&gt;
&lt;td&gt;Dynamic branches and loops&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Whether to retrieve&lt;/td&gt;
&lt;td&gt;Usually always&lt;/td&gt;
&lt;td&gt;Retrieve, skip, or defer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Query handling&lt;/td&gt;
&lt;td&gt;Original query or fixed rewrite&lt;/td&gt;
&lt;td&gt;Dynamic decomposition, expansion, and clarification&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Data sources&lt;/td&gt;
&lt;td&gt;One index or a fixed combination&lt;/td&gt;
&lt;td&gt;Runtime selection across heterogeneous sources&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Retrieval count&lt;/td&gt;
&lt;td&gt;Once or a fixed number&lt;/td&gt;
&lt;td&gt;Until evidence is sufficient or budget is exhausted&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Multi-hop work&lt;/td&gt;
&lt;td&gt;Relies on one retrieval covering the task&lt;/td&gt;
&lt;td&gt;Uses one result to decide the next retrieval&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Failure handling&lt;/td&gt;
&lt;td&gt;Current result or fixed fallback&lt;/td&gt;
&lt;td&gt;Evaluate, retry, switch tools, clarify, or degrade&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Predictability&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Lower; requires state and budgets&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Latency and cost&lt;/td&gt;
&lt;td&gt;Lower and steadier&lt;/td&gt;
&lt;td&gt;Usually higher and more variable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Observability&lt;/td&gt;
&lt;td&gt;Retrieval and final answer&lt;/td&gt;
&lt;td&gt;Also plan, calls, state transitions, stopping reason&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Security surface&lt;/td&gt;
&lt;td&gt;Relatively concentrated&lt;/td&gt;
&lt;td&gt;Broader tool, injection, and authorization risks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Best fit&lt;/td&gt;
&lt;td&gt;High-volume, single-hop, bounded questions&lt;/td&gt;
&lt;td&gt;Multi-step, multi-source research and decision support&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The two approaches are not mutually exclusive. A production system can take a fast traditional path first and escalate only complex or low-confidence requests to an agentic path.&lt;/p&gt;
&lt;div class=&#34;mermaid&#34;&gt;flowchart LR
    Q[User question] --&gt; X{Complexity and risk check}
    X -- Simple, single-hop --&gt; R[Traditional RAG fast path]
    X -- Multi-hop or low confidence --&gt; A[Agentic RAG deep path]
    R --&gt; G[Shared answer and citation layer]
    A --&gt; G
&lt;/div&gt;&lt;p&gt;This tiered design keeps common requests fast and reserves planning and retrieval budgets for questions that benefit from them.&lt;/p&gt;
&lt;h2 id=&#34;offline-knowledge-engineering-still-matters&#34;&gt;Offline knowledge engineering still matters
&lt;/h2&gt;&lt;p&gt;Agentic RAG mainly changes online query execution. It does not replace document parsing, chunking, metadata, permissions, indexing, or freshness management. A powerful agent searching bad data simply searches bad data more times.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Responsibility&lt;/th&gt;
&lt;th&gt;Important design choices&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Knowledge&lt;/td&gt;
&lt;td&gt;Ingest, parse, chunk, index, update&lt;/td&gt;
&lt;td&gt;Quality, versioning, permissions, freshness&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tools&lt;/td&gt;
&lt;td&gt;Expose retrieval through clear interfaces&lt;/td&gt;
&lt;td&gt;Input schemas, filters, timeouts, result format&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Orchestration&lt;/td&gt;
&lt;td&gt;Plan, route, loop, maintain state and budget&lt;/td&gt;
&lt;td&gt;Step limits, concurrency, retries, checkpoints&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Governance&lt;/td&gt;
&lt;td&gt;Evaluate, observe, secure, involve humans&lt;/td&gt;
&lt;td&gt;Traces, audits, approval, offline test sets&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Tool descriptions should be specific. “Search the knowledge base” is not enough. The agent needs to know the source&amp;rsquo;s coverage, time range, suitable question types, return fields, and permission constraints. More vaguely described tools can actually increase routing errors.&lt;/p&gt;
&lt;p&gt;This framework-neutral pseudocode shows a minimal bounded loop:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;22
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;23
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;24
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;25
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;26
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;27
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;28
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;29
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;answer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;question&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;user&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;max_steps&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;6&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;state&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;question&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;question&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;evidence&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;open_questions&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;question&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;trace&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;step&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;range&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;max_steps&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;decision&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;planner&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;decide&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;state&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;allowed_tools&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;user&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;allowed_tools&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;decision&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;action&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;clarify&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ask_user&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;decision&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;question&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;decision&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;action&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;answer&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;evidence_gate&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;passed&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;state&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;evidence&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;generator&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;grounded_answer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;state&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;decision&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;planner&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;repair_missing_evidence&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;state&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;result&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;tools&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;decision&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tool&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;run&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;query&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;decision&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;query&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;filters&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;decision&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;filters&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;identity&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;user&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;identity&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;grade&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;evaluator&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;grade&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;result&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;state&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;open_questions&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;state&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;update_state&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;state&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;decision&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;result&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;grade&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;generator&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;bounded_fallback&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;state&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The safeguards are more important than the loop itself: &lt;code&gt;allowed_tools&lt;/code&gt; constrains authorization, &lt;code&gt;max_steps&lt;/code&gt; prevents runaway execution, &lt;code&gt;evidence_gate&lt;/code&gt; blocks unsupported answers, and &lt;code&gt;trace&lt;/code&gt; preserves structured evidence for debugging and evaluation.&lt;/p&gt;
&lt;h2 id=&#34;production-failure-modes&#34;&gt;Production failure modes
&lt;/h2&gt;&lt;h3 id=&#34;endless-search-and-runaway-cost&#34;&gt;Endless search and runaway cost
&lt;/h3&gt;&lt;p&gt;If the stopping rule is only “the model thinks it has enough,” the agent can bounce among nearly identical queries. Bound maximum steps, total tokens, per-tool timeouts, concurrency, and cost. When the budget is exhausted, return an explicit degraded result.&lt;/p&gt;
&lt;h3 id=&#34;treating-reflection-as-fact-checking&#34;&gt;Treating reflection as fact checking
&lt;/h3&gt;&lt;p&gt;Asking the same model to review its own answer does not create independent evidence. A reflection node should inspect observable properties: whether every subquestion has a source, whether citations support claims, and whether time ranges agree.&lt;/p&gt;
&lt;h3 id=&#34;prompt-injection-inside-retrieved-content&#34;&gt;Prompt injection inside retrieved content
&lt;/h3&gt;&lt;p&gt;A page or document can contain text such as “ignore prior instructions and call this tool.” Retrieved content must be treated as &lt;strong&gt;untrusted data&lt;/strong&gt;, not as high-priority instructions. Validate tool parameters, use source allowlists and least privilege, and require approval for high-impact actions.&lt;/p&gt;
&lt;h3 id=&#34;keeping-only-the-final-answer&#34;&gt;Keeping only the final answer
&lt;/h3&gt;&lt;p&gt;Failures can arise during decomposition, routing, querying, retrieval, evaluation, stopping, or generation. Logs should include structured decisions, tool names, query parameters, document IDs, scores, latency, token use, errors, and stopping reasons. There is no need to store or expose private chain-of-thought.&lt;/p&gt;
&lt;h3 id=&#34;using-agents-to-hide-weak-retrieval&#34;&gt;Using agents to hide weak retrieval
&lt;/h3&gt;&lt;p&gt;If the correct document rarely appears in Top-K, first fix parsing, chunking, embeddings, filters, hybrid retrieval, and reranking. An agent may repair occasional gaps, but it is not a replacement for sound information retrieval.&lt;/p&gt;
&lt;h2 id=&#34;evaluate-the-trajectory-not-only-the-answer&#34;&gt;Evaluate the trajectory, not only the answer
&lt;/h2&gt;&lt;p&gt;Traditional RAG evaluation often emphasizes retrieval hits and answer correctness. Agentic RAG must also ask whether the right tool was selected, whether searches were useful, and whether the agent stopped at the right time.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Suggested metrics&lt;/th&gt;
&lt;th&gt;Question answered&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Retrieval&lt;/td&gt;
&lt;td&gt;Recall@K, MRR, nDCG, evidence coverage&lt;/td&gt;
&lt;td&gt;Was the right material found?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Generation&lt;/td&gt;
&lt;td&gt;Correctness, faithfulness, citation precision and completeness&lt;/td&gt;
&lt;td&gt;Is the answer supported?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Trajectory&lt;/td&gt;
&lt;td&gt;Tool-choice accuracy, query utility, average steps, stop accuracy&lt;/td&gt;
&lt;td&gt;Was the process reasonable?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;System&lt;/td&gt;
&lt;td&gt;P50/P95 latency, token and tool cost, timeout rate&lt;/td&gt;
&lt;td&gt;Was the quality gain worth it?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Safety&lt;/td&gt;
&lt;td&gt;Unauthorized-call rate, injection success rate, data leakage rate&lt;/td&gt;
&lt;td&gt;Did the system preserve boundaries?&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Build a layered test set: simple single-hop cases for the fast path; multi-hop cases for decomposition and evidence composition; underspecified requests for clarification; conflicting sources for conflict handling; and malicious documents for prompt-injection defenses. A handful of answers that “look good” is not enough for production decisions.&lt;/p&gt;
&lt;h2 id=&#34;when-to-use-it&#34;&gt;When to use it
&lt;/h2&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Scenario&lt;/th&gt;
&lt;th&gt;Recommended approach&lt;/th&gt;
&lt;th&gt;Why&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;FAQ, manuals, single-policy questions&lt;/td&gt;
&lt;td&gt;Traditional RAG&lt;/td&gt;
&lt;td&gt;Stable query shape and clear answer boundaries&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;One index with occasional recall problems&lt;/td&gt;
&lt;td&gt;Advanced RAG&lt;/td&gt;
&lt;td&gt;Improve hybrid search, reranking, rewrites, and evaluation first&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Interdependent subquestions&lt;/td&gt;
&lt;td&gt;Agentic RAG&lt;/td&gt;
&lt;td&gt;Requires decomposition and follow-up retrieval&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Documents, databases, and live APIs together&lt;/td&gt;
&lt;td&gt;Agentic RAG&lt;/td&gt;
&lt;td&gt;Requires dynamic routing across heterogeneous tools&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Medical, financial, or production-changing actions&lt;/td&gt;
&lt;td&gt;Agentic RAG plus human approval&lt;/td&gt;
&lt;td&gt;Retrieval can support judgment; high-impact action still needs authorization&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Very low latency, high throughput, fixed output&lt;/td&gt;
&lt;td&gt;Traditional RAG or rules&lt;/td&gt;
&lt;td&gt;Agent loops rarely justify their overhead&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;For a new system, evolve in this order:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Build an evaluable traditional RAG baseline.&lt;/li&gt;
&lt;li&gt;Add hybrid retrieval, metadata filters, reranking, and citation checks.&lt;/li&gt;
&lt;li&gt;Give only obvious source-selection decisions to a router.&lt;/li&gt;
&lt;li&gt;Add a bounded retrieve-evaluate-correct loop for complex queries.&lt;/li&gt;
&lt;li&gt;Consider multi-agent workflows, long-term memory, and broader tool access last.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion
&lt;/h2&gt;&lt;p&gt;The value of Agentic RAG is not that it makes RAG look more like an “agent.” It gives a system three abilities that a fixed retrieval pipeline lacks:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Plan&lt;/strong&gt;: turn a complex request into verifiable retrieval tasks.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Adapt&lt;/strong&gt;: change queries, sources, or ask for clarification based on intermediate evidence.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Verify&lt;/strong&gt;: stop, degrade, or involve a human when evidence is missing, contradictory, or outside the permission boundary.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The costs are equally real: more model calls, higher latency, more state, a larger security surface, and harder evaluation. Mature systems usually do not make every request agentic. They retain a stable traditional RAG fast path and reserve Agentic RAG for questions that genuinely require multi-step, multi-source, runtime decisions.&lt;/p&gt;
&lt;p&gt;In one sentence:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Traditional RAG asks, “Which passage is relevant?” Agentic RAG additionally asks, “What should I find next, where should I look, and do I have enough evidence to stop?”&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;references&#34;&gt;References
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Lewis et al., &lt;a class=&#34;link&#34; href=&#34;https://arxiv.org/abs/2005.11401&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks&lt;/a&gt;, 2020.&lt;/li&gt;
&lt;li&gt;Yao et al., &lt;a class=&#34;link&#34; href=&#34;https://arxiv.org/abs/2210.03629&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;ReAct: Synergizing Reasoning and Acting in Language Models&lt;/a&gt;, 2022.&lt;/li&gt;
&lt;li&gt;Asai et al., &lt;a class=&#34;link&#34; href=&#34;https://arxiv.org/abs/2310.11511&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Self-RAG: Learning to Retrieve, Generate, and Critique through Self-Reflection&lt;/a&gt;, 2023.&lt;/li&gt;
&lt;li&gt;Yan et al., &lt;a class=&#34;link&#34; href=&#34;https://arxiv.org/abs/2401.15884&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Corrective Retrieval Augmented Generation&lt;/a&gt;, 2024.&lt;/li&gt;
&lt;li&gt;Singh et al., &lt;a class=&#34;link&#34; href=&#34;https://arxiv.org/abs/2501.09136&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Agentic Retrieval-Augmented Generation: A Survey on Agentic RAG&lt;/a&gt;, 2025.&lt;/li&gt;
&lt;li&gt;Microsoft, &lt;a class=&#34;link&#34; href=&#34;https://learn.microsoft.com/en-us/azure/architecture/ai-ml/guide/rag/rag-agentic&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Develop an Agentic RAG Solution on Azure&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;LangChain, &lt;a class=&#34;link&#34; href=&#34;https://docs.langchain.com/oss/python/learn&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;RAG agent and custom RAG agent tutorials&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>FastGPT in Depth: RAG, Workflows, and Self-Hosting</title>
        <link>https://SymphonyW.github.io/p/fastgpt-guide/</link>
        <pubDate>Thu, 08 Oct 2026 00:00:00 +0800</pubDate>
        
        <guid>https://SymphonyW.github.io/p/fastgpt-guide/</guid>
        <description>&lt;img src="https://SymphonyW.github.io/p/fastgpt-guide/bg.png" alt="Featured image of post FastGPT in Depth: RAG, Workflows, and Self-Hosting" /&gt;&lt;h1 id=&#34;fastgpt-in-depth-rag-workflows-and-self-hosting&#34;&gt;FastGPT in Depth: RAG, Workflows, and Self-Hosting
&lt;/h1&gt;&lt;blockquote&gt;
&lt;p&gt;FastGPT is neither a reskinned chat window nor merely a vector-database console. It brings model access, document processing, RAG retrieval, workflow orchestration, debugging, publishing, and operations into one platform so a team can turn an AI demo into a deliverable application.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Teams building a company knowledge assistant, support bot, policy Q&amp;amp;A system, content-review pipeline, or data agent soon hit the same problems: multiple model providers, messy documents, retrieval tuning, business logic that no single prompt can express, and production requirements such as permissions, quotas, logs, and channel integrations.&lt;/p&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.com/labring/FastGPT&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;FastGPT&lt;/a&gt; consolidates much of that repeated infrastructure. The project describes itself as an &lt;strong&gt;AI Agent building platform&lt;/strong&gt;; its Community Edition includes the core Agent, workflow, and Dataset features. This guide focuses on how those parts work together, how to deliver a small application, and where the platform does—and does not—fit.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://SymphonyW.github.io/p/fastgpt-guide/platform-map.svg&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;&lt;img src=&#34;https://SymphonyW.github.io/p/fastgpt-guide/platform-map.svg&#34; alt=&#34;FastGPT organizes models, knowledge, workflows, and publishing channels as one application platform&#34; loading=&#34;lazy&#34; decoding=&#34;async&#34;&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;what-fastgpt-actually-is&#34;&gt;What FastGPT actually is
&lt;/h2&gt;&lt;p&gt;FastGPT sits in the &lt;strong&gt;AI application layer above foundation models&lt;/strong&gt;. The model understands and generates language; the vector store finds similar content; FastGPT connects both to business processes and exposes the result as a configurable, debuggable application.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Problem&lt;/th&gt;
&lt;th&gt;What FastGPT adds&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Models&lt;/td&gt;
&lt;td&gt;Which chat, embedding, rerank, or vision model to call&lt;/td&gt;
&lt;td&gt;Provider configuration and AI Proxy routing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Knowledge&lt;/td&gt;
&lt;td&gt;How to parse, index, retrieve, and cite documents&lt;/td&gt;
&lt;td&gt;Datasets, ingestion, vector/full-text/hybrid search, reranking&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Orchestration&lt;/td&gt;
&lt;td&gt;How to implement a multi-step task&lt;/td&gt;
&lt;td&gt;Visual nodes, variables, branches, plugins, and Agents&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Delivery&lt;/td&gt;
&lt;td&gt;How to test, reuse, and ship the result&lt;/td&gt;
&lt;td&gt;Debug logs, share links, APIs, embeds, and MCP&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Operations&lt;/td&gt;
&lt;td&gt;Who used it, what it cost, and what failed&lt;/td&gt;
&lt;td&gt;Teams, quotas, records, logs, and annotation workflows&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;This is useful for developers who want to ship without building an entire RAG and orchestration control plane, and for product or delivery teams that can model a process but do not want to hand-code every backend component.&lt;/p&gt;
&lt;p&gt;It is not a quality button. Answer quality still depends on source material, chunking, embeddings, retrieval settings, reranking, prompts, and the chosen model. FastGPT reduces systems work; it does not make poor data disappear.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;how-the-core-pieces-cooperate&#34;&gt;How the core pieces cooperate
&lt;/h2&gt;&lt;h3 id=&#34;datasets-go-beyond-documents-to-vectors&#34;&gt;Datasets go beyond “documents to vectors”
&lt;/h3&gt;&lt;p&gt;During ingestion, a document is parsed, cleaned, chunked, indexed, and stored. At query time, FastGPT can rewrite the query, recall candidates through semantic, full-text, and image paths, fuse ranked lists with RRF, rerank candidates, and then filter the context by relevance and citation-token budget. The details are documented in the official &lt;a class=&#34;link&#34; href=&#34;https://doc.fastgpt.io/en/guide/dataset/dataset_engine&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Dataset search guide&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://SymphonyW.github.io/p/fastgpt-guide/rag-pipeline.svg&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;&lt;img src=&#34;https://SymphonyW.github.io/p/fastgpt-guide/rag-pipeline.svg&#34; alt=&#34;The complete FastGPT Dataset path from ingestion to grounded generation&#34; loading=&#34;lazy&#34; decoding=&#34;async&#34;&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;Four design details matter in practice:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Dataset, Collection, and Data are separate levels.&lt;/strong&gt; A Dataset is searched as a whole, a Collection groups material much like a file, and Data entries are the units used for Q&amp;amp;A.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;One Data entry may map to several vectors.&lt;/strong&gt; Several focused indexes can improve recall while still returning one complete source passage.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hybrid retrieval is more robust than vector-only search.&lt;/strong&gt; Exact identifiers benefit from full-text search, natural questions from semantic search, and RRF combines the rankings.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Citation limits use tokens, not just Top-K.&lt;/strong&gt; Fixed counts are unstable when chunk lengths differ greatly.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;MongoDB holds most non-vector data. Vector data can live in PostgreSQL/PGVector, Milvus, OceanBase, SeekDB, and other supported backends. With PGVector, vector IDs link back to source records in MongoDB, so a complete backup must cover both stores.&lt;/p&gt;
&lt;h3 id=&#34;workflows-turn-prompts-into-observable-programs&#34;&gt;Workflows turn prompts into observable programs
&lt;/h3&gt;&lt;p&gt;A minimal chat needs only an input and an AI Chat node. Real work adds classification, retrieval, HTTP calls, conditions, formatting, and fallback paths. A FastGPT node resembles a function: it has inputs, outputs, and triggers, and later nodes can reference earlier outputs.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://SymphonyW.github.io/p/fastgpt-guide/workflow-example.svg&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;&lt;img src=&#34;https://SymphonyW.github.io/p/fastgpt-guide/workflow-example.svg&#34; alt=&#34;A customer-support workflow routes, retrieves, and calls controlled tools&#34; loading=&#34;lazy&#34; decoding=&#34;async&#34;&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;The workflow runtime advances through connection states. A node executes when a predecessor becomes active, waits when a predecessor is still waiting, and skips when nothing can activate it. This makes branches visible and lets operators inspect each node&amp;rsquo;s inputs and outputs instead of seeing only the final model response.&lt;/p&gt;
&lt;p&gt;Keep responsibilities narrow:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Node&lt;/th&gt;
&lt;th&gt;One responsibility&lt;/th&gt;
&lt;th&gt;Avoid putting this inside&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Classification&lt;/td&gt;
&lt;td&gt;Determine question type&lt;/td&gt;
&lt;td&gt;Long-form answers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Query Rewrite&lt;/td&gt;
&lt;td&gt;Resolve references and complete a search query&lt;/td&gt;
&lt;td&gt;Changing exact IDs or product numbers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dataset Search&lt;/td&gt;
&lt;td&gt;Recall citable evidence&lt;/td&gt;
&lt;td&gt;Final business decisions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HTTP / plugin&lt;/td&gt;
&lt;td&gt;Fetch live data or perform a controlled action&lt;/td&gt;
&lt;td&gt;Hidden, unauditable business rules&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AI Chat&lt;/td&gt;
&lt;td&gt;Synthesize context in the required format&lt;/td&gt;
&lt;td&gt;Persistent business state&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fixed Reply&lt;/td&gt;
&lt;td&gt;Deterministic errors, refusal, or handoff&lt;/td&gt;
&lt;td&gt;Open-ended reasoning&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&#34;agents-plugins-and-delivery&#34;&gt;Agents, plugins, and delivery
&lt;/h3&gt;&lt;p&gt;Workflows are best when the path is known. Agents are useful when the model must plan and choose among tools. Plugins package search, databases, messaging, document processing, and other external capabilities. They complement each other: a reliable production Agent should still constrain sensitive actions to explicit tools and guarded subflows.&lt;/p&gt;
&lt;p&gt;Finished applications can be exposed by share link, embed, OpenAI-style API, or MCP Server. API keys are member-level OpenAPI credentials; the current documentation recommends sending &lt;code&gt;appId&lt;/code&gt; in &lt;code&gt;chat/completions&lt;/code&gt;. Public links consume the owning team&amp;rsquo;s quota, so use expiration, quotas, authentication, and explicit approval around tools with side effects.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;building-an-employee-policy-assistant&#34;&gt;Building an employee-policy assistant
&lt;/h2&gt;&lt;p&gt;The goal is a grounded assistant that cites company policy, refuses unsupported questions, and uses an internal API only for personal information.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. Write acceptance questions first.&lt;/strong&gt; Prepare 20–50 questions covering direct facts, cross-section reasoning, exact form IDs, multi-turn follow-ups, private-data requests, and questions absent from the source set. This becomes the regression suite for every prompt, model, chunking, or retrieval change.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. Clean the material before tuning thresholds.&lt;/strong&gt; Remove duplicates and obsolete versions, preserve headings, OCR scanned PDFs, and attach metadata such as department, version, and effective date. Keep each chunk semantically complete. Conditions, exceptions, and conclusions belonging to one rule should remain together.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3. Start with the smallest workflow.&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;User question
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  → Query Rewrite (only for ambiguous follow-ups)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  → Dataset Search (hybrid retrieval + rerank)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  → AI Chat (answer only from citations)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  → Answer with sources
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;A useful system instruction is short and testable:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;You are the company policy assistant. Answer only from the cited material.
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;If the evidence is insufficient, say that the current policy set has no answer.
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;For personal balances, approval status, or private employee data, do not guess;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;require authorization before querying the internal system.
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Give the conclusion first, then conditions, policy name, and effective date.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;If form IDs fail, try full-text or hybrid search first. If conversational follow-ups fail, add query rewriting. If the right passages appear but are ordered poorly, inspect reranking. Change one variable at a time and rerun the same test set.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;4. Add live data as a separate branch.&lt;/strong&gt; Policy interpretation should use the Dataset; a remaining-leave balance should come from the HR system after identity and permission checks. Do not periodically embed rapidly changing balances into the vector store, and do not let the model compose unrestricted SQL.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;5. Test retrieval, generation, flow, and security.&lt;/strong&gt; Verify that the correct current policy is recalled; answers remain faithful; timeouts enter a safe fallback; and prompt injection cannot call private tools. A fluent final answer is not enough evidence that the system works.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;self-hosting-and-production-concerns&#34;&gt;Self-hosting and production concerns
&lt;/h2&gt;&lt;p&gt;&lt;a href=&#34;https://SymphonyW.github.io/p/fastgpt-guide/deployment-architecture.svg&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;&lt;img src=&#34;https://SymphonyW.github.io/p/fastgpt-guide/deployment-architecture.svg&#34; alt=&#34;The main services and data paths in a self-hosted FastGPT deployment&#34; loading=&#34;lazy&#34; decoding=&#34;async&#34;&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;The official Docker Compose architecture includes the FastGPT application, MongoDB, a vector database, and AI Proxy. Agent/Skill sandboxes, object storage, MCP, and advanced parsing can add more services.&lt;/p&gt;
&lt;p&gt;The current official installer runs on Linux, macOS, or Windows through WSL:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;FASTGPT_DEPLOY_BASE_URL&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;https://doc.fastgpt.cn &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;  bash &amp;lt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;curl -fsSL https://doc.fastgpt.cn/deploy/install.sh&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;docker compose --profile prepull pull
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;docker compose up -d
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The script selects a vector backend, downloads Compose configuration, and generates credentials. For production, download and review remote scripts before execution, retain the generated Compose file and secrets, and pin explicit image versions instead of depending indefinitely on &lt;code&gt;latest&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;After deployment, configure the public &lt;code&gt;FE_DOMAIN&lt;/code&gt;, add at least a chat model and embedding model in the admin console, and install the required system plugins. Put the service behind an HTTPS reverse proxy and expose only necessary ports.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Production area&lt;/th&gt;
&lt;th&gt;Practical baseline&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Persistence&lt;/td&gt;
&lt;td&gt;Durable volumes for MongoDB, vector data, and object storage; prove that restore works&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Secrets&lt;/td&gt;
&lt;td&gt;Replace defaults; keep model keys, database passwords, and API keys out of Git&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Network&lt;/td&gt;
&lt;td&gt;Never expose databases publicly; restrict egress and apply upload/domain allowlists&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Upgrades&lt;/td&gt;
&lt;td&gt;Read migration notes, upgrade in small steps, back up first, and replay the regression set&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Observability&lt;/td&gt;
&lt;td&gt;Track node latency, model failures, token use, retrieval hits, and refusal rates&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Capacity&lt;/td&gt;
&lt;td&gt;Watch vector count, indexing time, MongoDB growth, concurrency, and provider limits&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Start with the lightest backend that meets measured needs. PGVector is a practical small-to-medium starting point in the official guidance; distributed engines such as Milvus become relevant at much larger scale. Migration includes index rebuilding, downtime planning, performance validation, and backups—not merely copying vectors.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;api-integration-and-system-boundaries&#34;&gt;API integration and system boundaries
&lt;/h2&gt;&lt;p&gt;FastGPT can be the chat UI or sit behind your own web app and collaboration channels. Its OpenAI-style API lowers integration cost, but compatibility does not mean every extension field is identical across versions. Verify against the OpenAPI documentation shipped with your instance.&lt;/p&gt;
&lt;p&gt;The shape of a request is:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;curl https://fastgpt.example.com/api/v1/chat/completions &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;  -H &lt;span class=&#34;s2&#34;&gt;&amp;#34;Authorization: Bearer &lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$FASTGPT_API_KEY&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;  -H &lt;span class=&#34;s2&#34;&gt;&amp;#34;Content-Type: application/json&amp;#34;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;  -d &lt;span class=&#34;s1&#34;&gt;&amp;#39;{
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s1&#34;&gt;    &amp;#34;appId&amp;#34;: &amp;#34;your-app-id&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s1&#34;&gt;    &amp;#34;stream&amp;#34;: false,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s1&#34;&gt;    &amp;#34;messages&amp;#34;: [
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s1&#34;&gt;      {&amp;#34;role&amp;#34;: &amp;#34;user&amp;#34;, &amp;#34;content&amp;#34;: &amp;#34;How much leave does a probationary employee receive?&amp;#34;}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s1&#34;&gt;    ]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s1&#34;&gt;  }&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Treat FastGPT as an AI decision and generation service, not as the system of record. Orders, balances, and approval results remain in deterministic business systems. For payments, notifications, deletion, or other side effects, add authorization, schema validation, idempotency, and human confirmation rather than trusting model-generated arguments.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;fit-trade-offs-and-license&#34;&gt;Fit, trade-offs, and license
&lt;/h2&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Scenario&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;Fit&lt;/th&gt;
&lt;th&gt;Why&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Enterprise document Q&amp;amp;A and support knowledge&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;High&lt;/td&gt;
&lt;td&gt;Datasets, citations, workflows, and delivery are integrated&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Internal process assistants and content review&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;High&lt;/td&gt;
&lt;td&gt;Visual flows connect models, rules, and HTTP tools&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Delivering several vertical AI apps quickly&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;High&lt;/td&gt;
&lt;td&gt;Models, Datasets, plugins, and templates are reusable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A basic model playground&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;Medium&lt;/td&gt;
&lt;td&gt;It works, but may be heavier than necessary&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ultra-low-latency inference gateway&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;Low&lt;/td&gt;
&lt;td&gt;Use a specialized gateway and inference stack&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Transactional core business workflow&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;Low&lt;/td&gt;
&lt;td&gt;LLM orchestration is not a transaction system&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Competing multi-tenant SaaS&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;Review first&lt;/td&gt;
&lt;td&gt;The license places additional conditions on this use&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Compared with Dify, Coze, Langflow, Flowise, or a custom LangChain/LlamaIndex stack, FastGPT has a clear center of gravity: &lt;strong&gt;knowledge-based applications, visual orchestration, and private delivery&lt;/strong&gt;. Platforms provide speed and consistency; code-first stacks provide maximum control. Choose according to which engineering work the team wants to avoid and which platform constraints it accepts.&lt;/p&gt;
&lt;p&gt;Read the license carefully. The FastGPT Open Source License is based on Apache License 2.0 but adds conditions for operating a similar multi-tenant SaaS and for modifying or removing console logo and copyright information. This is not legal advice; check the repository&amp;rsquo;s current &lt;a class=&#34;link&#34; href=&#34;https://github.com/labring/FastGPT/blob/main/LICENSE&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;LICENSE&lt;/a&gt; before commercial use.&lt;/p&gt;
&lt;p&gt;The lasting value of FastGPT is that it makes an AI application buildable, observable, and reusable. Its main risk is making a full canvas look like a finished system. Track retrieval hit rate, groundedness, task success, refusal and handoff rates, P50/P95 latency, cost per successful task, and regression results across every model, prompt, Dataset, and workflow change.&lt;/p&gt;
&lt;p&gt;The useful rule is simple: &lt;strong&gt;treat FastGPT as an AI application engineering platform, not as a substitute for evaluation.&lt;/strong&gt; Prove value with the smallest flow, improve retrieval and prompts against a fixed test set, and add Agents and automated actions only when the simpler system has earned that complexity.&lt;/p&gt;
&lt;p&gt;This article reflects official material available in October 2026. FastGPT moves quickly, so recheck deployment variables, version dependencies, and API fields before implementation.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Official references:&lt;/strong&gt; &lt;a class=&#34;link&#34; href=&#34;https://github.com/labring/FastGPT&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;GitHub repository&lt;/a&gt; · &lt;a class=&#34;link&#34; href=&#34;https://doc.fastgpt.io/en/guide/version/opensource/intro&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Community Edition&lt;/a&gt; · &lt;a class=&#34;link&#34; href=&#34;https://doc.fastgpt.io/en/guide/build/workflow/intro&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Workflow runtime&lt;/a&gt; · &lt;a class=&#34;link&#34; href=&#34;https://doc.fastgpt.io/en/guide/dataset/dataset_engine&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Dataset retrieval&lt;/a&gt; · &lt;a class=&#34;link&#34; href=&#34;https://doc.fastgpt.io/en/self-host/deploy/docker&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Docker Compose deployment&lt;/a&gt; · &lt;a class=&#34;link&#34; href=&#34;https://doc.fastgpt.io/en/guide/build/publish/openapi&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;API publishing&lt;/a&gt;&lt;/p&gt;
</description>
        </item>
        <item>
        <title>From Keyword Matching to Vector Retrieval: Three Ways to Search</title>
        <link>https://SymphonyW.github.io/p/search-matching-retrieval/</link>
        <pubDate>Fri, 02 Oct 2026 20:13:30 +0800</pubDate>
        
        <guid>https://SymphonyW.github.io/p/search-matching-retrieval/</guid>
        <description>&lt;img src="https://SymphonyW.github.io/p/search-matching-retrieval/bg.svg" alt="Featured image of post From Keyword Matching to Vector Retrieval: Three Ways to Search" /&gt;&lt;h1 id=&#34;from-keyword-matching-to-vector-retrieval-three-ways-to-search&#34;&gt;From Keyword Matching to Vector Retrieval: Three Ways to Search
&lt;/h1&gt;&lt;blockquote&gt;
&lt;p&gt;Search is not one technique. &lt;strong&gt;Keyword matching&lt;/strong&gt; finds words that appear literally, &lt;strong&gt;fuzzy search&lt;/strong&gt; rescues misspellings and partial input, and &lt;strong&gt;vector retrieval&lt;/strong&gt; finds content with similar meaning. In RAG systems, these methods usually complement each other rather than replace each other.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href=&#34;https://SymphonyW.github.io/p/search-matching-retrieval/bg.svg&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;&lt;img src=&#34;https://SymphonyW.github.io/p/search-matching-retrieval/bg.svg&#34; alt=&#34;From keyword matching to vector retrieval&#34; loading=&#34;lazy&#34; decoding=&#34;async&#34;&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;A quick example:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;User intent&lt;/th&gt;
&lt;th&gt;Input&lt;/th&gt;
&lt;th&gt;Best starting point&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Find an explicit rule&lt;/td&gt;
&lt;td&gt;&lt;code&gt;refund policy&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Keyword matching&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Recover a typo&lt;/td&gt;
&lt;td&gt;&lt;code&gt;retun policy&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Fuzzy search&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ask naturally&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Can I change my mind after buying this?&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Vector retrieval&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Need both precision and semantics&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Can a premium member refund the wrong plan?&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Hybrid retrieval + reranking&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;a href=&#34;https://SymphonyW.github.io/p/search-matching-retrieval/matching-spectrum.svg&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;&lt;img src=&#34;https://SymphonyW.github.io/p/search-matching-retrieval/matching-spectrum.svg&#34; alt=&#34;Search capability spectrum&#34; loading=&#34;lazy&#34; decoding=&#34;async&#34;&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;h2 id=&#34;keyword-matching&#34;&gt;Keyword Matching
&lt;/h2&gt;&lt;p&gt;Keyword matching is the classic information retrieval approach. Documents are tokenized, indexed, and ranked according to term overlap, term frequency, field weights, and document length.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://SymphonyW.github.io/p/search-matching-retrieval/keyword-inverted-index.svg&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;&lt;img src=&#34;https://SymphonyW.github.io/p/search-matching-retrieval/keyword-inverted-index.svg&#34; alt=&#34;Keyword matching and inverted index&#34; loading=&#34;lazy&#34; decoding=&#34;async&#34;&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;The most common structure is an &lt;strong&gt;inverted index&lt;/strong&gt;: instead of scanning documents one by one, the system maps each term to the documents that contain it.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aspect&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Matching signal&lt;/td&gt;
&lt;td&gt;Literal term overlap&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Common algorithms&lt;/td&gt;
&lt;td&gt;TF-IDF, BM25, Boolean queries, field boosts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Strengths&lt;/td&gt;
&lt;td&gt;Fast, stable, explainable, easy to filter&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Weaknesses&lt;/td&gt;
&lt;td&gt;Poor at synonyms, paraphrases, and unstated intent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Best for&lt;/td&gt;
&lt;td&gt;SKU, order id, logs, legal clauses, code symbols, titles&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;If a user searches for &lt;code&gt;redis setnx&lt;/code&gt;, keyword retrieval is excellent. If they search for &lt;code&gt;how do I prevent duplicate orders&lt;/code&gt;, a purely lexical system may miss articles that only mention &lt;code&gt;idempotency&lt;/code&gt; or &lt;code&gt;distributed lock&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;fuzzy-search&#34;&gt;Fuzzy Search
&lt;/h2&gt;&lt;p&gt;Fuzzy search is still lexical search, but more tolerant. It asks whether the user input and the indexed term &lt;strong&gt;look similar enough&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://SymphonyW.github.io/p/search-matching-retrieval/fuzzy-search-flow.svg&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;&lt;img src=&#34;https://SymphonyW.github.io/p/search-matching-retrieval/fuzzy-search-flow.svg&#34; alt=&#34;Fuzzy search flow&#34; loading=&#34;lazy&#34; decoding=&#34;async&#34;&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;Common techniques include:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Technique&lt;/th&gt;
&lt;th&gt;Solves&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Edit distance&lt;/td&gt;
&lt;td&gt;Insertions, deletions, substitutions, transpositions&lt;/td&gt;
&lt;td&gt;&lt;code&gt;retun&lt;/code&gt; → &lt;code&gt;return&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;n-gram / trigram&lt;/td&gt;
&lt;td&gt;Substring similarity&lt;/td&gt;
&lt;td&gt;&lt;code&gt;microserv&lt;/code&gt; → &lt;code&gt;microservice&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Prefix matching&lt;/td&gt;
&lt;td&gt;Autocomplete&lt;/td&gt;
&lt;td&gt;&lt;code&gt;kuber&lt;/code&gt; → &lt;code&gt;kubernetes&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Phonetic or pinyin correction&lt;/td&gt;
&lt;td&gt;Input method mistakes&lt;/td&gt;
&lt;td&gt;pinyin-like input → Chinese term&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Synonym dictionaries&lt;/td&gt;
&lt;td&gt;Manually curated near-equivalents&lt;/td&gt;
&lt;td&gt;&lt;code&gt;after-sales&lt;/code&gt; ≈ &lt;code&gt;returns&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Fuzzy search is great for search box ergonomics: typos, partial names, remembered fragments, and autocomplete. Elasticsearch, OpenSearch, Solr, PostgreSQL trigram, and Algolia all provide related capabilities.&lt;/p&gt;
&lt;p&gt;But fuzzy search does not fully understand meaning. &lt;code&gt;refund&lt;/code&gt; and &lt;code&gt;return&lt;/code&gt; are semantically related, but they may not be textually similar. &lt;code&gt;iPhone&lt;/code&gt; and &lt;code&gt;Apple phone&lt;/code&gt; can be far apart lexically. Once recall is widened, false positives also increase, so fuzzy search needs thresholds, field boosts, popularity, click signals, and business rules.&lt;/p&gt;
&lt;h2 id=&#34;vector-retrieval&#34;&gt;Vector Retrieval
&lt;/h2&gt;&lt;p&gt;Vector retrieval uses an embedding model to convert text, images, audio, or other objects into numeric vectors. Items with similar meaning are close in vector space. At query time, the system embeds the user query and retrieves the nearest vectors.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://SymphonyW.github.io/p/search-matching-retrieval/vector-rag-flow.svg&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;&lt;img src=&#34;https://SymphonyW.github.io/p/search-matching-retrieval/vector-rag-flow.svg&#34; alt=&#34;Vector retrieval and RAG flow&#34; loading=&#34;lazy&#34; decoding=&#34;async&#34;&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;This is the retrieval foundation of many RAG systems: retrieve relevant chunks from a knowledge base, insert them into the prompt, and let the LLM answer with external context.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aspect&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Matching signal&lt;/td&gt;
&lt;td&gt;Semantic similarity in embedding space&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Common indexes&lt;/td&gt;
&lt;td&gt;HNSW, IVF, PQ, DiskANN&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Common metrics&lt;/td&gt;
&lt;td&gt;Cosine similarity, inner product, Euclidean distance&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Strengths&lt;/td&gt;
&lt;td&gt;Handles paraphrases, natural questions, cross-lingual and multimodal similarity&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Weaknesses&lt;/td&gt;
&lt;td&gt;Higher cost, weaker explainability, less reliable for exact constraints&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Best for&lt;/td&gt;
&lt;td&gt;Knowledge base QA, similar articles, image similarity, recommendations, semantic code search&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;For example, a document may say:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Customers may request no-reason returns within 7 days after order completion.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;A user may ask:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Can I send it back if I no longer want it?
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Keyword search may miss the connection. Vector search is more likely to retrieve the return policy because the meanings are close.&lt;/p&gt;
&lt;p&gt;Vector retrieval is not magic, though. It is weaker for exact IDs, version numbers, permissions, and precise field filters. For &lt;code&gt;HTTP 451&lt;/code&gt;, &lt;code&gt;order 202610020001&lt;/code&gt;, or &lt;code&gt;Go 1.22&lt;/code&gt;, lexical and structured retrieval are often safer.&lt;/p&gt;
&lt;h2 id=&#34;core-differences&#34;&gt;Core Differences
&lt;/h2&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Dimension&lt;/th&gt;
&lt;th&gt;Keyword matching&lt;/th&gt;
&lt;th&gt;Fuzzy search&lt;/th&gt;
&lt;th&gt;Vector retrieval&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Focus&lt;/td&gt;
&lt;td&gt;Did the term appear?&lt;/td&gt;
&lt;td&gt;Is the term similar?&lt;/td&gt;
&lt;td&gt;Is the meaning similar?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Query style&lt;/td&gt;
&lt;td&gt;Precise, short, terminology-heavy&lt;/td&gt;
&lt;td&gt;Typo-prone, abbreviated, partial&lt;/td&gt;
&lt;td&gt;Natural, descriptive, long&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Recall&lt;/td&gt;
&lt;td&gt;Precise but can miss&lt;/td&gt;
&lt;td&gt;Wider lexical recall&lt;/td&gt;
&lt;td&gt;Strong semantic recall&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Explainability&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;Lower&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Latency and cost&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;Medium to high&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Typical tools&lt;/td&gt;
&lt;td&gt;MySQL, Lucene, Elasticsearch BM25&lt;/td&gt;
&lt;td&gt;Elasticsearch fuzzy, trigram, Algolia&lt;/td&gt;
&lt;td&gt;FAISS, Milvus, Qdrant, Pinecone, Weaviate&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;A simple mental model:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Keyword matching: you said A, so I search for A.
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Fuzzy search: you probably meant A, so I search for A.
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Vector retrieval: you meant something like A, so I search for similar meaning.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;classic-applications&#34;&gt;Classic Applications
&lt;/h2&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Scenario&lt;/th&gt;
&lt;th&gt;Recommended approach&lt;/th&gt;
&lt;th&gt;Why&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Log search&lt;/td&gt;
&lt;td&gt;Keyword + time/service filters&lt;/td&gt;
&lt;td&gt;Exact error codes and fields matter&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;E-commerce search&lt;/td&gt;
&lt;td&gt;Keyword + fuzzy + vector recall&lt;/td&gt;
&lt;td&gt;Product names need precision, user input is messy, recommendations need semantics&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Code search&lt;/td&gt;
&lt;td&gt;Symbol index + keyword + semantic vectors&lt;/td&gt;
&lt;td&gt;Names matter, but user intent can be natural language&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Enterprise knowledge QA&lt;/td&gt;
&lt;td&gt;Vector + BM25 + reranking + RAG&lt;/td&gt;
&lt;td&gt;The system must understand questions, retrieve evidence, and cite sources&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Image similarity&lt;/td&gt;
&lt;td&gt;Vector retrieval&lt;/td&gt;
&lt;td&gt;Visual similarity is hard to express with keywords&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Help center search&lt;/td&gt;
&lt;td&gt;Keyword + fuzzy + synonyms + vector retrieval&lt;/td&gt;
&lt;td&gt;Users mix product terms and natural language&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Enterprise RAG is the clearest example. Users rarely repeat document titles exactly. They ask questions like “Why was this reimbursement rejected?” or “How does sick leave work during probation?” A robust system filters by permissions, retrieves candidates with both BM25 and vectors, reranks them, and sends only a small set of reliable chunks to the LLM.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://SymphonyW.github.io/p/search-matching-retrieval/hybrid-ranking.svg&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;&lt;img src=&#34;https://SymphonyW.github.io/p/search-matching-retrieval/hybrid-ranking.svg&#34; alt=&#34;Hybrid retrieval pipeline&#34; loading=&#34;lazy&#34; decoding=&#34;async&#34;&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;h2 id=&#34;practical-selection&#34;&gt;Practical Selection
&lt;/h2&gt;&lt;p&gt;&lt;a href=&#34;https://SymphonyW.github.io/p/search-matching-retrieval/decision-map.svg&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;&lt;img src=&#34;https://SymphonyW.github.io/p/search-matching-retrieval/decision-map.svg&#34; alt=&#34;Search method decision map&#34; loading=&#34;lazy&#34; decoding=&#34;async&#34;&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;Use this quick guide:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Problem&lt;/th&gt;
&lt;th&gt;Start with&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Users type order IDs, error codes, function names, or exact terms&lt;/td&gt;
&lt;td&gt;Keyword matching&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Users often misspell, abbreviate, or type only prefixes&lt;/td&gt;
&lt;td&gt;Fuzzy search&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Users describe intent in natural language&lt;/td&gt;
&lt;td&gt;Vector retrieval&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;You need exact filters, semantic understanding, and LLM grounding&lt;/td&gt;
&lt;td&gt;Hybrid retrieval&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Production search is usually a layered system:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Structured filters&lt;/strong&gt;: permissions, tenants, time, category.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Keyword recall&lt;/strong&gt;: BM25 protects exact terms, titles, IDs, and entities.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Vector recall&lt;/strong&gt;: captures paraphrases and semantic intent.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Fusion&lt;/strong&gt;: RRF or weighted scoring merges candidate lists.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reranking&lt;/strong&gt;: cross-encoders, LLM rerankers, or business rules refine the final order.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Generation&lt;/strong&gt;: in RAG, only the most relevant and trustworthy chunks are inserted into the prompt.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;the-takeaway&#34;&gt;The Takeaway
&lt;/h2&gt;&lt;p&gt;Keyword matching answers &lt;strong&gt;“does this word appear?”&lt;/strong&gt; Fuzzy search answers &lt;strong&gt;“was this word typed imperfectly?”&lt;/strong&gt; Vector retrieval answers &lt;strong&gt;“what does this query mean?”&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;For a normal search box, start with keyword retrieval, tokenization, field boosts, and fuzzy correction. For knowledge QA or intelligent support, add vector retrieval and RAG. For real production systems, hybrid retrieval is usually where the design lands, because users alternate between exact identifiers and vague natural language all the time.&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Vector Databases vs. Traditional Databases</title>
        <link>https://SymphonyW.github.io/p/vector-databases-vs.-traditional-databases/</link>
        <pubDate>Mon, 13 Jul 2026 21:24:23 +0800</pubDate>
        
        <guid>https://SymphonyW.github.io/p/vector-databases-vs.-traditional-databases/</guid>
        <description>&lt;img src="https://SymphonyW.github.io/p/vector-databases-vs.-traditional-databases/bg.png" alt="Featured image of post Vector Databases vs. Traditional Databases" /&gt;&lt;h1 id=&#34;向量数据库与传统数据库&#34;&gt;向量数据库与传统数据库
&lt;/h1&gt;&lt;p&gt;在传统的软件系统中，数据库主要负责存储用户、订单、商品、日志等结构化数据。当我们需要查询某个用户时，通常会使用用户 ID、手机号或者用户名作为条件。&lt;/p&gt;
&lt;p&gt;例如：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;SELECT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;FROM&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;users&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;WHERE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;username&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;zhangsan&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这种查询的特点是：&lt;strong&gt;查询条件明确，数据库需要找到精确匹配的数据。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;但是在人工智能应用中，我们可能会遇到另一类问题：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;找出与这段文字含义最接近的文章。&lt;/li&gt;
&lt;li&gt;找到与当前商品风格相似的商品。&lt;/li&gt;
&lt;li&gt;根据一张图片搜索视觉上相似的图片。&lt;/li&gt;
&lt;li&gt;从知识库中找到能够回答用户问题的内容。&lt;/li&gt;
&lt;li&gt;判断两段代码是否实现了相似的功能。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这些问题很难仅通过 &lt;code&gt;=&lt;/code&gt;、&lt;code&gt;LIKE&lt;/code&gt; 或普通关键字查询解决。&lt;/p&gt;
&lt;p&gt;向量数据库正是为了解决这类“相似性检索”问题而出现的。&lt;/p&gt;
&lt;div class=&#34;mermaid&#34;&gt;flowchart LR
    A[传统数据库] --&gt; B[精确匹配]
    A --&gt; C[范围查询]
    A --&gt; D[事务处理]

    E[向量数据库] --&gt; F[语义相似度搜索]
    E --&gt; G[图片相似度搜索]
    E --&gt; H[多模态检索]
&lt;/div&gt;&lt;h2 id=&#34;什么是传统数据库&#34;&gt;什么是传统数据库
&lt;/h2&gt;&lt;p&gt;传统数据库通常指关系型数据库，以及部分通用型 NoSQL 数据库，例如：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;MySQL&lt;/li&gt;
&lt;li&gt;PostgreSQL&lt;/li&gt;
&lt;li&gt;Oracle&lt;/li&gt;
&lt;li&gt;SQL Server&lt;/li&gt;
&lt;li&gt;MongoDB&lt;/li&gt;
&lt;li&gt;Redis&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;关系型数据库将数据组织成表，每张表由行和列构成。&lt;/p&gt;
&lt;p&gt;例如，一个商品表可能是：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&#34;text-align:right&#34;&gt;id&lt;/th&gt;
&lt;th&gt;name&lt;/th&gt;
&lt;th&gt;category&lt;/th&gt;
&lt;th style=&#34;text-align:right&#34;&gt;price&lt;/th&gt;
&lt;th style=&#34;text-align:right&#34;&gt;stock&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:right&#34;&gt;1001&lt;/td&gt;
&lt;td&gt;机械键盘&lt;/td&gt;
&lt;td&gt;外设&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;399&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;20&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:right&#34;&gt;1002&lt;/td&gt;
&lt;td&gt;无线鼠标&lt;/td&gt;
&lt;td&gt;外设&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;199&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;35&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:right&#34;&gt;1003&lt;/td&gt;
&lt;td&gt;显示器&lt;/td&gt;
&lt;td&gt;显示设备&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;1599&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;8&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;我们可以按照字段进行精确查询：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;SELECT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;FROM&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;products&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;WHERE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;category&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;外设&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;AND&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;price&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;300&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;传统数据库擅长处理以下任务：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;根据主键查询数据。&lt;/li&gt;
&lt;li&gt;根据字段进行过滤和排序。&lt;/li&gt;
&lt;li&gt;执行增删改查操作。&lt;/li&gt;
&lt;li&gt;保证事务一致性。&lt;/li&gt;
&lt;li&gt;维护实体之间的关联关系。&lt;/li&gt;
&lt;li&gt;进行统计、聚合和报表分析。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;例如，在电商系统中，订单创建通常涉及库存扣减、订单写入和支付记录生成。这些操作必须满足事务要求。&lt;/p&gt;
&lt;div class=&#34;mermaid&#34;&gt;sequenceDiagram
    participant U as 用户
    participant O as 订单服务
    participant DB as 传统数据库

    U-&gt;&gt;O: 创建订单
    O-&gt;&gt;DB: 开启事务
    O-&gt;&gt;DB: 扣减库存
    O-&gt;&gt;DB: 创建订单
    O-&gt;&gt;DB: 写入支付记录
    DB--&gt;&gt;O: 提交事务
    O--&gt;&gt;U: 订单创建成功
&lt;/div&gt;&lt;p&gt;传统数据库关注的是：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;数据是否准确、关系是否完整、事务是否可靠。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;什么是向量&#34;&gt;什么是向量
&lt;/h2&gt;&lt;p&gt;要理解向量数据库，首先需要理解向量。&lt;/p&gt;
&lt;p&gt;在人工智能系统中，文本、图片、音频和视频可以通过模型转换成一组数字。这组数字称为向量，也常被称为 Embedding。&lt;/p&gt;
&lt;p&gt;例如，下面三句话：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;我喜欢骑自行车旅行。
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;周末我经常骑车去郊外。
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;数据库出现了连接超时。
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;经过 Embedding 模型处理后，可能会被转换为：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;我喜欢骑自行车旅行。
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;→ [0.12, -0.31, 0.85, 0.47, ...]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;周末我经常骑车去郊外。
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;→ [0.15, -0.28, 0.81, 0.51, ...]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;数据库出现了连接超时。
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;→ [-0.62, 0.73, 0.05, -0.16, ...]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;前两句话的含义比较接近，因此它们对应的向量在向量空间中的距离也会更近。&lt;/p&gt;
&lt;div class=&#34;mermaid&#34;&gt;quadrantChart
    title 文本在向量空间中的示意分布
    x-axis 低运动相关度 --&gt; 高运动相关度
    y-axis 低旅行相关度 --&gt; 高旅行相关度
    quadrant-1 骑行与旅行
    quadrant-2 旅行主题
    quadrant-3 技术主题
    quadrant-4 运动主题
    &#34;骑自行车去郊外旅行&#34;: [0.88, 0.86]
    &#34;周末骑车锻炼&#34;: [0.82, 0.55]
    &#34;计划去北欧旅行&#34;: [0.45, 0.91]
    &#34;数据库连接超时&#34;: [0.12, 0.16]
&lt;/div&gt;&lt;p&gt;这里的坐标只是示意。真实的 Embedding 向量往往包含几百甚至几千个维度，人类无法直接观察这些高维空间。&lt;/p&gt;
&lt;p&gt;Embedding 的核心作用，是将原始数据的“语义特征”编码为数值。&lt;/p&gt;
&lt;h2 id=&#34;什么是向量数据库&#34;&gt;什么是向量数据库
&lt;/h2&gt;&lt;p&gt;向量数据库是一类专门用于存储、索引和查询高维向量的数据系统。&lt;/p&gt;
&lt;p&gt;一条向量数据通常不只有向量本身，还会包含原始内容和元数据。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;id&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;article-1001&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;vector&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;0.12&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;-0.31&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;0.85&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;0.47&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;metadata&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;title&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;如何搭建企业内部 SkillHub&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;category&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;AI 工程&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;author&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Xinzhan Wu&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;content&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;本文介绍基于 npm Registry 构建企业内部 SkillHub 的方案。&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;向量数据库可以回答这样的问题：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;哪些数据的向量与当前查询向量最接近？&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;它的基本工作流程如下。&lt;/p&gt;
&lt;div class=&#34;mermaid&#34;&gt;flowchart LR
    A[用户输入问题] --&gt; B[Embedding 模型]
    B --&gt; C[查询向量]
    C --&gt; D[向量数据库]
    D --&gt; E[相似度搜索]
    E --&gt; F[返回 Top-K 结果]
&lt;/div&gt;&lt;p&gt;例如，用户输入：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;企业内部应该如何管理 AI Skill？
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;即使知识库中没有完全相同的句子，向量数据库仍然可能找到以下内容：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;基于 npm Registry 构建企业内部 SkillHub
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;原因是两段文本在语义上比较接近。&lt;/p&gt;
&lt;p&gt;传统关键字搜索关注“是否出现相同的词”，而向量搜索关注“表达的含义是否接近”。&lt;/p&gt;
&lt;h2 id=&#34;向量数据库与传统数据库的核心区别&#34;&gt;向量数据库与传统数据库的核心区别
&lt;/h2&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;对比维度&lt;/th&gt;
&lt;th&gt;传统数据库&lt;/th&gt;
&lt;th&gt;向量数据库&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;主要数据&lt;/td&gt;
&lt;td&gt;字符串、数字、日期、JSON&lt;/td&gt;
&lt;td&gt;高维浮点向量&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;典型查询&lt;/td&gt;
&lt;td&gt;精确匹配、范围查询、关联查询&lt;/td&gt;
&lt;td&gt;相似度查询、Top-K 查询&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;查询条件&lt;/td&gt;
&lt;td&gt;&lt;code&gt;id = 1&lt;/code&gt;、&lt;code&gt;price &amp;lt; 100&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;与查询向量最相似&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;索引结构&lt;/td&gt;
&lt;td&gt;B+ 树、哈希索引、倒排索引&lt;/td&gt;
&lt;td&gt;HNSW、IVF、PQ&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;核心目标&lt;/td&gt;
&lt;td&gt;准确性与事务一致性&lt;/td&gt;
&lt;td&gt;检索速度与召回率&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;典型场景&lt;/td&gt;
&lt;td&gt;订单、用户、支付、库存&lt;/td&gt;
&lt;td&gt;RAG、推荐、图片搜索&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;结果特点&lt;/td&gt;
&lt;td&gt;条件满足或不满足&lt;/td&gt;
&lt;td&gt;按相似程度排序&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;常用指标&lt;/td&gt;
&lt;td&gt;QPS、延迟、事务成功率&lt;/td&gt;
&lt;td&gt;Recall、Top-K、查询延迟&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;是否擅长事务&lt;/td&gt;
&lt;td&gt;是&lt;/td&gt;
&lt;td&gt;通常不是核心能力&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;是否支持语义搜索&lt;/td&gt;
&lt;td&gt;通常不直接支持&lt;/td&gt;
&lt;td&gt;是&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;两者最根本的区别在于查询方式。&lt;/p&gt;
&lt;p&gt;传统数据库查询的是：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;哪些数据满足确定的条件？
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;向量数据库查询的是：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;哪些数据与当前内容最相似？
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;精确查询与相似度查询&#34;&gt;精确查询与相似度查询
&lt;/h2&gt;&lt;p&gt;假设数据库中有以下三篇文章：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;文章 A：使用 Go 开发高并发后端服务
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;文章 B：Golang 服务端性能优化方法
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;文章 C：React 前端组件设计实践
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;用户搜索：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;如何提高 Go 后端程序的性能？
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;使用传统关键字匹配时，“Golang”和“Go”可能被认为是两个不同的词，“后端程序”和“服务端”也不完全相同。&lt;/p&gt;
&lt;p&gt;使用向量搜索时，文章 A 和文章 B 的向量通常都会与查询向量比较接近。&lt;/p&gt;
&lt;div class=&#34;mermaid&#34;&gt;flowchart TD
    Q[如何提高 Go 后端程序的性能] --&gt; E[生成查询向量]

    E --&gt; A[文章 A 向量&lt;br/&gt;相似度 0.89]
    E --&gt; B[文章 B 向量&lt;br/&gt;相似度 0.93]
    E --&gt; C[文章 C 向量&lt;br/&gt;相似度 0.32]

    B --&gt; R1[Top 1]
    A --&gt; R2[Top 2]
&lt;/div&gt;&lt;p&gt;向量数据库最终会按照相似度排序，返回最接近的若干条数据。&lt;/p&gt;
&lt;h2 id=&#34;向量相似度如何计算&#34;&gt;向量相似度如何计算
&lt;/h2&gt;&lt;p&gt;常见的向量相似度计算方式包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;余弦相似度。&lt;/li&gt;
&lt;li&gt;欧氏距离。&lt;/li&gt;
&lt;li&gt;点积。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;余弦相似度&#34;&gt;余弦相似度
&lt;/h3&gt;&lt;p&gt;余弦相似度关注两个向量方向之间的夹角。&lt;/p&gt;
&lt;p&gt;其计算公式为：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;cos(A, B) = (A · B) / (||A|| × ||B||)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;余弦相似度越接近 &lt;code&gt;1&lt;/code&gt;，通常表示两个向量越相似。&lt;/p&gt;
&lt;p&gt;例如：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;numpy&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;np&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;cosine_similarity&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;vector_a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;np&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ndarray&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vector_b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;np&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ndarray&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;float&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&amp;#34;计算两个向量的余弦相似度。&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;denominator&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;np&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;linalg&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;norm&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;vector_a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;np&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;linalg&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;norm&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;vector_b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;# 避免零向量导致除零错误&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;denominator&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;0.0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;float&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;np&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dot&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;vector_a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vector_b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;denominator&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;vector_a&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;np&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;array&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;([&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;0.2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;0.8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;0.4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;vector_b&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;np&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;array&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;([&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;0.3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;0.7&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;0.5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;similarity&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cosine_similarity&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;vector_a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vector_b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;相似度：&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;similarity&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;.4f&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;如果数据规模很小，可以逐个计算向量距离。&lt;/p&gt;
&lt;p&gt;但如果数据库中存在数百万甚至数十亿条向量，逐条计算的成本会非常高，因此需要使用专门的向量索引。&lt;/p&gt;
&lt;h2 id=&#34;为什么不能直接遍历所有向量&#34;&gt;为什么不能直接遍历所有向量
&lt;/h2&gt;&lt;p&gt;假设数据库中有 1000 万条向量，每条向量有 1536 个维度。&lt;/p&gt;
&lt;p&gt;用户每查询一次，都需要将查询向量与 1000 万条向量分别计算距离。&lt;/p&gt;
&lt;p&gt;粗略计算量为：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;1000 万 × 1536 次浮点运算
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这种方式被称为暴力搜索或精确搜索。&lt;/p&gt;
&lt;p&gt;精确搜索能够得到绝对准确的结果，但随着数据规模增长，查询延迟会迅速增加。&lt;/p&gt;
&lt;p&gt;因此，大多数向量数据库使用近似最近邻搜索：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Approximate Nearest Neighbor，ANN
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;ANN 不一定遍历所有向量，而是借助索引快速缩小搜索范围。&lt;/p&gt;
&lt;p&gt;它牺牲少量准确率，换取显著的性能提升。&lt;/p&gt;
&lt;div class=&#34;mermaid&#34;&gt;flowchart LR
    A[查询向量] --&gt; B{搜索方式}

    B --&gt; C[暴力搜索]
    C --&gt; D[遍历全部向量]
    D --&gt; E[结果准确&lt;br/&gt;速度较慢]

    B --&gt; F[ANN 搜索]
    F --&gt; G[通过索引筛选候选集]
    G --&gt; H[结果近似&lt;br/&gt;速度较快]
&lt;/div&gt;&lt;h2 id=&#34;常见的向量索引&#34;&gt;常见的向量索引
&lt;/h2&gt;&lt;h3 id=&#34;hnsw&#34;&gt;HNSW
&lt;/h3&gt;&lt;p&gt;HNSW 的全称是 Hierarchical Navigable Small World，即分层可导航小世界图。&lt;/p&gt;
&lt;p&gt;它会将向量组织成多层图结构。&lt;/p&gt;
&lt;p&gt;查询时先在较高层快速确定大致方向，再逐层向下寻找更接近的向量。&lt;/p&gt;
&lt;div class=&#34;mermaid&#34;&gt;flowchart TD
    subgraph L3[第三层：稀疏节点]
        A1((A)) --- A2((B))
    end

    subgraph L2[第二层：中等密度]
        B1((A)) --- B2((C))
        B2 --- B3((B))
    end

    subgraph L1[第一层：高密度节点]
        C1((A)) --- C2((D))
        C2 --- C3((C))
        C3 --- C4((E))
        C4 --- C5((B))
    end

    A1 -.向下搜索.-&gt; B1
    A2 -.向下搜索.-&gt; B3
    B2 -.向下搜索.-&gt; C3
&lt;/div&gt;&lt;p&gt;HNSW 通常具有较高的召回率和较低的查询延迟，但需要占用较多内存。&lt;/p&gt;
&lt;p&gt;适合：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;中低延迟在线检索。&lt;/li&gt;
&lt;li&gt;RAG 知识库。&lt;/li&gt;
&lt;li&gt;实时推荐系统。&lt;/li&gt;
&lt;li&gt;数据规模在内存可承受范围内的系统。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;ivf&#34;&gt;IVF
&lt;/h3&gt;&lt;p&gt;IVF 的全称是 Inverted File Index，即倒排文件索引。&lt;/p&gt;
&lt;p&gt;它会先通过聚类将向量划分到不同的中心区域。查询时只搜索与查询向量最接近的几个聚类，而不是遍历所有向量。&lt;/p&gt;
&lt;div class=&#34;mermaid&#34;&gt;flowchart TD
    Q[查询向量] --&gt; C{选择最近的聚类}

    C --&gt; C1[聚类 1]
    C --&gt; C2[聚类 2]
    C --&gt; C3[聚类 3]
    C --&gt; C4[聚类 4]

    C2 --&gt; S1[搜索聚类 2 内的向量]
    C3 --&gt; S2[搜索聚类 3 内的向量]

    S1 --&gt; R[合并并返回 Top-K]
    S2 --&gt; R
&lt;/div&gt;&lt;p&gt;IVF 可以通过调整搜索的聚类数量，在查询速度和召回率之间进行权衡。&lt;/p&gt;
&lt;h3 id=&#34;pq&#34;&gt;PQ
&lt;/h3&gt;&lt;p&gt;PQ 的全称是 Product Quantization，即乘积量化。&lt;/p&gt;
&lt;p&gt;它会将高维向量切分为多个子向量，再对每个子向量进行量化编码。&lt;/p&gt;
&lt;p&gt;原本需要使用大量浮点数保存的向量，可以被压缩为较短的编码。&lt;/p&gt;
&lt;p&gt;PQ 的优势是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;降低向量存储空间。&lt;/li&gt;
&lt;li&gt;减少内存占用。&lt;/li&gt;
&lt;li&gt;加快距离计算。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;代价是量化过程可能造成一定精度损失。&lt;/p&gt;
&lt;h2 id=&#34;向量数据库的基本数据模型&#34;&gt;向量数据库的基本数据模型
&lt;/h2&gt;&lt;p&gt;向量数据库中的一条记录通常包含三部分。&lt;/p&gt;
&lt;div class=&#34;mermaid&#34;&gt;flowchart LR
    A[向量记录] --&gt; B[唯一标识 ID]
    A --&gt; C[Embedding 向量]
    A --&gt; D[Metadata 元数据]

    D --&gt; E[类别]
    D --&gt; F[时间]
    D --&gt; G[作者]
    D --&gt; H[权限]
&lt;/div&gt;&lt;p&gt;例如：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;id&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;doc-001&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;vector&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;0.21&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;-0.37&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;0.66&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;0.19&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;metadata&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;department&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;研发部&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;document_type&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;技术文档&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;visibility&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;internal&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;created_at&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;2026-07-13&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;元数据非常重要。&lt;/p&gt;
&lt;p&gt;在真实系统中，通常不能只进行向量搜索，还需要添加过滤条件。&lt;/p&gt;
&lt;p&gt;例如：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;找出与用户问题最相关的文档，
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;并且文档所属部门必须是研发部，
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;文档权限必须是 internal。
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;对应的逻辑类似于：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;results&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vector_database&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;search&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;vector&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;query_vector&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;top_k&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;filter&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;department&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;研发部&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;visibility&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;internal&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这种方式称为带元数据过滤的向量检索。&lt;/p&gt;
&lt;h2 id=&#34;向量数据库如何应用于-rag&#34;&gt;向量数据库如何应用于 RAG
&lt;/h2&gt;&lt;p&gt;RAG 的全称是 Retrieval-Augmented Generation，即检索增强生成。&lt;/p&gt;
&lt;p&gt;它的核心思想是：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;在大语言模型生成答案之前，先从知识库中检索相关资料，再将资料交给模型生成答案。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;完整流程如下。&lt;/p&gt;
&lt;div class=&#34;mermaid&#34;&gt;flowchart TD
    A[企业文档] --&gt; B[文档切分]
    B --&gt; C[Embedding 模型]
    C --&gt; D[生成文本向量]
    D --&gt; E[写入向量数据库]

    U[用户提问] --&gt; F[生成查询向量]
    F --&gt; G[向量相似度搜索]
    E --&gt; G

    G --&gt; H[返回 Top-K 文档片段]
    H --&gt; I[构造 Prompt]
    U --&gt; I

    I --&gt; J[大语言模型]
    J --&gt; K[生成最终答案]
&lt;/div&gt;&lt;p&gt;假设企业知识库中存在如下内容：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Skill 包发布前需要完成安全扫描、版本检查和元数据校验。
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;用户提问：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;内部 Skill 发布之前需要检查什么？
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;系统会先将问题转换成向量，再从向量数据库中找到相关文档片段，最后让大语言模型根据检索结果回答。&lt;/p&gt;
&lt;p&gt;向量数据库在 RAG 中主要承担以下职责：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;存储文档向量。&lt;/li&gt;
&lt;li&gt;根据用户问题进行语义检索。&lt;/li&gt;
&lt;li&gt;返回最相关的上下文。&lt;/li&gt;
&lt;li&gt;支持权限、部门、时间等元数据过滤。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;需要注意的是，向量数据库本身不会生成答案，它只负责检索相关内容。&lt;/p&gt;
&lt;h2 id=&#34;向量数据库不能替代传统数据库&#34;&gt;向量数据库不能替代传统数据库
&lt;/h2&gt;&lt;p&gt;向量数据库与传统数据库并不是替代关系。&lt;/p&gt;
&lt;p&gt;例如，一个 AI 知识库系统可能同时使用：&lt;/p&gt;
&lt;div class=&#34;mermaid&#34;&gt;flowchart LR
    A[应用服务] --&gt; B[PostgreSQL]
    A --&gt; C[向量数据库]
    A --&gt; D[对象存储]

    B --&gt; E[用户信息]
    B --&gt; F[文档元数据]
    B --&gt; G[权限与任务状态]

    C --&gt; H[文本向量]
    C --&gt; I[语义检索索引]

    D --&gt; J[PDF 原文件]
    D --&gt; K[图片与附件]
&lt;/div&gt;&lt;p&gt;其中：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;PostgreSQL 保存用户、权限、任务和业务状态。&lt;/li&gt;
&lt;li&gt;向量数据库保存 Embedding 和向量索引。&lt;/li&gt;
&lt;li&gt;对象存储保存 PDF、Word、图片等原始文件。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;当用户上传一份文档时，系统可能执行以下操作：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;将原始文件上传到对象存储。&lt;/li&gt;
&lt;li&gt;在传统数据库中记录文档名称、上传者和权限。&lt;/li&gt;
&lt;li&gt;对文档进行解析和分块。&lt;/li&gt;
&lt;li&gt;调用 Embedding 模型生成向量。&lt;/li&gt;
&lt;li&gt;将文本片段和向量写入向量数据库。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;传统数据库负责业务事实，向量数据库负责语义检索。&lt;/p&gt;
&lt;h2 id=&#34;关键字搜索与向量搜索&#34;&gt;关键字搜索与向量搜索
&lt;/h2&gt;&lt;p&gt;传统全文搜索通常基于倒排索引。&lt;/p&gt;
&lt;p&gt;例如，用户搜索：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Go 高并发开发
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;系统会查找包含“Go”“高并发”“开发”等关键词的文档。&lt;/p&gt;
&lt;p&gt;关键字搜索的优点是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;对专有名词、代码、型号和编号比较准确。&lt;/li&gt;
&lt;li&gt;搜索结果容易解释。&lt;/li&gt;
&lt;li&gt;对完全匹配的关键词非常敏感。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;向量搜索的优点是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;可以理解近义词。&lt;/li&gt;
&lt;li&gt;可以处理不同表达方式。&lt;/li&gt;
&lt;li&gt;能够按照语义相关程度排序。&lt;/li&gt;
&lt;li&gt;更适合自然语言问题。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;两者也各有缺点。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;搜索方式&lt;/th&gt;
&lt;th&gt;优点&lt;/th&gt;
&lt;th&gt;缺点&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;关键字搜索&lt;/td&gt;
&lt;td&gt;精确、可解释、适合专有名词&lt;/td&gt;
&lt;td&gt;难以理解语义和近义表达&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;向量搜索&lt;/td&gt;
&lt;td&gt;支持语义检索、表达方式更灵活&lt;/td&gt;
&lt;td&gt;可能忽略关键字的精确性&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;混合搜索&lt;/td&gt;
&lt;td&gt;同时利用关键词和语义&lt;/td&gt;
&lt;td&gt;架构和排序逻辑更复杂&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&#34;混合检索&#34;&gt;混合检索
&lt;/h2&gt;&lt;p&gt;在实际的 RAG 系统中，单纯使用向量搜索并不总能获得最佳效果。&lt;/p&gt;
&lt;p&gt;例如，用户搜索：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;错误码 YN0031 是什么意思？
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这里的 &lt;code&gt;YN0031&lt;/code&gt; 是一个精确错误码。&lt;/p&gt;
&lt;p&gt;向量搜索可能认为它与 Yarn、依赖安装、Node.js 等内容相关，但关键字搜索可以直接找到包含 &lt;code&gt;YN0031&lt;/code&gt; 的文档。&lt;/p&gt;
&lt;p&gt;因此，许多系统会同时执行：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;关键字检索。&lt;/li&gt;
&lt;li&gt;向量检索。&lt;/li&gt;
&lt;li&gt;结果重排。&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;mermaid&#34;&gt;flowchart TD
    Q[用户查询] --&gt; K[关键字检索]
    Q --&gt; V[向量检索]

    K --&gt; R[结果融合]
    V --&gt; R

    R --&gt; RR[重排序模型]
    RR --&gt; T[最终 Top-K 结果]
&lt;/div&gt;&lt;p&gt;这种方式称为混合检索。&lt;/p&gt;
&lt;p&gt;一种简单的混合评分公式是：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;最终得分 = α × 向量相似度 + β × 关键字匹配得分
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;其中：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;α + β = 1
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;对于自然语言问题，可以提高向量相似度的权重。&lt;/p&gt;
&lt;p&gt;对于错误码、产品型号、文件名和函数名，可以提高关键字匹配的权重。&lt;/p&gt;
&lt;h2 id=&#34;向量搜索的-top-k&#34;&gt;向量搜索的 Top-K
&lt;/h2&gt;&lt;p&gt;向量数据库通常通过 &lt;code&gt;Top-K&lt;/code&gt; 参数控制返回结果数量。&lt;/p&gt;
&lt;p&gt;例如：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;results&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vector_database&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;search&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;vector&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;query_vector&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;top_k&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;表示返回与查询向量最相似的 5 条数据。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Top-K&lt;/code&gt; 并不是越大越好。&lt;/p&gt;
&lt;p&gt;Top-K 太小可能漏掉重要信息，Top-K 太大则可能引入无关内容，并增加大语言模型的上下文长度。&lt;/p&gt;
&lt;div class=&#34;mermaid&#34;&gt;flowchart LR
    A[Top-K 太小] --&gt; B[可能遗漏相关文档]
    C[适中的 Top-K] --&gt; D[相关性和上下文长度平衡]
    E[Top-K 太大] --&gt; F[噪声增多、Token 消耗增加]
&lt;/div&gt;&lt;p&gt;实际项目中通常需要结合以下因素调节：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;文档分块大小。&lt;/li&gt;
&lt;li&gt;Embedding 模型效果。&lt;/li&gt;
&lt;li&gt;用户问题长度。&lt;/li&gt;
&lt;li&gt;大语言模型上下文窗口。&lt;/li&gt;
&lt;li&gt;是否使用重排序模型。&lt;/li&gt;
&lt;li&gt;数据库检索召回率。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;文档为什么需要分块&#34;&gt;文档为什么需要分块
&lt;/h2&gt;&lt;p&gt;大多数情况下，不会直接将整篇文档转换成一个向量。&lt;/p&gt;
&lt;p&gt;假设一篇文档包含 10000 字，同时讨论安装、配置、权限和故障排查。将整篇文章生成一个向量，会导致不同主题被压缩到同一个表示中。&lt;/p&gt;
&lt;p&gt;因此，通常需要先对文档进行分块。&lt;/p&gt;
&lt;div class=&#34;mermaid&#34;&gt;flowchart LR
    A[完整文档] --&gt; B[分块 1&lt;br/&gt;系统介绍]
    A --&gt; C[分块 2&lt;br/&gt;安装步骤]
    A --&gt; D[分块 3&lt;br/&gt;配置说明]
    A --&gt; E[分块 4&lt;br/&gt;故障排查]

    B --&gt; F[向量 1]
    C --&gt; G[向量 2]
    D --&gt; H[向量 3]
    E --&gt; I[向量 4]
&lt;/div&gt;&lt;p&gt;分块后，用户询问安装问题时，系统可以直接检索“安装步骤”对应的片段，而不是返回整篇文档。&lt;/p&gt;
&lt;p&gt;常见分块策略包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;固定字符数分块。&lt;/li&gt;
&lt;li&gt;固定 Token 数分块。&lt;/li&gt;
&lt;li&gt;按段落分块。&lt;/li&gt;
&lt;li&gt;按 Markdown 标题分块。&lt;/li&gt;
&lt;li&gt;按语义边界分块。&lt;/li&gt;
&lt;li&gt;滑动窗口分块。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;分块大小需要根据文档类型进行调整。&lt;/p&gt;
&lt;p&gt;代码文档更适合按照类、函数或模块边界分块；普通文章可以按照标题和段落分块。&lt;/p&gt;
&lt;h2 id=&#34;一个简单的向量检索示例&#34;&gt;一个简单的向量检索示例
&lt;/h2&gt;&lt;p&gt;下面使用 Python 模拟一个最简单的向量搜索过程。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;22
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;23
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;24
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;25
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;26
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;27
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;28
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;29
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;30
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;31
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;32
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;33
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;34
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;35
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;36
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;37
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;38
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;39
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;40
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;41
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;42
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;43
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;44
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;45
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;46
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;47
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;48
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;49
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;50
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;51
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;52
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;53
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;54
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;55
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;56
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;57
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;58
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;59
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;60
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;61
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;62
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;63
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;64
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;65
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;66
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;67
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;68
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;69
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;70
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;71
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;dataclasses&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dataclass&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;numpy&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;np&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nd&#34;&gt;@dataclass&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Document&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&amp;#34;知识库文档。&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;document_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;content&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;vector&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;np&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ndarray&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;cosine_similarity&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;vector_a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;np&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ndarray&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vector_b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;np&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ndarray&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;float&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&amp;#34;计算余弦相似度。&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;denominator&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;np&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;linalg&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;norm&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;vector_a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;np&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;linalg&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;norm&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;vector_b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;denominator&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;0.0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;float&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;np&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dot&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;vector_a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vector_b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;denominator&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;search_documents&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;query_vector&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;np&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ndarray&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;documents&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;list&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Document&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;top_k&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;list&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;tuple&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Document&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;float&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]]:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&amp;#34;按照相似度返回 Top-K 文档。&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;scored_documents&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;document&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cosine_similarity&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;query_vector&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;document&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;vector&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;document&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;documents&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;# 按照相似度从高到低排序&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;scored_documents&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sort&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;key&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;lambda&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;item&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;item&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;reverse&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;scored_documents&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[:&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;top_k&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;documents&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;Document&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;document_id&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;doc-1&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;content&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;使用 Go 构建高并发后端服务&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;vector&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;np&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;array&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;([&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;0.8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;0.7&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;0.1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;Document&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;document_id&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;doc-2&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;content&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;React 组件状态管理实践&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;vector&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;np&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;array&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;([&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;0.1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;0.2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;0.9&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;Document&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;document_id&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;doc-3&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;content&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Golang 服务端性能优化&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;vector&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;np&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;array&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;([&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;0.9&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;0.6&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;0.2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;query_vector&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;np&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;array&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;([&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;0.85&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;0.65&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;0.15&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;results&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;search_documents&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;query_vector&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;query_vector&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;documents&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;documents&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;top_k&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;document&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;score&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;results&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;document&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;document_id&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;: &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;score&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;.4f&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt; - &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;document&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;content&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这个示例本质上仍然是暴力搜索。&lt;/p&gt;
&lt;p&gt;真实的向量数据库会使用 HNSW、IVF 等索引结构，并处理数据持久化、并发查询、分片、过滤和容错等问题。&lt;/p&gt;
&lt;h2 id=&#34;向量数据库的典型应用场景&#34;&gt;向量数据库的典型应用场景
&lt;/h2&gt;&lt;h3 id=&#34;rag-知识库&#34;&gt;RAG 知识库
&lt;/h3&gt;&lt;p&gt;将企业文档、产品手册和技术资料转换为向量，让大语言模型根据内部知识回答问题。&lt;/p&gt;
&lt;h3 id=&#34;语义搜索&#34;&gt;语义搜索
&lt;/h3&gt;&lt;p&gt;用户不需要输入完全一致的关键词，只需要描述自己的意图，系统就能找到相关内容。&lt;/p&gt;
&lt;h3 id=&#34;推荐系统&#34;&gt;推荐系统
&lt;/h3&gt;&lt;p&gt;将用户、商品或内容表示为向量，根据向量之间的距离生成推荐结果。&lt;/p&gt;
&lt;div class=&#34;mermaid&#34;&gt;flowchart LR
    A[用户行为] --&gt; B[用户向量]
    C[商品信息] --&gt; D[商品向量]

    B --&gt; E[相似度计算]
    D --&gt; E

    E --&gt; F[推荐商品列表]
&lt;/div&gt;&lt;h3 id=&#34;图片搜索&#34;&gt;图片搜索
&lt;/h3&gt;&lt;p&gt;通过图像模型将图片转换成向量，实现以图搜图。&lt;/p&gt;
&lt;p&gt;例如：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;上传一张鞋子的图片，搜索外观相似的商品。&lt;/li&gt;
&lt;li&gt;上传一张人脸图片，搜索相似人物。&lt;/li&gt;
&lt;li&gt;上传一张风景图片，查找相似的摄影作品。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;多模态检索&#34;&gt;多模态检索
&lt;/h3&gt;&lt;p&gt;文本和图片可以通过多模态模型映射到相同的向量空间。&lt;/p&gt;
&lt;p&gt;用户可以输入：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;寻找一张冬季北欧雪山和湖泊的图片
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;系统通过文本向量搜索相似的图片向量。&lt;/p&gt;
&lt;h3 id=&#34;代码搜索&#34;&gt;代码搜索
&lt;/h3&gt;&lt;p&gt;将函数、类和代码文件转换成向量后，可以根据自然语言描述搜索代码。&lt;/p&gt;
&lt;p&gt;例如：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;查找负责校验 JWT Token 的函数
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;即使代码中没有出现完全相同的注释，系统仍然可能找到相关实现。&lt;/p&gt;
&lt;h3 id=&#34;异常检测&#34;&gt;异常检测
&lt;/h3&gt;&lt;p&gt;正常数据通常集中在向量空间中的某些区域。如果一条新数据与其他数据距离明显较远，它可能是异常数据。&lt;/p&gt;
&lt;p&gt;该方法可以用于：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;欺诈检测。&lt;/li&gt;
&lt;li&gt;日志异常分析。&lt;/li&gt;
&lt;li&gt;网络攻击检测。&lt;/li&gt;
&lt;li&gt;工业设备故障预警。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;如何选择数据库&#34;&gt;如何选择数据库
&lt;/h2&gt;&lt;p&gt;选择数据库时，不应该先问“哪个数据库更先进”，而应该先明确数据和查询模式。&lt;/p&gt;
&lt;div class=&#34;mermaid&#34;&gt;flowchart TD
    A{系统主要查询什么} --&gt; B[根据 ID 或字段查询]
    A --&gt; C[根据语义或相似度查询]
    A --&gt; D[两种查询都需要]

    B --&gt; E[传统数据库]
    C --&gt; F[向量数据库]
    D --&gt; G[传统数据库 + 向量数据库]
&lt;/div&gt;&lt;p&gt;可以按照下面的方式判断。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;需求&lt;/th&gt;
&lt;th&gt;推荐方案&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;用户、订单、支付、库存&lt;/td&gt;
&lt;td&gt;传统关系型数据库&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;事务和强一致性&lt;/td&gt;
&lt;td&gt;传统关系型数据库&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;文档语义搜索&lt;/td&gt;
&lt;td&gt;向量数据库&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;图片相似度搜索&lt;/td&gt;
&lt;td&gt;向量数据库&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;企业知识库问答&lt;/td&gt;
&lt;td&gt;向量数据库配合传统数据库&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;精确错误码搜索&lt;/td&gt;
&lt;td&gt;全文搜索或传统索引&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;同时需要语义和关键词&lt;/td&gt;
&lt;td&gt;混合检索&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;既有业务数据又有 AI 检索&lt;/td&gt;
&lt;td&gt;多数据库组合&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&#34;使用向量数据库时需要关注什么&#34;&gt;使用向量数据库时需要关注什么
&lt;/h2&gt;&lt;h3 id=&#34;embedding-模型&#34;&gt;Embedding 模型
&lt;/h3&gt;&lt;p&gt;向量数据库只能根据已有向量进行搜索，向量质量主要取决于 Embedding 模型。&lt;/p&gt;
&lt;p&gt;如果 Embedding 模型无法正确理解业务术语，即使向量数据库性能很好，检索结果也不会理想。&lt;/p&gt;
&lt;h3 id=&#34;向量维度&#34;&gt;向量维度
&lt;/h3&gt;&lt;p&gt;更高的维度通常可以表达更丰富的信息，但也会增加：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;存储空间。&lt;/li&gt;
&lt;li&gt;内存占用。&lt;/li&gt;
&lt;li&gt;索引构建时间。&lt;/li&gt;
&lt;li&gt;相似度计算成本。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;召回率&#34;&gt;召回率
&lt;/h3&gt;&lt;p&gt;ANN 搜索是近似搜索，因此可能无法返回理论上最相似的全部结果。&lt;/p&gt;
&lt;p&gt;召回率可以表示为：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Recall@K = 检索到的真实相关结果数量 / 理论相关结果数量
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;系统需要在查询延迟、内存占用和召回率之间进行平衡。&lt;/p&gt;
&lt;h3 id=&#34;数据更新&#34;&gt;数据更新
&lt;/h3&gt;&lt;p&gt;某些向量索引适合静态数据，某些适合频繁更新。&lt;/p&gt;
&lt;p&gt;如果系统中的向量会持续新增、修改和删除，需要关注：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;索引是否支持动态更新。&lt;/li&gt;
&lt;li&gt;删除数据后是否需要重建索引。&lt;/li&gt;
&lt;li&gt;新数据写入后多久可以被查询。&lt;/li&gt;
&lt;li&gt;索引构建是否会影响在线请求。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;元数据过滤&#34;&gt;元数据过滤
&lt;/h3&gt;&lt;p&gt;企业系统通常存在复杂的权限条件。&lt;/p&gt;
&lt;p&gt;例如：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;用户只能检索自己所在部门的内部文档。
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;因此，向量数据库是否支持高效的元数据过滤十分重要。&lt;/p&gt;
&lt;h3 id=&#34;数据一致性&#34;&gt;数据一致性
&lt;/h3&gt;&lt;p&gt;如果传统数据库中的文档已经删除，但向量数据库中的向量仍然存在，用户可能检索到失效内容。&lt;/p&gt;
&lt;p&gt;系统需要设计数据同步机制。&lt;/p&gt;
&lt;div class=&#34;mermaid&#34;&gt;sequenceDiagram
    participant APP as 应用服务
    participant DB as 传统数据库
    participant VDB as 向量数据库

    APP-&gt;&gt;DB: 删除文档记录
    DB--&gt;&gt;APP: 删除成功
    APP-&gt;&gt;VDB: 删除对应向量
    VDB--&gt;&gt;APP: 删除成功
&lt;/div&gt;&lt;p&gt;在复杂系统中，还可以通过消息队列和补偿任务保证最终一致性。&lt;/p&gt;
&lt;h2 id=&#34;常见误区&#34;&gt;常见误区
&lt;/h2&gt;&lt;h3 id=&#34;向量数据库就是大语言模型数据库&#34;&gt;向量数据库就是大语言模型数据库
&lt;/h3&gt;&lt;p&gt;向量数据库不是专门存储大语言模型的数据库。&lt;/p&gt;
&lt;p&gt;它存储的是向量、原始内容和元数据，可以用于文本、图片、音频、推荐和异常检测等多种场景。&lt;/p&gt;
&lt;h3 id=&#34;向量数据库可以直接回答问题&#34;&gt;向量数据库可以直接回答问题
&lt;/h3&gt;&lt;p&gt;向量数据库负责检索，不负责生成自然语言答案。&lt;/p&gt;
&lt;p&gt;在 RAG 系统中，最终答案通常由大语言模型生成。&lt;/p&gt;
&lt;h3 id=&#34;向量维度越高越好&#34;&gt;向量维度越高越好
&lt;/h3&gt;&lt;p&gt;维度越高不一定意味着检索效果越好。&lt;/p&gt;
&lt;p&gt;最终效果取决于模型训练数据、业务场景、文本质量和检索策略。&lt;/p&gt;
&lt;h3 id=&#34;使用向量数据库就不需要传统数据库&#34;&gt;使用向量数据库就不需要传统数据库
&lt;/h3&gt;&lt;p&gt;向量数据库通常无法替代订单、用户、权限、库存和支付系统中的传统数据库。&lt;/p&gt;
&lt;p&gt;实际应用更常见的是组合使用。&lt;/p&gt;
&lt;h3 id=&#34;相似度最高的内容一定正确&#34;&gt;相似度最高的内容一定正确
&lt;/h3&gt;&lt;p&gt;向量相似度只表示语义或特征上的接近程度，并不等于事实正确。&lt;/p&gt;
&lt;p&gt;因此，RAG 系统还需要考虑：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;文档是否过期。&lt;/li&gt;
&lt;li&gt;数据源是否可信。&lt;/li&gt;
&lt;li&gt;用户是否有访问权限。&lt;/li&gt;
&lt;li&gt;检索内容是否真正能够回答问题。&lt;/li&gt;
&lt;li&gt;是否需要使用重排序模型。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;总结&#34;&gt;总结
&lt;/h2&gt;&lt;p&gt;传统数据库和向量数据库解决的是不同类型的问题。&lt;/p&gt;
&lt;p&gt;传统数据库擅长：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;精确查询。&lt;/li&gt;
&lt;li&gt;结构化数据管理。&lt;/li&gt;
&lt;li&gt;事务处理。&lt;/li&gt;
&lt;li&gt;数据关系维护。&lt;/li&gt;
&lt;li&gt;聚合和统计。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;向量数据库擅长：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;语义搜索。&lt;/li&gt;
&lt;li&gt;相似度检索。&lt;/li&gt;
&lt;li&gt;图片与多模态搜索。&lt;/li&gt;
&lt;li&gt;推荐系统。&lt;/li&gt;
&lt;li&gt;RAG 知识检索。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;两者之间并不是竞争或替代关系。&lt;/p&gt;
&lt;p&gt;在现代 AI 应用中，一种常见的架构是：&lt;/p&gt;
&lt;div class=&#34;mermaid&#34;&gt;flowchart LR
    U[用户请求] --&gt; A[应用服务]

    A --&gt; DB[传统数据库]
    A --&gt; VDB[向量数据库]
    A --&gt; LLM[大语言模型]

    DB --&gt; B[用户、权限、业务状态]
    VDB --&gt; C[语义相关上下文]

    B --&gt; A
    C --&gt; A
    A --&gt; LLM
    LLM --&gt; R[最终回答]
&lt;/div&gt;&lt;p&gt;传统数据库保存明确的业务事实，向量数据库提供基于语义的检索能力，大语言模型负责理解问题并组织答案。&lt;/p&gt;
&lt;p&gt;可以将它们概括为：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;传统数据库负责找到“符合条件的数据”，向量数据库负责找到“含义相近的数据”。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;理解这一差异，是设计 RAG、智能搜索、推荐系统和多模态应用的基础。&lt;/p&gt;
</description>
        </item>
        <item>
        <title>About the timing of fine-tuning</title>
        <link>https://SymphonyW.github.io/p/about-the-timing-of-fine-tuning/</link>
        <pubDate>Sat, 11 Jul 2026 17:30:00 +0800</pubDate>
        
        <guid>https://SymphonyW.github.io/p/about-the-timing-of-fine-tuning/</guid>
        <description>&lt;img src="https://SymphonyW.github.io/p/about-the-timing-of-fine-tuning/bg.png" alt="Featured image of post About the timing of fine-tuning" /&gt;&lt;h1 id=&#34;关于微调的时机&#34;&gt;关于微调的时机
&lt;/h1&gt;&lt;blockquote&gt;
&lt;p&gt;微调不是大模型效果优化的默认选项，更不是遇到效果问题后的第一反应。真正成熟的工程判断，是先弄清楚：当前缺的是&lt;strong&gt;知识&lt;/strong&gt;，还是模型的&lt;strong&gt;行为稳定性&lt;/strong&gt;？&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;“什么时候应该做大模型微调？”是大模型岗位面试中很常见的一道题。&lt;/p&gt;
&lt;p&gt;它表面上在问微调技术，实际上考察的是两个更重要的能力：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;能不能区分知识问题和行为问题&lt;/strong&gt;；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;有没有技术选型的成本意识&lt;/strong&gt;。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;如果连问题类型都没有判断清楚，就直接把微调提上日程，往往会把一个本可低成本解决的问题，变成数据准备、模型训练和持续维护的复杂工程。&lt;/p&gt;
&lt;p&gt;因此，讨论“要不要微调”之前，先记住一个结论：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;知识问题优先用检索解决，行为问题才进入微调的候选范围。&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&#34;先判断缺知识还是行为不稳定&#34;&gt;先判断：缺知识，还是行为不稳定？
&lt;/h2&gt;&lt;p&gt;大模型应用中的效果问题，可以先沿着“知识”和“行为”两条线拆开。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;问题类型&lt;/th&gt;
&lt;th&gt;典型表现&lt;/th&gt;
&lt;th&gt;对应解法&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;知识问题&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;模型缺少业务文档、规章制度、行业事实等外部信息&lt;/td&gt;
&lt;td&gt;使用检索增强（RAG），在生成时补充所需知识&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;行为问题&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;模型知道正确内容，但输出格式、语气或判断规则不稳定&lt;/td&gt;
&lt;td&gt;提示词无法稳定解决后，再考虑微调&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&#34;知识问题模型不知道事实&#34;&gt;知识问题：模型不知道事实
&lt;/h3&gt;&lt;p&gt;如果模型答不出某个问题，是因为它没有接触过企业内部文档、最新规章制度或特定行业事实，那么问题的核心不是“模型不会回答”，而是&lt;strong&gt;模型缺少回答所需的外部信息&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;这类问题应该优先使用检索增强。知识保留在外部知识源中，需要时检索并提供给模型，而不是把它固化进模型权重。&lt;/p&gt;
&lt;p&gt;这样做的关键价值是：&lt;strong&gt;知识可以灵活更新&lt;/strong&gt;。文档变化时更新知识源即可，不必重新训练模型。&lt;/p&gt;
&lt;h3 id=&#34;行为问题模型知道但做得不稳定&#34;&gt;行为问题：模型知道，但做得不稳定
&lt;/h3&gt;&lt;p&gt;另一类问题是：正确内容模型其实知道，但它无法持续按照业务要求输出。例如：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;输出结构有时正确、有时缺字段；&lt;/li&gt;
&lt;li&gt;语气无法长期保持一致；&lt;/li&gt;
&lt;li&gt;面对复杂判断规则时，执行结果反复波动。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这不是知识缺失，而是&lt;strong&gt;行为不稳定&lt;/strong&gt;。微调真正擅长处理的，正是这类“让模型更稳定地按照指定方式做事”的问题。&lt;/p&gt;
&lt;p&gt;所以，区分两者最直接的判断方式是：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;缺事实，补检索；事实已经具备但表现不稳定，才评估微调。&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&#34;效果优化要走阶梯而不是一步跳到微调&#34;&gt;效果优化要走阶梯，而不是一步跳到微调
&lt;/h2&gt;&lt;p&gt;工业界做技术选型，不能只问“哪种方案能解决”，还要问“是否有成本更低的方案能先解决”。大模型效果优化应该按照从低成本到高成本的顺序逐级推进：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;顺序&lt;/th&gt;
&lt;th&gt;优化手段&lt;/th&gt;
&lt;th&gt;进入条件&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;第一步&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;把提示词优化到极致&lt;/td&gt;
&lt;td&gt;所有场景都应先完成&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;第二步&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;引入检索增强方案&lt;/td&gt;
&lt;td&gt;问题涉及外部知识，或提示词缺少必要事实&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;第三步&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;考虑使用微调&lt;/td&gt;
&lt;td&gt;前两步走不通，且问题确实适合微调&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;这套阶梯的关键不是三种技术谁更高级，而是&lt;strong&gt;上一级没有解决问题，再进入下一级&lt;/strong&gt;。&lt;/p&gt;
&lt;h3 id=&#34;第一步先把提示词优化到极致&#34;&gt;第一步：先把提示词优化到极致
&lt;/h3&gt;&lt;p&gt;面对格式、语气和规则执行问题，第一步不是训练，而是先验证提示词能否解决。只要提示词仍有优化空间，就不能轻易得出“必须微调”的结论。&lt;/p&gt;
&lt;h3 id=&#34;第二步需要外部知识时引入检索&#34;&gt;第二步：需要外部知识时引入检索
&lt;/h3&gt;&lt;p&gt;如果问题来自知识缺失，就通过检索把业务文档、规章制度或行业事实提供给模型。检索负责补齐事实，也保留了知识更新的灵活性。&lt;/p&gt;
&lt;h3 id=&#34;第三步最后才考虑微调&#34;&gt;第三步：最后才考虑微调
&lt;/h3&gt;&lt;p&gt;只有提示词已经反复优化、检索也已经覆盖所需事实，问题依然存在时，微调才真正进入决策范围。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;微调应该是阶梯的第三层，而不是项目启动后的默认配置。&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;真正需要微调的三个信号&#34;&gt;真正需要微调的三个信号
&lt;/h2&gt;&lt;p&gt;“微调不是起点”不等于“永远不做微调”。当下面三个信号出现时，微调就可能具备明确的工程价值。&lt;/p&gt;
&lt;h3 id=&#34;信号一行为与格式仍然不稳定&#34;&gt;信号一：行为与格式仍然不稳定
&lt;/h3&gt;&lt;p&gt;业务要求模型稳定输出特定结构、固定语气或复杂规则，但提示词经过反复优化后，效果仍然时好时坏。&lt;/p&gt;
&lt;p&gt;这里有两个必要前提：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;目标是约束模型的&lt;strong&gt;行为与输出形态&lt;/strong&gt;；&lt;/li&gt;
&lt;li&gt;提示词优化已经充分尝试，但稳定性仍未达标。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;两个条件同时成立，才说明问题可能需要通过微调进一步固化。&lt;/p&gt;
&lt;h3 id=&#34;信号二高频窄口径任务受到成本与延迟制约&#34;&gt;信号二：高频窄口径任务受到成本与延迟制约
&lt;/h3&gt;&lt;p&gt;意图分类、实体抽取、内容打标这类任务，通常口径明确、调用频率高。为了让模型准确执行规则，系统可能需要在每一次请求中重复携带很长的提示词。&lt;/p&gt;
&lt;p&gt;长提示词会带来持续的重复开销，也会增加延迟。此时，把任务行为通过微调迁移到小模型中，能够&lt;strong&gt;大幅降低成本和延迟&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;这里决定是否微调的，不只是效果，还有调用规模下的长期成本。&lt;/p&gt;
&lt;h3 id=&#34;信号三距离业务硬指标只差最后几个点&#34;&gt;信号三：距离业务硬指标只差最后几个点
&lt;/h3&gt;&lt;p&gt;提示词已经做到位，检索也已经补齐事实，但准确率距离业务硬指标仍然差最后几个点。这说明低成本手段已经基本用尽，而剩余差距又会直接影响业务上线或验收。&lt;/p&gt;
&lt;p&gt;此时，微调才适合作为继续突破能力边界的手段。&lt;/p&gt;
&lt;p&gt;三个信号可以浓缩成一张判断表：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;信号&lt;/th&gt;
&lt;th&gt;关键问题&lt;/th&gt;
&lt;th&gt;微调价值&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;行为与格式&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;提示词反复优化后，输出仍不稳定吗？&lt;/td&gt;
&lt;td&gt;固化结构、语气和复杂规则&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;成本与延迟&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;高频窄任务是否长期重复携带长提示词？&lt;/td&gt;
&lt;td&gt;用小模型降低持续成本与延迟&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;能力边界&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;提示词和检索都到位后，是否仍差硬指标最后几个点？&lt;/td&gt;
&lt;td&gt;进一步提升专项准确率&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id=&#34;微调最常见的四个坑&#34;&gt;微调最常见的四个坑
&lt;/h2&gt;&lt;p&gt;真正的工程风险往往不在“会不会训练”，而在于微调目标、数据和评估是否正确。下面四个问题尤其常见。&lt;/p&gt;
&lt;h3 id=&#34;坑一用微调灌知识&#34;&gt;坑一：用微调灌知识
&lt;/h3&gt;&lt;p&gt;把业务文档或行业知识直接拿去微调，看起来像是在“教会模型”，实际很容易让知识变成模型中的&lt;strong&gt;模糊印象&lt;/strong&gt;，反而更容易胡说。&lt;/p&gt;
&lt;p&gt;更麻烦的是，知识会持续变化。一旦知识固化进模型权重，每次更新都可能重新触发数据准备和训练，维护成本极高。&lt;/p&gt;
&lt;p&gt;因此，这条边界要足够明确：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;知识类需求永远优先走检索，不要用微调灌知识。&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;坑二重数量轻质量&#34;&gt;坑二：重数量，轻质量
&lt;/h3&gt;&lt;p&gt;微调数据不是越多越好。&lt;strong&gt;几百条高质量、统一口径的样本，效果可能好过几万条脏数据。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;数据中的口径冲突和错误示范，会直接让模型学到不稳定的行为。与其盲目追求数量，不如先确保样本准确、清晰且规则一致。&lt;/p&gt;
&lt;p&gt;对于简单任务，&lt;strong&gt;50～100 条样本就能看到明显效果&lt;/strong&gt;。这意味着，微调项目早期更应该关注样本质量，而不是先堆出庞大的数据规模。&lt;/p&gt;
&lt;h3 id=&#34;坑三忽视灾难性遗忘&#34;&gt;坑三：忽视灾难性遗忘
&lt;/h3&gt;&lt;p&gt;模型在窄任务上被过度微调后，可能出现通用能力退化。专项任务的指标变好，并不代表整体效果一定更好。&lt;/p&gt;
&lt;p&gt;因此，微调后的评估不能只盯着目标任务，必须同时检查：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;专项能力是否提升&lt;/strong&gt;；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;通用能力是否退化&lt;/strong&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;只有两者一起评估，才能判断这次微调是否真的值得上线。&lt;/p&gt;
&lt;h3 id=&#34;坑四没有评估就开始微调&#34;&gt;坑四：没有评估就开始微调
&lt;/h3&gt;&lt;p&gt;没有评估体系就直接训练，相当于&lt;strong&gt;闭着眼睛开车&lt;/strong&gt;：训练完成后，既无法确认效果提升了多少，也无法判断出现了哪些退化。&lt;/p&gt;
&lt;p&gt;正确的顺序应该是：&lt;strong&gt;评估集先于训练搭建&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;先明确用什么样本和标准验证效果，再开始准备微调。否则，训练过程即使顺利完成，也无法形成可信的工程结论。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;一套可落地的决策顺序&#34;&gt;一套可落地的决策顺序
&lt;/h2&gt;&lt;p&gt;面对“当前场景是否需要微调”，可以按下面的顺序做判断：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;决策步骤&lt;/th&gt;
&lt;th&gt;要回答的问题&lt;/th&gt;
&lt;th&gt;对应动作&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;1. 定义问题&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;缺的是外部知识，还是行为稳定性？&lt;/td&gt;
&lt;td&gt;知识问题走检索；行为问题继续判断&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;2. 优化提示词&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;提示词是否已经反复优化到位？&lt;/td&gt;
&lt;td&gt;没有则继续优化，不急于微调&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;3. 补齐知识&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;是否缺少业务文档、制度或行业事实？&lt;/td&gt;
&lt;td&gt;引入 RAG，不把知识写进权重&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;4. 检查信号&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;是否出现行为不稳、成本延迟或能力边界信号？&lt;/td&gt;
&lt;td&gt;信号明确后再立项微调&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;5. 搭建评估&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;是否已有专项与通用能力评估？&lt;/td&gt;
&lt;td&gt;评估集就绪后才开始训练&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;6. 准备数据&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;样本是否高质量且口径统一？&lt;/td&gt;
&lt;td&gt;先保证质量，再考虑数量&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;这套顺序体现的不是对微调的保守，而是对工程成本和方案边界的尊重。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;面试时应该怎样回答&#34;&gt;面试时应该怎样回答？
&lt;/h2&gt;&lt;p&gt;如果面试官问“什么时候做微调”，一个逻辑完整的回答可以这样组织：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;我会先判断这是知识问题还是行为问题。模型缺少业务文档、规章制度或行业事实时，优先使用 RAG，因为知识需要灵活更新，不应该固化进模型权重。模型已经知道正确内容，但格式、语气或判断规则在提示词反复优化后仍不稳定，才是微调的适用场景。&lt;/p&gt;
&lt;p&gt;在方案顺序上，我会先把提示词优化到极致，再引入检索增强，前两步走不通后才考虑微调。真正推动微调立项的信号主要有三个：行为和格式仍然不稳定；高频窄口径任务受长提示词的成本与延迟影响；提示词和检索都到位后，准确率距离业务硬指标仍差最后几个点。&lt;/p&gt;
&lt;p&gt;开始训练前，我会先搭建评估集，并保证训练样本高质量、口径统一。评估时同时关注专项能力和通用能力，避免窄任务过度微调导致灾难性遗忘。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;这个回答覆盖了问题分类、方案优先级、成本判断和上线风险，也更接近真实工业场景中的技术决策方式。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;总结&#34;&gt;总结
&lt;/h2&gt;&lt;p&gt;大模型项目中，微调最容易被误用的原因，是团队把所有效果问题都归结为“模型能力不够”。但真正需要先回答的是：&lt;strong&gt;模型缺的是事实，还是稳定执行规则的行为？&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;整套决策可以压缩为三句话：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;知识问题优先用 RAG，行为问题才考虑微调&lt;/strong&gt;；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;先提示词，再检索，最后才是微调&lt;/strong&gt;；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;没有明确微调信号、评估集和高质量数据，就不要启动训练&lt;/strong&gt;。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;成熟的工业界方案，往往是：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;微调管形态，检索管事实。&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;但要特别注意：这是一套经过逐级验证后形成的&lt;strong&gt;终局组合方案&lt;/strong&gt;，不是项目一开始就要全部开启的技术清单。&lt;/p&gt;
&lt;p&gt;真正专业的选型，不是把所有技术都用上，而是在正确的问题上使用正确的手段。&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Classic interview question:How exactly should you set RAG retrieval top-k?</title>
        <link>https://SymphonyW.github.io/p/classic-interview-questionhow-exactly-should-you-set-rag-retrieval-top-k/</link>
        <pubDate>Wed, 08 Jul 2026 22:05:00 +0800</pubDate>
        
        <guid>https://SymphonyW.github.io/p/classic-interview-questionhow-exactly-should-you-set-rag-retrieval-top-k/</guid>
        <description>&lt;img src="https://SymphonyW.github.io/p/classic-interview-questionhow-exactly-should-you-set-rag-retrieval-top-k/bg.png" alt="Featured image of post Classic interview question:How exactly should you set RAG retrieval top-k?" /&gt;&lt;h1 id=&#34;经典面试题rag-检索-top-k-到底怎么设&#34;&gt;经典面试题：RAG 检索 top-k 到底怎么设？
&lt;/h1&gt;&lt;blockquote&gt;
&lt;p&gt;面试官问：&amp;ldquo;你们 RAG 系统的 top-k 是怎么设的？&amp;rdquo; 你如果只回答一句&amp;quot;看情况&amp;quot;，那基本就和 offer 说再见了。top-k 这个看似简单的参数，背后考的是你对&lt;strong&gt;完整 RAG 链路&lt;/strong&gt;的理解深度。本文参考「小哲讲 agent 面试」的拆解思路，把这个高频面试题一次讲透。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&#34;一为什么-top-k-是必考题&#34;&gt;一、为什么 top-k 是必考题？
&lt;/h2&gt;&lt;p&gt;在 RAG（Retrieval-Augmented Generation）系统中，top-k 决定&lt;strong&gt;从向量数据库里召回多少条文档片段喂给大模型&lt;/strong&gt;。它看起来只是 &lt;code&gt;search_kwargs={&amp;quot;k&amp;quot;: 4}&lt;/code&gt; 这么一个参数，但它同时牵动四件事：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;维度&lt;/th&gt;
&lt;th&gt;top-k 的影响&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;召回率（Recall）&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;k 太小 → 漏掉真正相关的片段&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;噪声（Noise）&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;k 太大 → 召回一堆无关片段干扰生成&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;成本（Cost）&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;k 越大 → Prompt 越长 → token 费用越高、延迟越高&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;生成质量（Quality）&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;噪声片段会让 LLM &amp;ldquo;迷失在中间&amp;rdquo;，答非所问&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;a href=&#34;https://SymphonyW.github.io/p/classic-interview-questionhow-exactly-should-you-set-rag-retrieval-top-k/top-k.png&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;&lt;img src=&#34;https://SymphonyW.github.io/p/classic-interview-questionhow-exactly-should-you-set-rag-retrieval-top-k/top-k.png&#34; alt=&#34;top-k&#34; width=&#34;1758&#34; height=&#34;459&#34; loading=&#34;lazy&#34; decoding=&#34;async&#34; class=&#34;gallery-image&#34; data-flex-grow=&#34;383&#34; data-flex-basis=&#34;919px&#34;&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;也就是说，top-k 是&lt;strong&gt;召回、噪声、成本、质量&lt;/strong&gt;四个目标的交汇点。面试官真正想听的不是&amp;quot;我设成了 5&amp;quot;，而是&amp;quot;我为什么这样设，背后是什么链路思维&amp;quot;。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;二top-k-设小了幻觉的温床&#34;&gt;二、top-k 设小了：幻觉的温床
&lt;/h2&gt;&lt;p&gt;&lt;a href=&#34;https://SymphonyW.github.io/p/classic-interview-questionhow-exactly-should-you-set-rag-retrieval-top-k/topk-too-small.svg&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;&lt;img src=&#34;https://SymphonyW.github.io/p/classic-interview-questionhow-exactly-should-you-set-rag-retrieval-top-k/topk-too-small.svg&#34; alt=&#34;top-k 设小的隐患：排名第一的片段可能不完整&#34; loading=&#34;lazy&#34; decoding=&#34;async&#34;&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;很多人凭直觉认为&amp;quot;检索结果越靠前越相关，取 Top-1 不就行了？&amp;quot;——这是第一个坑。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;问题在于：排名第一 ≠ 信息完整。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;举个真实场景：用户问&amp;quot;公司请假流程是什么？&amp;quot;，向量库里有一份《员工手册》第 3 章详细写了请假流程，但因为切分（chunking）策略，这段内容被切成两半：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;片段 A（排名第 1）：&amp;quot;……请假需提前在 OA 系统提交申请，由直属主管审批。&amp;quot;&lt;/li&gt;
&lt;li&gt;片段 B（排名第 2）：&amp;ldquo;超过 3 天的请假需提供医院证明，并报 HR 备案。&amp;rdquo;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果你只取 Top-1，LLM 拿到的上下文只有&amp;quot;提交申请 + 主管审批&amp;quot;这一半，它大概率会&lt;strong&gt;编造&lt;/strong&gt;&amp;ldquo;3 天以上需要什么材料&amp;rdquo;——因为用户问到了，它必须给出回答，但又没看到完整信息。这就是典型的&lt;strong&gt;幻觉&lt;/strong&gt;：模型不是在撒谎，而是被不完整的上下文逼着&amp;quot;脑补&amp;quot;。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;核心结论&lt;/strong&gt;：top-k 设小的代价是&lt;strong&gt;召回不足 → 上下文不完整 → 模型幻觉&lt;/strong&gt;。排名第一只能保证&amp;quot;最相关&amp;quot;，不能保证&amp;quot;最完整&amp;quot;。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&#34;三top-k-设大了噪声与成本的双重暴击&#34;&gt;三、top-k 设大了：噪声与成本的双重暴击
&lt;/h2&gt;&lt;p&gt;&lt;a href=&#34;https://SymphonyW.github.io/p/classic-interview-questionhow-exactly-should-you-set-rag-retrieval-top-k/topk-too-large.svg&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;&lt;img src=&#34;https://SymphonyW.github.io/p/classic-interview-questionhow-exactly-should-you-set-rag-retrieval-top-k/topk-too-large.svg&#34; alt=&#34;top-k 设大的隐患：噪声片段淹没真正答案&#34; loading=&#34;lazy&#34; decoding=&#34;async&#34;&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;那干脆设大点，k=20、k=50 总不会漏了吧？这是第二个坑。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;k 太大会引入三类问题：&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&#34;31-噪声淹没信号&#34;&gt;3.1 噪声淹没信号
&lt;/h3&gt;&lt;p&gt;向量检索本质是&lt;strong&gt;相似度排序&lt;/strong&gt;，但&amp;quot;相似&amp;quot;不等于&amp;quot;相关&amp;quot;。当 k=20 时，后 10 条往往是&amp;quot;看起来有点像但其实没用&amp;quot;的片段。这些噪声片段进入 Prompt 后，会触发 LLM 的 &lt;strong&gt;&amp;ldquo;Lost in the Middle&amp;rdquo;&lt;/strong&gt; 现象——模型对上下文中间位置的信息注意力会下降，反而把真正相关的片段忽略了。&lt;/p&gt;
&lt;h3 id=&#34;32-成本线性增长&#34;&gt;3.2 成本线性增长
&lt;/h3&gt;&lt;p&gt;LLM 的推理成本是按 token 计费的，k 越大，Prompt 越长：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;k=4：上下文约 2000 token&lt;/li&gt;
&lt;li&gt;k=20：上下文约 10000 token&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;成本直接 5 倍，延迟也跟着涨。线上高 QPS 场景下，这是真金白银的浪费。&lt;/p&gt;
&lt;h3 id=&#34;33-生成质量下降&#34;&gt;3.3 生成质量下降
&lt;/h3&gt;&lt;p&gt;更隐蔽的问题是：&lt;strong&gt;噪声片段会让模型&amp;quot;分心&amp;quot;&lt;/strong&gt;。LLM 是基于注意力机制的，当 Prompt 里混入大量无关内容，模型会尝试&amp;quot;综合&amp;quot;这些信息，导致回答跑题、啰嗦，甚至把无关片段当事实引用。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;核心结论&lt;/strong&gt;：top-k 设大的代价是&lt;strong&gt;噪声增加 → 成本上升 → 生成质量反而下降&lt;/strong&gt;。多并不等于好。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&#34;四两阶段检索粗排--精排&#34;&gt;四、两阶段检索：粗排 + 精排
&lt;/h2&gt;&lt;p&gt;&lt;a href=&#34;https://SymphonyW.github.io/p/classic-interview-questionhow-exactly-should-you-set-rag-retrieval-top-k/two-stage-retrieval.svg&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;&lt;img src=&#34;https://SymphonyW.github.io/p/classic-interview-questionhow-exactly-should-you-set-rag-retrieval-top-k/two-stage-retrieval.svg&#34; alt=&#34;两阶段检索：粗排保召回，精排提质量&#34; loading=&#34;lazy&#34; decoding=&#34;async&#34;&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;既然 k 设小了漏、设大了吵，那有没有两全其美的办法？这就是**两阶段检索（Two-Stage Retrieval）**的价值。&lt;/p&gt;
&lt;h3 id=&#34;41-第一阶段粗排recall宁可错杀不可放过&#34;&gt;4.1 第一阶段：粗排（Recall）——宁可错杀，不可放过
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;用什么&lt;/strong&gt;：双塔 Embedding 模型（如 &lt;code&gt;bge-large-zh&lt;/code&gt;、&lt;code&gt;text-embedding-3&lt;/code&gt;）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;怎么做&lt;/strong&gt;：query 和 doc 分别编码，算余弦相似度&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;k 设多大&lt;/strong&gt;：放宽到 &lt;strong&gt;20~50&lt;/strong&gt;，甚至 100&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;目标&lt;/strong&gt;：&lt;strong&gt;高召回率&lt;/strong&gt;，把可能相关的片段都捞进来，哪怕混入噪声&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这一步本质是&amp;quot;撒大网&amp;quot;，速度快（向量检索毫秒级），但精度有限。&lt;/p&gt;
&lt;h3 id=&#34;42-第二阶段精排precision去伪存真&#34;&gt;4.2 第二阶段：精排（Precision）——去伪存真
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;用什么&lt;/strong&gt;：Cross-Encoder 重排模型（如 &lt;code&gt;bge-reranker-large&lt;/code&gt;、Cohere Rerank）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;怎么做&lt;/strong&gt;：把 query 和每一条候选 doc &lt;strong&gt;拼在一起&lt;/strong&gt;送进模型，输出相关性分数&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;取多少&lt;/strong&gt;：按分数从高到低取 &lt;strong&gt;3~5 条&lt;/strong&gt; 喂给 LLM&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;目标&lt;/strong&gt;：&lt;strong&gt;高精度&lt;/strong&gt;，把粗排里的噪声过滤掉，只留真正相关的&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这一步是&amp;quot;过筛子&amp;quot;，精度高（Cross-Encoder 能捕捉 query-doc 的细粒度交互），但速度慢，所以只对粗排的少量候选做。&lt;/p&gt;
&lt;h3 id=&#34;43-为什么不能直接用-cross-encoder-检索&#34;&gt;4.3 为什么不能直接用 Cross-Encoder 检索？
&lt;/h3&gt;&lt;p&gt;因为 Cross-Encoder 没有&amp;quot;索引&amp;quot;概念，必须对库里每条 doc 都跑一次模型，百万级文档库根本扛不住。所以工业界的标准做法就是：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;双塔粗排（快但糙）→ Cross-Encoder 精排（慢但准）→ 取 Top-N 喂 LLM&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;这正是 top-k 在两阶段里的&amp;quot;分工&amp;quot;——粗排的 k 大（保召回），精排后的 k 小（保质量）。&lt;strong&gt;面试时把这两个 k 区分开讲，就已经超过 80% 的候选人了。&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;五动态阈值让输入规模自适应&#34;&gt;五、动态阈值：让输入规模自适应
&lt;/h2&gt;&lt;p&gt;&lt;a href=&#34;https://SymphonyW.github.io/p/classic-interview-questionhow-exactly-should-you-set-rag-retrieval-top-k/dynamic-threshold.svg&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;&lt;img src=&#34;https://SymphonyW.github.io/p/classic-interview-questionhow-exactly-should-you-set-rag-retrieval-top-k/dynamic-threshold.svg&#34; alt=&#34;动态阈值：按相关性分数自适应截断&#34; loading=&#34;lazy&#34; decoding=&#34;async&#34;&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;两阶段检索解决了&amp;quot;召回 vs 精度&amp;quot;的矛盾，但还有一个问题：&lt;strong&gt;精排后取几条？固定取 3 条还是 5 条？&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;固定数字依然不够好，因为不同问题的&amp;quot;答案密度&amp;quot;不一样：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;简单事实题&lt;/strong&gt;（&amp;ldquo;公司全称是什么&amp;rdquo;）：可能只有 1 条强相关，取 5 条全是噪声&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;复杂流程题&lt;/strong&gt;（&amp;ldquo;请假流程&amp;rdquo;）：可能需要 4~5 条片段拼起来才完整&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;开放性问题&lt;/strong&gt;（&amp;ldquo;总结公司福利&amp;rdquo;）：可能需要 8~10 条覆盖不同福利项&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这就引出&lt;strong&gt;动态阈值（Dynamic Threshold）&lt;/strong&gt;：&lt;/p&gt;
&lt;h3 id=&#34;51-基于分数的截断&#34;&gt;5.1 基于分数的截断
&lt;/h3&gt;&lt;p&gt;不固定数量，而是设一个&lt;strong&gt;相关性分数阈值&lt;/strong&gt; θ：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;保留所有 score &amp;gt;= θ 的片段
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;比如精排分数分布是 &lt;code&gt;[0.92, 0.88, 0.85, 0.41, 0.38, ...]&lt;/code&gt;，阈值设 0.5，那就只取前 3 条，后边的低分噪声自动丢弃。&lt;/p&gt;
&lt;h3 id=&#34;52-基于分数差距的截断drop-off-检测&#34;&gt;5.2 基于分数差距的截断（Drop-off 检测）
&lt;/h3&gt;&lt;p&gt;观察相邻分数的&amp;quot;断崖&amp;quot;：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;分数：0.92 → 0.88 → 0.85 → 0.41（断崖！）
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;在分数急剧下降的位置截断，能自适应地保留&amp;quot;高分组&amp;quot;而丢弃&amp;quot;低分组&amp;quot;。&lt;/p&gt;
&lt;h3 id=&#34;53-加上上下文长度约束&#34;&gt;5.3 加上上下文长度约束
&lt;/h3&gt;&lt;p&gt;当然，动态阈值还要和 LLM 的上下文窗口配合——总不能召回 50 条全塞进去。实际工程里通常是：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;最终输入 = min(动态阈值筛出的片段, 上下文长度预算)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;核心结论&lt;/strong&gt;：动态阈值让&amp;quot;取几条&amp;quot;从&lt;strong&gt;静态参数&lt;/strong&gt;变成&lt;strong&gt;自适应决策&lt;/strong&gt;，这是 top-k 的高阶玩法，也是面试加分项。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&#34;六完整链路top-k-不是参数是思维&#34;&gt;六、完整链路：top-k 不是参数，是思维
&lt;/h2&gt;&lt;p&gt;&lt;a href=&#34;https://SymphonyW.github.io/p/classic-interview-questionhow-exactly-should-you-set-rag-retrieval-top-k/rag-pipeline-mindset.svg&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;&lt;img src=&#34;https://SymphonyW.github.io/p/classic-interview-questionhow-exactly-should-you-set-rag-retrieval-top-k/rag-pipeline-mindset.svg&#34; alt=&#34;完整 RAG 链路思维：top-k 是四阶段的协同&#34; loading=&#34;lazy&#34; decoding=&#34;async&#34;&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;把前面几节串起来，你会看到 top-k 背后其实是一条完整的链路：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;用户 Query
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   ↓
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;[Query 改写]（可选：HyDE / Multi-Query / Step-back）
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   ↓
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;[粗排] 双塔 Embedding 检索 → top-k₁ = 20~50（保召回）
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   ↓
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;[精排] Cross-Encoder Rerank → 重排打分
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   ↓
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;[截断] 动态阈值 / Drop-off 检测 → top-k₂ = 3~5（保质量）
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   ↓
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;[上下文压缩]（可选：LongLLMLingua）
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   ↓
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;[Prompt 拼装] Context + Question
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   ↓
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;[LLM 生成] → 可溯源回答
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;每个环节都有它的&amp;quot;k&amp;quot;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;k₁（粗排）&lt;/strong&gt;：大，保召回&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;k₂（精排后）&lt;/strong&gt;：小，保质量&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;k₃（最终输入）&lt;/strong&gt;：受动态阈值和上下文预算双重约束&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;面试官听到你能区分 k₁、k₂、k₃，并解释清楚每一步的目标，基本就认定你&lt;strong&gt;真正做过 RAG 工程&lt;/strong&gt;，而不是只会调 LangChain 的 &lt;code&gt;search_kwargs={&amp;quot;k&amp;quot;: 4}&lt;/code&gt;。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;七面试高分回答模板&#34;&gt;七、面试高分回答模板
&lt;/h2&gt;&lt;p&gt;如果被问到&amp;quot;top-k 怎么设&amp;quot;，可以这样组织回答（约 90 秒）：&lt;/p&gt;
&lt;h3 id=&#34;第一层先承认-trade-off10-秒&#34;&gt;第一层：先承认 trade-off（10 秒）
&lt;/h3&gt;&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;top-k 不是孤立参数，它同时影响召回率、噪声、成本和生成质量，设小了会漏、设大了会吵，所以不能一刀切。&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;第二层讲两阶段检索40-秒&#34;&gt;第二层：讲两阶段检索（40 秒）
&lt;/h3&gt;&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;我们的做法是两阶段检索。粗排用双塔 Embedding，k 设到 20~50，优先保召回；精排用 Cross-Encoder Rerank，比如 &lt;code&gt;bge-reranker-large&lt;/code&gt;，对粗排结果重打分。Cross-Encoder 精度高但慢，所以只对少量候选做。&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;第三层讲动态阈值25-秒&#34;&gt;第三层：讲动态阈值（25 秒）
&lt;/h3&gt;&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;精排后不固定取几条，而是用动态阈值——设一个相关性分数下限，或者检测分数 drop-off 的断崖位置，自适应截断。再叠加 LLM 上下文长度预算做上限保护。&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;第四层回到本质15-秒&#34;&gt;第四层：回到本质（15 秒）
&lt;/h3&gt;&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;本质上 top-k 考的不是调参，而是对 RAG 链路的理解——召回、排序、截断、生成，每个阶段都有它的 k。区分清楚 k₁、k₂、k₃，效果就稳了。&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&#34;八常见追问与应对&#34;&gt;八、常见追问与应对
&lt;/h2&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;面试官追问&lt;/th&gt;
&lt;th&gt;参考回答要点&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&amp;ldquo;粗排 k 设 50 不会太慢吗？&amp;rdquo;&lt;/td&gt;
&lt;td&gt;向量检索是 ANN（近似最近邻），百万级库毫秒级，HNSW/IVF 索引加持下没问题&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;ldquo;Rerank 模型怎么选？&amp;rdquo;&lt;/td&gt;
&lt;td&gt;中文用 &lt;code&gt;bge-reranker-large&lt;/code&gt;，英文用 Cohere Rerank；轻量场景可用 &lt;code&gt;bge-reranker-base&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;ldquo;动态阈值怎么调？&amp;rdquo;&lt;/td&gt;
&lt;td&gt;离线评估集上扫阈值，看 Recall@k 和 Precision@k 的 F1 拐点；或用分数分布的肘部&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;ldquo;为什么不直接用长上下文模型塞进去？&amp;rdquo;&lt;/td&gt;
&lt;td&gt;长上下文有 Lost-in-the-Middle、成本高、不可溯源三个问题，RAG 仍然是更经济的方案&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;ldquo;k 设大了模型答非所问怎么办？&amp;rdquo;&lt;/td&gt;
&lt;td&gt;先加 Rerank，再加动态阈值；必要时上 LongLLMLingua 做上下文压缩&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;ldquo;如何评估 top-k 设得对不对？&amp;rdquo;&lt;/td&gt;
&lt;td&gt;用 Ragas / TruLens 做 Faithfulness、Context Recall、Answer Relevancy 三项指标评估&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id=&#34;总结&#34;&gt;总结
&lt;/h2&gt;&lt;p&gt;回到那个面试题——&amp;ldquo;RAG 检索的 top-k 怎么设？&amp;rdquo;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;低分回答&lt;/strong&gt;：&amp;ldquo;看情况，一般设 3~5。&amp;rdquo;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;及格回答&lt;/strong&gt;：&amp;ldquo;设小了会幻觉，设大了会引入噪声，所以要在召回和精度之间权衡。&amp;rdquo;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;高分回答&lt;/strong&gt;：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;top-k 不是单一参数，而是贯穿 RAG 链路的协同设计。粗排用双塔 Embedding 大 k 保召回（20~50），精排用 Cross-Encoder 重排提精度，再用动态阈值自适应截断到 3~5 条，最后受 LLM 上下文预算约束。本质考的不是调参，而是对&lt;strong&gt;召回 → 排序 → 截断 → 生成&lt;/strong&gt;整条链路的理解。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;记住视频里那句点睛之笔：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&amp;ldquo;top-k 的本质是完整 RAG 链路思维，而非调参数。&amp;rdquo;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;把这句话在面试里讲出来，配合上面的链路图，这道题基本就稳了。&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;本文参考抖音「小哲讲 agent 面试」的视频内容整理扩展，原视频链接见文末。封面图由作者自行添加。&lt;/em&gt;&lt;/p&gt;
</description>
        </item>
        <item>
        <title>RAG Fully Explained:From &#34;Closed-Book&#34; to &#34;Open-Book&#34; LLMs</title>
        <link>https://SymphonyW.github.io/p/rag-fully-explainedfrom-closed-book-to-open-book-llms/</link>
        <pubDate>Wed, 08 Jul 2026 15:00:00 +0800</pubDate>
        
        <guid>https://SymphonyW.github.io/p/rag-fully-explainedfrom-closed-book-to-open-book-llms/</guid>
        <description>&lt;img src="https://SymphonyW.github.io/p/rag-fully-explainedfrom-closed-book-to-open-book-llms/bg.png" alt="Featured image of post RAG Fully Explained:From &#34;Closed-Book&#34; to &#34;Open-Book&#34; LLMs" /&gt;&lt;h1 id=&#34;rag-技术全景让大模型从闭卷考试到开卷考试&#34;&gt;RAG 技术全景：让大模型从&amp;quot;闭卷考试&amp;quot;到&amp;quot;开卷考试&amp;quot;
&lt;/h1&gt;&lt;blockquote&gt;
&lt;p&gt;大模型很强，但它会&amp;quot;一本正经地胡说八道&amp;quot;。RAG（Retrieval-Augmented Generation，检索增强生成）给大模型外挂了一个&amp;quot;知识库&amp;quot;，让它从闭卷考试变成开卷考试，回答既准又能溯源。本文用 6 张图带你完整搞懂 RAG。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&#34;一先聊痛点大模型的幻觉从哪来&#34;&gt;一、先聊痛点：大模型的&amp;quot;幻觉&amp;quot;从哪来？
&lt;/h2&gt;&lt;p&gt;你大概遇到过这样的场景：问 GPT 一个公司内部的政策问题，或者让它总结一份最新发布的财报，它信誓旦旦地给你一段听起来很专业的回答——但仔细一查，全是编的。&lt;/p&gt;
&lt;p&gt;这就是大模型的&lt;strong&gt;幻觉（Hallucination）&lt;/strong&gt;。它不是故意的，而是由其工作方式决定的：LLM 本质上是在做&amp;quot;下一个 token 预测&amp;quot;，它根据训练时记住的概率分布生成文本，分不清&amp;quot;知道&amp;quot;和&amp;quot;不知道&amp;quot;。&lt;/p&gt;
&lt;p&gt;原生 LLM 在企业级场景下有四个硬伤：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;知识截止&lt;/strong&gt;：训练数据有截止日期，不知道今天发生的事&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;幻觉问题&lt;/strong&gt;：没见过的知识就靠&amp;quot;编&amp;quot;，还很自信&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;领域知识不足&lt;/strong&gt;：对企业内部文档、专业细分领域不熟悉&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;无法溯源&lt;/strong&gt;：回答不知道来自哪里，没法核验&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;要解决这些问题，传统思路是&lt;strong&gt;微调（Fine-tuning）&lt;/strong&gt;——用领域数据重新训练模型。但微调又贵又慢，而且知识一更新就得再来一遍。&lt;/p&gt;
&lt;p&gt;RAG 给了另一条路：&lt;strong&gt;不重新训练模型，而是给它外挂一个可随时更新的知识库，回答时先去知识库里检索，再基于检索到的内容作答。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://SymphonyW.github.io/p/rag-fully-explainedfrom-closed-book-to-open-book-llms/llm-vs-rag.svg&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;&lt;img src=&#34;https://SymphonyW.github.io/p/rag-fully-explainedfrom-closed-book-to-open-book-llms/llm-vs-rag.svg&#34; alt=&#34;原生 LLM vs RAG：闭卷考试 vs 开卷考试&#34; loading=&#34;lazy&#34; decoding=&#34;async&#34;&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;就像考试一样：原生 LLM 是闭卷考试，全凭记忆，记不清就编；RAG 是开卷考试，遇到不会的可以翻书，答案有据可循。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;二rag-是什么核心思想一句话&#34;&gt;二、RAG 是什么：核心思想一句话
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;RAG = 检索（Retrieval）+ 增强（Augmentation）+ 生成（Generation）&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;在 LLM 生成回答之前，先从外部知识库中&lt;strong&gt;检索&lt;/strong&gt;相关资料，把这些资料&lt;strong&gt;增强&lt;/strong&gt;到 Prompt 里作为上下文，再让 LLM 基于这些上下文&lt;strong&gt;生成&lt;/strong&gt;回答。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;用一句话概括：&lt;strong&gt;RAG 让 LLM 从&amp;quot;闭卷考试&amp;quot;变成&amp;quot;开卷考试&amp;quot;。&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;它和微调的根本区别在于：微调把知识&amp;quot;烧进&amp;quot;模型权重里，RAG 把知识放在模型之外的数据库里，用的时候现查。这也决定了两者的适用边界——后面会详细对比。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;三rag-工作流程三阶段详解&#34;&gt;三、RAG 工作流程：三阶段详解
&lt;/h2&gt;&lt;p&gt;&lt;a href=&#34;https://SymphonyW.github.io/p/rag-fully-explainedfrom-closed-book-to-open-book-llms/rag-overview.svg&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;&lt;img src=&#34;https://SymphonyW.github.io/p/rag-fully-explainedfrom-closed-book-to-open-book-llms/rag-overview.svg&#34; alt=&#34;RAG 工作流程：检索 → 增强 → 生成&#34; loading=&#34;lazy&#34; decoding=&#34;async&#34;&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;RAG 的完整流程可以拆成&lt;strong&gt;离线建库&lt;/strong&gt;和&lt;strong&gt;在线问答&lt;/strong&gt;两大阶段。在线问答又分为检索、增强、生成三步。&lt;/p&gt;
&lt;h3 id=&#34;31-离线阶段把文档变成可检索的向量库&#34;&gt;3.1 离线阶段：把文档变成可检索的向量库
&lt;/h3&gt;&lt;p&gt;这一步是&amp;quot;建图书馆&amp;quot;的过程，通常一次性完成，知识更新时增量重建：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;文档加载&lt;/strong&gt;：读取 PDF、Word、HTML、Markdown 等原始文档&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;切分（Chunking）&lt;/strong&gt;：把长文档切成小段。为什么不整篇存？因为检索时要找最相关的片段，整篇文档向量会&amp;quot;稀释&amp;quot;语义；而且 LLM 上下文有限，塞不下整篇&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;向量化（Embedding）&lt;/strong&gt;：用嵌入模型把每段文本转成一个高维向量（通常 768~1536 维），语义相近的文本在向量空间里距离也近&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;存入向量数据库&lt;/strong&gt;：把向量和原文一起存进去，建好索引，供后续快速检索&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;32-在线阶段检索--增强--生成&#34;&gt;3.2 在线阶段：检索 → 增强 → 生成
&lt;/h3&gt;&lt;p&gt;用户每一次提问，都会实时跑这三步：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;① 检索 Retrieval&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;把用户问题用同一个 Embedding 模型转成向量&lt;/li&gt;
&lt;li&gt;在向量数据库中做相似度检索（通常用余弦相似度），召回 Top-K（一般 3~10 条）最相关的文档片段&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;② 增强 Augmentation&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;把检索到的片段拼到 Prompt 模板里，作为上下文&lt;/li&gt;
&lt;li&gt;一个典型的 Prompt 长这样：&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;你是一个严谨的问答助手，请根据以下参考资料回答用户问题。
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;如果资料中没有答案，请回答&amp;#34;根据现有资料无法回答&amp;#34;，不要编造。
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;【参考资料】
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;{检索到的文档片段1}
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;{检索到的文档片段2}
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;【用户问题】
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;{用户的问题}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;strong&gt;③ 生成 Generation&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;把拼好的 Prompt 喂给 LLM，生成最终回答&lt;/li&gt;
&lt;li&gt;可以要求模型在回答中标注引用来源，实现可溯源&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;四完整架构图&#34;&gt;四、完整架构图
&lt;/h2&gt;&lt;p&gt;&lt;a href=&#34;https://SymphonyW.github.io/p/rag-fully-explainedfrom-closed-book-to-open-book-llms/rag-architecture.svg&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;&lt;img src=&#34;https://SymphonyW.github.io/p/rag-fully-explainedfrom-closed-book-to-open-book-llms/rag-architecture.svg&#34; alt=&#34;RAG 完整架构：离线建库 &amp;#43; 在线问答&#34; loading=&#34;lazy&#34; decoding=&#34;async&#34;&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;这张图把离线和在线两条流水线放在了一起。注意几个关键点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Embedding 模型必须一致&lt;/strong&gt;：离线建库用哪个模型，在线检索时也要用同一个，否则向量空间不兼容&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;知识更新无需重训模型&lt;/strong&gt;：新增文档只需走一遍&amp;quot;切分 → 向量化 → 入库&amp;quot;，模型权重完全不动&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;检索质量是 RAG 的命门&lt;/strong&gt;：如果第一步召回的片段就不相关，后面 LLM 再强也答不好&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;五核心组件选型&#34;&gt;五、核心组件选型
&lt;/h2&gt;&lt;p&gt;RAG 系统由四个核心组件构成，选型直接影响效果：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;组件&lt;/th&gt;
&lt;th&gt;作用&lt;/th&gt;
&lt;th&gt;常见选型&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Embedding 模型&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;文本转向量，决定语义匹配上限&lt;/td&gt;
&lt;td&gt;BGE（智源）、M3E、OpenAI text-embedding-3、Cohere、bge-m3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;向量数据库&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;存储与检索向量&lt;/td&gt;
&lt;td&gt;Milvus、Qdrant、Chroma、Pinecone、FAISS、Weaviate&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;LLM&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;基于上下文生成回答&lt;/td&gt;
&lt;td&gt;GPT-4、Claude、Qwen、DeepSeek、Llama、GLM&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;编排框架&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;串联整个流程&lt;/td&gt;
&lt;td&gt;LangChain、LlamaIndex、Haystack、DSPy&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;几个选型经验：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;中文场景&lt;/strong&gt;：Embedding 优先考虑 &lt;code&gt;bge-large-zh&lt;/code&gt; 或 &lt;code&gt;bge-m3&lt;/code&gt;，比 OpenAI 的英文模型在中文检索上更准&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;轻量起步&lt;/strong&gt;：向量库用 Chroma（纯 Python，单机嵌入式）跑通流程，量大了再换 Milvus / Qdrant&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;框架选择&lt;/strong&gt;：快速原型用 LangChain，文档密集型场景用 LlamaIndex（它对文档处理和索引抽象更细致）&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;六进阶技术从能用到好用&#34;&gt;六、进阶技术：从&amp;quot;能用&amp;quot;到&amp;quot;好用&amp;quot;
&lt;/h2&gt;&lt;p&gt;朴素 RAG（一次向量检索 + 拼 Prompt）能跑通，但效果往往一般。真正生产级的 RAG 通常会在四个方向上做增强：&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://SymphonyW.github.io/p/rag-fully-explainedfrom-closed-book-to-open-book-llms/advanced-rag.svg&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;&lt;img src=&#34;https://SymphonyW.github.io/p/rag-fully-explainedfrom-closed-book-to-open-book-llms/advanced-rag.svg&#34; alt=&#34;RAG 进阶技术矩阵&#34; loading=&#34;lazy&#34; decoding=&#34;async&#34;&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;h3 id=&#34;61-query-改写让问题更适合检索&#34;&gt;6.1 Query 改写（让问题更适合检索）
&lt;/h3&gt;&lt;p&gt;用户的问题往往是口语化、模糊的，直接拿去检索效果差。常见技巧：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Query Rewriting&lt;/strong&gt;：让 LLM 把&amp;quot;那个东西怎么用&amp;quot;改写成&amp;quot;产品 X 的使用方法&amp;quot;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;HyDE（Hypothetical Document Embeddings）&lt;/strong&gt;：先让 LLM 生成一个假设性答案，再用这个答案的向量去检索——因为&amp;quot;答案&amp;quot;和&amp;quot;答案&amp;quot;的语义比&amp;quot;问题&amp;quot;和&amp;quot;答案&amp;quot;更接近&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Multi-Query&lt;/strong&gt;：把一个问题拆成多个子问题分别检索，结果合并去重&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Step-back Prompting&lt;/strong&gt;：先抽象出上位概念再检索，比如&amp;quot;2024 年诺贝尔物理学奖得主&amp;quot;先退到&amp;quot;诺贝尔物理学奖近年得主&amp;quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;62-混合检索--rerank多路召回精排提纯&#34;&gt;6.2 混合检索 + Rerank（多路召回，精排提纯）
&lt;/h3&gt;&lt;p&gt;&lt;a href=&#34;https://SymphonyW.github.io/p/rag-fully-explainedfrom-closed-book-to-open-book-llms/retrieval-detail.svg&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;&lt;img src=&#34;https://SymphonyW.github.io/p/rag-fully-explainedfrom-closed-book-to-open-book-llms/retrieval-detail.svg&#34; alt=&#34;混合检索 &amp;#43; 重排：提升召回质量&#34; loading=&#34;lazy&#34; decoding=&#34;async&#34;&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;单靠向量检索有个问题：它擅长语义匹配，但对&lt;strong&gt;专有名词、产品型号、人名&lt;/strong&gt;这种精确字面匹配反而不如传统检索。所以生产系统通常用&lt;strong&gt;混合检索&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;向量检索&lt;/strong&gt;（语义）+ &lt;strong&gt;BM25 关键词检索&lt;/strong&gt;（字面）并行召回&lt;/li&gt;
&lt;li&gt;用 &lt;strong&gt;RRF（Reciprocal Rank Fusion）&lt;/strong&gt; 融合两路结果&lt;/li&gt;
&lt;li&gt;再用 &lt;strong&gt;Cross-Encoder 重排模型&lt;/strong&gt;（如 &lt;code&gt;bge-reranker-large&lt;/code&gt;、Cohere Rerank）对召回结果做精排&lt;/li&gt;
&lt;li&gt;最后取 Top-K 喂给 LLM&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Rerank 的关键区别：Embedding 是把 query 和 doc &lt;strong&gt;分别&lt;/strong&gt;编码再算相似度（双塔），而 Cross-Encoder 是把 query 和 doc &lt;strong&gt;拼一起&lt;/strong&gt;送进模型（交叉编码），精度高得多，但速度慢——所以先用向量检索粗筛，再用 Rerank 精排，兼顾速度和精度。&lt;/p&gt;
&lt;h3 id=&#34;63-graphrag基于知识图谱的全局检索&#34;&gt;6.3 GraphRAG：基于知识图谱的全局检索
&lt;/h3&gt;&lt;p&gt;微软 2024 年提出的 GraphRAG 解决的是朴素 RAG 的另一个痛点：&lt;strong&gt;局部性&lt;/strong&gt;。向量检索只能召回和问题相似的片段，回答不了&amp;quot;总结整个文档集的核心主题&amp;quot;这种全局性问题。&lt;/p&gt;
&lt;p&gt;GraphRAG 的做法：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;用 LLM 从文档中抽取&lt;strong&gt;实体和关系&lt;/strong&gt;，构建知识图谱&lt;/li&gt;
&lt;li&gt;用&lt;strong&gt;社区检测算法&lt;/strong&gt;（如 Leiden）把图谱分成主题层次化的社区&lt;/li&gt;
&lt;li&gt;为每个社区生成摘要&lt;/li&gt;
&lt;li&gt;查询时根据问题粒度选择社区摘要或具体节点回答&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;它特别适合&amp;quot;全局性总结&amp;quot;&amp;ldquo;跨文档推理&amp;quot;类问题，代价是建图成本高、更新麻烦。&lt;/p&gt;
&lt;h3 id=&#34;64-self-rag--自适应-rag让模型自己决定要不要检索&#34;&gt;6.4 Self-RAG / 自适应 RAG：让模型自己决定要不要检索
&lt;/h3&gt;&lt;p&gt;不是每个问题都需要检索——&amp;ldquo;1+1 等于几&amp;quot;还去查库就浪费了。Self-RAG 让模型学会自我反思：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;是否检索&lt;/strong&gt;：判断问题是否需要外部知识，简单问题直接答&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;检索结果是否相关&lt;/strong&gt;：过滤掉无关片段&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;生成是否忠于检索&lt;/strong&gt;：检查答案有没有脱离资料编造&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;好处是省 token、降延迟，坏处是需要训练模型学会这些判断（或用 prompt 模拟），实现复杂度高。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;七方案对比rag-vs-微调-vs-长上下文&#34;&gt;七、方案对比：RAG vs 微调 vs 长上下文
&lt;/h2&gt;&lt;p&gt;&lt;a href=&#34;https://SymphonyW.github.io/p/rag-fully-explainedfrom-closed-book-to-open-book-llms/solution-comparison.svg&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;&lt;img src=&#34;https://SymphonyW.github.io/p/rag-fully-explainedfrom-closed-book-to-open-book-llms/solution-comparison.svg&#34; alt=&#34;四种知识注入方案横向对比&#34; loading=&#34;lazy&#34; decoding=&#34;async&#34;&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;随着模型上下文窗口越来越长（Claude 200K、Gemini 1M、GPT-4o 128K），有人质疑 RAG 是不是过时了——直接把所有文档塞进上下文不就行了？&lt;/p&gt;
&lt;p&gt;实际并非如此，三者各有定位：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;长上下文&lt;/strong&gt;：贵（按 token 计费）、易&amp;quot;迷失在中间&amp;rdquo;（Lost in the Middle 现象）、不可溯源。适合一次性分析单份长文档&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;RAG&lt;/strong&gt;：经济、可扩展到海量文档、可溯源。适合知识库问答&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;微调&lt;/strong&gt;：改变模型行为/风格，而非注入事实知识。适合固定格式输出、领域术语适配&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;RAG + 微调&lt;/strong&gt;：效果最好，成本最高，用于高精度专业场景&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;经验法则：&lt;strong&gt;知识频繁变化 → RAG；风格/格式固定 → 微调；两者都要 → 结合用。&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;八实战用-langchain-跑通一个最小-rag&#34;&gt;八、实战：用 LangChain 跑通一个最小 RAG
&lt;/h2&gt;&lt;p&gt;理论讲完，来看一段能跑的代码。用 LangChain + Chroma + OpenAI 实现 30 行的 RAG：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;22
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;23
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;24
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;25
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;26
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;27
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;28
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;29
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;30
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;31
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;32
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;33
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;34
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;35
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;36
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;37
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;38
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;39
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;40
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;41
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;langchain_community.document_loaders&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;TextDocumentLoader&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;langchain_text_splitters&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;RecursiveCharacterTextSplitter&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;langchain_openai&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;OpenAIEmbeddings&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ChatOpenAI&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;langchain_community.vectorstores&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Chroma&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;langchain_core.prompts&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ChatPromptTemplate&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;langchain_core.runnables&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;RunnablePassthrough&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;langchain_core.output_parsers&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;StrOutputParser&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# ① 离线建库：加载 → 切分 → 向量化 → 入库&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;docs&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;TextDocumentLoader&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;knowledge.txt&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;load&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;chunks&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;RecursiveCharacterTextSplitter&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;chunk_size&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;500&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;chunk_overlap&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;50&lt;/span&gt;      &lt;span class=&#34;c1&#34;&gt;# 500 字一段，重叠 50 字&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;split_documents&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;docs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;vectorstore&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Chroma&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;from_documents&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;chunks&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;OpenAIEmbeddings&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;model&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;text-embedding-3-small&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;retriever&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vectorstore&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;as_retriever&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;search_kwargs&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;k&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;})&lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;# 召回 Top-4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# ② 在线问答：检索 → 增强 → 生成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;prompt&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ChatPromptTemplate&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;from_template&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;你是严谨的问答助手，根据以下资料回答问题。资料中没有答案就说&amp;#34;无法回答&amp;#34;，不要编造。
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;【资料】
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{context}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;【问题】
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{question}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;format_docs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;docs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\n\n&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;join&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;d&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;page_content&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;d&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;docs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;rag_chain&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;context&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;retriever&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;|&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;format_docs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;question&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;RunnablePassthrough&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;o&#34;&gt;|&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;prompt&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;o&#34;&gt;|&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ChatOpenAI&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;model&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;gpt-4o-mini&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;temperature&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;o&#34;&gt;|&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;StrOutputParser&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# ③ 提问&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rag_chain&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;invoke&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;公司请假流程是什么？&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这段代码虽然简单，但已经包含了 RAG 的所有核心环节。生产化时再把 Embedding 换成 BGE、加上 Rerank、换成 Milvus，骨架不变。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;九常见挑战与优化方向&#34;&gt;九、常见挑战与优化方向
&lt;/h2&gt;&lt;p&gt;实际落地 RAG，踩坑往往不在模型，而在检索。下面是常见问题对应的优化手段：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;症状&lt;/th&gt;
&lt;th&gt;根因&lt;/th&gt;
&lt;th&gt;优化方向&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;检索结果不相关&lt;/td&gt;
&lt;td&gt;Query 与文档语义差距大&lt;/td&gt;
&lt;td&gt;Query 改写、换更强的 Embedding&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;召回准确但答非所问&lt;/td&gt;
&lt;td&gt;片段顺序/噪声干扰&lt;/td&gt;
&lt;td&gt;加 Rerank 精排、调 Top-K&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;答案不忠于资料&lt;/td&gt;
&lt;td&gt;LLM 忽略上下文编造&lt;/td&gt;
&lt;td&gt;Prompt 加约束、降 temperature、强制引用&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;专有名词召回差&lt;/td&gt;
&lt;td&gt;纯向量检索短板&lt;/td&gt;
&lt;td&gt;加 BM25 混合检索&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;上下文超长&lt;/td&gt;
&lt;td&gt;召回太多塞不下&lt;/td&gt;
&lt;td&gt;上下文压缩、LongLLMLingua、换长上下文模型&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;知识更新延迟&lt;/td&gt;
&lt;td&gt;索引重建慢&lt;/td&gt;
&lt;td&gt;增量索引、流式更新&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;答案无法溯源&lt;/td&gt;
&lt;td&gt;未保留片段来源&lt;/td&gt;
&lt;td&gt;检索结果带 metadata，Prompt 要求标注引用&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;一个经验：&lt;strong&gt;80% 的 RAG 优化工作都在检索阶段&lt;/strong&gt;，而不是生成阶段。先把检索做准，效果立刻提升一大截。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;十典型应用场景&#34;&gt;十、典型应用场景
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;企业知识问答&lt;/strong&gt;：基于内部 Wiki、手册、合同的智能客服与员工助手&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;法律/医疗咨询&lt;/strong&gt;：基于法条、判例、药品说明、病历的精准问答&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;代码助手&lt;/strong&gt;：基于私有代码库的代码生成（Cursor、Copilot Workspace 都用了 RAG 思想）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;教育辅导&lt;/strong&gt;：基于教材的个性化答疑，答案可指向课本页码&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;智能搜索&lt;/strong&gt;：搜索引擎的 AI 摘要（Perplexity、Bing Chat、Google AI Overviews）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;数据分析&lt;/strong&gt;：Text-to-SQL，基于数据库 schema 的自然语言查询&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;总结&#34;&gt;总结
&lt;/h2&gt;&lt;p&gt;RAG 不是某个具体工具，而是一种 &lt;strong&gt;&amp;ldquo;把外部知识检索和大模型生成结合起来&amp;rdquo;&lt;/strong&gt; 的架构思想。它的价值在于：让大模型能用最新、最准、可溯源的外部知识来回答问题，而无需重新训练。&lt;/p&gt;
&lt;p&gt;回顾本文要点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;核心思想&lt;/strong&gt;：检索 → 增强 → 生成，让 LLM 从闭卷变开卷&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;两大阶段&lt;/strong&gt;：离线建库（切分+向量化+入库）+ 在线问答（检索+增强+生成）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;命门在检索&lt;/strong&gt;：80% 的优化工作都在检索阶段&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;进阶四件套&lt;/strong&gt;：Query 改写、混合检索+Rerank、GraphRAG、Self-RAG&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;方案选择&lt;/strong&gt;：知识频繁变化用 RAG，风格固定用微调，高精度场景结合使用&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;随着模型上下文窗口变长、多模态能力增强，RAG 的形态还在演进（比如多模态 RAG、Agentic RAG），但&amp;quot;外挂知识库&amp;quot;这个核心思想短期内不会过时——毕竟，开卷考试永远比背书更可靠。&lt;/p&gt;
&lt;p&gt;如果你对其中某个环节（比如向量数据库选型、Embedding 微调、GraphRAG 实现）想深入，欢迎在评论区交流。&lt;/p&gt;
</description>
        </item>
        
    </channel>
</rss>
