tans-agents-ui / scripts /test-tools.mjs
Copilot
fix(models): drop GitHub Llama-3.1 (no tool-calling via Azure endpoint)
d67f090
Raw
History Blame Contribute Delete
4.6 kB
// Test tool-calling support across all configured models.
import { readFileSync } from "node:fs"
import { streamText, tool } from "ai"
import { createGoogleGenerativeAI } from "@ai-sdk/google"
import { createGroq } from "@ai-sdk/groq"
import { createOpenAI } from "@ai-sdk/openai"
import { z } from "zod"
// Tiny inline .env.local loader (avoids extra dep)
try {
const env = readFileSync(".env.local", "utf8")
for (const line of env.split("\n")) {
const m = line.match(/^\s*([A-Z_][A-Z0-9_]*)\s*=\s*"?([^"\r\n]*)"?\s*$/)
if (m && !process.env[m[1]]) process.env[m[1]] = m[2]
}
} catch {}
const PROVIDERS = {
google: {
models: [
"gemini-2.5-flash-lite",
"gemini-2.5-flash",
"gemini-2.5-pro",
"gemini-2.0-flash",
"gemini-2.0-flash-lite",
],
},
groq: {
models: [
"llama-3.3-70b-versatile",
"llama-3.1-8b-instant",
"openai/gpt-oss-120b",
"openai/gpt-oss-20b",
"qwen/qwen3-32b",
"meta-llama/llama-4-scout-17b-16e-instruct",
],
},
github: {
models: [
"gpt-4o-mini",
"gpt-4o",
"Meta-Llama-3.1-8B-Instruct",
"Meta-Llama-3.1-405B-Instruct",
],
},
}
const tools = {
calculator: tool({
description: "Evaluate a math expression. Use for arithmetic.",
parameters: z.object({ expression: z.string() }),
execute: async ({ expression }) => {
const r = Function(`"use strict";return (${expression})`)()
return { result: r }
},
}),
currentTime: tool({
description: "Get current ISO date-time.",
parameters: z.object({}),
execute: async () => ({ now: new Date().toISOString() }),
}),
}
function build(provider, modelId) {
if (provider === "google")
return createGoogleGenerativeAI({ apiKey: process.env.GOOGLE_GENERATIVE_AI_API_KEY })(modelId)
if (provider === "groq") return createGroq({ apiKey: process.env.GROQ_API_KEY })(modelId)
if (provider === "github")
return createOpenAI({
apiKey: process.env.GITHUB_TOKEN,
baseURL: "https://models.inference.ai.azure.com",
})(modelId)
}
async function testOne(provider, modelId) {
const t0 = Date.now()
try {
const result = streamText({
model: build(provider, modelId),
tools,
maxSteps: 3,
system:
"Khi user hỏi tính toán PHẢI gọi tool calculator. " +
"Khi user hỏi giờ PHẢI gọi tool currentTime. Không tự tính.",
messages: [{ role: "user", content: "Tính giúp: 137 * 29 + 8 = ?" }],
})
let toolCalled = false
let toolName = null
let text = ""
let chunks = 0
let firstChunkMs = null
for await (const part of result.fullStream) {
chunks++
if (firstChunkMs === null) firstChunkMs = Date.now() - t0
if (part.type === "tool-call") {
toolCalled = true
toolName = part.toolName
} else if (part.type === "text-delta") {
text += part.textDelta
} else if (part.type === "error") {
throw part.error
}
}
return {
ok: true,
toolCalled,
toolName,
streaming: chunks > 3,
chunks,
ttfbMs: firstChunkMs,
totalMs: Date.now() - t0,
textPreview: text.slice(0, 80).replace(/\s+/g, " "),
}
} catch (e) {
return { ok: false, error: (e?.message || String(e)).slice(0, 240), totalMs: Date.now() - t0 }
}
}
const results = []
for (const [provider, info] of Object.entries(PROVIDERS)) {
for (const m of info.models) {
process.stdout.write(`Testing ${provider}/${m} ... `)
const r = await testOne(provider, m)
const status = r.ok
? r.toolCalled
? `OK tool=${r.toolName} stream=${r.streaming ? "y" : "n"} chunks=${r.chunks} ttfb=${r.ttfbMs}ms total=${r.totalMs}ms`
: `NO-TOOL stream=${r.streaming ? "y" : "n"} total=${r.totalMs}ms text="${r.textPreview}"`
: `ERR ${r.error}`
console.log(status)
results.push({ provider, model: m, ...r })
await new Promise((r) => setTimeout(r, 800))
}
}
console.log("\n=== SUMMARY ===")
for (const r of results) {
const tool = r.ok ? (r.toolCalled ? "OK " : "NO ") : "ERR"
const stream = r.ok ? (r.streaming ? "y" : "n") : "-"
console.log(`${tool} stream=${stream} ${r.provider.padEnd(8)} ${r.model}`)
}
const broken = results.filter((r) => !r.ok)
const noTool = results.filter((r) => r.ok && !r.toolCalled)
console.log(`\n${results.length} tested · ${broken.length} broken · ${noTool.length} no tool-call`)
if (broken.length) {
console.log("\nBROKEN:")
for (const b of broken) console.log(` ${b.provider}/${b.model}: ${b.error}`)
}