SPB Git forge

spb/polyllm

Public
15commits 1branches 0releases
2.2 MBsize
maindefault branch
13 days agolast push
TypeScript 97.4% SQL 1% JavaScript 0.9% CSS 0.6%
5.0 KB · 61 lines typescript
Raw Blame History
1import { MODELS, rawPost, rawSSE, save, short, WEATHER_TOOL } from "./lib.ts";23const out: Record<string, unknown> = {};4await Promise.all(MODELS.map(async (model) => {5  const messages: any[] = [{ role: "user", content: "What is the weather in Montreal right now? Use the tool." }];6  const s = await rawSSE("/chat/completions", { model, messages, tools: [WEATHER_TOOL], tool_choice: "auto", max_tokens: 4000, stream_options: { include_usage: true } });7  // accumulate8  const acc: any = { role: "assistant", content: "", reasoning_content: "", tool_calls: [] as any[] };9  const toolChunks: any[] = [];10  let finish: string | null = null; let usage: any = null;11  for (const c of s.chunks) {12    if (c === "[DONE]") continue;13    if (c.usage) usage = c.usage;14    for (const ch of c.choices ?? []) {15      const d = ch.delta ?? {};16      if (d.content) acc.content += d.content;17      if (d.reasoning_content) acc.reasoning_content += d.reasoning_content;18      if (d.tool_calls) { toolChunks.push(d.tool_calls); for (const tc of d.tool_calls) { const i = tc.index ?? 0; acc.tool_calls[i] ??= { id: "", type: "function", function: { name: "", arguments: "" } }; if (tc.id) acc.tool_calls[i].id = tc.id; if (tc.type) acc.tool_calls[i].type = tc.type; if (tc.function?.name) acc.tool_calls[i].function.name += tc.function.name; if (tc.function?.arguments) acc.tool_calls[i].function.arguments += tc.function.arguments; } }19      if (ch.finish_reason) finish = ch.finish_reason;20    }21  }22  console.log(`\n[${model}] step1 stream status=${s.status} finish=${finish} nToolChunks=${toolChunks.length} reasoningLen=${acc.reasoning_content.length} content=${short(acc.content, 60)}`);23  console.log("  tool_calls delta chunks (first 3):", short(toolChunks.slice(0, 3), 700));24  console.log("  accumulated:", short(acc.tool_calls, 300), "usage:", JSON.stringify(usage));25  if (s.error) console.log("  error:", short(s.error, 400));2627  const results: any = { step1: { status: s.status, finish, toolChunks, acc, usage, error: s.error } };28  if (acc.tool_calls.length) {29    const toolMsgs = acc.tool_calls.map((tc: any) => ({ role: "tool", tool_call_id: tc.id, name: tc.function.name, content: JSON.stringify({ city: "Montreal", temp_c: 21, condition: "sunny" }) }));30    // (A) full replay incl. reasoning_content31    const withR = await rawPost("/chat/completions", { model, messages: [...messages, { role: "assistant", content: acc.content || null, reasoning_content: acc.reasoning_content, tool_calls: acc.tool_calls }, ...toolMsgs], tools: [WEATHER_TOOL], max_tokens: 4000 });32    console.log(`  step2 WITH reasoning_content: ${withR.status} finish=${(withR.body as any)?.choices?.[0]?.finish_reason} ${short((withR.body as any)?.choices?.[0]?.message?.content ?? withR.body, 120)}`);33    // (B) replay WITHOUT reasoning_content34    const noR = await rawPost("/chat/completions", { model, messages: [...messages, { role: "assistant", content: acc.content || null, tool_calls: acc.tool_calls }, ...toolMsgs], tools: [WEATHER_TOOL], max_tokens: 4000 });35    console.log(`  step2 WITHOUT reasoning_content: ${noR.status} finish=${(noR.body as any)?.choices?.[0]?.finish_reason} ${short((noR.body as any)?.choices?.[0]?.message?.content ?? noR.body, 200)}`);36    // (C) replay with EMPTY reasoning_content string37    const emptyR = await rawPost("/chat/completions", { model, messages: [...messages, { role: "assistant", content: acc.content || null, reasoning_content: "", tool_calls: acc.tool_calls }, ...toolMsgs], tools: [WEATHER_TOOL], max_tokens: 4000 });38    console.log(`  step2 EMPTY reasoning_content: ${emptyR.status} finish=${(emptyR.body as any)?.choices?.[0]?.finish_reason} ${short((emptyR.body as any)?.choices?.[0]?.message?.content ?? emptyR.body, 200)}`);39    results.step2 = { withReasoning: withR, withoutReasoning: noR, emptyReasoning: emptyR };40    results.step2WithUsage = (withR.body as any)?.usage;41    console.log("  step2 usage (with):", JSON.stringify((withR.body as any)?.usage));42  }43  out[model] = results;44}));4546// k2.6 thinking disabled: tool round trip without reasoning at all47{48  const model = "kimi-k2.6";49  const messages: any[] = [{ role: "user", content: "What is the weather in Montreal right now? Use the tool." }];50  const r1 = await rawPost("/chat/completions", { model, messages, tools: [WEATHER_TOOL], thinking: { type: "disabled" }, max_tokens: 500 });51  const m = (r1.body as any)?.choices?.[0]?.message;52  console.log(`\n[k2.6 thinking=disabled] step1 ${r1.status} finish=${(r1.body as any)?.choices?.[0]?.finish_reason} keys=${Object.keys(m ?? {})} tc=${m?.tool_calls?.length}`);53  let r2: any = null;54  if (m?.tool_calls?.length) {55    r2 = await rawPost("/chat/completions", { model, messages: [...messages, m, ...m.tool_calls.map((tc: any) => ({ role: "tool", tool_call_id: tc.id, name: tc.function.name, content: "{\"temp_c\":21}" }))], tools: [WEATHER_TOOL], thinking: { type: "disabled" }, max_tokens: 500 });56    console.log(`  step2 ${r2.status} ${short((r2.body as any)?.choices?.[0]?.message?.content ?? r2.body, 150)}`);57  }58  out["kimi-k2.6/thinking-disabled"] = { r1, r2 };59}60save("03-tools-stream", out);61