Tool Calling Patterns: ReAct 与其它工具调用方式

其他意图识别与工具调用方式 除了传统的 Slot Filling 和现代的 Function Calling,AI Agent 还有多种实现意图识别和工具调用的方式,各有特点和适用场景。 1. ReAct(Reasoning + Acting) ReAct 是一种让 LLM 交替进行推理(Reasoning)和行动(Acting)的方法,通过思维链(Chain of Thought)引导 LLM 一步步分析问题并选择工具。 工作原理 用户输入 → LLM 推理(Thought) → 决定行动(Action) → 执行工具 → 观察结果(Observation) → 继续推理 → ... 实现示例 react_prompt_template = """ 你是一个智能助手,可以使用以下工具: 1. search(query): 搜索信息 2. calculate(expression): 计算数学表达式 3. get_weather(city): 查询天气 请按以下格式回答: Thought: [你的思考过程] Action: [工具名称] Action Input: [工具参数] Observation: [工具返回的结果] ... (重复 Thought/Action/Observation 直到得出答案) Answer: [最终答案] 问题:{question} """ # 用户问题:"北京明天的天气适合户外活动吗?" # LLM 输出: """ Thought: 我需要先查询北京明天的天气 Action: get_weather Action Input: {"city": "北京", "date": "明天"} Observation: 明天北京天气:晴,温度 22°C,微风 Thought: 根据天气信息,晴天、温度适中、微风,非常适合户外活动 Answer: 根据天气预报,北京明天天气晴朗,温度 22°C,微风,非常适合户外活动。 """ 优势 可解释性强:每一步推理过程都清晰可见 灵活性高:LLM 可以动态调整策略 支持复杂任务:可以进行多步推理和工具调用 劣势 Token 消耗大:每次推理都需要完整的对话历史 速度较慢:需要多次 LLM 调用 格式依赖:依赖 LLM 严格遵循输出格式 2. Prompt-based Tool Selection(基于提示的工具选择) 通过精心设计的 Prompt 让 LLM 直接输出工具调用的 JSON 或结构化文本。 ...

Created 26266-04-26 · Updated 23236-07-23 · 6 min · 1195 words · -

React 入门

React 是由 Meta(前 Facebook)开发并开源的 JavaScript UI 库,专注于构建用户界面。它于 2013 年开源,目前已成为最流行的前端技术之一。 react 核心概念 组件(Component) React 的核心单元是组件(Component)。组件是一个返回 UI 描述的函数(或类),可以像拼积木一样组合成复杂的界面。 function Greeting({ name }) { return <h1>Hello, {name}!</h1>; } 组件分为两类: 函数组件:现代 React 的主流写法,配合 Hooks 使用 类组件:早期写法,新项目不推荐使用 JSX JSX 是 JavaScript 的语法扩展,允许在 JS 文件中写类似 HTML 的结构。它不是 HTML,会被编译工具(如 Babel、SWC)编译为 React.createElement() 调用。 const element = <div className="container">Hello</div>; // 编译后等价于: const element = React.createElement("div", { className: "container" }, "Hello"); 详见:JSX 介绍 Props Props(属性)是组件的输入,由父组件传入,在子组件内部是只读的。 function Button({ label, onClick }) { return <button onClick={onClick}>{label}</button>; } // 使用 <Button label="提交" onClick={() => console.log("clicked")} /> State State(状态)是组件内部管理的可变数据。状态变化会触发组件重新渲染。 import { useState } from "react"; function Counter() { const [count, setCount] = useState(0); return ( <div> <p>当前计数:{count}</p> <button onClick={() => setCount(count + 1)}>+1</button> </div> ); } 虚拟 DOM React 在内存中维护一棵虚拟 DOM 树。每次状态更新时,React 通过 Diffing 算法对比新旧虚拟 DOM,计算出最小变更集,再批量更新真实 DOM,从而提升性能。 ...

Created 17176-05-17 · Updated 16166-06-16 · 2 min · 353 words · -

React 状态管理:Zustand、Jotai 与 Redux 对比

