เรียกใช้ในไม่กี่บรรทัด
LARN API ใช้รูปแบบเดียวกับ OpenAI Chat Completions จึงใช้กับ SDK ของ OpenAI และเครื่องมือที่รองรับ OpenAI ได้ทันที เปลี่ยนแค่ base URL กับ API key
| Base URL | |
| การยืนยันตัวตน | Authorization: Bearer larn-sk-… |
| Endpoints | POST /v1/chat/completions GET /v1/models GET /v1/models/{id} |
สร้าง API key ได้ที่ แดชบอร์ด
โมเดล
มีโมเดลเดียวชื่อ larn ใส่ชื่อนี้ในช่อง model แล้วใช้ได้เลย ระบบปรับความเร็วกับความลึกให้เหมาะกับแต่ละคำถามเอง ไม่ต้องเลือกโมเดลหรือ effort
- ส่งชื่อโมเดลอื่นมา หรือไม่ส่งช่อง model เลย ก็ได้คำตอบจากโมเดลนี้ตามค่าเริ่มต้นของระบบ เครื่องมือที่ตั้งชื่อโมเดลของเจ้าอื่นค้างไว้จึงใช้ได้ทันทีที่เปลี่ยน base URL กับ API key ถ้าได้ 404 model_not_found แปลว่าผู้ดูแลระบบตั้งให้รับเฉพาะชื่อนี้ ให้เปลี่ยนเป็นชื่อข้างบน
- GET /v1/models คืนรายการเดียวคือโมเดลนี้
- พารามิเตอร์เลือก effort เช่น reasoning_effort ถูกเมิน เพราะระบบเลือกความลึกให้เอง
- โมเดลเบื้องหลังถูกอัปเดตไปเรื่อย ๆ โดยที่ชื่อนี้และโค้ดของคุณไม่ต้องเปลี่ยน คำตอบต่อคำถามเดียวกันจึงอาจไม่เหมือนเดิมทุกครั้ง อย่าออกแบบงานที่ต้องพึ่งคำตอบที่เหมือนเดิมทุกตัวอักษร
พารามิเตอร์ที่รองรับ: messages, stream, stream_options, temperature, top_p, max_tokens, max_completion_tokens, stop, seed, presence_penalty, frequency_penalty, tools, tool_choice, parallel_tool_calls, response_format, logit_bias, logprobs, top_logprobs
ตอนนี้เปิดให้ใช้งานเฉพาะผู้ที่ได้รับเชิญ ติดต่อผู้ดูแลระบบเพื่อขอบัญชี
ตอบทันที
เมื่อเรียกแบบ stream คำตอบจะเริ่มด้วยข้อความเปิดสั้น ๆ แล้วคำตอบเต็มตามมาใน stream เดียวกัน ผู้ใช้ของคุณจึงไม่ต้องจ้องหน้าจอว่างระหว่างรอ ข้อความเปิดมาเป็น delta.content ธรรมดา client ทั่วไปไม่ต้องทำอะไรเพิ่ม
ระบบข้ามขั้นนี้เองเมื่อไม่ได้ stream เมื่อมี tools เมื่อขอ response_format เป็น JSON หรือเมื่อข้อความสุดท้ายไม่ได้มาจาก user งานอัตโนมัติแบบนี้จึงได้คำตอบล้วนอยู่แล้ว
ปิดเมื่อไม่ต้องการ
งานอัตโนมัติที่เรียกแบบ stream และต้องการเฉพาะคำตอบเต็ม ให้ปิดด้วยวิธีใดวิธีหนึ่ง
- ทั้ง key: ตั้งค่า "ตอบทันที" ของ key ในแดชบอร์ดเป็นปิด
- ทีละ request ด้วย header
x-larn-instant: off - หรือใส่ใน body
"larn": {"instant": false}
ค้นเว็บ
มีสองทาง ทางแรกคือให้โปรแกรมของคุณค้นเอง (tool calling มาตรฐาน) ซึ่งไม่มีค่าใช้จ่ายเพิ่มจากเรา ทางที่สองคือให้ระบบค้นให้ เป็นบริการเสริมที่คิดเครดิตเพิ่มต่อการค้นหนึ่งครั้ง
ทางที่ 1: ค้นเองที่ฝั่งคุณ
ประกาศ tool ค้นเว็บของคุณใน tools โมเดลจะตอบเป็น tool_calls ให้โปรแกรมของคุณไปค้นด้วย key ของคุณเอง แล้วส่งผลกลับมาเป็นข้อความ role "tool" ตัวอย่างนี้ใช้ Brave Search จะเปลี่ยนเป็นบริการค้นเจ้าไหนก็ได้
import json, requests
from openai import OpenAI
client = OpenAI(base_url="https://api.larn.io/v1", api_key="larn-sk-...")
def web_search(query: str) -> str:
r = requests.get("https://api.search.brave.com/res/v1/web/search",
headers={"X-Subscription-Token": "YOUR_SEARCH_KEY"},
params={"q": query, "count": 5}, timeout=10)
hits = r.json().get("web", {}).get("results", [])
return json.dumps([{"title": h["title"], "url": h["url"], "text": h.get("description", "")} for h in hits], ensure_ascii=False)
tools = [{"type": "function", "function": {
"name": "web_search", "description": "Search the internet for current information",
"parameters": {"type": "object", "properties": {"query": {"type": "string"}}, "required": ["query"]}}}]
messages = [{"role": "user", "content": "หาราคาแรม kingston ให้หน่อย"}]
while True:
res = client.chat.completions.create(model="larn", messages=messages, tools=tools)
msg = res.choices[0].message
messages.append(msg) # เก็บข้อความของผู้ช่วยไว้ทั้งก้อน
if not msg.tool_calls:
print(msg.content)
break
for call in msg.tool_calls: # ตอบทุก tool call ด้วย id ของมัน
args = json.loads(call.function.arguments)
messages.append({"role": "tool", "tool_call_id": call.id, "content": web_search(args["query"])})
ถ้าต้องการให้ผู้ใช้เห็นทันทีว่า "กำลังจะค้น" ระหว่างรอ tool call ให้เรียกแบบ stream แล้วเปิด "ตอบทันที" สำหรับ request ที่มี tools ด้วยวิธีใดวิธีหนึ่ง ข้อความเปิดจะสั้น บอกแค่ว่ากำลังจะทำอะไร และไม่บอกผลที่ยังไม่ได้ค้น จากนั้นตามด้วย tool_calls และ finish_reason "tool_calls" ตามปกติ ค่าเริ่มต้นคือปิด เพื่อให้งานอัตโนมัติได้คำตอบล้วน
- header
x-larn-instant: on - ใน body
"larn": {"instant": true} - หรือตั้งค่า "ตอบทันที" ของ key เป็นเปิดเสมอ
ทางที่ 2: ให้ระบบค้นให้ (คิดเครดิตเพิ่ม)
เพิ่ม tool ชนิด larn:web_search ใน request ที่ต้องการ โมเดลจะตัดสินใจเองว่าต้องค้นไหม ระบบไปค้นแล้วตอบโดยอ้างอิงผลค้น ต้องขอทุกครั้ง ระบบไม่ค้นเองถ้าไม่ได้ขอ
{
"model": "larn",
"stream": true,
"messages": [{ "role": "user", "content": "หาราคาแรม kingston ให้หน่อย" }],
"tools": [{ "type": "larn:web_search", "parameters": { "max_results": 5, "max_searches": 2, "country": "th", "language": "th" } }]
}
- คิดเครดิตต่อการค้นที่สำเร็จหนึ่งครั้ง ค้นไม่สำเร็จไม่คิดค่าค้น และโมเดลจะตอบจากความรู้เดิมพร้อมบอกว่าค้นไม่ได้
- parameters ไม่ใส่ก็ได้: max_results (จำนวนผลต่อการค้น), max_searches (จำนวนครั้งสูงสุดต่อ request), country (รหัสประเทศ 2 ตัวอักษร), language (รหัสภาษา) ค่าที่เกินเพดานของระบบจะถูกลดลงมา
- chunk สุดท้าย (หรือคำตอบแบบไม่ stream) มี x_larn.searches คือจำนวนครั้งที่คิดเงิน และ x_larn.sources คือรายการแหล่งอ้างอิง เลข n ตรงกับ [n] ในคำตอบ
- ระหว่างค้น stream จะมี chunk ว่างที่ x_larn.part เป็น "search" และ status เป็น "searching" แล้ว "done" ใช้แสดงสถานะบนหน้าจอได้
- ใช้คู่กับ tools ของคุณเองได้ ถ้าโมเดลเรียก tool ของคุณ คุณจะได้ tool_calls ตามปกติ (รอบนั้นระบบไม่ค้นและไม่คิดค่าค้น) ชื่อ larn_web_search สงวนไว้ ห้ามใช้ตั้งชื่อ tool ของคุณใน request ที่ขอ larn:web_search
- เมื่อ stream และขอแค่ larn:web_search ข้อความเปิดจะบอกก่อนว่ากำลังจะค้นให้เอง ปิดได้ด้วยวิธีเดียวกับ "ตอบทันที"
- ส่ง web_search_options แทนได้ (อ่านเฉพาะ user_location.approximate.country) แต่คำตอบไม่มี annotations ให้ใช้ x_larn.sources
data: {"choices":[{"delta":{"content":""}}],"x_larn":{"part":"search","status":"searching"}}
data: {"choices":[{"delta":{"content":"แรม Kingston Fury 16GB ราคาประมาณ … [1]"}}]}
data: {"choices":[{"delta":{},"finish_reason":"stop"}],"x_larn":{"request_id":"req_…","searches":1,"sources":[{"n":1,"title":"…","url":"https://…"}]}}
data: [DONE]
Streaming
- ส่ง "stream": true เพื่อรับคำตอบแบบ server-sent events ในรูปแบบเดียวกับ OpenAI และปิดท้ายด้วย data: [DONE]
- ส่ง "stream_options": {"include_usage": true} เพื่อรับจำนวน token ใน chunk สุดท้าย
- ระหว่างที่โมเดลคิดนาน ระบบจะส่งบรรทัด ": keep-alive" มาเป็นระยะ SDK มาตรฐานข้ามบรรทัดนี้ให้เอง
- เมื่อโมเดลคิดเป็นขั้นตอน เนื้อหาการคิดอาจมาใน delta.reasoning_content แยกจาก delta.content
- ทุกคำตอบมี header x-larn-request-id และ x_larn.request_id ในคำตอบ ใช้อ้างอิงเวลาแจ้งปัญหา
ข้อผิดพลาด
ข้อผิดพลาดใช้รูปแบบเดียวกับ OpenAI: {"error": {"message", "type", "code"}} ถ้า stream เริ่มไปแล้ว ข้อผิดพลาดจะมาเป็น data: {"error": …} ใน stream
| HTTP | code | ความหมายและสิ่งที่ควรทำ |
|---|---|---|
| 400 | invalid_request | รูปแบบ request ไม่ถูกต้อง ดู message และ param |
| 400 | context_length_exceeded | บทสนทนายาวเกินไป ตัดข้อความเก่าหรือลด max_tokens |
| 400 | tools_not_supported | ตอนนี้ตอบ request ที่มี tools ไม่ได้ ลองใหม่ภายหลัง หรือส่งโดยไม่มี tools |
| 400 | web_search_not_enabled | บริการค้นเว็บฝั่ง server ยังไม่เปิด |
| 404 | model_not_found | ระบบตั้งให้รับเฉพาะชื่อโมเดลที่ประกาศไว้ ใช้ชื่อในหัวข้อ "โมเดล" |
| 401 | invalid_api_key | ไม่มี key หรือ key ไม่ถูกต้อง หรือถูกเพิกถอนแล้ว |
| 402 | insufficient_credits | เครดิตไม่พอสำหรับส่วนที่คิดเครดิต เช่น ค้นเว็บฝั่ง server เติมเครดิตในแดชบอร์ด |
| 403 | web_search_not_allowed | key นี้ถูกปิดสิทธิ์ค้นเว็บฝั่ง server |
| 413 | request_too_large | ขนาด request เกินกำหนด |
| 429 | rate_limit_exceeded | ส่งถี่เกินไป รอแล้วลองใหม่แบบเพิ่มช่วงรอทีละขั้น |
| 502 | upstream_interrupted | คำตอบถูกตัดกลางทาง ส่งใหม่ได้เลย |
| 503 | no_backend_available | ทุกระบบไม่ว่างชั่วคราว ลองใหม่ในไม่กี่วินาที |
| 429 | concurrency_limit_exceeded | request พร้อมกันของบัญชีครบตามแผนแล้ว (ระบบรอให้ราว 2 วินาทีก่อนตอบ) รอตามค่า retry-after แล้วลองใหม่ |
| 429 | fair_use_limit_reached | ใช้ชั้นสำรองของรอบนี้ครบตามนโยบายใช้งานอย่างเป็นธรรม และเครื่องของเราไม่ว่างในตอนนี้ ลองใหม่ภายหลัง |
| 403 | plan_unavailable | แผนของบัญชีนี้ยังไม่เปิดให้บริการ เลือกแผนอื่นในแดชบอร์ดหรือติดต่อผู้ดูแลระบบ |
| 503 | over_capacity | เครื่องของเราที่แผนนี้ใช้ได้ไม่ว่างชั่วคราว ลองใหม่ในไม่กี่วินาที |
| 503 | no_local_backend | request นี้ถูกจำกัดให้ใช้เครื่องของเราเท่านั้น และตอนนี้ยังไม่มีเครื่องพร้อม ลองใหม่ในอีกสักครู่ |
ใช้เครื่องของเราเท่านั้น
ปกติเมื่อเครื่องของเราไม่ว่างหรือยังไม่พร้อม ระบบจะส่งคำถามให้ผู้ให้บริการภายนอกที่เป็นระบบสำรองตอบแทน เพื่อให้คุณได้คำตอบเสมอ ถ้างานของคุณไม่ต้องการให้ข้อมูลออกไปนอกเครื่องของเรา ให้ใช้ key แบบ "ใช้เครื่องของเราเท่านั้น"
- ตั้งได้ตอนสร้าง key หรือสลับภายหลังในแดชบอร์ด หน้า API keys การเปลี่ยนค่ามีผลภายในราว 30 วินาที
- ครอบคลุมทุกขั้นของ request: ข้อความเปิด คำตอบหลัก และการเขียนต่อเมื่อคำตอบถูกตัดกลางทาง
- ถ้าไม่มีเครื่องของเราพร้อม จะได้ HTTP 503 พร้อม code no_local_backend และ header retry-after ระบบจะไม่ตอบจากระบบสำรองให้ ลองใหม่อีกครั้งได้เลย เครื่องที่พักอยู่จะถูกปลุกตั้งแต่ request แรก
- ค้นเว็บฝั่ง server (larn:web_search) ใช้กับ request แบบนี้ไม่ได้ เพราะคำค้นต้องออกไปผู้ให้บริการค้นภายนอก จะได้ 403 web_search_not_allowed ส่วน tool ค้นเว็บของแอปคุณเองยังใช้ได้ตามปกติ
- ถ้าคำตอบถูกตัดกลางทางและไม่มีเครื่องของเราอีกตัวรับช่วงได้ จะได้ upstream_interrupted ให้ส่งใหม่
- จำกัดเฉพาะบาง request ของ key ปกติได้ด้วยการใส่ใน body
"larn": {"local_only": true}ค่านี้ทำได้แค่เข้มขึ้น ใช้ปลดข้อจำกัดของ key ไม่ได้
บัญชีและรหัสผ่าน
- เปลี่ยนรหัสผ่านได้ในแดชบอร์ด หน้าบัญชี (ต้องใช้รหัสผ่านปัจจุบัน)
- ถ้าลืมรหัสผ่าน ติดต่อผู้ดูแลระบบเพื่อขอลิงก์ตั้งรหัสผ่านใหม่ ระบบยังไม่ส่งอีเมลเอง ลิงก์ใช้ได้ครั้งเดียวและหมดอายุใน 60 นาที ดูรายละเอียดที่ หน้าตั้งรหัสผ่านใหม่
- เมื่อตั้งรหัสผ่านใหม่ อุปกรณ์ที่เข้าระบบค้างไว้ทั้งหมดจะถูกออกจากระบบ ส่วน API key ไม่เปลี่ยนและยังใช้ได้ตามเดิม
แผนและขีดจำกัด
ทุกบัญชีอยู่ในแผนรายเดือนหนึ่งแผน การเรียกโมเดลไม่คิดตาม token แต่ละแผนต่างกันที่สามขีดด้านล่างและการเก็บข้อมูล ดูแผนและวันหมดรอบของคุณได้ในแดชบอร์ด
- request พร้อมกัน: นับรวมทุก API key ของบัญชี หน้าลองใช้ในแดชบอร์ด และ tool chat ของ MCP ถ้าครบแล้ว request ใหม่รอได้ราว 2 วินาที ถ้ายังไม่มีช่องว่างจะได้ 429 concurrency_limit_exceeded พร้อม retry-after: 1
- ขนาดข้อความเข้า: ประมาณจาก messages และ tools ที่ส่งมา เกินขีดของแผนได้ 400 context_length_exceeded ข้อความ error บอกขนาดโดยประมาณและขีดของแผน
- ขนาดคำตอบ: max_tokens หรือ max_completion_tokens ที่ขอเกินแผนถูกลดลงให้เอง ไม่ตอบ error ถ้าคำตอบยาวถึงขีดของแผน stream จะจบด้วย finish_reason "length" ส่วนที่โมเดลใช้คิดนับรวมเป็นคำตอบตามที่ผู้ให้บริการนับ
- การเก็บข้อมูล: แผน FREE อาจเก็บข้อความและคำตอบเพื่อปรับปรุงบริการตามนโยบายความเป็นส่วนตัว แผนเสียเงินไม่เก็บ และส่งต่อเฉพาะผู้ให้บริการที่ไม่เก็บข้อมูล ข้อมูลกำกับ (เวลา จำนวน token สถานะ ต้นทุน) ยังถูกบันทึกทุกแผน
- นโยบายใช้งานอย่างเป็นธรรม: บริการตอบจากเครื่องของเราเป็นหลัก และใช้ชั้นสำรองได้ในปริมาณจำกัดต่อรอบ เมื่อใช้ครบและเครื่องของเราไม่ว่างจะได้ 429 fair_use_limit_reached ให้รอแล้วลองใหม่
- ทุกข้อผิดพลาดของแผนอยู่ในตารางหัวข้อ "ข้อผิดพลาด" สำหรับ 429 ให้รอตาม retry-after แล้วลองใหม่
ขีดจำกัดและค่าใช้จ่าย
- การเรียก
larnไม่คิดเครดิตตาม token ส่วนที่หักเครดิตตอนนี้มีเฉพาะการค้นเว็บฝั่ง server (คิดต่อการค้น) จากเครดิตที่เติมไว้ล่วงหน้า - request ที่ถูกหักเครดิตมีค่าบริการขั้นต่ำที่ขึ้นกับงานที่ระบบทำจริงเพื่อตอบ request นั้น ยอดที่หักจริงของทุก request ดูได้ในประวัติการใช้งาน (my_logs มี min_charge = 1 เมื่อคิดตามขั้นต่ำ)
- ตอนนี้เปิดให้ใช้งานเฉพาะผู้ที่ได้รับเชิญ ติดต่อผู้ดูแลระบบเพื่อขอบัญชี
- rate limit นับต่อ key ค่าเริ่มต้น 120 request ต่อนาที ถ้าต้องการมากกว่านี้ติดต่อผู้ดูแลระบบ
- ไม่รองรับ n มากกว่า 1
ต่อกับผู้ช่วย AI ผ่าน MCP
LARN API มี MCP server ในตัว (Streamable HTTP) ที่ /mcp ต่อด้วย API key ของคุณ แล้วผู้ช่วย AI จะดูการใช้งาน จัดการ key เติมเครดิต และเรียกโมเดลแทนคุณได้