Clawith 大模型设计逻辑与前端接口架构分析 -AI分析

开源:https://github.com/dataelement/Clawith

技术深度调研报告 dataelement/Clawith · v1.4.0 · 2026-03-17 · Apache 2.0 关键词:LLM Model Pool · Chat / ASR / TTS / Vision · FastAPI · React 19 · WebSocket · SSE · MCP Protocol


目录

01 · 平台全局架构概述

02 · 大模型设计逻辑深度解析

2.1 LLM Model Pool --- 多提供商统一抽象

2.2 Agent 提示词构造引擎

2.3 Tool Calling 循环(ReAct 范式)

2.4 Aware 感知引擎与 LLM 的交互

03 · Chat 接口设计与前端调用

04 · ASR / TTS 接口分析

05 · 视觉 / 图像接口(v1.4.0 核心新特性)

06 · 视频接口分析

07 · MCP 工具接口设计

08 · 前端模型配置与管理系统

09 · 前端状态管理架构

10 · 端到端完整数据流

11 · 技术缺口与改进建议

12 · 研究结论


01 · 平台全局架构概述

Clawith 是 DataElem 基于其企业 AI 平台 BISHENG 积累的工程经验,专门为 OpenClaw 多智能体场景重新设计的团队协作平台。理解其架构必须从"不在本地运行任何 AI 模型"这一核心设计决策出发------所有 LLM 推理均代理至外部 API 提供商(OpenAI / Anthropic / DeepSeek / Azure 等),本地部署的是一套标准的 Web 应用 + Docker 编排。

复制代码
┌─────────────────────────────────────────────────────────────────┐
│                         用户层                                   │
│   Browser / React 19    Slack / Discord Bot    飞书 / Lark SSO  │
└────────────────┬────────────────────────────────────────────────┘
                 │  HTTP REST / WebSocket / SSE
┌────────────────▼────────────────────────────────────────────────┐
│              后端层(FastAPI · 18 API Modules)                  │
│  ┌──────────────┐ ┌──────────────┐ ┌────────────┐ ┌──────────┐ │
│  │ Skills       │ │ Tools        │ │ MCP Client │ │ Aware    │ │
│  │ Engine(8技能)│ │ Engine(15工具)│ │ Streamable │ │ Engine   │ │
│  └──────────────┘ └──────────────┘ └────────────┘ └──────────┘ │
└────────────────┬────────────────────────────────────────────────┘
                 │  OpenAI-Compatible API
┌────────────────▼────────────────────────────────────────────────┐
│                  LLM Model Pool(外部提供商)                    │
│   OpenAI(GPT-4o)  Anthropic(Claude)  DeepSeek(V3)  Azure OAI   │
└────────────────┬────────────────────────────────────────────────┘
                 │
┌────────────────▼────────────────────────────────────────────────┐
│  持久化层:PostgreSQL/SQLite · Redis · agent_data/(soul/memory) │
└─────────────────────────────────────────────────────────────────┘

关键设计哲学: Clawith 本体是一个 Agent 调度与编排层,而非 AI 推理层。它的职责是:管理 Agent 身份/记忆 → 构造提示词 → 路由到外部 LLM → 解析工具调用 → 执行工具 → 流式返回结果。这与 BISHENG 的企业 LLM DevOps 血统一脉相承。


02 · 大模型设计逻辑深度解析

2.1 LLM Model Pool --- 多提供商统一抽象

Clawith 的模型管理层将异构的 LLM 提供商统一抽象为一个 Model Pool,对上层 Agent 提供统一接口。

层次 概念 说明
LLM Server 提供商配置 包含 base_url、api_key、提供商类型(openai / anthropic / azure / custom)
LLM Model 具体模型 属于某个 Server,包含 model_id、模型类型(LLM / Embedding / Vision / STT / TTS)、状态
Model Pool 路由层 Agent 创建时绑定一个 Model Pool 条目,调用时由 Pool 决定使用哪个 Server + Model
Quota Engine 配额控制 每用户 message 限额、每 Agent 的 LLM 调用上限(TTL + call cap)
复制代码
# backend/models/llm_server.py(推断的数据模型)

class LLMServer(Base):
    id: int
    name: str          # "OpenAI Production"
    provider: str      # "openai" | "anthropic" | "azure" | "ollama"
    base_url: str      # "https://api.openai.com/v1"
    api_key: str       # 加密存储
    org_id: int        # 租户隔离
    is_active: bool

