3.给 RAG 装上“质检员“:幻觉检测、自动重试、智能切分|基于 LangGraph + DeepSeek 的实战笔记

基于LangGraph构建智能检索代理:从RAG到Agentic RAG的实战指南 最近在准备 AI 大模型相关的面试,发现 Agent、RAG、LangChain、LangGraph 这些概念是高频考点,但网上资料要么太零散,要么只讲理论没有实战。很多同学在搭建一个能自主决策、带检索增强的智能体(Agentic RAG)时,常常卡在流程编排和状态管理上,导致系统要么“有问必查”效率低下,要么“该查不查”回答不准。 本文将从零开始,手把手带你构建一个基于 LangGraph 的智能检索代理(Custom RAG Agent)。这个项目不仅覆盖了从文档预处理、向量检索到智能体决策的完整链路, 阅读详情

前言:RAG 的"最后一公里"问题

如果你做过 RAG,大概率遇到过这些问题:

  • 检索回来 5 篇文档,其中 2 篇完全不相关,LLM 被噪声干扰,回答质量下降
  • LLM 明明检索到了正确内容,回答里却掺了编造的信息(幻觉)
  • 整个流程是线性的,检索不好 → 生成就差,没有任何纠错机会
  • 不同文档适合不同的切分策略,但每次都要手动试

这些问题的本质是:线性 Chain 缺乏决策和反馈能力。数据从头流到尾,中间出了问题只能在最终结果里发现。

LangGraph 解决的就是这个问题——把 RAG 流程建模为状态图,每个步骤是一个节点,节点之间可以有条件分支、循环重试、兜底降级。

打个比方:线性 Chain 像流水线,产品从头走到尾,中间有瑕疵也只能到终点才发现;LangGraph 像有质检环节的流水线,每个关键节点都能检查、退回、换条路走。

🔗 项目地址:GitHub - daixueyun3377/RAG-demo,对标 dev-LangGraph 分支


一、30 行代码理解 LangGraph 核心概念

在看完整项目之前,先用一个最小示例理解 LangGraph 的三个核心概念:

from typing import TypedDict
from langgraph.graph import StateGraph, START, END

# 1. State:贯穿整个图的"黑板",每个节点都能读写
class MyState(TypedDict):
    question: str
    answer: str
    is_good: bool

# 2. Node:普通 Python 函数,接收 state,返回部分更新
def generate(state: MyState) -> dict:
    # 实际项目里这里调 LLM
    return {"answer": f"关于'{state['question']}'的回答...", "is_good": True}

def fallback(state: MyState) -> dict:
    return {"answer": "抱歉,我无法回答这个问题。"}

# 3. Conditional Edge:根据 state 动态决定下一步
def check_quality(state: MyState) -> str:
    return "done" if state["is_good"] else "fallback"

# 构建图
graph = StateGraph(MyState)
graph.add_node("generate", generate)
graph.add_node("fallback", fallback)
graph.add_edge(START, "generate")
graph.add_conditional_edges("generate", check_quality, {"done": END, "fallback": "fallback"})
graph.add_edge("fallback", END)

# 编译并执行
app = graph.compile()
result = app.invoke({"question": "什么是RAG?", "answer": "", "is_good": False})
print(result["answer"])

三个概念对应关系:

概念作用类比
State全局状态,所有节点共享的"黑板"流水线上的工单,每个工位都能读写
Node一个处理步骤,读 state、返回部分更新流水线上的一个工位
Conditional Edge根据 state 动态选择下一个节点质检员,决定产品走哪条线

理解了这三个概念,下面的完整项目就好懂了。


二、整体架构

系统分为查询链路和入库链路两条主线:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

技术选型:LangGraph 做图编排,FastAPI 做服务层,Chroma 做向量库(嵌入式,零部署),DeepSeek 做 LLM(便宜够用),硅基流动提供免费的 BGE Embedding 和 Reranker API。


三、项目结构

├── app/
│   ├── config.py          # 配置管理(环境变量)
│   ├── llm.py             # LLM / Embedding / Langfuse 初始化
│   ├── retriever.py       # 文档加载、切分、向量存储、检索器、Reranker
│   ├── ingest.py          # 智能入库 LangGraph 图(文档分析 + 质量验证 + 降级重试)
│   ├── rag_graph.py       # RAG 查询 LangGraph 图(评估 + 幻觉检测 + 条件路由)
│   └── main.py            # FastAPI 入口,定义 API 接口
├── tests/
│   ├── test_rag_graph.py  # 单元测试
│   └── test_integration.py # 集成测试(真实服务)
├── docs/
│   └── sample.md          # 示例文档
├── .env.example           # 环境变量模板
└── requirements.txt

核心是两个 LangGraph 图:rag_graph.py(查询)和 ingest.py(入库),底层能力由 retriever.py(检索/切分)和 llm.py(模型初始化)提供。


