SPB Git forge

spb/polyllm

Public
15commits 1branches 0releases
2.2 MBsize
maindefault branch
14 days agolast push
TypeScript 97.4% SQL 1% JavaScript 0.9% CSS 0.6%
2.9 KB · 65 lines typescript
Raw Blame History
1// Probe (d): function-call round trip with streaming; record tool_calls delta shape.2import { CHAT_MODELS, client, rawSSE, save, short } from "./lib.ts";34const tools: any = [5  {6    type: "function",7    function: {8      name: "get_weather",9      description: "Get current weather for a city",10      parameters: {11        type: "object",12        properties: { city: { type: "string" }, unit: { type: "string", enum: ["c", "f"] } },13        required: ["city"],14      },15    },16  },17];18const results: Record<string, any> = {};19for (const model of CHAT_MODELS) {20  const r: any = {};21  const messages: any[] = [{ role: "user", content: "What's the weather in Montreal right now? Use the tool." }];22  // round 1 streaming (raw) to capture delta shape23  const s = await rawSSE("/chat/completions", { model, messages, tools, tool_choice: "auto", stream: true, stream_options: { include_usage: true }, max_completion_tokens: 300 });24  if ((s as any).error) {25    r.round1 = { status: s.status, error: (s as any).error };26    console.log(model, "round1 ERR", s.status, short((s as any).error));27    results[model] = r;28    continue;29  }30  const tcChunks = s.events.filter((e) => e.data?.choices?.[0]?.delta?.tool_calls);31  r.round1 = {32    nChunks: s.events.length,33    toolCallChunks: tcChunks.map((e) => e.data),34    finishReasons: [...new Set(s.events.map((e) => e.data?.choices?.[0]?.finish_reason).filter(Boolean))],35    usage: s.events.find((e) => e.data?.usage)?.data?.usage,36  };37  console.log(model, "round1 toolCallChunks", tcChunks.length, "finish", r.round1.finishReasons, short(tcChunks[0]?.data?.choices[0].delta, 300));38  // assemble tool call39  const acc: Record<number, any> = {};40  for (const e of tcChunks) for (const tc of e.data.choices[0].delta.tool_calls) {41    const a = (acc[tc.index ?? 0] ??= { id: "", name: "", args: "" });42    if (tc.id) a.id = tc.id;43    if (tc.function?.name) a.name += tc.function.name;44    if (tc.function?.arguments) a.args += tc.function.arguments;45  }46  const calls = Object.values(acc);47  if (!calls.length) {48    results[model] = r;49    continue;50  }51  messages.push({ role: "assistant", content: null, tool_calls: calls.map((c) => ({ id: c.id, type: "function", function: { name: c.name, arguments: c.args } })) });52  for (const c of calls) messages.push({ role: "tool", tool_call_id: c.id, content: JSON.stringify({ temp_c: 21, condition: "sunny" }) });53  // round 2 via SDK, non-stream54  try {55    const res = await client.chat.completions.create({ model, messages, tools, max_completion_tokens: 200 });56    r.round2 = { content: res.choices[0].message.content, finish: res.choices[0].finish_reason, usage: res.usage };57    console.log(model, "round2", short(res.choices[0].message.content, 120));58  } catch (e: any) {59    r.round2 = { error: e.status, body: e.error ?? e.message };60    console.log(model, "round2 ERR", e.status, short(e.error ?? e.message));61  }62  results[model] = r;63}64save("03-tools-stream.json", results);65