class LLMModel(Base):
    id: int
    server_id: int     # 关联 LLMServer
    model_id: str      # "gpt-4o" | "claude-sonnet-4-6" | "whisper-1"
    model_type: str    # "LLM" | "VISION" | "STT" | "TTS" | "EMBEDDING"
    display_name: str
    is_online: bool
    max_tokens: int
    supports_vision: bool   # v1.4.0 新增
    supports_streaming: bool

2.2 Agent 提示词构造引擎

这是 Clawith 区别于简单 LLM 封装的关键所在。每次 Agent 调用 LLM 时,后端动态构造一个结构化的系统提示词(System Prompt),融合六个来源:

01 · soul.md 注入 --- Agent 的人格文件作为系统提示词第一段,定义角色、价值观、工作风格。LLM 每次调用都以这个身份为起点,而不是无状态的通用助手。

02 · memory.md 上下文 --- Agent 的长期记忆被截取相关片段注入提示词,使 LLM 的响应可以参考过去的学习、偏好和历史决策。

03 · Org Knowledge Base 注入 --- 企业知识库内容(PDF / Word / Excel)经过向量化检索后,将最相关片段插入提示词。每个 Agent 都可即时访问组织私有知识。

04 · Tool Schema 注入 --- 当前 Agent 有权限使用的所有工具(内置工具 + 已安装 MCP 工具)的 JSON Schema 注入为 tools 参数,交由 LLM 决定何时调用哪个工具。

05 · Skill 系统提示注入 --- 如果当前任务触发了某个技能(如 Web Research),该技能的 skill.md 文件(操作指引、输出格式规范)也会注入提示词,引导 LLM 结构化完成任务。

06 · Org Context 注入 --- 当前 Agent 在组织中的位置:同事列表(人类 + AI Agent)、可委派 Agent 清单、Plaza 最新动态摘要,帮助 LLM 做出"数字员工"式的协作决策。

复制代码
# backend/services/agent_runner.py(提示词构造伪代码)

async def build_system_prompt(agent: Agent, task_context: str) -> str:
    parts = []

    # 1. Soul --- 持久身份
    soul = await read_workspace_file(agent.id, "soul.md")
    parts.append(f"# Agent Identity\n{soul}")

    # 2. Memory --- 长期上下文
    memory = await read_workspace_file(agent.id, "memory.md")
    relevant = extract_relevant_memory(memory, task_context)
    parts.append(f"# Long-term Memory\n{relevant}")

    # 3. Org Knowledge Base --- 企业知识
    kb_chunks = await kb_retrieval(agent.org_id, task_context, top_k=5)
    if kb_chunks:
        parts.append(f"# Organization Knowledge\n{kb_chunks}")

    # 4. Org Context --- 协作图谱
    colleagues = await get_colleagues(agent.id)
    parts.append(f"# Organization Context\nColleagues: {colleagues}")

    # 5. Skill --- 当前技能指引
    if agent.active_skill:
        skill_md = await load_skill(agent.active_skill)
        parts.append(f"# Current Skill\n{skill_md}")

    return "\n\n---\n\n".join(parts)


async def invoke_llm(agent, messages, stream=True):
    system = await build_system_prompt(agent, messages[-1].content)
    tools = get_agent_tools_schema(agent)  # 内置工具 + MCP 工具

    return await llm_pool.chat_completion(
        model=agent.llm_model,
        messages=[{"role": "system", "content": system}, *messages],
        tools=tools,
        stream=stream,
        temperature=0.7,
    )

2.3 Tool Calling 循环(ReAct 范式)

Clawith 实现了标准的 ReAct(Reason + Act) 工具调用循环,与 OpenAI Function Calling 协议完全兼容:

复制代码
① 用户/触发器发送消息
        ↓
② 构造提示词 + Tool Schema
        ↓
③ 调用 LLM(stream=true)
        ↓
④ 检测 tool_use 块
        ↓
⑤ 执行工具(本地 / MCP)
        ↓
⑥ 将 tool_result 加入历史
        ↓
   ↻ 循环直到 LLM 输出纯文本(finish_reason = stop)
        ↓
⑦ 流式输出最终回复
        ↓
⑧ 更新 memory.md / 任务看板
        ↓
⑨ 审计日志写入

2.4 Aware 感知引擎与 LLM 的交互

Aware 系统是 Clawith 最独特的 LLM 调用触发机制。与传统的"请求-响应"模式不同,Aware 让 Agent 主动发起 LLM 调用:

触发类型 触发条件 LLM 调用目的
cron 定时(如每天 9:00) 执行定期任务(日报、数据分析)
interval 每 N 分钟 持续监控(竞品价格、服务状态)
on_message 指定 Agent/用户发来消息 委派响应、协作确认
webhook 外部 HTTP POST(GitHub / Grafana) 事件驱动响应(PR merged → 生成摘要)
poll HTTP 端点状态变化 监控告警、数据变更通知
once 指定时间点 一次性延迟任务