四、RAG 查询图:7 个节点的设计逻辑

4.1 全局流程

START → transform_query → retrieve → grade_documents
                                          ↓
                                ┌─── 有相关文档? ───┐
                                ↓ yes               ↓ no
                              rerank             fallback → END
                                ↓
                             generate
                                ↓
                        check_hallucination
                                ↓
                      ┌─── 有依据? ───────────┐
                      ↓ yes      ↓ no(<2次)   ↓ no(≥2次)
                     END     generate(重试)   fallback → END

7 个节点,2 个条件路由,1 个循环。下面按设计决策来讲——不是"这个节点做了什么",而是"为什么需要这个节点"。

4.2 State:图的全局黑板

class RAGState(TypedDict):
    question: str           # 用户原始问题
    search_query: str       # 变换后的检索 query
    retrieval_mode: str     # vector / bm25 / hybrid
    query_transform: str    # none / rewrite / hyde
    use_reranker: bool
    top_k: int
    retrieved_docs: list    # 检索到的原始文档
    relevant_docs: list     # 评估后保留的文档
    answer: str
    hallucination_pass: bool
    retry_count: int
    sources: list
    steps: list             # 执行轨迹(调试用)

注意 retrieved_docs 和 relevant_docs 是两个字段——检索结果和评估后的结果分开存。这样在调试时能清楚看到评估过滤了多少噪声。steps 记录每一步的执行轨迹,最终通过 API 返回,这是可观测性的关键。

4.3 设计决策 1:为什么要做文档评估?

问题:检索回来的 top-5 文档里,可能有 2-3 篇跟问题无关。这些噪声文档会稀释上下文,导致 LLM 生成质量下降。

方案:在检索和生成之间加一个 grade_documents 节点,让 LLM 一次调用批量判断每篇文档是否相关。

def grade_documents(state: RAGState) -> dict:
    question = state["question"]
    docs = state["retrieved_docs"]
    if not docs:
        return {"relevant_docs": [], "steps": [...]}

    llm = get_llm()
    # 把所有文档拼成一个列表,一次 LLM 调用搞定
    doc_list = "\n\n".join(f"[文档{i}]\n{doc.page_content}" for i, doc in enumerate(docs))
    grade_prompt = ChatPromptTemplate.from_template(
        "你是一个文档相关性评估专家。判断以下每篇文档是否与用户问题相关。\n"
        "请对每篇文档只回答 'yes' 或 'no',每行一个结果。\n\n"
        "用户问题:{question}\n\n文档列表:\n{documents}"
    )
    raw_result = (grade_prompt | llm | StrOutputParser()).invoke({...}).strip()

    # 解析结果(下面单独讲这个函数)
    grade_results = _parse_grade_result(raw_result, len(docs))
    relevant = [doc for doc, ok in zip(docs, grade_results) if ok]
    return {"relevant_docs": relevant, "steps": [...]}

为什么用批量评估而不是逐篇调用? 逐篇调用 5 篇文档就是 5 次 LLM 请求,延迟和成本都是 5 倍。批量评估只需 1 次调用。

评估完之后,通过条件路由决定下一步:

def route_after_grading(state: RAGState) -> str:
    if state.get("relevant_docs"):
        return "rerank"    # 有相关文档 → 继续流程
    return "fallback"      # 全部不相关 → 直接兜底

4.4 实战经验:永远不要假设 LLM 的输出格式是稳定的

上面的 _parse_grade_result 是个值得单独拿出来讲的函数。我们期望 LLM 输出整齐的 yes/no,但实际运行中会遇到各种格式:

# 理想情况
yes
no
yes

# 实际可能遇到的
[文档0] yes
1. no
yes, this document is relevant

所以解析函数需要做鲁棒性处理:

def _parse_grade_result(raw: str, num_docs: int) -> list[bool]:
    """解析 LLM 批量评估结果,兼容多种输出格式"""
    results = [True] * num_docs  # 默认保守保留

    lines = [line.strip() for line in raw.splitlines() if line.strip()]
    parsed_idx = 0

    for line in lines:
        if parsed_idx >= num_docs:
            break
        lower = line.lower()
        # 去掉常见前缀:[文档0]、1.、文档0:
        cleaned = re.sub(r"^(\[?文档\s*\d+\]?[:\s]*|\d+[.)\]:\s]+)", "", lower).strip()
        if cleaned.startswith("yes"):
            results[parsed_idx] = True
            parsed_idx += 1
        elif cleaned.startswith("no"):
            results[parsed_idx] = False
            parsed_idx += 1
        # 无法解析的行直接跳过,不推进 index

    return results

两个关键设计:

  • 默认值是 True(保留):LLM 少输出几行时,未评估的文档保守保留,宁可多保留噪声,也不误删相关文档
  • 兼容多种前缀格式:用正则去掉 [文档0]、1. 等前缀后再判断

