R
Interview Deckreact · next.js · senior/staff
0·0·122
IA Básico

AI no Frontend — Integração Prática

Integrar LLMs em apps React/Next.js: Vercel AI SDK, streaming UI, gestão de estado e UX patterns.

Integrar IA em apps frontend envolve: SDK para comunicação com LLMs (Vercel AI SDK, OpenAI SDK), gerenciamento de estado de conversação (mensagens, loading, error), streaming para UX responsiva, e patterns de UI específicos para IA (skeleton durante geração, auto-scroll, cópia de código, feedback de qualidade). O backend pode ser um Route Handler Next.js ou endpoint externo.

Problema
Gerenciar estado de chat complexo manualmente: lista de mensagens, loading per-message, retry, scroll automático, suporte a markdown. Reinventar a roda para cada projeto.
Solução
Vercel AI SDK: useChat() para conversas multi-turn, useCompletion() para single completions, useObject() para geração de objetos estruturados. Combinar com react-markdown para renderizar MD, react-syntax-highlighter para código, e framer-motion para animações de entrada dos tokens.
Tip
Nunca exponha API keys no cliente. Toda chamada a LLM vai pelo servidor (Next.js Route Handler). O cliente chama seu próprio backend, que chama a API do LLM. Isso também permite adicionar auth, rate limiting, e logging sem mudar o frontend.
// Next.js Route Handler com autenticação
// app/api/chat/route.ts
import { streamText } from 'ai'
import { openai } from '@ai-sdk/openai'
import { getSession } from '@/lib/auth'

export async function POST(req: Request) {
  const session = await getSession(req)
  if (!session) return new Response('Unauthorized', { status: 401 })

  const { messages } = await req.json()

  const result = streamText({
    model: openai('gpt-4o'),
    system: 'Assistente técnico de React e Next.js.',
    messages,
    maxTokens: 2000,
  })
  return result.toDataStreamResponse()
}

// Componente de chat completo
'use client'
import { useChat } from 'ai/react'
import ReactMarkdown from 'react-markdown'
import { useEffect, useRef } from 'react'

export function ChatInterface() {
  const { messages, input, handleInputChange, handleSubmit, isLoading } = useChat()
  const bottomRef = useRef<HTMLDivElement>(null)

  useEffect(() => {
    bottomRef.current?.scrollIntoView({ behavior: 'smooth' })
  }, [messages])

  return (
    <div className="chat-container">
      <div className="messages">
        {messages.map(m => (
          <div key={m.id} className={`message ${m.role}`}>
            <ReactMarkdown>{m.content}</ReactMarkdown>
          </div>
        ))}
        {isLoading && <div className="typing-indicator">⋯</div>}
        <div ref={bottomRef} />
      </div>
      <form onSubmit={handleSubmit}>
        <input value={input} onChange={handleInputChange} />
        <button type="submit" disabled={isLoading}>Enviar</button>
      </form>
    </div>
  )
}
Q.Como adicionar auto-scroll no chat?
A.Ref no elemento final da lista de mensagens + useEffect que chama scrollIntoView toda vez que messages muda: `useEffect(() => { bottomRef.current?.scrollIntoView({ behavior: "smooth" }) }, [messages])`. Atenção: só fazer auto-scroll se o usuário não scrollou para cima manualmente — verificar se está próximo do bottom antes de scrollar.
Q.Como renderizar markdown e código no output do LLM?
A.react-markdown + remark-gfm para markdown básico. Para blocos de código com syntax highlight: substituir o componente code do react-markdown por react-syntax-highlighter. Adicionar botão de cópia em cada bloco de código. A maioria dos LLMs gera markdown — sempre parsear a resposta, nunca exibir como texto cru.
Q.Como implementar feedback de qualidade (thumbs up/down)?
A.Adicionar botões 👍/👎 em cada mensagem do assistente. Salvar o feedback com o messageId e a resposta completa no backend. Usar para: melhorar prompts (análise de thumbs down), criar golden dataset para evals, identificar queries problemáticas. LangSmith e Braintrust têm UI de feedback integrada.
97/122← →