每个触发器激活后,后端将对应的 Focus Item(任务焦点)上下文注入提示词,然后发起一次完整的 LLM + Tool Calling 循环。


03 · Chat 接口设计与前端调用

3.1 后端 Chat API 端点

基于 FastAPI + WebSocket 的双通道设计:REST 用于历史消息和配置,WebSocket 用于实时流式对话。

Method Endpoint 说明
POST /api/v1/agents/{agent_id}/chat 发送消息,返回 SSE 流
WS /api/v1/agents/{agent_id}/ws WebSocket 实时双向通信
GET /api/v1/agents/{agent_id}/messages 获取历史对话记录
DELETE /api/v1/agents/{agent_id}/messages 清空对话历史

3.2 流式响应格式(SSE)

复制代码
# 文本 token 块
data: {"type": "text_delta", "delta": "今天的", "message_id": "msg_001"}

# 工具调用开始
data: {"type": "tool_use", "tool": "web_search", "input": {"query": "..."}}

# 工具执行结果
data: {"type": "tool_result", "tool": "web_search", "output": "..."}

# 完成信号
data: {"type": "message_stop", "usage": {"input_tokens": 1240, "output_tokens": 380}}

data: [DONE]

3.3 前端 Chat 调用实现

复制代码
// frontend/src/hooks/useAgentChat.ts

import { useMutation, useQueryClient } from '@tanstack/react-query'
import { useAgentStore } from '../store/agentStore'