这个经验适用于所有需要解析 LLM 结构化输出的场景:先定义好降级策略,再写解析逻辑。

4.5 设计决策 2:为什么要做幻觉检测?

问题:即使检索到了正确文档,LLM 也可能在回答中掺入编造的信息。

方案:生成回答后,再调一次 LLM 做事实核查。

def check_hallucination(state: RAGState) -> dict:
    answer = state["answer"]
    docs = state["relevant_docs"]
    llm = get_llm()

    doc_contents = "\n\n".join([doc.page_content for doc in docs])
    prompt = ChatPromptTemplate.from_template(
        "你是一个事实核查专家。请判断以下回答是否完全基于提供的参考文档。\n"
        "只回答 'yes'(有依据)或 'no'(存在编造)。\n\n"
        "参考文档:\n{documents}\n\n回答:\n{answer}"
    )
    result = (prompt | llm | StrOutputParser()).invoke({...}).strip().lower()
    passed = result.startswith("yes")
    retry_count = state.get("retry_count", 0)

    return {
        "hallucination_pass": passed,
        "retry_count": retry_count + (0 if passed else 1),
        "steps": [...],
    }

检测不通过怎么办?通过条件路由形成循环:

def route_after_hallucination(state: RAGState) -> str:
    if state.get("hallucination_pass", False):
        return "finish"        # 通过 → 返回结果
    if state.get("retry_count", 0) < 2:
        return "regenerate"    # 未通过且重试<2次 → 重新生成
    return "fallback"          # 多次失败 → 兜底回答

generate → check_hallucination → generate 形成循环,这是线性 Chain 做不到的。

为什么重试上限是 2 次? LLM 生成有随机性,同样的 context 可能生成不同的回答。2 次重试是在"给 LLM 纠错机会"和"避免无限循环"之间的平衡。实测下来,如果 2 次都不通过,大概率是文档本身信息不足,再试也没用。

4.6 设计决策 3:流式查询为什么要单独建一个图?

项目里有两个查询图:rag_graph(同步,带幻觉检测)和 stream_rag_graph(流式,不带幻觉检测)。

为什么流式要去掉幻觉检测?因为流式场景下,token 是逐个发送给客户端的。如果生成完毕后幻觉检测不通过,触发重试,用户会看到两段矛盾的输出——前半段是第一次生成的内容,后半段是重试后的内容,体验很差。

所以流式图的设计是:transform_query → retrieve → grade_documents → rerank → generate → END,直接输出,不做幻觉检测。这是一个可靠性 vs 体验的 trade-off:同步接口追求回答质量,流式接口追求响应体验。

4.7 其他节点

  • transform_query:支持三种模式。none 直接透传原始问题;rewrite 让 LLM 把口语化问题改写为更适合检索的查询(比如"RAG 咋回事" → “RAG 检索增强生成 技术原理”);hyde 让 LLM 先生成一个假设性回答,用这个回答的 embedding 去检索,比原始问题更接近目标文档
  • retrieve:支持三种检索模式。vector 纯向量检索(语义匹配),bm25 纯关键词检索(精确匹配),hybrid 混合检索——用 RRF(Reciprocal Rank Fusion)融合两者结果,公式是 score = 0.6/(60+rank_vector) + 0.4/(60+rank_bm25),向量权重略高因为语义匹配通常更重要
  • rerank:可选,调用硅基流动 BGE Reranker 做二次排序。Reranker 用 Cross-Encoder 对 query-document pair 精细打分,比 embedding 余弦相似度更准确。调用失败时自动降级使用原始排序,不中断流程
  • fallback:兜底回答,两种情况触发——无相关文档、幻觉检测多次失败

4.8 构建状态图

def build_rag_graph() -> StateGraph:
    graph = StateGraph(RAGState)

    # 注册节点
    graph.add_node("transform_query", transform_query)
    graph.add_node("retrieve", retrieve)
    graph.add_node("grade_documents", grade_documents)
    graph.add_node("rerank", rerank)
    graph.add_node("generate", generate)
    graph.add_node("check_hallucination", check_hallucination)
    graph.add_node("fallback", fallback)

    # 固定边
    graph.add_edge(START, "transform_query")
    graph.add_edge("transform_query", "retrieve")
    graph.add_edge("retrieve", "grade_documents")
    graph.add_edge("rerank", "generate")
    graph.add_edge("generate", "check_hallucination")
    graph.add_edge("fallback", END)

    # 条件边:文档评估后 → 有相关文档走 rerank,否则走 fallback
    graph.add_conditional_edges("grade_documents", route_after_grading,
        {"rerank": "rerank", "fallback": "fallback"})

    # 条件边:幻觉检测后 → 通过结束,未通过重试或兜底(含循环)
    graph.add_conditional_edges("check_hallucination", route_after_hallucination,
        {"finish": END, "regenerate": "generate", "fallback": "fallback"})

    return graph.compile()

