ต้นทุน
รักษาต้นทุนโมเดลให้คาดการณ์ได้เมื่อการใช้งานเติบโต
ส่งทุกงานผ่าน endpoint เดียวที่เข้ากันได้กับ OpenAI กำหนดเส้นทางไปโมเดลที่ถูกที่สุดที่ทำงานได้ และบันทึกการใช้โทเคนที่ทุกคำตอบคืนมา
คัดลอกพรอมป์ต์
แทนช่องในวงเล็บเหลี่ยมแล้ววางใน Claude Code, Codex หรือ AI ที่เข้าถึงเทอร์มินัล ระบบจะติดตั้งสกิล Felo ถามก่อนใช้เครดิต และรันเวิร์กโฟลว์
ตรวจสอบค่าใช้จ่ายโมเดลของเราและเสนอแผนการกำหนดเส้นทางสำหรับงานเหล่านี้: [รายการงานหรือฟีเจอร์] ข้อจำกัด: งบรายเดือน [จำนวน] เป้าหมาย latency [เป้าหมาย] ระดับคุณภาพ [ระดับ] อ่านแค็ตตาล็อกโมเดลสดก่อนแนะนำสิ่งใด สร้าง: 1. ตารางงาน -> โมเดลที่แนะนำ 2. งานใดลดระดับได้หนึ่งขั้น และความเสี่ยงด้านคุณภาพ 3. แผนบันทึกการใช้งานตามงานและฟีเจอร์ 4. สิ่งที่ต้องวัดก่อนเปลี่ยนโปรดักชัน กฎ: - อ่าน ID และราคาโมเดลปัจจุบันจากแค็ตตาล็อกสด ห้ามอ้างราคาจากความจำ - ห้ามเปลี่ยนการตั้งค่าโปรดักชันหรือส่งทราฟฟิกจริง - ถามก่อนใช้เครดิตในการเรียกทดสอบ - เก็บแผน rollback และเพดานการใช้จ่ายต่อฟีเจอร์ - เขียนแผนลง ./routing-plan.md และสรุปในแชท
สำเนายังรวมขั้นตอนติดตั้งและกฎความปลอดภัย
สิ่งที่คุณได้รับ
ตัวอย่างผลลัพธ์จากการรันหนึ่งครั้ง ไม่ใช่การสร้างสด
| งาน | ปัจจุบัน | เสนอ | ความเสี่ยง |
|---|---|---|---|
| จำแนกตั๋ว | โมเดลแรง | โมเดลเร็ว | ต่ำ |
| ร่างคำตอบ | โมเดลแรง | โมเดลแรง | ไม่มี |
| สรุป changelog | โมเดลแรง | โมเดลเร็ว | กลาง |
ก่อนเปลี่ยนอะไร: บันทึกการใช้งานต่องานหนึ่งสัปดาห์ และเปรียบเทียบคุณภาพใน 50 ตัวอย่างผลลัพธ์
การเรียกที่แน่นอน
สำหรับนักพัฒนา: เวิร์กโฟลว์เดียวกันในรูปโค้ดตามลำดับการทำงาน
แสดงการเรียก API จริง
ทุกงานผ่าน endpoint เดียว
ใช้ endpoint เดียวที่เข้ากันได้กับ OpenAI และคีย์เดียว ไม่มี 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 จากทุกคำตอบและบันทึกโทเคนและความหน่วงตามฟีเจอร์
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 และราคาเปลี่ยน ต้องอ่านแคตตาล็อกสดเสมอ
- ไม่ประเมินคุณภาพแทนคุณ ต้องมีตัวอย่างของคุณ
- ไม่แทนที่ระบบเรียกเก็บเงินหรือ observability
คำถาม
ใบแจ้งหนี้จะลดไหม?
บอกว่างานใดลดระดับได้ แต่การประหยัดจริงหลังเทียบตัวอย่างและบันทึกการใช้แล้วเท่านั้น
เรียกโมเดลอัตโนมัติไหม?
เฉพาะเมื่อคุณอนุมัติการเรียกทดสอบ ค่าเริ่มต้นอ่านแคตตาล็อกและเขียนข้อเสนอโดยไม่แตะทราฟฟิกโปรดักชัน
รู้ได้อย่างไรว่าโมเดลใดถูกกว่า?
อ่านแคตตาล็อกโมเดลสดและหน้าค่าบริการ เวิร์กโฟลว์ไม่ตรึงราคาเพราะเปลี่ยน
ตรึงผู้ให้บริการได้ไหม?
ได้เมื่อความหน่วงสำคัญกว่าราคา การตรึงเป็นการเลือก ไม่ใช่กลยุทธ์ retry ให้เพิ่ม fallback ของคุณ
ควรบันทึกอะไร?
ต่อการเรียก: งาน ฟีเจอร์ โมเดล prompt token, completion token, รวม และความหน่วง รวมตามฟีเจอร์ก่อนตั้งงบ
การทบทวนหนึ่งครั้งมีค่าใช้จ่ายเท่าไร?
อ่านแคตตาล็อกไม่สร้างการเรียกโมเดล การเรียกทดสอบคิดตามการใช้งาน พรอมป์ต์ขออนุมัติก่อน
เวิร์กโฟลว์ที่เกี่ยวข้อง
ตอบคำถามฝ่ายสนับสนุนจากเอกสารของคุณเอง
สร้าง LiveDoc โหลดศูนย์ช่วยเหลือและ runbook ภายใน ดึงส่วนที่ตอบทิกเก็ต และให้โมเดลตอบจากหลักฐานนั้นเท่านั้น
เปิดเวิร์กโฟลว์วิจัยเปลี่ยนคำถามหนึ่งข้อเป็นบรีฟวิจัยที่มีแหล่งอ้างอิง
ถามเว็บ บันทึกหน้าเว็บที่อยู่เบื้องหลังคำตอบเป็น Markdown เพิ่มสิ่งที่ผู้ปฏิบัติพูดบน X และเก็บหลักฐานใน LiveDoc ที่ค้นซ้ำได้
เปิดเวิร์กโฟลว์สำนักงานเปลี่ยนหน้างานวิจัยเป็นงานนำเสนอ
สกัดหน้า เก็บเป็นบริบท LiveDoc ให้ PPT Task API สร้างเด็ค และถามจนได้ลิงก์ที่เสร็จ
เปิดเวิร์กโฟลว์ปรับให้เป็นของคุณ
สูตรเดิม ปรับตามวิธีที่คุณส่งมอบจริง
บันทึกก่อนเท่านั้น
ก่อนโปรดักชัน บันทึกการใช้งานหนึ่งสัปดาห์แล้วตัดสินใจลดระดับ
งบต่อฟีเจอร์
ตั้งวงเงินรายเดือนต่อฟีเจอร์และเตือนหรือลดระดับเมื่อเกิน
ตรึงผู้ให้บริการเพื่อความหน่วง
เมื่อความหน่วงสำคัญกว่าราคา ตรึงผู้ให้บริการและเพิ่ม fallback
ไปต่อ
หน้าเอกสารอ้างอิงเบื้องหลังสูตรนี้และก้าวต่อไป