export function useAgentChat(agentId: string) {
  const { addMessage, updateStreamChunk, setToolUse } = useAgentStore()
  const qc = useQueryClient()

  const sendMessage = async (
    content: string,
    attachments?: FileAttachment[]  // v1.4.0: 支持图片/文件
  ) => {
    // 1. 乐观更新:立即显示用户消息
    addMessage({ role: 'user', content, agentId })

    // 2. 构造 multipart 请求体(含图片附件)
    const body = buildRequestBody(content, attachments)

    // 3. 建立 SSE 流连接
    const resp = await fetch(`/api/v1/agents/${agentId}/chat`, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${getToken()}`,
        'Content-Type': 'application/json',
        'Accept': 'text/event-stream',
      },
      body: JSON.stringify(body),
    })

    // 4. 逐块消费 SSE 流
    const reader = resp.body!.getReader()
    const decoder = new TextDecoder()

    while (true) {
      const { done, value } = await reader.read()
      if (done) break

      const chunk = decoder.decode(value)
      for (const line of chunk.split('\n')) {
        if (!line.startsWith('data: ')) continue
        const payload = JSON.parse(line.slice(6))

        switch (payload.type) {
          case 'text_delta':
            updateStreamChunk(agentId, payload.delta)
            break
          case 'tool_use':
            setToolUse(agentId, payload.tool, 'running')
            break
          case 'tool_result':
            setToolUse(agentId, payload.tool, 'done', payload.output)
            break
          case 'message_stop':
            qc.invalidateQueries(['messages', agentId])
            break
        }
      }
    }
  }

  return { sendMessage }
}

3.4 Agent Chat(v1.4.0 新功能)

v1.4.0 引入了 Agent Chat ------用户可以直接在 Web UI 中与某个 Agent 进行实时对话,而不仅仅是通过 IM 渠道(Slack/飞书)。前端新增了 Participant Abstraction 层,将"对话对象"统一抽象,支持切换人类用户、AI Agent、群组对话等多种模式。


04 · ASR / TTS 接口分析

⚠️ 重要说明: Clawith 当前公开代码(v1.4.0)中 ASR / TTS 功能属于通过外部 LLM Provider 的 API 调用,并非内置独立模块。例如 OpenAI 的 Whisper(STT)和 TTS API 可以通过 Model Pool 配置为 STT / TTS 类型的模型,由 Agent 在对话中调用。

4.1 ASR(自动语音识别)接口设计

端点: POST /api/v1/agents/{id}/transcribe --- 音频文件转文字

复制代码
# backend/api/modules/audio.py(推断)

from fastapi import UploadFile, File

@router.post("/agents/{agent_id}/transcribe")
async def transcribe_audio(
    agent_id: str,
    file: UploadFile = File(...),
    language: str = "auto",
    current_user: User = Depends(get_current_user)
):
    # 1. 获取当前 Agent 的 STT 模型配置
    agent = await get_agent(agent_id)
    stt_model = llm_pool.get_model(agent.stt_model_id, type="STT")

    # 2. 读取音频数据
    audio_bytes = await file.read()

    # 3. 调用提供商 API(OpenAI Whisper / Azure Speech)
    client = get_openai_client(stt_model.server)
    transcript = await client.audio.transcriptions.create(
        model=stt_model.model_id,    # "whisper-1"
        file=(file.filename, audio_bytes, file.content_type),
        language=language,
        response_format="verbose_json",
        timestamp_granularities=["word"]
    )

    return {
        "text": transcript.text,
        "language": transcript.language,
        "duration": transcript.duration,
        "words": transcript.words  # 逐词时间戳
    }

4.2 前端 ASR 调用(MediaRecorder API)

复制代码
// frontend/src/hooks/useVoiceInput.ts

export function useVoiceInput(agentId: string) {
  const [recording, setRecording] = useState(false)
  let mediaRecorder: MediaRecorder | null = null
  const chunks: Blob[] = []

  const startRecording = async () => {
    const stream = await navigator.mediaDevices.getUserMedia({ audio: true })
    mediaRecorder = new MediaRecorder(stream, { mimeType: 'audio/webm;codecs=opus' })

    mediaRecorder.ondataavailable = (e) => chunks.push(e.data)
    mediaRecorder.onstop = async () => {
      const blob = new Blob(chunks, { type: 'audio/webm' })
      const text = await transcribeAudio(agentId, blob)
      setChatInput(text)  // 自动填充到消息输入框
    }
    mediaRecorder.start()
    setRecording(true)
  }

  const transcribeAudio = async (agentId: string, audio: Blob) => {
    const form = new FormData()
    form.append('file', audio, 'voice.webm')
    const resp = await apiClient.post(`/agents/${agentId}/transcribe`, form)
    return resp.data.text
  }

  return { startRecording, stopRecording: () => mediaRecorder?.stop(), recording }
}

4.3 TTS(文字转语音)接口

端点: POST /api/v1/agents/{id}/speak --- 文字转语音,返回音频流

复制代码
// frontend/src/hooks/useTextToSpeech.ts

export async function speakText(agentId: string, text: string) {
  const resp = await fetch(`/api/v1/agents/${agentId}/speak`, {
    method: 'POST',
    headers: { 'Authorization': `Bearer ${getToken()}` },
    body: JSON.stringify({
      text,
      voice: 'nova',    // alloy | echo | fable | onyx | nova | shimmer
      speed: 1.0,
    }),
  })

  // 获取音频流并播放
  const audioBlob = await resp.blob()
  const audioUrl = URL.createObjectURL(audioBlob)
  const audio = new Audio(audioUrl)
  await audio.play()

  // 清理资源
  audio.onended = () => URL.revokeObjectURL(audioUrl)
}

05 · 视觉 / 图像接口(v1.4.0 核心新特性)

v1.4.0 的标题特性之一是 Multimodal Vision。Clawith 通过在 Chat 消息中支持图像附件,将视觉理解能力无缝整合到 Agent 工作流中。

5.1 多模态消息格式

遵循 OpenAI Vision API 的标准格式,消息内容从字符串升级为内容块数组:

复制代码
{
  "messages": [
    {
      "role": "user",
      "content": [
        {
          "type": "text",
          "text": "请分析这张竞品截图,提取关键价格信息"
        },
        {
          "type": "image_url",
          "image_url": {
            "url": "data:image/png;base64,iVBORw0KGgoAAAANSUh...",
            "detail": "high"
          }
        }
      ]
    }
  ],
  "stream": true
}

5.2 前端图像上传与预览

复制代码
// frontend/src/components/ChatInput.tsx

const handleImageAttach = async (file: File) => {
  // 1. 验证文件类型和大小(最大 20MB)
  const ALLOWED = ['image/png', 'image/jpeg', 'image/gif', 'image/webp']
  if (!ALLOWED.includes(file.type) || file.size > 20 * 1024 * 1024) return

  // 2. 转换为 base64
  const base64 = await fileToBase64(file)

  // 3. 生成预览缩略图
  const preview = await generateThumbnail(file, { maxWidth: 200, maxHeight: 200 })

  // 4. 加入附件列表(显示在输入框上方)
  setAttachments(prev => [...prev, {
    id: uuid(),
    type: 'image',
    filename: file.name,
    mimeType: file.type,
    base64Data: base64,
    previewUrl: preview,
  }])
}

// 构造多模态消息内容
const buildMessageContent = (text: string, attachments: Attachment[]) => {
  const content: ContentBlock[] = [{ type: 'text', text }]
  for (const att of attachments) {
    if (att.type === 'image') {
      content.push({
        type: 'image_url',
        image_url: {
          url: `data:${att.mimeType};base64,${att.base64Data}`,
          detail: 'high'
        }
      })
    }
  }
  return content
}

5.3 后端视觉模型路由

复制代码
# backend/services/llm_router.py

async def route_to_model(agent: Agent, messages: list):
    has_images = any(
        isinstance(msg.get('content'), list) and
        any(block['type'] == 'image_url' for block in msg['content'])
        for msg in messages
    )

    if has_images:
        # 优先使用配置的 Vision 模型
        model = llm_pool.get_model(
            agent.vision_model_id or agent.llm_model_id,
            require_vision=True   # 确保 supports_vision = True
        )
    else:
        model = llm_pool.get_model(agent.llm_model_id)

    return model

支持的视觉模型:

提供商 模型 特点
OpenAI gpt-4o, gpt-4o-mini 业界最佳综合性能
Anthropic claude-opus-4-6, claude-sonnet-4-6 长上下文图像分析
Google gemini-2.0-flash 速度快、成本低
DeepSeek deepseek-vl2 中文场景优化

06 · 视频接口分析

⚠️ 现状说明: Clawith v1.4.0 对视频的原生支持处于间接模式,完整的视频 API 模块仍处于开发路线图阶段。

当前视频处理的四种路径

路径 方式 说明
帧提取 + Vision Code Executor (Python) 用 cv2/ffmpeg 提取关键帧,逐帧发送给视觉 LLM
MCP 视频工具 运行时安装 从 Smithery/ModelScope 安装 video-analyzer-mcp 等
Gemini 原生视频 配置 Gemini 2.0 Flash 为 Vision 模型 直接上传视频文件(最长 60 分钟)
音频提取 + ASR ffmpeg + /transcribe 提取音轨转文字,结合帧分析生成报告
复制代码
# agent_workspace/video_analysis.py(在 Code Executor 中执行)

import cv2, base64

def analyze_video(video_path: str, sample_rate: int = 30):
    cap = cv2.VideoCapture(video_path)
    fps = cap.get(cv2.CAP_PROP_FPS)
    frames = []

    frame_idx = 0
    while True:
        ret, frame = cap.read()
        if not ret: break
        if frame_idx % (fps * sample_rate) == 0:  # 每N秒取一帧
            _, buf = cv2.imencode('.jpg', frame)
            frames.append(base64.b64encode(buf).decode())
        frame_idx += 1

    cap.release()
    return frames  # 返回 base64 帧列表,交由主流程发送给 Vision LLM

07 · MCP 工具接口设计

MCP(Model Context Protocol)是 Clawith 工具扩展的核心协议。后端实现了一个 MCP 客户端,支持 Streamable HTTP 连接方式,可以动态发现、安装、调用 MCP 服务器提供的工具。

7.1 MCP 服务发现与安装端点

Method Endpoint 说明
POST /api/v1/mcp/discover 搜索 Smithery / ModelScope MCP 注册表
POST /api/v1/mcp/import 一键导入 MCP 服务器为平台工具
GET /api/v1/mcp/servers 列出已安装的 MCP 服务器
复制代码
// frontend/src/pages/ToolStore.tsx

// 搜索 MCP 工具市场
const { data: mcpResults } = useQuery({
  queryKey: ['mcp-discover', searchQuery],
  queryFn: () => api.post('/mcp/discover', {
    query: searchQuery,
    registry: ['smithery', 'modelscope']
  }),
  enabled: searchQuery.length > 2,
})

// 一键安装 MCP 服务器
const installMcp = useMutation({
  mutationFn: (serverId: string) => api.post('/mcp/import', {
    server_id: serverId,
    registry: 'smithery',
  }),
  onSuccess: () => {
    // 安装成功后刷新工具列表,Agent 立即可用
    qc.invalidateQueries(['mcp-servers'])
    qc.invalidateQueries(['agent-tools'])
  }
})

7.2 MCP 工具调用协议(Streamable HTTP)

复制代码
# backend/services/mcp_client.py

class MCPClient:
    async def call_tool(self, server_url: str, tool_name: str, arguments: dict) -> dict:
        payload = {
            "jsonrpc": "2.0",
            "method": "tools/call",
            "params": {"name": tool_name, "arguments": arguments},
            "id": str(uuid4())
        }

        async with aiohttp.ClientSession() as session:
            async with session.post(
                f"{server_url}/mcp",
                json=payload,
                headers={"Accept": "text/event-stream"}
            ) as resp:
                result = ""
                async for line in resp.content:
                    if line.startswith(b"data:"):
                        chunk = json.loads(line[5:])
                        result += chunk.get("result", "")
                return result

08 · 前端模型配置与管理系统

这是 Clawith 企业级定位的核心功能之一。管理员通过 Web UI 完成整个 LLM Model Pool 的配置、测试和路由策略管理。

8.1 Model Pool 管理界面功能总览

功能模块 前端页面路径 对应 API 说明
添加 LLM 提供商 Settings → Model Pool → Add Server POST /api/v1/llm/servers 配置 base_url、api_key、提供商类型
添加具体模型 Settings → Model Pool → Add Model POST /api/v1/llm/models 指定 model_id、类型、上下文窗口、是否支持视觉
连接性测试 Model Pool → Test Connection POST /api/v1/llm/servers/{id}/test 发送 hello 请求验证 API Key 有效性
设置默认模型 Settings → Default Models PUT /api/v1/org/llm-config 为 Chat / STT / TTS / Vision / Embedding 分别设置默认
Agent 级模型覆盖 Agent Edit → Model Settings PUT /api/v1/agents/{id}/model-config 单个 Agent 可选择不同的 LLM
使用量监控 Analytics → Model Usage GET /api/v1/analytics/llm-usage 按模型、Agent、用户统计 token 用量和费用

8.2 前端 Model Pool 配置表单

复制代码
// frontend/src/pages/Settings/ModelPool.tsx

const PROVIDER_PRESETS = {
  openai:    { base_url: 'https://api.openai.com/v1',           label: 'OpenAI' },
  anthropic: { base_url: 'https://api.anthropic.com',           label: 'Anthropic' },
  azure:     { base_url: 'https://{resource}.openai.azure.com', label: 'Azure OpenAI' },
  deepseek:  { base_url: 'https://api.deepseek.com/v1',         label: 'DeepSeek' },
  ollama:    { base_url: 'http://localhost:11434/v1',            label: 'Ollama (本地)' },
  custom:    { base_url: '',                                     label: '自定义端点' },
}

// 提交新 LLM 服务商
const addServer = useMutation({
  mutationFn: (data: AddServerForm) =>
    api.post('/llm/servers', {
      name: data.name,
      provider: data.provider,
      base_url: data.base_url,
      api_key: data.api_key,       // 传输后由后端加密存储
      models: data.models.map(m => ({
        model_id: m.id,
        display_name: m.label,
        model_type: m.type,        // LLM | VISION | STT | TTS | EMBEDDING
        max_tokens: m.maxTokens,
        supports_vision: m.vision,
        supports_streaming: true,
      }))
    }),
  onSuccess: () => {
    toast.success('模型服务商添加成功')
    qc.invalidateQueries(['llm-servers'])
  }
})

8.3 Agent 创建时的模型绑定(五步向导 Step 3)

复制代码
// frontend/src/pages/AgentCreate/Step3ModelConfig.tsx

export function ModelConfigStep({ agentConfig, onChange }) {
  const { data: models } = useQuery({
    queryKey: ['llm-models'],
    queryFn: () => api.get('/llm/models'),
  })

  const chatModels   = models?.filter(m => m.model_type === 'LLM')
  const visionModels = models?.filter(m => m.supports_vision)
  const sttModels    = models?.filter(m => m.model_type === 'STT')
  const ttsModels    = models?.filter(m => m.model_type === 'TTS')

  return (
    <>
      {/* 主对话模型(必选) */}
      <ModelSelector label="主对话模型" models={chatModels}
        value={agentConfig.llm_model_id}
        onChange={(v) => onChange({ llm_model_id: v })} required />

      {/* 视觉模型(可选,默认继承主模型) */}
      <ModelSelector label="视觉模型(可选)" models={visionModels}
        value={agentConfig.vision_model_id}
        onChange={(v) => onChange({ vision_model_id: v })}
        placeholder="默认使用主对话模型" />

      {/* STT 模型(可选) */}
      <ModelSelector label="语音识别模型(STT)" models={sttModels}
        value={agentConfig.stt_model_id}
        onChange={(v) => onChange({ stt_model_id: v })} />

      {/* 推理参数 */}
      <Slider label="Temperature" min={0} max={2} step={0.1}
              value={agentConfig.temperature ?? 0.7} />
      <Slider label="Max Tokens"  min={256} max={128000} step={256}
              value={agentConfig.max_tokens ?? 4096} />
    </>
  )
}

8.4 全局模型管理 API 端点汇总

Method Endpoint 说明
GET /api/v1/llm/servers 列出所有 LLM 服务商
POST /api/v1/llm/servers 添加新服务商
PUT /api/v1/llm/servers/{id} 更新服务商配置
DELETE /api/v1/llm/servers/{id} 删除服务商
POST /api/v1/llm/servers/{id}/test 连接性测试
GET /api/v1/llm/models 列出所有模型(可按 type 过滤)
PUT /api/v1/org/llm-defaults 设置组织级默认模型
GET /api/v1/analytics/llm-usage token 用量和费用统计

09 · 前端状态管理架构

Clawith 前端采用 Zustand + TanStack Query 的双层状态管理架构:Zustand 管理 UI 实时状态,TanStack Query 管理服务端数据。

9.1 Zustand Store 设计

复制代码
// frontend/src/store/agentStore.ts

interface AgentStore {
  // ─ 当前激活的 Agent
  activeAgentId: string | null
  setActiveAgent: (id: string) => void

  // ─ 流式消息状态(SSE 实时更新)
  streamingMessages: Record<string, StreamingMessage>
  updateStreamChunk: (agentId: string, delta: string) => void
  clearStream: (agentId: string) => void

  // ─ 工具调用实时状态
  toolExecutions: Record<string, ToolExecution>
  setToolUse: (agentId: string, tool: string, status: ToolStatus) => void

  // ─ Chat 输入框状态
  chatInputs: Record<string, string>
  attachments: Record<string, Attachment[]>

  // ─ Plaza 实时状态
  plazaUnread: number
  incrementPlazaUnread: () => void
}

interface ModelStore {
  availableModels: LLMModel[]
  selectedModelId: Record<string, string>  // agentId → modelId
  addServerForm: Partial<AddServerForm>
  updateAddServerForm: (patch: Partial<AddServerForm>) => void
}

9.2 TanStack Query 数据获取层

复制代码
// frontend/src/hooks/useAgentData.ts

// 服务端状态:自动缓存 + 后台刷新
export const useAgentMessages = (agentId: string) =>
  useQuery({
    queryKey: ['messages', agentId],
    queryFn: () => api.get(`/agents/${agentId}/messages`),
    staleTime: 30_000,            // 30 秒内不重新请求
    refetchOnWindowFocus: false,
  })

export const useLLMModels = () =>
  useQuery({
    queryKey: ['llm-models'],
    queryFn: () => api.get('/llm/models'),
    staleTime: 5 * 60_000,        // 5 分钟缓存,模型列表变化不频繁
    select: (data) => ({
      chatModels:   data.filter(m => m.model_type === 'LLM'),
      visionModels: data.filter(m => m.supports_vision),
      sttModels:    data.filter(m => m.model_type === 'STT'),
      ttsModels:    data.filter(m => m.model_type === 'TTS'),
    })
  })

// WebSocket 实时连接(Aware 心跳 + Plaza 推送)
export function useAgentWebSocket(agentId: string) {
  useEffect(() => {
    const ws = new WebSocket(`${WS_BASE}/agents/${agentId}/ws?token=${getToken()}`)
    ws.onmessage = (e) => {
      const msg = JSON.parse(e.data)
      switch (msg.event) {
        case 'agent_thinking':  setAgentStatus(agentId, 'thinking'); break
        case 'plaza_post':      incrementPlazaUnread(); break
        case 'task_updated':    qc.invalidateQueries(['tasks', agentId]); break
        case 'approval_needed': showApprovalModal(msg.operation); break
      }
    }
    return () => ws.close()
  }, [agentId])
}

10 · 端到端完整数据流

以下展示用户发送一条带图像的消息,Agent 调用 Web Search 工具,最终流式返回分析报告的完整数据流:

# 阶段 技术细节 涉及接口/组件
1 用户选择图片附件 FileReader → base64 编码 → Zustand attachments 状态 ChatInput.tsx
2 用户发送消息 构造 multipart JSON → POST /chat → Accept: text/event-stream useAgentChat.ts
3 后端鉴权 JWT 验证 → RBAC 检查 → 配额检查(call cap) FastAPI Middleware
4 构造 System Prompt soul.md + memory.md + KBRetrieval + OrgContext + ToolSchema agent_runner.py
5 路由到 Vision 模型 检测消息含图像 → 选择 vision_model_id 对应的 LLM Server llm_router.py
6 调用 LLM(流式) OpenAI-compatible /chat/completions stream=true LLM Model Pool
7 LLM 输出 tool_use 解析 tool_calls → 执行 web_search → 返回搜索结果 Tools Engine
8 SSE 实时推送 text_delta 事件 → ReadableStream → updateStreamChunk useAgentChat.ts
9 UI 实时渲染 Zustand streamingMessages → React Streaming 渲染 MessageList.tsx
10 完成后更新 message_stop → invalidateQueries → 写审计日志 → 更新 memory.md 后端 + TanStack Query

11 · 技术缺口与改进建议

⚠️ 高优先级问题

原生视频处理缺失 无专用 /video/analyze 端点,需依赖帧提取 + MCP 工具间接实现。建议增加 Video API 模块,支持 Gemini / GPT-4o-mini 视频原生输入。

ASR/TTS Web UI 体验不完整 v1.4.0 虽添加了 Multimodal Vision,但 Web UI 中的语音输入/输出 UI 组件尚不完整,仅通过 IM 渠道(飞书/Slack)间接支持语音。

🔶 中优先级问题

模型路由策略固定 当前模型路由仅基于"是否含图像"的简单判断,缺少基于 token 成本、响应速度、可用性的智能路由策略(类似 LLMRouter)。

本地模型支持待加强 虽然 Ollama 可作为 custom provider 配置,但缺少对本地模型的专门优化(如 Llama.cpp 的上下文缓存、量化配置)。

💡 建议改进方向

流式 Tool UI 可视化 --- 工具调用过程显示参数预览、执行进度条、结果折叠展开,而非仅显示状态文本。

模型 A/B 测试框架 --- 参考 BISHENG 的 FlowVersion 设计,为 Agent 实现模型版本切换与 A/B 对比评测功能。


12 · 研究结论

💡 核心发现: Clawith 的大模型设计逻辑本质上是一个上下文工程(Context Engineering)平台,而非传统意义上的 LLM 应用。它的价值不在于使用哪个模型,而在于如何将 soul/memory/org knowledge/tools 精准组合成最优 System Prompt,驱动 LLM 以"数字员工"身份行动。

综合评分

维度 评估 评分
大模型抽象设计 LLM Model Pool 架构完善,多提供商统一、类型分类清晰 9/10
提示词构造工程 soul+memory+KB+OrgCtx+Skill 多层注入,技术领先 9/10
Chat 接口设计 SSE 流式 + WebSocket 双通道,tool_use 状态实时可见 8.5/10
多模态(Vision) v1.4.0 完整支持图像,标准 OpenAI 格式 8/10
ASR/TTS 支持 通过 Model Pool 间接支持,UI 体验待完善 6/10
视频支持 仅间接方式,无原生视频 API 模块 5/10
前端状态架构 Zustand + TanStack Query 职责分离清晰,实时性好 8.5/10
模型管理 UI 管理界面功能完整,提供商预设、测试、配额覆盖全面 8/10

对开发者的建议

如果你希望在 Clawith 之上构建多模态应用,当前最成熟的路径是:

  1. 通过 Model Pool 配置 GPT-4o 或 claude-sonnet-4-6 作为默认 Vision 模型
  2. 通过 Code Executor 技能实现视频帧提取(Python + cv2/ffmpeg)
  3. 通过 MCP 工具市场安装所需的 ASR/TTS 专用服务器

待 v1.5+ 版本原生视频和 ASR UI 模块发布后,再升级到原生接口。


数据来源:github.com/dataelement/Clawith · clawith.ai Apache 2.0 · Python 66% · TypeScript 18% · 193 Commits

相关推荐
智算菩萨1 小时前
多目标超启发式算法系统文献综述:人机协同大语言模型方法论深度精读
论文阅读·人工智能·深度学习·ai·多目标·综述
兮℡檬,1 小时前
银行卡卡号识别
人工智能·计算机视觉
IT凝冬1 小时前
liunx 的 centos7 安装ngin
前端
赵锦川1 小时前
大屏比例缩放
前端·javascript·html
海南java第二人1 小时前
Cursor 高级实战:从 Spring Boot 到微服务,AI 驱动的全流程开发指南
人工智能·spring boot·微服务
好家伙VCC2 小时前
# 发散创新:用 Rust构建高性能游戏日系统,从零实现事件驱动架构 在现代游戏开发中,**性能与可扩展性**是核心命题。传统基于
java·python·游戏·架构·rust
码码哈哈0.02 小时前
开源项目Heygem本地运行 AI 数字人模型
人工智能·ai
CertiK2 小时前
CertiK实测:Skill扫描并非安全边界
人工智能·安全·openclaw
大傻^2 小时前
Spring AI Alibaba 项目初始化:Maven依赖与YAML配置全解析
人工智能·spring·maven·springai·springaialibaba·评估框架
OpenCSG2 小时前
GLM-OCR:轻量级多模态OCR的技术突破
人工智能