编译后的图可以 .invoke(state) 执行,也可以 .get_graph().draw_mermaid() 导出 Mermaid 流程图(访问 /graph 端点即可看到)。


五、智能入库图:自动选策略 + 质量验证 + 降级重试

上一版入库时,切分策略是用户手动指定的(fixed / recursive / semantic)。但不同文档适合不同策略:

文档特征推荐策略原因
有标题、列表、代码块recursive按结构边界切分,保持语义完整
长段落、少标记semantic基于 embedding 相似度自动找切分点
纯文本流、无段落fixed没有明显边界,固定长度最稳定

手动选策略的问题是:你得先看一遍文档才知道它适合哪种策略,而且选错了也不知道。

5.1 入库图流程

START → load_document → analyze_document → split_document → validate_chunks
                                                                 ↓
                                                       ┌── 质量合格? ──┐
                                                       ↓ yes           ↓ no
                                                 store_document   fallback_strategy
                                                       ↓                ↓
                                                      END        split_document (重试)

5.2 文档分析:为什么不用 LLM?

入库是高频操作,每次都调 LLM 太贵也太慢。所以文档分析用纯规则启发式,零 LLM 调用,零延迟。

分析三个维度:

  • 结构化标记密度 = (标题数 + 列表数 + 代码块数 + 表格行数) / 千字符。密度高说明文档结构化程度高,适合 recursive
  • 段落平均长度 = 总长度 / 段落数。段落长说明内容连续,适合 semantic
  • 换行密度 = 换行数 / 千字符。换行少说明是纯文本流,适合 fixed

决策逻辑:

if structure_density > 3:
    strategy = "recursive"      # 高结构化 → 递归切分
    if code_block_count >= 3:
        chunk_size = 1024       # 代码块多,用大 chunk 保持完整性
elif structure_density < 1 and avg_para_len > 500:
    strategy = "semantic"       # 低结构化 + 长段落 → 语义切分
elif structure_density < 0.5 and newline_density < 5:
    strategy = "fixed"          # 纯文本流 → 固定切分
else:
    strategy = "recursive"      # 默认

5.3 切分质量验证

切分完不是直接入库,而是先过四个硬指标:

_MIN_CHUNKS = 1           # 至少切出 1 个块(空结果说明出了问题)
_MAX_EMPTY_RATIO = 0.1    # 空块(<10字符)占比不超过 10%
_MIN_AVG_LENGTH = 50      # 平均块长度不低于 50 字符(太碎了)
_MAX_AVG_LENGTH = 3000    # 平均块长度不超过 3000 字符(没切开)

任何一个不通过就触发降级,按 recursive → fixed → semantic 的顺序依次尝试,直到质量合格或所有策略都试过。

这又是一个 LangGraph 的循环:split → validate → fallback → split → validate → ...

5.4 实际效果对比

用项目自带的 docs/sample.md(一篇 RAG 技术介绍,有标题、列表、无代码块)测试:

策略chunk_size切出块数平均长度效果
fixed_2562566~220 字符切分过碎,一个知识点被拆成多块
fixed_5125123~400 字符基本可用,但在段落中间断开
recursive_5125124~350 字符按段落边界切分,语义完整
recursive_102410242~600 字符块太大,多个主题混在一起
semanticauto4~350 字符按语义相似度切分,效果好但依赖 Embedding

智能入库的分析结果:结构化标记密度高(5.2/千字) → 选择 recursive 策略 + 512 chunk size,一次通过质量验证。

你可以调用 /compare-chunks 接口上传自己的文档,看看不同策略的实际效果差异。


六、API 接口与实际效果

6.1 接口一览

接口方法说明
/uploadPOST上传文档并入库(手动指定策略)
/smart-uploadPOST智能上传(自动选策略 + 质量验证)
/queryPOSTRAG 查询(同步,含幻觉检测)
/query/streamPOST流式查询(SSE 逐 token 输出,无幻觉检测)
/graphGETRAG 查询图 Mermaid 可视化
/ingest-graphGET智能入库图 Mermaid 可视化
/compare-chunksPOST对比不同切分策略效果
/healthGET健康检查(LLM / Embedding / Chroma 状态)

6.2 查询效果示例

curl -X POST "http://localhost:8080/query" \
  -H "Content-Type: application/json" \
  -d '{"question": "RAG的核心流程是什么?", "retrieval_mode": "hybrid"}'

响应(重点看 graph_steps):

{
  "answer": "RAG 的核心流程包括两个阶段:索引阶段和查询阶段...",
  "sources": [
    {"text": "RAG(Retrieval-Augmented Generation)...", "source": "docs/sample.md"}
  ],
  "config": {
    "retrieval_mode": "hybrid",
    "query_transform": "none",
    "use_reranker": false,
    "top_k": 5
  },
  "graph_steps": [
    "query_passthrough",
    "retrieve(hybrid) → 5 docs",
    "grade_documents(batch) → 3/5 relevant",
    "rerank_skipped",
    "generate",
    "hallucination_check → pass"
  ]
}

