비용
사용량이 늘어도 모델 비용을 예측 가능하게 유지하기
모든 작업을 같은 OpenAI-compatible endpoint로 보내고 작업을 수행할 수 있는 가장 저렴한 모델로 라우팅하며 각 응답이 반환하는 토큰 사용량을 기록합니다.
프롬프트 복사
대괄호 항목을 바꾼 뒤 Claude Code, Codex 또는 터미널에 접근할 수 있는 AI에 붙여넣으세요. Felo 스킬을 설치하고 크레딧을 쓰기 전에 확인한 뒤 워크플로를 실행합니다.
우리 모델 지출을 검토하고 이 작업들을 위한 라우팅 계획을 제안해 주세요: [작업 또는 기능 목록]. 제약: 월 예산 [금액], 지연 목표 [목표], 품질 기준 [기준]. 무엇이든 추천하기 전에 라이브 모델 카탈로그를 읽으세요. 다음을 작성해 주세요. 1. 작업 -> 모델 추천 표. 2. 한 단계 내릴 수 있는 작업과 품질 위험. 3. 작업과 기능별 사용 로그 계획. 4. 프로덕션을 바꾸기 전에 측정할 것. 규칙: - 현재 모델 ID와 가격을 라이브 카탈로그에서 읽으세요. 기억에서 요금을 인용하지 마세요. - 프로덕션 설정을 바꾸거나 실제 트래픽을 보내지 마세요. - 테스트 호출에 크레딧을 쓰기 전에 먼저 물어보세요. - 롤백 계획과 기능별 지출 한도를 유지하세요. - 계획을 ./routing-plan.md에 쓰고 채팅에서 요약해 주세요.
복사 내용에는 설치 단계와 안전 규칙도 포함됩니다.
완성되는 것
실행 시 예제 출력입니다. 실시간 생성이 아닙니다.
| 작업 | 현재 | 제안 | 위험 |
|---|---|---|---|
| 티켓 분류 | 강한 모델 | 빠른 모델 | 낮음 |
| 답변 초안 | 강한 모델 | 강한 모델 | 없음 |
| 체인지로그 요약 | 강한 모델 | 빠른 모델 | 중간 |
바꾸기 전에: 일주일 동안 작업별 사용량을 기록하고 무작위 50개 출력에서 품질을 비교한다.
실제 호출
개발자용: 같은 워크플로를 실행 순서대로 담은 복사 가능한 코드.
실제 API 호출 보기
모든 작업을 같은 endpoint로 보내기
OpenAI-compatible endpoint와 키를 통일해 공급자마다 SDK를 나누지 않습니다.
routing.ts const BASE_URL = "https://openapi.felo.ai/api/v1"; const headers = { Authorization: `Bearer ${process.env.FELO_API_KEY}`, "Content-Type": "application/json", }; type Completion = { choices: { message: { content: string } }[]; usage: { prompt_tokens: number; completion_tokens: number; total_tokens: number }; }; async function chat(model: string, prompt: string): Promise<Completion> { const res = await fetch(`${BASE_URL}/chat/completions`, { method: "POST", headers, body: JSON.stringify({ model, messages: [{ role: "user", content: prompt }] }), }); if (!res.ok) throw new Error(`${res.status}: ${await res.text()}`); return res.json() as Promise<Completion>; } const summary = await chat( "claude-haiku-5-5", "Summarize this changelog in three bullets: …", ); console.log(summary.choices[0].message.content);예제 출력
{ "choices": [{ "message": { "content": "• …" } }], "usage": { "prompt_tokens": 812, "completion_tokens": 96, "total_tokens": 908 } }작업별로 모델 라우팅하기
작업 복잡도로 빠른 모델이나 강한 모델을 고르고 먼저 현재 기준을 기록합니다.
routing.ts type TaskKind = "classify" | "extract" | "summarize" | "draft" | "review"; const MODEL_ROUTES: Record<TaskKind, string> = { classify: "claude-haiku-5-5", extract: "claude-haiku-5-5", summarize: "claude-haiku-5-5", draft: "claude-sonnet-5-5", review: "claude-sonnet-5-5", }; export async function route(kind: TaskKind, prompt: string) { const model = MODEL_ROUTES[kind]; const result = await chat(model, prompt); return { model, text: result.choices[0].message.content, usage: result.usage, }; }예제 출력
{ "model": "claude-haiku-5-5", "text": "• …", "usage": { "prompt_tokens": 812, "completion_tokens": 96, "total_tokens": 908 } }사용량을 읽고 기록하기
각 응답의 usage를 읽어 기능별로 token과 지연을 기록합니다.
routing.ts type UsageRecord = { model: string; kind: TaskKind; promptTokens: number; completionTokens: number; totalTokens: number; }; const usageLog: UsageRecord[] = []; function logUsage(kind: TaskKind, model: string, usage: Completion["usage"]) { const entry: UsageRecord = { model, kind, promptTokens: usage.prompt_tokens, completionTokens: usage.completion_tokens, totalTokens: usage.total_tokens, }; usageLog.push(entry); console.log(JSON.stringify(entry)); // ship this line to your metrics store return entry; } export function tokensByModel() { return usageLog.reduce<Record<string, number>>((totals, entry) => { totals[entry.model] = (totals[entry.model] ?? 0) + entry.totalTokens; return totals; }, {}); } const result = await route("summarize", "Summarize this changelog in three bullets: …"); logUsage("summarize", result.model, result.usage); console.log(tokensByModel());예제 출력
{"model":"claude-haiku-5-5","kind":"summarize","promptTokens":812,"completionTokens":96,"totalTokens":908} { "claude-haiku-5-5": 18234, "claude-sonnet-5-5": 4201 }하나의 키로 모든 공급자 다루기
같은 Felo 키로 카탈로그의 모델을 호출해 공급자 관리를 줄입니다.
routing.ts async function chatOnChannel(model: string, prompt: string, channel?: string) { const res = await fetch(`${BASE_URL}/chat/completions`, { method: "POST", headers: { ...headers, ...(channel ? { "X-Felo-Channel": channel } : {}), }, body: JSON.stringify({ model, messages: [{ role: "user", content: prompt }] }), }); if (!res.ok) throw new Error(`${res.status}: ${await res.text()}`); return res.json() as Promise<Completion>; } // Leave `channel` undefined for the default supplier. export function routePinned(kind: TaskKind, prompt: string, channel?: string) { return chatOnChannel(MODEL_ROUTES[kind], prompt, channel); }가격은 라이브 카탈로그에서 읽기
요금을 고정하지 않고 모델 카탈로그와 가격 페이지에서 현재 가격을 읽습니다.
routing.ts type Catalog = { data: { id: string; owned_by: string; model_kind: string }[]; }; export async function chatModelIds() { const res = await fetch( `${BASE_URL}/models?exclude_video_and_decisions=true`, { headers }, ); if (!res.ok) throw new Error(`${res.status}: ${await res.text()}`); const catalog = (await res.json()) as Catalog; return catalog.data .filter((model) => model.model_kind === "chat") .map((model) => model.id); } // Price `tokensByModel()` against https://openapi.felo.ai/pricing and // https://openapi.felo.ai/models. Keep the links, not the rates, in your code.예제 출력
["claude-haiku-5-5", "claude-sonnet-5-5"]
포함되는 것
- 통일된 endpoint와 키
- 작업별 빠른/강한 모델 선택
- 각 응답의 토큰 사용량 로그
- 코드에 고정하지 않고 라이브 카탈로그에서 읽는 가격
하지 않는 것
- 청구서 절감을 보장하지 않음
- 프로덕션 트래픽을 자동 전환하지 않음
- 모델 id와 가격은 변하므로 항상 라이브 카탈로그를 읽음
- 품질 평가를 대신하지 않음. 자체 샘플 필요
- 청구나 관측 시스템을 대체하지 않음
자주 묻는 질문
청구서가 줄어드나요?
어떤 작업을 더 저렴한 계층으로 내릴 수 있는지 제안하지만 샘플 출력을 비교하고 사용량을 기록해야 절감이 현실이 됩니다.
자동으로 모델을 호출하나요?
테스트 호출을 승인할 때만 합니다. 기본은 카탈로그를 읽고 제안을 쓰며 프로덕션 트래픽은 건드리지 않습니다.
어떤 모델이 더 저렴한지 어떻게 알나요?
라이브 모델 카탈로그와 가격 페이지를 읽습니다. 가격이 변하므로 워크플로는 요금을 고정하지 않습니다.
공급자를 고정할 수 있나요?
네, 지연이 가격보다 중요할 때 가능합니다. 고정은 선택이지 재시도 전략이 아니며 fallback은 직접 추가합니다.
무엇을 기록해야 하나요?
호출마다 작업, 기능, 모델, prompt token, completion token, 총 token, 지연을 기록합니다. 기능별로 집계한 뒤 예산을 정합니다.
리뷰 한 번 비용은?
카탈로그 읽기는 모델 호출을 만들지 않습니다. 테스트 호출은 사용량 기반이며 프롬프트는 호출 전에 승인을 요청합니다.
관련 워크플로
자신의 문서로 지원 질문에 답하기
LiveDoc을 만들고 헬프 센터와 내부 runbook을 읽어 들인 뒤 티켓에 답할 구절을 검색하고 그 증거만으로 모델이 답하게 합니다.
워크플로 열기리서치질문 하나를 출처 있는 리서치 브리프로 바꾸기
웹에 질문을 던지고, 답변의 근거 페이지를 Markdown으로 가져오고, X의 실무자 의견을 더한 뒤 증거를 나중에도 검색할 수 있는 LiveDoc에 남깁니다.
워크플로 열기오피스리서치 페이지를 슬라이드 덱으로 바꾸기
페이지를 추출해 LiveDoc 맥락으로 저장하고 PPT Task API가 deck을 만드는 동안 완료 링크를 폴링합니다.
워크플로 열기내 방식으로 바꾸기
같은 레시피를 실제 배포 방식에 맞게 조정합니다.
먼저 기록만 하기
프로덕션 전에 일주일 사용량을 기록한 뒤 다운그레이드를 판단합니다.
기능별 예산 정하기
각 기능에 월 상한을 두고 초과 시 경고하거나 축소합니다.
지연 우선으로 공급자 고정
지연이 가격보다 중요하면 공급자를 고정하고 자체 fallback을 더합니다.
더 알아보기
이 레시피의 배경이 되는 참고 페이지와 다음에 볼 곳.