Chat

Le SDK
Construisez des interfaces de chat AI avec streaming, raisonnement et appel d'outils.

Nuxt UI fournit un ensemble de composants conçus pour créer des interfaces de chat alimentées par l'IA. Ils s'intègrent parfaitement au [Vercel AI SDKhttps://ai-sdk.dev/) pour le streaming des réponses, le raisonnement, l'appel d'outils, et plus encore.

Découvrez les modèles Nuxt et Vue AI Chat sur GitHub pour des implémentations prêtes pour la production.

Composants

composanteDescription
](/docs/components/chat-messages)Liste de messages déroulable avec défilement automatique et indicateur de chargement.
ChatMessageBulle de message individuelle avec avatar, actions et slots.
ChatPromptTextarea amélioré pour soumettre des invites.
ChatPromptSubmitBouton Soumettre avec gestion automatique de l'état.
Bloc rétractable pour le processus de raisonnement/pensée de l'IA.
@@Bloc rétractable pour l'état d'invocation de l'outil d'IA.
](/docs/components/chat-shimmer)Animation de miroitement de texte pour les états de streaming.
Layout wrapper pour intégrer le chat dans des modaux ou des tiroirs.

Installation d'un

Les composants Chat sont conçus pour être utilisés avec la classe [Vercel AI SDKhttps://ai-sdk.dev/), en particulier la classe [Chat](https://ai-sdk.dev/docs/reference/ai-sdk-ui/use-chatpour la gestion de l'état du chat et des réponses en streaming.

Installer les dépendances requises:

pnpm add ai @ai-sdk/gateway @ai-sdk/vue @comark/vue
@comark/vue fournit le composant Markdown utilisé pour rendre les réponses AI en streaming Markdown, il rend incrémentiellement les jetons à mesure qu 'ils arrivent, évitant le scintillement et la ré-analyse que les rendus Markdown traditionnels provoquent.

Pour utiliser les composants [prose de l'interface utilisateur Nuxt ](/docs/typographyComark, activez l'option prose dans votre vite.config.ts:
vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import ui from '@nuxt/ui/vite'

export default defineConfig({
  plugins: [
    vue(),
    ui({
      prose: true
    })
  ]
})

Serveur

Créez un point de terminaison API serveur pour gérer les demandes de chat en utilisant . Vous pouvez utiliser le [Vercel AI Gatewayhttps://vercel.com/ai-gateway) pour accéder aux modèles d'IA via un point de terminaison centralisé:

server/api/chat.post.ts
import { streamText, convertToModelMessages, toUIMessageStream, createUIMessageStreamResponse } from 'ai'
import { gateway } from '@ai-sdk/gateway'

export default defineEventHandler(async (event) => {
  const { messages } = await readBody(event)

  const result = streamText({
    model: gateway('anthropic/claude-sonnet-5'),
    maxOutputTokens: 10000,
    instructions: 'You are a helpful assistant.',
    messages: await convertToModelMessages(messages)
  })

  const stream = toUIMessageStream({ stream: result.stream })
  return createUIMessageStreamResponse({ stream })
})

@@ph156@@raisonnement

Pour activer reasoning, configurez providerOptions pour votre fournisseur (Anthropic,Google,OpenAI)):

server/api/chat.post.ts
import { streamText, convertToModelMessages, toUIMessageStream, createUIMessageStreamResponse } from 'ai'
import { gateway } from '@ai-sdk/gateway'

export default defineEventHandler(async (event) => {
  const { messages } = await readBody(event)

  const result = streamText({
    model: gateway('anthropic/claude-sonnet-5'),
    maxOutputTokens: 10000,
    instructions: 'You are a helpful assistant.',
    messages: await convertToModelMessages(messages),
    providerOptions: {
      anthropic: {
        thinking: {
          type: 'adaptive'
        },
        effort: 'low'
      },
      google: {
        thinkingConfig: {
          includeThoughts: true,
          thinkingLevel: 'low'
        }
      },
      openai: {
        reasoningEffort: 'low',
        reasoningSummary: 'detailed'
      }
    }
  })

  const stream = toUIMessageStream({ stream: result.stream })
  return createUIMessageStreamResponse({ stream })
})

Recherche sur le Web

Certains fournisseurs proposent des outils de recherche Web intégrés:Anthropic,,[OpenAI](PH2222 @.

import { streamText, convertToModelMessages, toUIMessageStream, createUIMessageStreamResponse } from 'ai'
import { anthropic } from '@ai-sdk/anthropic'
import { gateway } from '@ai-sdk/gateway'

export default defineEventHandler(async (event) => {
  const { messages } = await readBody(event)

  const result = streamText({
    model: gateway('anthropic/claude-sonnet-5'),
    instructions: 'You are a helpful assistant.',
    messages: await convertToModelMessages(messages),
    tools: {
      web_search: anthropic.tools.webSearch_20260209({})
    }
  })

  const stream = toUIMessageStream({ stream: result.stream })
  return createUIMessageStreamResponse({ stream })
})

MCP Client

Donnez à votre chatbot des fonctionnalités avancées d'appel d'outils à l'aide du de @ai-sdk/mcp. MCP permet à votre IA d'effectuer des actions dynamiques, telles que la recherche dans votre documentation ou l'exécution de tâches personnalisées, afin de fournir des réponses plus pertinentes et plus précises.

Pour commencer, installez le paquet MCP:

npm install @ai-sdk/mcp

Ensuite, configurez votre point de terminaison serveur pour utiliser les outils MCP:

server/api/chat.post.ts
import { streamText, convertToModelMessages, isStepCount, toUIMessageStream, createUIMessageStreamResponse } from 'ai'
import { createMCPClient } from '@ai-sdk/mcp'
import { gateway } from '@ai-sdk/gateway'

export default defineEventHandler(async (event) => {
  const { messages } = await readBody(event)

  const httpClient = await createMCPClient({
    transport: { type: 'http', url: 'https://your-app.com/mcp' }
  })
  try {
    const tools = await httpClient.tools()

    const result = streamText({
      model: gateway('anthropic/claude-sonnet-5'),
      maxOutputTokens: 10000,
      instructions: 'You are a helpful assistant. Use your tools to search for relevant information before answering questions.',
      messages: await convertToModelMessages(messages),
      stopWhen: isStepCount(6),
      tools,
      onEnd: async () => {
        await httpClient.close()
      },
      onError: async (error) => {
        console.error(error)
        await httpClient.close()
      }
    })

    const stream = toUIMessageStream({ stream: result.stream })
    return createUIMessageStreamResponse({ stream })
  } catch (error) {
    // Close the MCP client if setup fails before streaming starts
    await httpClient.close()
    throw error
  }
})

Approbation de l'outil

Exiger une confirmation de l'utilisateur avant qu 'un outil ne s'exécute avec l'option toolApproval](https://ai-sdk.dev/docs/agents/tool-approvals). La partie outil fait une pause dans l'état approval-requested jusqu'à ce que l'utilisateur réponde:

server/api/chat.post.ts
import { streamText, convertToModelMessages, toUIMessageStream, createUIMessageStreamResponse, tool } from 'ai'
import { gateway } from '@ai-sdk/gateway'
import { z } from 'zod'

export default defineEventHandler(async (event) => {
  const { messages } = await readBody(event)

  const result = streamText({
    model: gateway('anthropic/claude-sonnet-5'),
    maxOutputTokens: 10000,
    instructions: 'You are a helpful assistant.',
    messages: await convertToModelMessages(messages),
    tools: {
      deleteFile: tool({
        description: 'Delete a file from the project',
        inputSchema: z.object({ path: z.string() }),
        execute: async ({ path }) => ({ deleted: path })
      })
    },
    toolApproval: {
      deleteFile: 'user-approval'
    }
  })

  const stream = toUIMessageStream({ stream: result.stream })
  return createUIMessageStreamResponse({ stream })
})

Client Configuration

Utilisez le composable useChat de @ai-sdk/vue pour gérer l'état du chat et vous connecter à votre point de terminaison serveur:

<script setup lang="ts">
import { ref } from 'vue'
import { isReasoningUIPart, isTextUIPart, isToolUIPart, getToolName, lastAssistantMessageIsCompleteWithApprovalResponses } from 'ai'
import { useChat } from '@ai-sdk/vue'
import { isPartStreaming, isToolStreaming } from '@nuxt/ui/utils/ai'
import { Markdown } from '@comark/vue'
import shiki from '@comark/vue/plugins/shiki'

const plugins = [shiki()]

const input = ref('')

const { messages, status, error, sendMessage, regenerate, stop, addToolApprovalResponse } = useChat({
  sendAutomaticallyWhen: lastAssistantMessageIsCompleteWithApprovalResponses,
  onError(error) {
    console.error(error)
  }
})

function onSubmit() {
  sendMessage({ text: input.value })

  input.value = ''
}
</script>

<template>
  <UChatMessages
    :messages="messages"
    :status="status"
  >
    <template #content="{ message }">
      <template
        v-for="(part, index) in message.parts"
        :key="`${message.id}-${part.type}-${index}`"
      >
        <UChatReasoning
          v-if="isReasoningUIPart(part)"
          :text="part.text"
          :streaming="isPartStreaming(part)"
        >
          <Markdown
            :value="part.text"
            :streaming="isPartStreaming(part)"
            :plugins="plugins"
            class="*:first:mt-0 *:last:mb-0"
          />
        </UChatReasoning>

        <UChatTool
          v-else-if="isToolUIPart(part)"
          :text="getToolName(part)"
          :streaming="isToolStreaming(part)"
          :actions="part.state === 'approval-requested' ? [
            { label: 'Approve', onClick: () => addToolApprovalResponse({ id: part.approval.id, approved: true }) },
            { label: 'Deny', color: 'neutral', variant: 'ghost', onClick: () => addToolApprovalResponse({ id: part.approval.id, approved: false }) }
          ] : undefined"
        />

        <template v-else-if="isTextUIPart(part)">
          <Markdown
            v-if="message.role === 'assistant'"
            :value="part.text"
            :streaming="isPartStreaming(part)"
            :plugins="plugins"
            class="*:first:mt-0 *:last:mb-0"
          />
          <p v-else-if="message.role === 'user'" class="whitespace-pre-wrap">
            {{ part.text }}
          </p>
        </template>
      </template>
    </template>
  </UChatMessages>

  <UChatPrompt
    v-model="input"
    :error="error"
    @submit="onSubmit"
  >
    <UChatPromptSubmit
      :status="status"
      @stop="stop()"
      @reload="regenerate()"
    />
  </UChatPrompt>
</template>
Pour une configuration Comark réutilisable (plugins, classe, etc.), utilisez defineMarkdownComponent pour créer un composant personnalisé au lieu de passer des props en ligne à chaque fois.
components/chat/Markdown.ts
import { defineMarkdownComponent } from '@comark/vue'
import shiki from '@comark/vue/plugins/shiki'

export default defineMarkdownComponent({
  name: 'ChatMarkdown',
  plugins: [shiki()],
  class: '*:first:mt-0 *:last:mb-0'
})
Lorsque vous utilisez le plugin shiki, ajoutez le CSS suivant à votre feuille de style pour prendre en charge le mode sombre:
main.css
html.dark .shiki span {
  color: var(--shiki-dark) !important;
  background-color: var(--shiki-dark-bg) !important;
  font-style: var(--shiki-dark-font-style) !important;
  font-weight: var(--shiki-dark-font-weight) !important;
  text-decoration: var(--shiki-dark-text-decoration) !important;
}
Lisez le tutoriel complet Build an AI Chatbot pour un guide étape par étape.