通过 graph_steps 可以清楚看到:检索了 5 篇文档,评估后保留了 3 篇(过滤了 2 篇噪声),幻觉检测一次通过。这种可观测性在调试 RAG 效果时非常有用。

6.3 智能入库效果示例

curl -X POST "http://localhost:8080/smart-upload" -F "file=@docs/sample.md"
{
  "message": "智能入库完成:recursive 策略,15 个文本块",
  "filename": "sample.md",
  "strategy": "recursive",
  "chunk_size": 1024,
  "analysis": "结构化标记密度高(5.2/千字);含4个代码块,用大块保持完整性",
  "tried_strategies": ["recursive"],
  "graph_steps": [
    "load → 1 docs from sample.md",
    "analyze(rule) → recursive(size=1024): 结构化标记密度高...",
    "split(recursive, size=1024) → 15 chunks",
    "validate → PASS",
    "store → 15 chunks ingested"
  ]
}

一次通过,没有触发降级。如果换一篇纯文本流的文档,系统会自动选 fixed 策略。


七、成本考量

相比不做评估和检测的基础 RAG,本方案每次查询新增了 2 次 LLM 调用:

环节LLM 调用次数说明
Query 变换0 或 1 次none 模式不调用,rewrite/hyde 调用 1 次
文档评估1 次批量评估,不管几篇文档都是 1 次
生成回答1 次
幻觉检测1 次通过则结束,不通过最多重试 2 次

正常情况下一次查询 3 次 LLM 调用(评估 + 生成 + 幻觉检测)。用 DeepSeek(约 ¥1/百万 token),一次查询成本不到 ¥0.01。用 GPT-4o 就要注意控制了。

进一步优化的方向:

  • 文档评估改用小模型或本地模型,降低延迟和成本
  • 只在低置信度场景开启幻觉检测(比如检索分数低于阈值时才检测)

八、快速上手

# 1. 克隆项目
git clone https://github.com/daixueyun3377/RAG-demo.git
cd RAG-demo
git checkout dev-LangGraph

# 2. 安装依赖
pip install -r requirements.txt

# 3. 配置环境变量
cp .env.example .env
# 编辑 .env,填入 DeepSeek API Key 和硅基流动 API Key
# 硅基流动:https://cloud.siliconflow.cn 注册即送免费额度

# 4. 启动服务
uvicorn app.main:app --reload --port 8080

# 5. 试一试
# Swagger UI: http://localhost:8080/docs
# RAG 流程图: http://localhost:8080/graph
# 入库流程图: http://localhost:8080/ingest-graph

建议的体验顺序:

  1. 先访问 /graph 看流程图,对照本文理解每个节点
  2. 调用 /smart-upload 上传 docs/sample.md,观察自动选择的切分策略
  3. 调用 /query 问"RAG 有什么优势",重点看 graph_steps
  4. 对比 use_reranker: true/false 和不同 query_transform 的效果差异

九、对比:这次升级了什么?

能力基础 RAG(线性 Chain)LangGraph 版
执行流程线性管道,一条路走到黑状态图,条件分支 + 循环重试
文档质量控制检索到什么用什么LLM 批量评估相关性,过滤噪声
幻觉检测无生成后验证,不通过自动重试
失败处理直接报错兜底回答,优雅降级
入库策略手动指定规则分析 + 质量验证 + 降级重试
可观测性只有最终结果graph_steps 记录每一步执行轨迹
流式输出无SSE 逐 token 输出(专用精简图)

十、我的思考与后续计划

用了 LangGraph 之后,最大的感受是流程变得可控了。之前的线性 Chain,数据从头流到尾,中间出了问题只能在最终结果里发现。现在每个节点都有明确的输入输出,条件路由让系统能"做决策",循环重试让系统能"自我纠错"。

当然也有代价:代码复杂度上升了,调试时需要理解图的执行路径。graph_steps 和 Mermaid 可视化在一定程度上缓解了这个问题。

后续计划:

  • 多轮对话:在 State 里加入 chat_history,实现上下文记忆
  • 自适应检索:根据问题类型自动选择检索模式(简单问题用 BM25,复杂问题用 hybrid + reranker)
  • 评估体系:接入 RAGAS,量化每个节点的效果,用数据驱动优化

总结

从线性 Chain 到 LangGraph 状态图,核心变化是让 RAG 系统具备了决策和反馈能力:

  • 文档评估过滤噪声,让 LLM 只看相关内容
  • 幻觉检测验证回答,发现编造自动重试
  • 条件路由让系统能做决策,不再一条路走到黑
  • 智能入库自动选策略,质量不合格自动降级

