首页 > 教程攻略 > ai资讯 >Atoms多模型同时调用同步异步切换方式

Atoms多模型同时调用同步异步切换方式

来源:互联网 时间:2026-08-25 13:26:11

通过Jotai原子组合实现多模型切换与同步/异步模式一键切换:modelSelectorAtom调度三模型配置,activeModelCallAtom动态路由,syncResponseAtom提供同步模板填充,executeModelCallAtom触发异步流式请求,displayResponseAtom根据modeAtom自动适配渲染模式。

Atoms多模型同时调用同步异步切换方式

你需要在同一个 React 组件中,让多个 Jotai 原子分别触发不同模型(如 OpenAI、Claude、本地 Ollama)的调用,并能随时在同步渲染(如预设 prompt 模板填充)和异步请求(如 real-time streaming)之间切换。

创建可切换行为的原子组

先定义一个基础原子存储当前选中的模型标识符,它将作为后续所有派生原子的调度开关:

const modelSelectorAtom = atom('openai');

再创建三个独立原子,每个对应一个模型的调用逻辑。注意:它们不直接执行请求,只封装调用意图与参数结构——真正的执行由消费端决定。

const openaiCallAtom = atom((get) => ({ model: 'gpt-4o', messages: get(chatHistoryAtom) }));

const claudeCallAtom = atom((get) => ({ model: 'claude-3-haiku-20240307', messages: get(chatHistoryAtom), max_tokens: 512 }));

const ollamaCallAtom = atom((get) => ({ model: 'llama3.2', messages: get(chatHistoryAtom), options: { temperature: 0.7 } }));

按模型标识动态路由到对应原子

使用一个只读派生原子,根据 modelSelectorAtom 的值返回对应模型的调用配置:

const activeModelCallAtom = atom((get) => {
 const selector = get(modelSelectorAtom);
 switch (selector) {
  case 'openai': return get(openaiCallAtom);
  case 'claude': return get(claudeCallAtom);
  case 'ollama': return get(ollamaCallAtom);
  default: return get(openaiCallAtom);
 }
});

这个原子本身不触发网络请求,只是做配置组装。它确保下游无论何时读取,拿到的都是当前选中模型的最新参数快照。

同步模式:用 atomWithDefault 预填充响应

方法一:为每个模型准备一个“模拟响应原子”,用于开发调试或离线 fallback:

const mockOpenaiResponseAtom = atomWithDefault(() => '我已收到您的消息,正在思考中...');

方法二:构建一个带默认值的派生原子,在无异步执行时返回静态内容:

const syncResponseAtom = atom((get) => {
 const config = get(activeModelCallAtom);
 return `【${config.model}】已加载模板:${JSON.stringify(config.messages.slice(-1)[0]?.content || '')}`;
});

【注意:syncResponseAtom 不依赖任何异步状态,因此绝不会触发 Suspense 或 loading 状态】

异步模式:用 write-only atom 触发真实请求

第一步:定义一个可写原子,接收配置并返回 Promise:

const executeModelCallAtom = atom(null, (get, set, config) => {
 const controller = new AbortController();
 set(abortControllerAtom, controller);
 fetch('/api/chat', { method: 'POST', body: JSON.stringify(config), signal: controller.signal })
  .then(r => r.json())
  .then(data => set(modelResponseAtom, data))
  .catch(err => { if (err.name !== 'AbortError') set(errorAtom, err.message) });
});

第二步:在组件中调用它,传入 activeModelCallAtom 的当前值:

const [_, execute] = useAtom(executeModelCallAtom);
useEffect(() => { execute(get(activeModelCallAtom)); }, [activeModelCallAtom]);

第三步:用 useAtomValue 监听 modelResponseAtom 获取结果,或用 useAtom 处理 errorAtom 显示错误。

一键切换同步/异步行为

① 创建控制开关原子:
const modeAtom = atom<'sync' | 'async'>('sync');

② 定义一个响应读取原子,让它能自动适配模式:
const displayResponseAtom = atom((get) => {
 const mode = get(modeAtom);
 if (mode === 'sync') return get(syncResponseAtom);
 return get(modelResponseAtom) || '等待响应...';
});

③ 在用户界面(UI)中设置一个切换按钮:

④ 最终消费:
const response = useAtomValue(displayResponseAtom);