LARN.ioAPI
LARN / API / DOCS

เรียกใช้ในไม่กี่บรรทัด

LARN API ใช้รูปแบบเดียวกับ OpenAI Chat Completions จึงใช้กับ SDK ของ OpenAI และเครื่องมือที่รองรับ OpenAI ได้ทันที เปลี่ยนแค่ base URL กับ API key

Base URL
การยืนยันตัวตนAuthorization: Bearer larn-sk-…
EndpointsPOST /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

HTTPcodeความหมายและสิ่งที่ควรทำ
400invalid_requestรูปแบบ request ไม่ถูกต้อง ดู message และ param
400context_length_exceededบทสนทนายาวเกินไป ตัดข้อความเก่าหรือลด max_tokens
400tools_not_supportedตอนนี้ตอบ request ที่มี tools ไม่ได้ ลองใหม่ภายหลัง หรือส่งโดยไม่มี tools
400web_search_not_enabledบริการค้นเว็บฝั่ง server ยังไม่เปิด
404model_not_foundระบบตั้งให้รับเฉพาะชื่อโมเดลที่ประกาศไว้ ใช้ชื่อในหัวข้อ "โมเดล"
401invalid_api_keyไม่มี key หรือ key ไม่ถูกต้อง หรือถูกเพิกถอนแล้ว
402insufficient_creditsเครดิตไม่พอสำหรับส่วนที่คิดเครดิต เช่น ค้นเว็บฝั่ง server เติมเครดิตในแดชบอร์ด
403web_search_not_allowedkey นี้ถูกปิดสิทธิ์ค้นเว็บฝั่ง server
413request_too_largeขนาด request เกินกำหนด
429rate_limit_exceededส่งถี่เกินไป รอแล้วลองใหม่แบบเพิ่มช่วงรอทีละขั้น
502upstream_interruptedคำตอบถูกตัดกลางทาง ส่งใหม่ได้เลย
503no_backend_availableทุกระบบไม่ว่างชั่วคราว ลองใหม่ในไม่กี่วินาที
429concurrency_limit_exceededrequest พร้อมกันของบัญชีครบตามแผนแล้ว (ระบบรอให้ราว 2 วินาทีก่อนตอบ) รอตามค่า retry-after แล้วลองใหม่
429fair_use_limit_reachedใช้ชั้นสำรองของรอบนี้ครบตามนโยบายใช้งานอย่างเป็นธรรม และเครื่องของเราไม่ว่างในตอนนี้ ลองใหม่ภายหลัง
403plan_unavailableแผนของบัญชีนี้ยังไม่เปิดให้บริการ เลือกแผนอื่นในแดชบอร์ดหรือติดต่อผู้ดูแลระบบ
503over_capacityเครื่องของเราที่แผนนี้ใช้ได้ไม่ว่างชั่วคราว ลองใหม่ในไม่กี่วินาที
503no_local_backendrequest นี้ถูกจำกัดให้ใช้เครื่องของเราเท่านั้น และตอนนี้ยังไม่มีเครื่องพร้อม ลองใหม่ในอีกสักครู่

ใช้เครื่องของเราเท่านั้น

ปกติเมื่อเครื่องของเราไม่ว่างหรือยังไม่พร้อม ระบบจะส่งคำถามให้ผู้ให้บริการภายนอกที่เป็นระบบสำรองตอบแทน เพื่อให้คุณได้คำตอบเสมอ ถ้างานของคุณไม่ต้องการให้ข้อมูลออกไปนอกเครื่องของเรา ให้ใช้ 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 แล้วลองใหม่

ขีดจำกัดและค่าใช้จ่าย

  • rate limit นับต่อ key ค่าเริ่มต้น 120 request ต่อนาที ถ้าต้องการมากกว่านี้ติดต่อผู้ดูแลระบบ
  • ไม่รองรับ n มากกว่า 1

ต่อกับผู้ช่วย AI ผ่าน MCP

LARN API มี MCP server ในตัว (Streamable HTTP) ที่ /mcp ต่อด้วย API key ของคุณ แล้วผู้ช่วย AI จะดูการใช้งาน จัดการ key เติมเครดิต และเรียกโมเดลแทนคุณได้