본문으로 건너뛰기

Quick Start: Octane

Octane 앱에 AI 채팅을 추가할 수 있습니다. 이 페이지를 마치면 TanStack AI로 구동되는 스트리밍 채팅 컴포넌트를 갖게 됩니다.

팁: 제공자마다 키를 하나씩 사용하고 싶지 않다면 OpenRouter를 사용하세요. 하나의 API 키로 300개 이상의 모델을 제공합니다.

1. 설치

npm install @tanstack/ai @tanstack/ai-octane @tanstack/ai-openai octane
# or
pnpm add @tanstack/ai @tanstack/ai-octane @tanstack/ai-openai octane

@tanstack/ai-octane은 컴파일되지 않은 .tsrx 소스를 게시합니다. Octane 플러그인이 이를 컴파일합니다. 앱 빌드에 octane/compiler/vite(또는 rspack / rspeedy에 해당하는 항목)를 추가하세요.

2. 서버에서 스트리밍

TanStack AI SSE를 반환하는 백엔드라면 무엇이든 작동합니다. 다음은 그러한 Express 핸들러입니다.

import express from 'express'
import { chat, toServerSentEventsResponse } from '@tanstack/ai'
import { openaiText } from '@tanstack/ai-openai'

const app = express()
app.use(express.json())

app.post('/api/chat', async (req, res) => {
const { messages } = req.body

if (!process.env.OPENAI_API_KEY) {
res.status(500).json({ error: 'OPENAI_API_KEY not configured' })
return
}

try {
const stream = chat({
adapter: openaiText('gpt-5.5'),
messages,
})

const response = toServerSentEventsResponse(stream)
res.writeHead(response.status, Object.fromEntries(response.headers))

const body = response.body
if (body) {
const reader = body.getReader()
const pump = async () => {
const { done, value } = await reader.read()
if (done) {
res.end()
return
}
res.write(value)
await pump()
}
await pump()
}
} catch (error) {
res.status(500).json({
error: error instanceof Error ? error.message : 'An error occurred',
})
}
})

app.listen(3000, () => console.log('Server running on port 3000'))

chat()은 클라이언트가 보내는 AG-UI threadId를 devtools 상관 관계에 사용합니다.

3. Octane에서 useChat 호출

import { useState } from 'octane'
import { useChat, fetchServerSentEvents } from '@tanstack/ai-octane'

export function Chat() {
const [input, setInput] = useState('')
const { messages, sendMessage, isLoading } = useChat({
connection: fetchServerSentEvents('/api/chat'),
})

function handleSubmit() {
if (input.trim() && !isLoading) {
void sendMessage(input)
setInput('')
}
}

return (
<div>
{messages.map((message) => (
<div key={message.id}>
<strong>{message.role === 'assistant' ? 'Assistant' : 'You'}</strong>
<p>
{message.parts
.filter((part) => part.type === 'text')
.map((part) => part.content)
.join('')}
</p>
</div>
))}
<form
onSubmit={(event) => {
event.preventDefault()
handleSubmit()
}}
>
<input
value={input}
placeholder="Type a message..."
disabled={isLoading}
onInput={(event) => setInput(event.currentTarget.value)}
/>
<button type="submit" disabled={!input.trim() || isLoading}>
Send
</button>
</form>
</div>
)
}

useChat은 텍스트 상자를 관리하지 않습니다. 값을 useState에 보관하고 sendMessage에 전달하세요. Octane 텍스트 컨트롤은 onInput을 발생시키며 합성 onChange는 발생시키지 않습니다.

4. 서버에 API 키 저장

# OpenRouter (one key, many models)
OPENROUTER_API_KEY=sk-or-...

# OpenAI
OPENAI_API_KEY=your-openai-api-key

서버가 이 키를 읽습니다. 브라우저로 보내지 마세요.

Octane 참고 사항

  • 컴파일되지 않은 소스. 패키지에 dist가 없습니다. Octane 컴파일러가 @tanstack/ai-octane을 확인해야 합니다.
  • React와 동일한 훅 이름. useChat, useGeneration, useAudioRecorder 등이 있습니다. 가져오기 경로를 @tanstack/ai-react에서 @tanstack/ai-octane으로 변경하세요.
  • 정리는 자동입니다. 훅은 마운트 시 attach()를 호출하고 언마운트 시 detach()dispose()를 호출합니다.

다음 단계

  • 옵션, 큐, 인터럽트 및 도구는 Octane API를 참조하세요.
  • 함수 호출은 Tools를 참조하세요.
  • 다른 제공자는 Adapters를 참조하세요.