如果你也在做 RAG,建议把项目跑起来,看看 graph_steps 的输出,比光看代码理解深刻得多。

📌 本文为个人学习笔记,如有错误欢迎指正。项目代码持续更新中,欢迎 Star ⭐

基于多模态智能体的交互式室内设计框架:LLM如何重塑人机协同设计 大语言模型(LLM)与智能体(Agent)技术正推动各行业智能化转型,其核心在于通过自然语言理解与任务规划能力,实现复杂流程的自动化与交互化。从概念上讲,LLM作为系统的“大脑”,负责意图理解、推理与调度;而智能体框架则通过ReAct等模式,将专业工具(如视觉分析、空间规划)封装为可调用的模块,实现从指令到执行的技术闭环。其技术价值在于大幅降低了专业工具的使用门槛,使非专业人士也能通过自然对话参与复杂设计过程。在应用场景上,这种“智能协同设计”范式尤其适用于高度依赖专业知识、个性化需求强烈的领域,如室内空间 阅读详情

相关推荐

Pandas入门教程(二十二):股票数据分析实战——yfinance 获取数据、技术指标与收益率分析

把 Pandas 用在真实场景,才能体会它的价值。本文以茅台股票为例,用 yfinance 获取历史行情,完成缺失值处理与列筛选,绘制收盘价曲线,计算 SMA 移动平均线与 RSI 相对强弱指数,并通过日收益率、累计收益率和波动率完成完整的量化分析流程。

Smell_of_earth的博客 332

AI Agent核心架构与工作流详解:从任务理解到工具调用的完整闭环

在人工智能领域,智能体(Agent)是实现任务自动化和复杂问题求解的关键技术。其核心原理在于模拟人类的“感知-思考-行动”循环,通过大语言模型(LLM)作为认知中枢,将模糊的用户指令转化为可执行的结构化任务。这一过程的技术价值在于,它使AI系统能够自主规划、调用外部工具并处理动态环境,从而完成从信息处理到实际操作的跃迁。典型的应用场景包括智能客服、自动化办公、个性化推荐等。本文以“订机票”为例,深入剖析了Agent内部的任务理解、动态规划、工具调用与状态管理机制,并探讨了如何通过提示工程和记忆系统设计来应对

a359798678的博客 358

如何处理动态语言(Python / JS)的“隐形”调用链?

本文揭示动态语言(Python/JS)中静态AST解析导致调用链“断链”的核心问题,提出通过运行时追踪补全图谱的解决方案。基于Code-Graph-RAG的cgr trace机制,分别利用pytest插件与V8 Profiler捕获真实调用路径,将动态边合并至静态图谱,并在权重体系中提升动态边优先级。实践表明,该方法可显著提升图谱覆盖率,实现“结构+行为”双视角理解代码,为MCP与Rerank系统提供可靠支持。

xianyinsuifeng的博客 412

AI全栈实战 | 3.9-01 爬虫入门:requests 加 BeautifulSoup 三分钟跑通,但 90% 的人栽在这 4 个“礼貌“问题上

⚠️:本文内容仅用于。请遵守目标站点的服务条款与相关法律法规,不得对目标服务造成负担,不得采集、传播个人隐私数据。技术是中性的,边界在你手里。爬虫的入门技术(requests 发请求 + BeautifulSoup 解析)三分钟就能学会。真正区分"会用爬虫"和"会做爬虫的人"的,是这篇我们跑通"请求→解析→存储"的最小闭环,然后重点把"合规与礼貌"这根弦给你绷上。

源码获取 | 运行部署 | 定制二开修改,如果回复不及时请耐心等待,请见谅。 411

中国高质量夜间灯光数据

中国高质量夜间灯光数据是CnOpenData与吉林高分遥感应用研究院有限公司合作的数据库 ,基于多源夜间灯光卫星遥感影像,经过科学手段对数据进行降噪、修正、分析统计,以年度、月度为更新频率,以省市县三级行政区划作为统计单元,制作高质量夜间灯光数据。

Sunny9qx的博客 3311

lenovo联想拯救者Legion Y9000P 2022款2023款2024款笔记本电脑(82RF,82WK,82WQ,83DE,83DF)原装出厂Windows11预装OEM系统镜像下载

联想原装出厂系统自带所有驱动、出厂主题壁纸、系统属性联机支持标志、系统属性专属LOGO标志、Office办公软件、联想电脑管家、联想浏览器、联想软件商店、legionzone控制中心等预装程序。链接:https://pan.baidu.com/s/1YBji_oh7xOkq-NxnS8Mm8g?链接:https://pan.baidu.com/s/1S7_enXmuoja1a9ASvUT5Fg?拯救者Legion Y9000P IRX9H 2024款【83DE】原厂Win11系统包。

QQ17855069的博客 6523

从一段视频到可漫游的 4D 有声场景:思路拆解与最小复现手记

