前言
随着AI应用的不断发展,搜索的习惯正在被重构。
到目前为止,回过头来看,搜索经历的三个阶段:
- 传统搜索,把知识或者内容摆在你面前,然后进行筛选、归纳、综合。
- Rag的兴起,获取、总结变得高效,你只需要关注最终结果。
- deepsearch,目前年龄尚短,但提供了更新的泛式,我们已经被教育可以等待,只要你告诉我你还在干活(不是仅仅转圈圈),它提供了一种 agentic 的方式,供给的内容也就更有深度。
deep 流为什么会是未来的泛式
继大模型爆火以来,对传统 AI 搜索的重构就没有停止过,从Perplexity AI 作为最早一批 基于大模型的AI 搜索作为定义者正式上线,Perplexity AI可视为首个成功将大模型与搜索引擎融合并规模商用的产品, 到2023年8月23日推出国内首款AI搜索产品“天工AI搜索”, 到后来 AI 搜索或者联网搜索成为各类 AI 产品的标配,再到2024 年底 2025 年初的时候目前大量的玩家(包括传统搜索引擎提供商)都已跻身 deep search 领域。
deepsearch 究竟有什么重大的突破?事实上我理解,deepsearch 并没有比 RAG 有太多高明的地方。我更愿意称它为 agentic search,deep 只是它的目标。之所以会火我想大概是因为它确实够深,另外一点就是之前提到过的用户也已经被教育需要更长的等待,也就是归根到底还是综合体验变好(等待时间变长其实我理解是用户对思考过程的信任,认知上的感受已经是它真的在思考而不是胡乱魔怔,这其实也是一种增强体验)。
既然 deepsearch 的本质还是 agentic search,那它的核心流程依然可以用下面这张图概括。
这张图核心描述的是 LLM 与外界交互实时获取需要的知识或者认知,来不断细化拆解问题,最终解决它的过程。特定于 deepsearch 来说,我们需要定义一个不断循环的迭代,迭代中的每一步都会使用 LLM 来指导我们下一步的动作,然后我们会根据 LLM 的指示做出对应的操作来完善上下文,然后继续交给 LLM做出下一步规划,如此循环不断重复,直到 LLM 告我我们可以结束了或者达到了我们承受的极限(比如 token 过多,步数过多,即价格成本和时间成本超过我们的承受能力),我们就停止。它可以表示成下面的伪代码:
while (step <= max_step_num or token <= max_token_num):
reasoning and planing;
decide next step;
tool use or reflect or answer;
从 以上deepsearch 原理的分析,不难看出,deepsearch 整个的控制中心已经完全不需要人类的参与,我们只需要告诉它我们需要什么(回答我的 query),即目标就可以了。最终它会按照目标推演它要做的事情,对于 deepsearch,这可能是问题拆解、不断深入(可能是多跳问题、TOT拆解或者COT拆解)、数据搜索、提取调用,然后他会把搜索提取到的内容不断补充整合到他的上下文中,并记录整个迭代的过程(为什么、怎么做、结果)最终给我们一个完善、精细的回答。
从中我们能发现,在这个 LLM 爆炸的时代,这种泛式对于人类来说是一种极简的美学泛式。这可能正是 AGI 实现的关键一步,这种泛式的好处是越来越不需要人类的参与,但我们确能更好的获取。这就是我们所说为什么 agentic search 才是未来搜索的新泛式。
如何实现一个agentic search
以上我们已经大致了解了agentic search 的核心,即一个不断循环规划的迭代。这里我们选用 llmack 这个框架进行实现,当然本文也会尽可能详细解释框架本身是如何运转 agentic search 的。
settings := engine.DefaultSettings()
settings.LLMModel.Provider = openaic.Name
settings.LLMModel.Name = "hunyuan-large"
settings.Agent.Mode = "ReAct"
settings.Tools = append(settings.Tools, search.Serper)
eng := engine.NewAgentEngine(settings, engine.WithLogger(&log.WrapLogger{}))
esm := eng.Execute(context.Background(), engine.Input{
Query: "运行时计算的过程是怎样的?",
})
finalAnswer := ""
for evt := esm.Next(); evt != nil; evt = esm.Next() {
if evt.Error != nil {
panic(evt.Error)
}
if cv, ok := evt.Data.(*llm.Chunk); ok {
finalAnswer += cv.Delta.Message.Content()
}
}
fmt.Println(finalAnswer)
这段代码定义了 agentic search 执行的入口,它定义了一个AgentEngine,并初始化相关的配置。(这里我们没有使用像 R1 这种原生推理的模型,而是使用了基于 ReAct 模式的模型,其实都是一样的, llmack 框架本身也非常容易切换为其它模型。)这段代码最终会以流式的方式接收到 LLM 的回复,我们会把最终结果打印出来。需要注意的是第 5 行代码,我们给于它一个search.Serper的工具,这个工具可以帮助它搜索相关词条并爬取网页详细内容。
下面我们来仔细分析 AgentEngine 是如何通过简单的配置运转以达成一个 agentic search 的目标。核心代码如下所示:
thoughts := []map[string]any{}
for range MaxIterationNum {
result, err := rp.planning(ctx, inputs, thoughts) // 推导下一步动作
if err != nil {
continue
}
value.stream <- result.Thoughts.Speak
if result.Tool != nil {
if result.Tool.Name == "finish" {
thoughts = append(thoughts, map[string]any{
"thought": result.Thoughts.Text,
"tool_name": result.Tool.Name,
"tool_args": result.Tool.Args,
"tool_result": "finished",
})
break
} else {
// TODO check function name valid?
toolResult, err := tool.Spawn(result.Tool.Name).Invoke(ctx, result.Tool.Args)
log.InfoContextf(ctx, "react agent invoke tool: %s, %v response: %s error: %v \n", result.Tool.Name, result.Tool.Args, toolResult, err)
if err != nil {
continue
}
thoughts = append(thoughts, map[string]any{
"thought": result.Thoughts,
"tool_name": result.Tool.Name,
"tool_args": result.Tool.Args,
"tool_result": toolResult,
})
}
}
}
这里的关键细节即第 3 行,会调用 LLM 实现规划,决策下一步动作。然后由我们的硬代码进行逻辑操作,对程序做出状态迁移。
决策提示词:
You are an AI assistant to solve complex problems. Your decisions must always be made independently without seeking user assistance. Play to your strengths as an LLM and pursue simple strategies with no legal complications.
If you have completed all your tasks or reached end state, make sure to use the "finish" tool. Respond to the human as helpfully and accurately as possible.
{{instruction}}
You have access to the following tools:
{{tools}}
PERFORMANCE EVALUATION:
- Continuously review and analyze your actions to ensure you are performing to the best of your abilities.
- Use instruction to decide the flow of execution and decide the next steps for achieving the task.
- Constructively self-criticize your big-picture behavior constantly.
- Reflect on past decisions and strategies to refine your approach.
- Every tool has a cost, so be smart and efficient.
You have context following:
{{thoughts}}
Respond with only valid JSON conforming to the following schema: {
"$schema": "json-schema.org/draft-07/sc…",
"type": "object",
"properties": {
"thoughts": {
"type": "object",
"properties": {
"text": {
"type": "string",
"description": "thought"
},
"reasoning": {
"type": "string",
"description": "short reasoning"
},
"plan": {
"type": "string",
"description": "- short bulleted\n - list that conveys\n - long-term plan"
},
"criticism": {
"type": "string",
"description": "constructive self-criticism"
},
"speak": {
"type": "string",
"description": "thoughts summary to say to user"
}
},
"required": ["text", "reasoning", "plan", "criticism", "speak"],
"additionalProperties": false
},
"tool": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "tool name"
},
"args": {
"type": "object",
"description": "tool arguments"
}
},
"required": ["name", "args"],
"additionalProperties": false
}
},
"required": ["thoughts", "tool"],
"additionalProperties": false
}
以上实现过程尚未完全完善,后续我会不断完善,并进行后续详细分析讲解,谢谢大家。