Native client libraries สำหรับ https://gateway.kiatdamrong.shop — ครอบทุก endpoint รวม Wizard / Grounding / Knowledge / read_file. API surface เดียวกันทุกภาษา.
tools/release_sdks.py + .github/workflows/release-sdks.yml.| Language | Install (วันนี้, from source) | Install (planned) | Tests | Live verified |
|---|---|---|---|---|
| Python | pip install -e ./sdks/python | pip install ai-gateway-th | manual | ✅ |
| Node / TS | cd sdks/node && npm i && npm run build | npm i @ai-gateway-th/sdk | 25/25 ✅ | ✅ |
| .NET (net8/net9) | dotnet add reference sdks/dotnet/AiGatewayTh/AiGatewayTh.csproj | dotnet add package AiGatewayTh | builds clean | — |
| Java + Spring | mvn -f sdks/java/pom.xml install | Maven shop.kiatdamrong:ai-gateway-th-sdk | 6/6 ✅ | — |
เปลี่ยนแค่ naming convention ของภาษา — snake_case (Python), camelCase (Node/Java), PascalCaseAsync (.NET).
health() · models()chat(req, idempotencyKey?)embeddings(req) — gateway-embed 768-dim Thai-capablesmart(req, opts?) · smart_stream()wizard_polish(text, style?)wizard_shorten(text, targetChars?, style?) NEWwizard_fact_check(claim)wizard_grounded_summarize(question)wizard_translate_th(text, sourceLang?, style?) NEWwizard_fix_thai(text) NEWweb_search(query, n?)read_url(url, maxChars?)read_file(file, filename?, maxChars?)knowledge_query(packId, query, topK?, audienceLevel?)list_knowledge_packs()compose(messages, ...) NEWcharts_render(chart, format?, ...) NEWsubmit_job() / get_job() / list_jobs(limit) / wait_for_job()audit(request_id)Per-call backend tier (NEW 2026-06-01): ทุก wizard + smart endpoint รองรับ tier="standard"|"premium"|"frontier" opt-in. premium = Gemini Flash judge (เร็ว, ~$0.075/M tokens), frontier = Claude Haiku judge (เร็วสุด, ~$0.80/M tokens). PII auto-pin LOCAL via X-Gateway-Tier-Downgraded-Reason: pdpa_pinned. Per-step usage.per_step[] ใน response สำหรับลูกค้าคำนวณค่าใช้จ่าย client-side. Paid judges ยังเข้าถึง Smart Engine tools (lookup_knowledge / web_search / read_url) ได้ครบ. ดู INTEGRATION_GUIDE_TH.md §12.10
Not in SDK (intentional): admin endpoints (web UI ที่ /admin/tenants) · demo endpoints (/v1/analyze-csv, /v1/cohorts/analyze, /v1/exam). ดู INTEGRATION_GUIDE_TH.md §12.9
pip install -e ./sdks/python # from source (today) # pip install ai-gateway-th # when published
from ai_gateway_th import GatewayClient, GatewayError
c = GatewayClient(
base_url="https://gateway.kiatdamrong.shop",
token="<YOUR_TOKEN>",
tenant_id="<YOUR_TENANT_ID>",
)
# Chat (OpenAI-compat)
r = c.chat("gateway-th",
[{"role": "user", "content": "อธิบาย scaffolding"}],
idempotency_key="msg-001")
# Wizard polish (Typhoon SAFE — ลบ translationese)
p = c.wizard_polish("ที่ซึ่งผู้เรียนถูกทำให้มีส่วนร่วม",
style="neutral")
# Grounded summarize (reads real sources)
s = c.wizard_grounded_summarize(
"สรุปแนวทาง active learning ป.4 จากแหล่งจริง")
# read_file — PDF / DOCX / XLSX / CSV / TXT
with open("plan.pdf", "rb") as f:
doc = c.read_file(f, max_chars=30000)
# Compose pipeline (writer → judge → revise)
r = c.compose(
messages=[{"role":"user","content":"เขียนบทความ active learning"}],
max_revisions=2, editor_score_threshold=80)
# Charts (deterministic, no LLM)
img = c.charts_render(
chart={"type":"bar","title":"Q1","categories":{"A":3,"B":5,"C":2}},
format="svg", width=400, height=300)
# Knowledge packs (list + query)
packs = c.list_knowledge_packs()
hits = c.knowledge_query(packs["data"][0]["pack_id"], "binary search")
# Tier opt-in (Phase 1 — 2026-06-01). Customer pays for faster/nicer judge.
# Same call shape, just add tier=. Per-step usage in response for billing.
r = httpx.post(BASE+"/v1/wizard/polish",
headers=hdr,
json={"text":"...", "tier":"premium"}) # or "frontier" / "standard"
# r.json()["usage"]["per_step"] -> tokens per backend (compute cost client-side)
# r.headers["X-Gateway-Tier-Used"] -> what tier actually ran (PDPA may downgrade)
# r.headers["X-Gateway-Compose-Judge-Tools"] == "on" -> paid judge used our tools
# Smart streaming (long compose >100s)
for ev in c.smart_stream(messages=[
{"role": "user", "content": "ออกแบบบทเรียน ป.4"}]):
if ev["event"] == "smart.complete":
print(ev["data"]["choices"][0]["message"]["content"])
break
# Error handling
try:
c.chat("bad-model", [{"role": "user", "content": "x"}])
except GatewayError as e:
print(e.status_code, e.error_type, e.request_id)
cd sdks/node && npm install && npm run build # npm i @ai-gateway-th/sdk # when published
import { GatewayClient, GatewayError } from "@ai-gateway-th/sdk";
const c = new GatewayClient({
baseUrl: "https://gateway.kiatdamrong.shop",
token: process.env.GATEWAY_TOKEN!,
tenantId: process.env.GATEWAY_TENANT_ID,
});
// Chat
const r = await c.chat({
model: "gateway-th",
messages: [{ role: "user", content: "อธิบาย scaffolding" }],
}, { idempotencyKey: "msg-001" });
// Wizard polish
const p = await c.wizardPolish(
"ที่ซึ่งผู้เรียนถูกทำให้มีส่วนร่วม",
{ style: "neutral" });
// read_file (Blob / Uint8Array / ArrayBuffer)
import { readFileSync } from "node:fs";
const bytes = readFileSync("plan.pdf");
const doc = await c.readFile(bytes, {
filename: "plan.pdf",
contentType: "application/pdf",
maxChars: 30000,
});
// Smart streaming with cancel
const ctrl = new AbortController();
for await (const ev of c.smartStream(
{ messages: [{ role: "user", content: "ออกแบบบทเรียน" }] },
{ signal: ctrl.signal },
)) {
if (ev.event === "smart.complete") {
console.log((ev.data as any).choices[0].message.content);
}
}
// Error handling
try { await c.chat({ model: "bad", messages: [] }); }
catch (e) {
if (e instanceof GatewayError) console.error(e.statusCode, e.errorType);
}
// Tier opt-in (Phase 1, 2026-06-01)
const r = await c.wizardPolish("...", { tier: "premium" });
// r.usage.per_step has token counts per backend; compute cost client-side
// Headers: X-Gateway-Tier-Used + X-Gateway-Tier-Downgraded-Reason (if PII)
dotnet add reference sdks/dotnet/AiGatewayTh/AiGatewayTh.csproj # dotnet add package AiGatewayTh # when published
using AiGatewayTh;
using var client = new GatewayClient(new GatewayClientOptions
{
Token = Environment.GetEnvironmentVariable("GATEWAY_TOKEN")!,
TenantId = "your-tenant",
BaseUrl = "https://gateway.kiatdamrong.shop",
});
// Chat
var r = await client.ChatAsync(new ChatCompletionRequest
{
Model = "gateway-th",
Messages = new() {
new() { Role = "user", Content = "อธิบาย scaffolding" }
},
}, idempotencyKey: "msg-001");
// Wizard polish
var p = await client.WizardPolishAsync(
"ที่ซึ่งผู้เรียนถูกทำให้มีส่วนร่วม", style: "neutral");
// read_file
byte[] bytes = File.ReadAllBytes("plan.pdf");
var doc = await client.ReadFileAsync(
bytes, filename: "plan.pdf",
contentType: "application/pdf", maxChars: 30000);
// Error handling
try { await client.ChatAsync(req); }
catch (GatewayException ex) when (ex.ErrorType == GatewayErrorType.RateLimitError)
{ /* exponential backoff already ran 3x */ }
// ASP.NET Core DI
// builder.Services.AddHttpClient("ai-gateway", c => {
// c.BaseAddress = new Uri("https://gateway.kiatdamrong.shop");
// });
// builder.Services.AddSingleton(sp => new GatewayClient(new()
// {
// Token = builder.Configuration["AiGateway:Token"]!,
// HttpClient = sp.GetRequiredService<IHttpClientFactory>()
// .CreateClient("ai-gateway"),
// }));
// Tier opt-in (Phase 1, 2026-06-01)
var r = await client.WizardPolishAsync("...", tier: "premium");
// r["usage"]["per_step"] has token counts per backend
// Response headers: X-Gateway-Tier-Used + X-Gateway-Tier-Downgraded-Reason
cd sdks/java && mvn clean install
<!-- pom.xml -->
<dependency>
<groupId>shop.kiatdamrong</groupId>
<artifactId>ai-gateway-th-sdk</artifactId>
<version>0.5.0</version>
</dependency>
import shop.kiatdamrong.aigateway.*;
GatewayClient client = new GatewayClient(
GatewayClientOptions.builder()
.token(System.getenv("GATEWAY_TOKEN"))
.tenantId("your-tenant")
.baseUrl("https://gateway.kiatdamrong.shop")
.build());
// Chat
Types.ChatCompletionRequest req = new Types.ChatCompletionRequest();
req.model = "gateway-th";
req.messages = List.of(
new Types.ChatMessage("user", "อธิบาย scaffolding"));
Types.ChatCompletionResponse r = client.chat(req, "msg-001");
// Wizard polish
Map<String,Object> p = client.wizardPolish(
"ที่ซึ่งผู้เรียนถูกทำให้มีส่วนร่วม", "neutral", null, null);
// read_file
byte[] bytes = Files.readAllBytes(Path.of("plan.pdf"));
Map<String,Object> doc = client.readFile(
bytes, "plan.pdf", "application/pdf", 30000);
// Error handling
try { client.chat(req); }
catch (GatewayException ex) {
log.warn("gateway error {} {}: {}",
ex.getStatusCode(), ex.getErrorType(), ex.getMessage());
}
// Spring Boot auto-config (application.yml):
// ai-gateway:
// token: ${GATEWAY_TOKEN}
// base-url: https://gateway.kiatdamrong.shop
// then @Autowired GatewayClient ใน service
// Tier opt-in (Phase 1, 2026-06-01)
Map<String,Object> r = client.wizardPolish(
"...", "neutral", null, "premium", null);
// r["usage"]["per_step"] has token counts per backend
// Headers: X-Gateway-Tier-Used + X-Gateway-Tier-Downgraded-Reason
| Pattern | Python | Node | .NET | Java |
|---|---|---|---|---|
| Idempotency | idempotency_key= | {idempotencyKey} | idempotencyKey: | chat(req, "key") |
| Cancel | KeyboardInterrupt | AbortSignal | CancellationToken | thread interrupt |
| Streaming | smart_stream() | smartStream() | SmartStreamAsync() | smartStream() |
| Retry | 3 attempts on 5xx + network errors, exponential backoff 1s→2s→4s (configurable) | |||
| Tier opt-in | tier="premium" | {tier:"premium"} | tier:"premium" | 5th positional arg |
Streaming methods ส่ง SSE keepalive (: ping) อัตโนมัติ — กัน Cloudflare tunnel idle-timeout ที่ 100s. Tier rates ดูที่ /pricing.
ทุก endpoint + Wizard / Grounding / Knowledge / Admin + auth + PDPA + audit + bench numbers อยู่ในไฟล์ Markdown ใน repo:
docs/wewasanad/INTEGRATION_GUIDE_TH.md — คู่มือเต็ม (TH)sdks/README.md — overview ของทั้ง 4 ภาษาsdks/{python,node,dotnet,java}/README.md — รายละเอียดเฉพาะภาษาsdks/PUBLISHING.md — checklist ตอน publish PyPI/npm/NuGet/Mavenติดต่อ [email protected] เพื่อรับไฟล์ + Bearer token + tenant_id.
🪄 ลองใน Playground 📚 OpenAPI / Swagger