什么是状态管理,它解决什么问题 React 的数据流是单向的:数据通过 Props 从父组件流向子组件。这在小型应用中很好用,但随着应用规模扩大,会遇到两个典型痛点: Prop Drilling(属性透传) 同一份数据需要从顶层组件一层一层往下传,中间层组件本身并不使用这个数据,却不得不接收并转发它。组件层级越深,代码越难维护。 App(持有 user 状态) └─ Layout └─ Sidebar └─ UserAvatar(需要 user)← 要传三层 props 跨组件状态同步困难 当两个没有父子关系的组件需要访问同一份数据时,只能把状态提升到它们共同的祖先组件,然后再层层传下去。状态越分散,同步越容易出 bug。 状态管理库的解法 把共享状态提取到组件树之外的独立 Store,任何组件都可以直接订阅和修改,不需要层层传递 Props。 Store(独立于组件树) ↗ ↗ ComponentA ComponentB React 主流状态管理方案对比 库 定位 包大小 学习曲线 Zustand 轻量、直觉式 API ~1 KB 低 Jotai 原子化状态,细粒度订阅 ~3 KB 低 Redux Toolkit 功能完整,适合大型项目 ~20 KB 高 Zustand Zustand 是目前最流行的轻量状态管理库,API 极简,和 Vue 的 Pinia 非常相似。 创建 Store: ...

Created 18186-05-18 · Updated 18186-05-18 · 4 min · 685 words · -

React 函数组件与类组件

React 有两种组件写法:函数组件(Function Component) 和 类组件(Class Component)。现代 React 项目几乎全面使用函数组件,类组件属于历史遗留写法。 函数组件 函数组件就是一个普通的 JavaScript 函数,接收 Props,返回 JSX。 function Greeting({ name }) { return <h1>Hello, {name}!</h1>; } // 也可以用箭头函数 const Greeting = ({ name }) => <h1>Hello, {name}!</h1>; React 16.8 引入 Hooks 之后,函数组件可以使用状态和生命周期,成为主流写法。 类组件 类组件通过继承 React.Component 实现,必须定义 render() 方法返回 JSX。 import { Component } from "react"; class Greeting extends Component { render() { return <h1>Hello, {this.props.name}!</h1>; } } 有状态的类组件: class Counter extends Component { constructor(props) { super(props); this.state = { count: 0 }; } render() { return ( <div> <p>计数:{this.state.count}</p> <button onClick={() => this.setState({ count: this.state.count + 1 })}> +1 </button> </div> ); } } 同一功能的对比 以一个带状态的计数器为例,对比两种写法的差异: 类组件写法: class Counter extends Component { constructor(props) { super(props); this.state = { count: 0 }; this.handleClick = this.handleClick.bind(this); // 必须手动绑定 this } componentDidMount() { document.title = `计数:${this.state.count}`; } componentDidUpdate() { document.title = `计数:${this.state.count}`; } componentWillUnmount() { document.title = "App"; } handleClick() { this.setState({ count: this.state.count + 1 }); } render() { return ( <button onClick={this.handleClick}> 计数:{this.state.count} </button> ); } } 函数组件写法: ...

Created 17176-05-17 · Updated 17176-05-17 · 3 min · 481 words · -

React Hooks 详解

Hook 是 React 16.8 引入的一类特殊函数,命名以 use 开头。它让函数组件拥有了原本只有类组件才有的能力:状态管理、生命周期、跨组件共享逻辑。 为什么需要 Hook React 16.8 之前,函数组件只能做纯渲染,没有状态、没有生命周期。要用这些功能必须写类组件,但类组件存在几个痛点: this 绑定容易出错 生命周期方法(componentDidMount / componentDidUpdate)把不相关的逻辑强行塞在一起 状态逻辑难以在组件之间复用 Hook 彻底解决了这些问题,现代 React 项目基本全面使用函数组件 + Hook。 Hook 使用规则 这两条规则必须严格遵守,否则会导致 Bug。 只在函数组件或自定义 Hook 的顶层调用 Hook,不能在条件语句、循环、嵌套函数中调用 只在 React 函数中调用 Hook,不能在普通 JS 函数中调用 // ❌ 错误:在条件语句中调用 if (condition) { const [value, setValue] = useState(0); } // ✅ 正确:在顶层调用 const [value, setValue] = useState(0); if (condition) { setValue(1); } 内置 Hook useState 管理组件的局部状态。 const [state, setState] = useState(initialValue); state:当前状态值 setState:更新状态的函数,调用后触发重渲染 initialValue:初始值,也可以传入一个函数(懒初始化) import { useState } from "react"; function Counter() { const [count, setCount] = useState(0); return ( <div> <p>计数:{count}</p> <button onClick={() => setCount(count + 1)}>+1</button> <button onClick={() => setCount(prev => prev - 1)}>-1</button> </div> ); } 函数式更新:当新状态依赖上一个状态时,推荐传函数给 setState,避免闭包陷阱: ...