只需一段手机视频,你就能生成可"走进去"的 4D 有声场景:转头时狗叫声方向随之变化,走近时声音更清晰。本文拆解 Video-to-4DAVScene 的核心思路,手把手带你用几十行 Python 搭出最小管线,把视频中的运动物体变成带空间位置的声源,并附上三个真实踩坑的排障经验,代码可直接跑。🎧

helloagent的博客 235

Aduino 通过I2C接口读取MPU6050模块数据

Aduino ESP9266通过I2C接口读取MPU6050模块数据 MPU6050模块 原理图 所需库:Adafruit_MPU6050 Adafruit_BusIO Adafruit Unified Sensor 接线示意图 ESP8266---MPU6050 VCC -- 3.3v GND -- GND D2 -- SDA D1 -- SCL 示例程序代码 #include <Adafruit_MPU6050.h> #include <Adafruit

perseverance51博客 621

【每天一个 Python 小案例30】Python 基础知识综合小项目:我的工具盒

作为系列收官,本篇把前 29 篇的知识点合成一个能直接用的命令行工具"我的工具盒":计算器(用 ast 解析表达式,不碰 eval)、单位换算与温度转换(一张换算表 + 特例分支)、记账与分类统计(Decimal + JSON 持久化)、以及用"字典当命令表"把菜单和业务逻辑解耦的主循环。文中对比了 eval 的安全隐患与 ast 白名单的做法,解释了 lambda 闭包在字典里的写法与晚绑定陷阱,并在最后给出整个系列的知识地图,把变量、数据结构、控制流、函数、类、异常、文件、标准库八块内容对应到具体篇目。

xinjiyaya的博客 427

基于多智能体强化学习的轨道追逃博弈方法复现

本文提出了一种基于多智能体深度强化学习(MADDPG)的空间轨道追逃博弈方法。通过构建Actor-Critic网络架构,采用集中训练分布式执行的策略,使卫星群能够自主协调完成对非合作目标的围捕任务。代码实现了经验回放缓冲区、噪声探索机制和网络参数更新等核心功能,通过奖励函数设计平衡最短时间、燃料消耗和碰撞规避等目标。仿真结果表明该方法能有效利用数量优势,涌现出智能协同行为,为解决复杂空间博弈问题提供了新思路。

huanghm88的专栏 337

4 屏 + 8 摄像头一开,谁在悄悄拖慢你的座舱域控?

如果你觉得座舱卡顿:❌ 别第一反应怪 SoC❌ 别盲目堆算力。

weixin_43199439的博客 148

详解Python条件语句

在 Python 中,if...else 是一种条件语句,可以根据给定的条件执行不同的操作。这个语句通常用于控制程序的流程。

2601_96798737的博客 208

OpenCV自学记录(1)——(一拳超人)图像处理基础(图像获取、图像变化)

学习深度学习进行图像分类和目标检测时,要有一定的图像处理的基础。在学习深度学习之前,看了一本《图像处理技术基础》,现在也忘得差不多了,后悔当初没有整理记录下来。现在整理一下图像处理的常用方法,最后实现一个小项目——基于OpenCV的车牌号识别。 OpenCV自学记录(1)——图像处理基础(一)1、图像获取1.1获取图像数据1.2 获取摄像头图像数据2、图像变化2.1 移动(translation)...

qq_40784418的博客 1455

Python3 协程:异步编程的核心机制与实战

协程是解决I/O密集型任务等待瓶颈的高效机制,相比线程更轻量、无锁开销。从yield到async/await的演进,使异步编程语义清晰、易于理解。通过async/await可实现并发执行多个任务(如gather、create_task),显著提升网络请求、爬虫等场景性能。关键在于使用异步库(如aiohttp)替代同步库,避免阻塞事件循环。合理控制超时与并发数,才能发挥协程最大优势。

Lxn2zh的博客 159

5 分钟上手 Kimi Work:安装、配置、跑通第一个任务

这篇文章提供了Kimi Work的快速入门指南,帮助用户在5分钟内完成从安装到运行第一个任务的全过程。主要内容包括: 安装步骤: macOS用户下载.dmg文件并拖入Applications Windows用户下载.exe安装包,需注意中文路径问题 初始设置: 使用现有Kimi账号登录 检查任务配额和文件访问权限 首个任务推荐: 建议从简单的本地文件整理开始(如按类型分类桌面文件) 详细说明了任务执行流程和审批机制 常见问题: 计划生成卡顿的解决方法 文件无变化的排查步骤 进阶建议: 提供难度递增的后续任务

sg_knight的专栏 2785

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

二进制木马免杀-Python 分离免杀与 Web 挂马

二进制木马免杀-Python 分离免杀与 Web 挂马

2503_94637398的博客 268

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

torch.compile 差异仅 1e-6,边界样本预测为何翻转

