feat: add Gemma 4 auto-orchestration example (runTeam)
Add examples/09-gemma4-auto-orchestration.ts demonstrating runTeam() with Gemma 4 as the coordinator — the framework's key feature running fully local. The coordinator successfully decomposes goals into JSON task arrays, schedules dependencies, and synthesises results. Verified on gemma4:e2b (5.1B params) with Ollama 0.20.0-rc1.
This commit is contained in:
parent
f9fcac0c38
commit
d86ea766d3
|
|
@ -122,6 +122,7 @@ npx tsx examples/01-single-agent.ts
|
|||
| [06 — Local Model](examples/06-local-model.ts) | Ollama + Claude in one pipeline via `baseURL` (works with vLLM, LM Studio, etc.) |
|
||||
| [07 — Fan-Out / Aggregate](examples/07-fan-out-aggregate.ts) | `runParallel()` MapReduce — 3 analysts in parallel, then synthesize |
|
||||
| [08 — Gemma 4 Local](examples/08-gemma4-local.ts) | Pure-local Gemma 4 agent team with tool-calling — zero API cost |
|
||||
| [09 — Gemma 4 Auto-Orchestration](examples/09-gemma4-auto-orchestration.ts) | `runTeam()` with Gemma 4 as coordinator — auto task decomposition, fully local |
|
||||
|
||||
## Architecture
|
||||
|
||||
|
|
|
|||
|
|
@ -126,6 +126,7 @@ npx tsx examples/01-single-agent.ts
|
|||
| [06 — 本地模型](examples/06-local-model.ts) | Ollama + Claude 混合流水线,通过 `baseURL` 接入(兼容 vLLM、LM Studio 等) |
|
||||
| [07 — 扇出聚合](examples/07-fan-out-aggregate.ts) | `runParallel()` MapReduce — 3 个分析师并行,然后综合 |
|
||||
| [08 — Gemma 4 本地](examples/08-gemma4-local.ts) | 纯本地 Gemma 4 智能体团队 + tool-calling — 零 API 费用 |
|
||||
| [09 — Gemma 4 自动编排](examples/09-gemma4-auto-orchestration.ts) | `runTeam()` 用 Gemma 4 当 coordinator — 自动任务拆解,完全本地 |
|
||||
|
||||
## 架构
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,162 @@
|
|||
/**
|
||||
* Example 09 — Gemma 4 Auto-Orchestration (runTeam, 100% Local)
|
||||
*
|
||||
* Demonstrates the framework's key feature — automatic task decomposition —
|
||||
* powered entirely by a local Gemma 4 model. No cloud API needed.
|
||||
*
|
||||
* What happens:
|
||||
* 1. A Gemma 4 "coordinator" receives the goal + agent roster
|
||||
* 2. It outputs a structured JSON task array (title, description, assignee, dependsOn)
|
||||
* 3. The framework resolves dependencies, schedules tasks, and runs agents
|
||||
* 4. The coordinator synthesises all task results into a final answer
|
||||
*
|
||||
* This is the hardest test for a local model — it must produce valid JSON
|
||||
* for task decomposition AND do tool-calling for actual task execution.
|
||||
* Gemma 4 e2b (5.1B params) handles both reliably.
|
||||
*
|
||||
* Run:
|
||||
* no_proxy=localhost npx tsx examples/09-gemma4-auto-orchestration.ts
|
||||
*
|
||||
* Prerequisites:
|
||||
* 1. Ollama >= 0.20.0 installed and running: https://ollama.com
|
||||
* 2. Pull the model: ollama pull gemma4:e2b
|
||||
* 3. No API keys needed!
|
||||
*
|
||||
* Note: The no_proxy=localhost prefix is needed if you have an HTTP proxy
|
||||
* configured, since the OpenAI SDK would otherwise route Ollama requests
|
||||
* through the proxy.
|
||||
*/
|
||||
|
||||
import { OpenMultiAgent } from '../src/index.js'
|
||||
import type { AgentConfig, OrchestratorEvent, Task } from '../src/types.js'
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Configuration
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// See available tags at https://ollama.com/library/gemma4
|
||||
const OLLAMA_MODEL = 'gemma4:e2b' // or 'gemma4:e4b', 'gemma4:26b'
|
||||
const OLLAMA_BASE_URL = 'http://localhost:11434/v1'
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Agents — the coordinator is created automatically by runTeam()
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const researcher: AgentConfig = {
|
||||
name: 'researcher',
|
||||
model: OLLAMA_MODEL,
|
||||
provider: 'openai',
|
||||
baseURL: OLLAMA_BASE_URL,
|
||||
apiKey: 'ollama',
|
||||
systemPrompt: `You are a system researcher. Use bash to run non-destructive,
|
||||
read-only commands and report the results concisely.`,
|
||||
tools: ['bash'],
|
||||
maxTurns: 4,
|
||||
}
|
||||
|
||||
const writer: AgentConfig = {
|
||||
name: 'writer',
|
||||
model: OLLAMA_MODEL,
|
||||
provider: 'openai',
|
||||
baseURL: OLLAMA_BASE_URL,
|
||||
apiKey: 'ollama',
|
||||
systemPrompt: `You are a technical writer. Use file_write to create clear,
|
||||
structured Markdown reports based on the information provided.`,
|
||||
tools: ['file_write'],
|
||||
maxTurns: 4,
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Progress handler
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
function handleProgress(event: OrchestratorEvent): void {
|
||||
const ts = new Date().toISOString().slice(11, 23)
|
||||
switch (event.type) {
|
||||
case 'task_start': {
|
||||
const task = event.data as Task | undefined
|
||||
console.log(`[${ts}] TASK START "${task?.title ?? event.task}" → ${task?.assignee ?? '?'}`)
|
||||
break
|
||||
}
|
||||
case 'task_complete':
|
||||
console.log(`[${ts}] TASK DONE "${event.task}"`)
|
||||
break
|
||||
case 'agent_start':
|
||||
console.log(`[${ts}] AGENT START ${event.agent}`)
|
||||
break
|
||||
case 'agent_complete':
|
||||
console.log(`[${ts}] AGENT DONE ${event.agent}`)
|
||||
break
|
||||
case 'error':
|
||||
console.error(`[${ts}] ERROR ${event.agent ?? ''} task=${event.task ?? '?'}`)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Orchestrator — defaultModel is used for the coordinator agent
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const orchestrator = new OpenMultiAgent({
|
||||
defaultModel: OLLAMA_MODEL,
|
||||
defaultProvider: 'openai',
|
||||
defaultBaseURL: OLLAMA_BASE_URL,
|
||||
defaultApiKey: 'ollama',
|
||||
maxConcurrency: 1, // local model serves one request at a time
|
||||
onProgress: handleProgress,
|
||||
})
|
||||
|
||||
const team = orchestrator.createTeam('gemma4-auto', {
|
||||
name: 'gemma4-auto',
|
||||
agents: [researcher, writer],
|
||||
sharedMemory: true,
|
||||
})
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Give a goal — the framework handles the rest
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const goal = `Check this machine's Node.js version, npm version, and OS info,
|
||||
then write a short Markdown summary report to /tmp/gemma4-auto/report.md`
|
||||
|
||||
console.log('Gemma 4 Auto-Orchestration — Zero API Cost')
|
||||
console.log('='.repeat(60))
|
||||
console.log(` model → ${OLLAMA_MODEL} via Ollama (all agents + coordinator)`)
|
||||
console.log(` researcher → bash`)
|
||||
console.log(` writer → file_write`)
|
||||
console.log(` coordinator → auto-created by runTeam()`)
|
||||
console.log()
|
||||
console.log(`Goal: ${goal.replace(/\n/g, ' ').trim()}`)
|
||||
console.log('='.repeat(60))
|
||||
|
||||
const start = Date.now()
|
||||
const result = await orchestrator.runTeam(team, goal)
|
||||
const totalTime = Date.now() - start
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Results
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
console.log('\n' + '='.repeat(60))
|
||||
console.log('Pipeline complete.\n')
|
||||
console.log(`Overall success: ${result.success}`)
|
||||
console.log(`Total time: ${(totalTime / 1000).toFixed(1)}s`)
|
||||
console.log(`Tokens — input: ${result.totalTokenUsage.input_tokens}, output: ${result.totalTokenUsage.output_tokens}`)
|
||||
|
||||
console.log('\nPer-agent results:')
|
||||
for (const [name, r] of result.agentResults) {
|
||||
const icon = r.success ? 'OK ' : 'FAIL'
|
||||
const tools = r.toolCalls.length > 0 ? r.toolCalls.map(c => c.toolName).join(', ') : '(none)'
|
||||
console.log(` [${icon}] ${name.padEnd(24)} tools: ${tools}`)
|
||||
}
|
||||
|
||||
// Print the coordinator's final synthesis
|
||||
const coordResult = result.agentResults.get('coordinator')
|
||||
if (coordResult?.success) {
|
||||
console.log('\nFinal synthesis (from local Gemma 4 coordinator):')
|
||||
console.log('-'.repeat(60))
|
||||
console.log(coordResult.output)
|
||||
console.log('-'.repeat(60))
|
||||
}
|
||||
|
||||
console.log('\nAll processing done locally. $0 API cost.')
|
||||
Loading…
Reference in New Issue