Created 17176-05-17 · Updated 17176-05-17 · 4 min · 675 words · -

JSX 是什么

JSX 解决了什么问题 在 JSX 出现之前,用 JavaScript 描述 UI 结构需要这样写: const el = React.createElement( 'div', { className: 'card' }, React.createElement('h2', null, title), React.createElement('p', null, content), React.createElement('button', { onClick: handleClick }, '确认') ); 嵌套稍深就几乎无法阅读。而人类天然擅长读 HTML 这种树形标签结构。 JSX 解决的核心问题是:让 UI 结构可视化,让开发者用熟悉的标签思维描述界面,同时保留 JavaScript 的全部表达能力。 // JSX 版本,结构一目了然 const el = ( <div className="card"> <h2>{title}</h2> <p>{content}</p> <button onClick={handleClick}>确认</button> </div> ); JSX 是什么 JSX(JavaScript XML)是一种 JavaScript 的语法扩展,允许在 JS 代码里直接写类似 HTML 的标签。 它既不是真正的 HTML,也不是模板引擎,而是 React.createElement() 的语法糖。浏览器不认识 JSX,需要由 Babel 等编译工具在构建阶段将其转换为普通 JavaScript。 // 你写的 JSX const element = <h1 className="title">Hello, {name}</h1>; // Babel 编译后(React 17 之前) const element = React.createElement( 'h1', { className: 'title' }, 'Hello, ', name ); // Babel 编译后(React 17+ 新 JSX Transform) import { jsx as _jsx } from 'react/jsx-runtime'; const element = _jsx('h1', { className: 'title', children: ['Hello, ', name] }); React 17 之后引入了新的 JSX Transform,编译器自动引入 react/jsx-runtime,不再需要在每个文件顶部写 import React from 'react'。 ...

Created 17176-05-17 · Updated 17176-05-17 · 3 min · 597 words · -

React 虚拟 DOM 与 Diff 算法

什么是虚拟 DOM 虚拟 DOM(Virtual DOM)是用 JavaScript 对象来描述真实 DOM 结构的一棵树,存在于内存中,是真实 DOM 的轻量级副本。 内存中的实际结构 React Element 虚拟 DOM 节点是一个普通的 JavaScript 对象(Plain Object),React 内部称它为 React Element,由 React.createElement() 创建。 // 你写的 JSX const el = <div className="box"><h1>Hello</h1></div> // Babel 编译后实际执行的 const el = React.createElement( 'div', { className: 'box' }, React.createElement('h1', null, 'Hello') ) // 返回的对象结构 { $$typeof: Symbol(react.element), // 防 XSS 的安全标记 type: 'div', key: null, ref: null, props: { className: 'box', children: { $$typeof: Symbol(react.element), type: 'h1', key: null, ref: null, props: { children: 'Hello' }, _owner: null, } }, _owner: null, } 树状结构靠 props.children 的引用嵌套形成,多个子节点时 children 是一个数组: div (React Element) └── props.children: [ h1 (React Element) └── props.children: "Hello" p (React Element) └── props.children: "World" ] React Element 只是"描述长什么样"的不可变快照,每次渲染都会重新创建,不会长期驻留内存。 ...

Created 17176-05-17 · Updated 17176-05-17 · 2 min · 401 words · -