รัน RAG brain ของ Quivr บน custom OpenAI-compatible endpoint
Updated 2026-07-29
LLMEndpointConfig ของ quivr-core รับฟิลด์ llm_base_url เก็บ supplier ไว้เป็น openai ตั้ง llm_base_url เป็น https://api.apisrouter.com/v1 ส่ง key เดียว แล้วทุก brain.ask() จะสร้างคำตอบผ่าน gateway ด้วย model id ในแคตตาล็อกใดก็ได้
คำตอบสั้น ๆ: llm_base_url ใน LLMEndpointConfig
Quivr เวอร์ชันปัจจุบันคือ quivr-core ซึ่งเป็น Python RAG library และการต่อสาย LLM ของมันชัดเจน LLMEndpointConfig พก supplier (ค่าเริ่มต้น openai), model, llm_base_url และ llm_api_key; LLMEndpoint.from_config() สร้าง client จริงจากฟิลด์เหล่านั้น และสำหรับ supplier openai client นั้นคือ ChatOpenAI ของ LangChain ที่สร้างด้วย base URL ของคุณ ตั้ง llm_base_url เป็น https://api.apisrouter.com/v1 ตั้ง model เป็น id ในแคตตาล็อกใดก็ได้ แล้วส่ง endpoint ให้ Brain ของคุณ key สามารถมาจากฟิลด์ config หรือ environment: เมื่อ llm_api_key ไม่ได้ตั้งค่าไว้ quivr-core จะ resolve มันจาก environment variable ที่ตั้งชื่อตาม supplier ซึ่งสำหรับ supplier openai คือ OPENAI_API_KEY ทั้งสองเส้นทางเป็นพฤติกรรมต้นทาง อ่านได้ใน quivr_core/rag/entities/config.py และ quivr_core/llm/llm_endpoint.py
from quivr_core.llm import LLMEndpoint
from quivr_core.rag.entities.config import (
DefaultModelSuppliers, LLMEndpointConfig)
llm = LLMEndpoint.from_config(LLMEndpointConfig(
supplier=DefaultModelSuppliers.OPENAI,
model="claude-sonnet-4-6", # any catalog id
llm_base_url="https://api.apisrouter.com/v1",
llm_api_key=os.environ["APISROUTER_API_KEY"],
))Quivr เป็นอะไรตอนนี้ และช่อง LLM อยู่ตรงไหน
Quivr (QuivrHQ บน GitHub มีดาวประมาณ 39K) เริ่มต้นจากแอปพลิเคชัน second-brain แบบเต็มรูปแบบและเปลี่ยนทิศไปเป็น quivr-core: RAG library ที่มีความเห็นชัดเจนซึ่งคุณฝังเข้าไปในผลิตภัณฑ์ของคุณเอง คุณป้อนไฟล์ให้มัน มัน parse และแบ่ง chunk, embed chunk เข้า vector store (FAISS เป็นค่าเริ่มต้น รองรับ PGVector) และตอบคำถามเหนือมันผ่าน retrieval workflow ที่ตั้งค่าได้ Brain object คือหน่วยหลัก: Brain.from_files() ทำ ingestion, brain.ask() ทำ retrieve และ generate Generation คือขั้นตอนเดียวที่ต้องการ chat model retrieval workflow ประกอบ context จากเอกสารของคุณ และ LLMEndpoint ที่คุณส่งเข้าไปเขียนคำตอบที่อิงหลักฐาน endpoint นั้นถูกสร้างครั้งเดียวจาก LLMEndpointConfig ดังนั้นการตัดสินใจเรื่อง base URL เกิดขึ้นตอนสร้างและมีผลกับทุก ask() บน brain นั้น เพราะ ChatOpenAI ส่งฟิลด์ model ผ่านเป็นสตริงธรรมดาผ่าน /v1/chat/completions id สามารถเป็น Claude, DeepSeek, GPT หรือ Gemini เมื่อ endpoint หลัง llm_base_url เสิร์ฟพวกมัน ข้อสังเกตตรง ๆ เกี่ยวกับสถานะโปรเจกต์: repository เงียบมาตั้งแต่กลางปี 2025 ดังนั้นให้ถือว่า quivr-core เป็น library ที่มั่นคงมากกว่าจะเคลื่อนไหวเร็ว พื้นผิว config ที่อธิบายที่นี่ตรงกับ main branch ล่าสุด และประวัติที่เงียบหมายความว่ามันไม่น่าจะเปลี่ยนใต้เท้าคุณ มันยังหมายความว่า tutorial เก่าที่อธิบายแอป full-stack ที่เลิกใช้แล้ว (ไฟล์ .env ของ backend, frontend ที่ hosted ไว้) ไม่ตรงกับโค้ดอีกต่อไป
ตั้งค่าแบบเต็ม: brain ที่มี LLM route ผ่าน gateway
แพทเทิร์นที่ใช้จริงส่ง LLMEndpoint ที่ตั้งค่าแล้วเข้าไปใน Brain.from_files สิ่งอื่นทั้งหมดเกี่ยวกับ brain (การ parse, การแบ่ง chunk, FAISS store, retrieval workflow) เป็นอิสระจาก LLM endpoint และยังคงค่าเริ่มต้นของมัน ระวังเรื่อง embedder ถ้าคุณไม่ส่งตัวไหนเข้าไป quivr-core จะสร้าง OpenAIEmbeddings ของ LangChain ด้วยค่าเริ่มต้นของมันเอง ซึ่ง authenticate ด้วย OPENAI_API_KEY และเล็ง endpoint ของ OpenAI มาตรฐาน นั่นคือ client แยกต่างหากจาก chat LLM: การ route generation ผ่าน gateway ไม่ได้ย้ายมัน ส่ง embedder ของคุณเอง (wrapper แบบ sentence-transformers ท้องถิ่น หรือ instance Embeddings ของ LangChain ที่คุณตั้งค่าเอง) ถ้าคุณไม่ต้องการให้ครึ่ง embedding พึ่งพาบัญชี OpenAI
import os
from quivr_core import Brain
from quivr_core.llm import LLMEndpoint
from quivr_core.rag.entities.config import (
DefaultModelSuppliers, LLMEndpointConfig)
llm = LLMEndpoint.from_config(LLMEndpointConfig(
supplier=DefaultModelSuppliers.OPENAI,
model="claude-sonnet-4-6",
llm_base_url="https://api.apisrouter.com/v1",
llm_api_key=os.environ["APISROUTER_API_KEY"],
max_output_tokens=2048,
temperature=0.3,
))
brain = Brain.from_files(
name="team-docs",
file_paths=["handbook.pdf", "runbook.md"],
llm=llm,
# embedder=... # separate component; see note above
)
print(brain.ask("What is the on-call escalation policy?").answer)เลือกโมเดลสำหรับคำตอบ RAG
การเปรียบเทียบผู้เข้าแข่งขันเป็นการเปลี่ยนแปลงตอนสร้าง: สร้าง LLMEndpoint สองตัวเทียบกับ base URL เดียวกัน สอง brain บนไฟล์เดียวกัน แล้ว diff คำตอบบนชุดคำถามคงที่ usage log ต่อ key ตั้งราคาการรันของแต่ละผู้เข้าแข่งขัน ดังนั้นคุณภาพต่อ token จึงถูกวัด ไม่ใช่ถกเถียง
- RAG generation เป็นงานที่ input หนัก: chunk ที่ retrieve มาครองสัดส่วนของ prompt ราคาต่อ input token ตั้งต้นทุนของคำตอบ ซึ่งเป็นเหตุผลที่ id เร็วมักลดบิลลงครึ่งหนึ่งโดยไม่แตะคุณภาพ retrieval
- claude-sonnet-4-6 คือค่าเริ่มต้นที่เชื่อถือได้สำหรับคำตอบที่อิงหลักฐาน ที่เคารพ context ที่ retrieve มาและปฏิเสธอย่างสะอาดเมื่อเอกสารไม่มีคำตอบ
- ผลิตภัณฑ์ที่ฝังอยู่ในระบบและมี volume สูง (use case ที่ Quivr ระบุไว้) ทำงานได้ดีบน claude-haiku-4-5-20251001, deepseek-v4-flash หรือ gemini-3.5-flash สำหรับคำถามทั่วไป
- max_context_tokens ใน config เดียวกันควบคุมว่า pipeline บรรจุ context ที่ retrieve มาได้มากแค่ไหน การเพิ่มมันเข้ากันได้ดีกับ id แบบ context ยาวและเพิ่มค่าใช้จ่าย input ตามสัดส่วน
- model prefix ที่ไม่รู้จักจะ fallback ไปที่ tokenizer ทั่วไปสำหรับการจัดงบ ซึ่งเป็นแค่เรื่องความสวยงาม ตัว request เองพก id ของคุณไปยัง endpoint โดยไม่เปลี่ยนแปลง
จ่ายตามการใช้งาน · ถูกกว่าราคาทางการ
Selected models are priced below official list prices. Exact input, output, cache, and per-request prices are shown for each model.
| โมเดล | ราคาทางการ | ราคาของเรา |
|---|---|---|
| Claude Sonnet 4.6 | $3.00 / $15.00 per M | $2.40 / $12.00 per M |
| Claude Haiku 4.5 20251001 | $1.00 / $5.00 per M | $0.80 / $4.00 per M |
| GPT-5.4 mini | $0.75 / $4.50 per M | $0.60 / $3.60 per M |
| DeepSeek V4 Flash | $0.14 / $0.28 per M | $0.10 / $0.30 per M |
| Gemini 3.5 Flash | $1.50 / $9.00 per M | $1.20 / $7.20 per M |
แก้ไขความเข้าใจผิดที่พบบ่อยเกี่ยวกับ Quivr
คู่มือที่หมุนเวียนอยู่อธิบายพื้นผิวที่ Quivr ไม่มีอีกต่อไป ดังนั้นคุ้มค่าที่จะระบุให้ชัดว่าโค้ดปัจจุบันทำอะไรจริง ๆ quivr-core อิง LangChain ไม่ใช่ LiteLLM enum supplier เลือก LangChain chat class และ openai แม็ปไปที่ ChatOpenAI พร้อม llm_base_url ของคุณ ถ้า tutorial บอกให้คุณตั้งค่า LiteLLM proxy หรือ setting api_base ข้างใน Quivr นั่นอธิบายสถาปัตยกรรมเก่ากว่า ฟิลด์ปัจจุบันคือ llm_base_url บน LLMEndpointConfig แอป full-stack เลิกใช้แล้ว คำแนะนำเกี่ยวกับ .env ของ backend, การตั้งค่า Supabase หรือ model picker ในแอปหมายถึงแอปก่อนการเปลี่ยนทิศ ซึ่งไม่ใช่สิ่งที่ repository นี้ ship อีกต่อไป การตั้งค่าตอนนี้เกิดขึ้นในโค้ด Python ของคุณ (หรือแอปของคุณเองรอบ library) env var ของ key มาจาก supplier สำหรับ supplier openai คือ OPENAI_API_KEY แม้ endpoint จะไม่ใช่ OpenAI ก็ตาม ถ้าคุณไม่ต้องการใช้ชื่อนั้นซ้ำ ให้ส่ง llm_api_key อย่างชัดเจนใน config ซึ่งมีความสำคัญกว่าและเก็บ environment ให้สะอาด embedder แยกต่างหาก การ route generation ไม่ได้ย้าย embedding; embedder ค่าเริ่มต้นคือ OpenAIEmbeddings พร้อม credential ของตัวเอง ตัดสินใจสองครึ่งนี้แยกกัน และการ re-embed store ที่มีอยู่จำเป็นก็ต่อเมื่อคุณเปลี่ยน embedding model เอง
ใครที่ route quivr-core ผ่าน gateway
- ทีมผลิตภัณฑ์ที่ฝัง RAG ในแอปของตัวเองที่ต้องการให้ generation model เป็นค่า config ไม่ใช่พันธะกับ vendor ที่ฝังลึกใน stack
- นักพัฒนาที่รันหลาย brain ที่ระดับคุณภาพต่างกัน: key เดียว endpoint เดียว model id ต่อ brain
- ทีมที่ต้องการคำตอบที่อิงหลักฐานคุณภาพ Claude เบื้องหลัง config ทรง OpenAI โดยไม่ต้องเพิ่ม SDK หรือบัญชี provider ตัวที่สอง
- builder ที่ทำ benchmark โมเดล generation บน corpus คงที่ ที่ผู้เข้าแข่งขันแต่ละรายเป็นแค่การเปลี่ยน LLMEndpointConfig หนึ่งครั้ง
- นักพัฒนาที่ไม่มีสิทธิ์เข้าถึงระบบเก็บเงินของ vendor รายหนึ่ง การเข้าถึงแบบเติมเงินโดยไม่ต้องใช้บัตรตัดการพึ่งพาการสมัครต่อ provider ออกไป
ตรวจสอบ endpoint และ debug ask() แรก
ยืนยันว่า gateway ลิสต์โมเดลของคุณก่อนจะ ingest อะไร ฟิลด์ model ต้องตรงกับ id ที่เสิร์ฟจริงเป๊ะ ความล้มเหลวในการรันครั้งแรกคาดเดาได้ คำเตือนว่า API key สำหรับ supplier openai ไม่ได้ตั้งค่าไว้หมายความว่าทั้ง llm_api_key และ OPENAI_API_KEY มองไม่เห็นตอนสร้าง config คำเตือนเกิดขึ้นตอนสร้าง ความล้มเหลวเกิดตอน ask() ครั้งแรก 401 หมายความว่า key ที่ resolve ได้ไม่ตรงกับ endpoint ใน llm_base_url error model-not-found คือการพิมพ์ id ผิดเทียบกับ /v1/models และ authentication error ที่เกี่ยวกับ embedding ระหว่าง Brain.from_files คือ embedder ค่าเริ่มต้นที่แยกต่างหากกำลังขอ credential OpenAI ของตัวเอง ซึ่งไม่มีการตั้งค่า llm_base_url ใดจะแก้ได้ ส่ง embedder ที่คุณควบคุมเอง เมื่อคำตอบไหลลื่นแล้ว console ของ APIsRouter แสดงโมเดลต่อ request, จำนวน token และค่าใช้จ่าย สำหรับ library ที่บรรจุ chunk ที่ retrieve มาเข้าไปในทุก prompt ตัวเลข token ต่อคำตอบบน corpus จริงของคุณคือตัวเลขที่ควรขับเคลื่อนการเลือกโมเดลของคุณ
curl -s https://api.apisrouter.com/v1/models \
-H "Authorization: Bearer $APISROUTER_API_KEY" | head -50คำถามที่พบบ่อย
Quivr รองรับ custom OpenAI-compatible base URL ไหม?
รองรับ LLMEndpointConfig ของ quivr-core มีฟิลด์ llm_base_url และสำหรับ supplier openai library สร้าง ChatOpenAI ของ LangChain เทียบกับ URL นั้น ตั้งมันเป็น gateway endpoint แล้วส่ง model id ในแคตตาล็อกใดก็ได้
Quivr อิง LiteLLM ไหม?
ไม่ใช่ในโค้ดปัจจุบัน quivr-core เลือก LangChain chat class ตาม supplier; supplier openai ใช้ ChatOpenAI พร้อม llm_base_url ของคุณ คู่มือที่อธิบาย LiteLLM api_base ข้างใน Quivr อ้างถึงสถาปัตยกรรมเก่ากว่า
brain.ask() ตอบด้วยโมเดล Claude หรือ DeepSeek ได้ไหม?
ได้ ฟิลด์ model ถูกส่งผ่านเป็นสตริงธรรมดาผ่าน /v1/chat/completions ดังนั้น claude-sonnet-4-6, deepseek-v4-flash หรือ id อื่นใดที่ endpoint เสิร์ฟก็ใช้ได้ภายใต้ supplier openai
environment variable ตัวไหนเก็บ key?
เมื่อ llm_api_key ไม่ได้ตั้งค่าไว้ใน config quivr-core จะได้ตัวแปรมาจากชื่อ supplier: OPENAI_API_KEY สำหรับ supplier openai การตั้ง llm_api_key อย่างชัดเจนใน LLMEndpointConfig มีความสำคัญกว่าและหลีกเลี่ยงการใช้ชื่อนั้นซ้ำ
llm_base_url ย้าย embedding ด้วยไหม?
ไม่ย้าย embedder ค่าเริ่มต้นเป็น OpenAIEmbeddings client แยกต่างหากพร้อม credential และ endpoint ของตัวเอง route generation ผ่าน gateway แล้วส่ง embedder ของคุณเองถ้าคุณต้องการให้ครึ่ง embedding พ้นจาก OpenAI ด้วย
โปรเจกต์ Quivr ยังมีการดูแลอยู่ไหม?
repository เงียบมาตั้งแต่กลางปี 2025 ดังนั้นให้ถือว่ามันเป็น library ที่มั่นคงมากกว่าจะเคลื่อนไหวเร็ว พื้นผิว llm_base_url ที่บันทึกไว้ที่นี่ตรงกับ main branch ล่าสุด และแอป full-stack ก่อนการเปลี่ยนทิศที่มันแทนที่ก็เลิกใช้แล้ว