torch.compile 加速后输出与 eager 不一致,部分预测翻转。逐层对比与 graph break 分析定位到动态分支翻转根因。容差回归仅适用于无分支翻转场景,零容忍场景应禁用编译。

昨日种种,皆成今我。今日种种,皆成新我。 159

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

蓝桥杯·全国青少年信息素养大赛·电子学会Python/C++考级 备考:莫队算法离线区间查询详解

备赛进行时:第十八届蓝桥杯软件赛报名已于 2026-10-08 10:00 开启、12-18 14:00 截止,省赛定在 2027-04-10(C/C++·Python 程序设计 9:00–13:00);中国电子学会 2026 年 12 月软件编程(C/C++ 一级至十级、Python 一级至六级)考级报名 9/23–12/2 16:00、统考 12-12;全国青少年信息素养大赛 2026—2027 赛季算法应用主题赛也已进入复盘练兵窗口。

IT_Scratch的博客 143

【Python】国家中小学智慧教育平台电子教材批量下载与 PDF 合成实战

成果:两本语文电子课本(一年级上册 118 页 / 23MB、三年级上册 130 页 / 30.3MB),合计 248 页、约 54MB,单本下载加合成 40~60 秒,PDF 页数校验全部通过。经验教训SPA 站点的数据接口优先从 bundle 里挖,比抓页面稳得多;资源链接要按 private/public 分组看待,只取平台公开部分;页数、目录名这类“可推断”的信息,永远用实际响应验证一次;受限环境里“能不能跑浏览器”要在方案定稿前确认。后续计划:这版 PDF 是图片版,没有文字层;

木头大左的博客 139

魔塔社区微调训练Qwen2-1.5B-Instruct模型并烧录到‌RK3568开发板教程

本文基于Ubuntu 22.04 + CUDA 13.0.3环境,使用LLaMA-Factory框架对Qwen2-1.5B-Instruct模型进行LoRA微调,训练儿童故事生成专用模型。通过配置qwen模板、制作alpaca格式数据集、执行sft训练并合并LoRA权重,最终将模型转换为GGUF格式,并量化为Q4_K_M以适配RK3568嵌入式平台。全程支持国产镜像加速下载与显存优化,实现高效轻量化部署。

浅清秋慕夏的博客 187

【回眸】DeepSeek V4.1 Flash 快速上手与实战

本文介绍如何高效本地部署开源大模型,通过现代化工具链实现分钟级环境搭建。聚焦显存优化、一键安装、代码调用与多轮对话实现,解决“显存不足”“连接超时”等痛点,提供参数调优与结构化输出技巧,助力开发者在离线场景下快速构建稳定、高效的本地推理系统。

啤酒鸭的物联网开发记录博客 224

智叟云集-手机证据抓取系统的工程结构与应用入口

本文系统阐述手机证据抓取系统的工程结构与应用入口,涵盖四大层面:工程目录划分(Android、Python服务、Web页面、测试与构建工具);Android组件通过Manifest声明可启动页面,主界面由MainActivity管理;Python服务通过run.py解析参数并启动FastAPI应用,支持远程访问;浏览器页面采用HTML/CSS/JS分离架构,静态资源通过路径关联,实现动态交互。各模块分工明确,协同构建可运行的采集系统。

2301_77178996的博客 233

Java Arrays.asList 常见坑详解|UnsupportedOperationException、数组联动、基本类型 bug

解析 Arrays.asList 常见开发陷阱,演示 UnsupportedOperationException、底层数组引用共享、基本类型数组问题,区分 Arrays 内部 ArrayList 与 java.util.ArrayList,给出数组转 List 的各种场景正确代码。

weixin_42617033的博客 473

利用python中matplotlib.pyplot库绘制图

plt.plot(x,y) # x,y是每个点的坐标,plot()把每个点按顺序画折线。plt.subplots(2,2)表示绘制2*2的子图布局,axs[0,0]表示在第0行第0列绘制子图...coordinates_i[:,0]表示获取每一行(每一个spot)的第0列(x坐标)coordinates_i[:,1]表示获取每一行(每一个spot)的第0列(y坐标)plot.subplot(2,2,1) 表示子图布局是2*2的,开始绘制第一个。也可以导入数据绘制。可以设置color属性,设置颜色。

qq_46147236的博客 102

Spring Boot 自动配置原理

Spring Boot 自动配置由 @EnableAutoConfiguration 导入选择器,读取 jar 中 .imports 候选清单,经去重、排序、排除后逐类做条件判断,通过才注册 Bean。延迟导入让用户 Bean 优先,@ConditionalOnMissingBean 使默认配置让位。失效时查清单和 Negative matches。

2401_89855466的博客 378
上一篇: 2.从 LangChain 到 LangGraph:我在 RAG 入库流程上的三次设计迭代(纯个人思考,轻喷
下一篇: 4.给 RAG 系统装上“黑匣子“:LangGraph + Langfuse 全链路可观测性实战
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值