Chrome Built-in AI ๊ธฐ๋ฐ ๋ฉํฐ ์์ด์ ํธ ์กฐ๋ฆฝ ํ๋ ์์ํฌ
์๋ฒ, API ํค, ํ ํฐ ๋น์ฉ ์์ด ์ฌ์ฉ์ ๋ธ๋ผ์ฐ์ ์์์ ์ ๋ถ ๋๋ฉ๋๋ค.
ํ๊ตญ์ด | English
import { Agent, chain, summarizer, tool, translator } from 'my-little-agent'
// 1. ์์ด์ ํธ๊ฐ ๋ถ๋ฅด๋ ์ปค์คํ
ํจ์
const findOrder = tool<{ id: string }>({
name: 'findOrder',
description: '์ฃผ๋ฌธ๋ฒํธ๋ก ์ฃผ๋ฌธ ์ ๋ณด๋ฅผ ์กฐํํ๋ค',
parameters: {
type: 'object',
properties: { id: { type: 'string' } },
required: ['id'],
},
execute: ({ id }) => db.orders.get(id),
})
// 2. ๋๊ตฌ๋ฅผ ์ฅ ์์ด์ ํธ
const desk = new Agent({
instruction: '๊ณ ๊ฐ ์๋ด์. ์ฃผ๋ฌธ ๊ด๋ จ ์ง๋ฌธ์ ๋ฐ๋์ ๋๊ตฌ๋ก ํ์ธํ๊ณ ๋ตํ๋ค.',
tools: [findOrder],
stateless: true,
})
// 3. ๋ต๋ณ์ ์ค์ด๊ณ ํ๊ตญ์ด๋ก. ๋ค ๋ ๋จ๊ณ๋ Chrome ์ ์ฉ ๋ชจ๋ธ์ด๋ผ ์์ด์ ํธ์ ์ปจํ
์คํธ ์ฐฝ์ 1ํ ํฐ๋ ์ฐ์ง ์๋๋ค.
const flow = chain(desk, summarizer({ length: 'short' }), translator({ to: 'ko' }))
await flow.run('Where is my order A-1024?')- ์๋ฒ๋ฆฌ์ค โ ๋ชจ๋ธ์ด Chrome ์์ ์์ต๋๋ค. ํ๋ก์๋, ํค ๊ด๋ฆฌ๋, ๊ณผ๊ธ ๋์๋ณด๋๋ ์์ต๋๋ค.
- ๋น์ฉ 0์ โ ๊ฐ๋ฐ์์๊ฒ ํ ํฐ ์๊ธ์ด ์ฒญ๊ตฌ๋์ง ์๊ณ , ์ฌ์ฉ์๊ฐ ์๊ธฐ API ํค๋ฅผ ๋ถ์ฌ๋ฃ์ ํ์๋ ์์ต๋๋ค.
- ์ ๋ณด ๋ณดํธ โ ์๋ฃยท๊ธ์ตยท์ฌ๋ด ๋ฌธ์์ฒ๋ผ ์ธ๋ถ ์ ์ก์ด ๋งํ ๋ฐ์ดํฐ๋ ๋ค๋ฃฐ ์ ์์ต๋๋ค. ์คํ๋ผ์ธ์์๋ ๋๋๋ค.
-
๋๊ตฌ ํธ์ถ โ ๋ชจ๋ธ์๊ฒ ํจ์๋ฅผ ์ฅ์ฌ์ฃผ๋ ค๋ฉด, ์ถ๋ ฅ์ JSON Schema๋ก ๋ฌถ๊ณ โ ํ์ฑํ๊ณ โ ์๋ ๋๊ตฌ๋ฅผ ์ง๋ชฉํ๋ฉด ๋๋๋ฆฌ๊ณ โ ์คํ ๊ฒฐ๊ณผ๋ฅผ ๋ค์ ๋ฃ์ด์ฃผ๊ณ โ ์ต์ข ๋ต์ด ๋์ฌ ๋๊น์ง ๋ฐ๋ณตํด์ผ ํฉ๋๋ค. ์ด ๋ฃจํ๋ฅผ
tools: [...]ํ ์ค๋ก ์ค์์ต๋๋ค. -
๋ฉํฐ ์์ด์ ํธ ์กฐ๋ฆฝ โ ์์ฐจ(
chain) ยท ๋์(parallel) ยท ๋ถ๊ธฐ(router) ยท ์ฌ์์ฑ(refine) ๋ค ๊ฐ์ง. ๊ฒฐ๊ณผ๋ฌผ๋ ๋ค์ ๋ถํ์ด๋ผ ์๋ก ์ค์ฒฉ๋ฉ๋๋ค.chain(parallel([a, b]), router({ โฆ }))์ฒ๋ผ์. -
์ปจํ ์คํธ ์ฐฝ ๊ด๋ฆฌ โ ์จ๋๋ฐ์ด์ค ๋ชจ๋ธ์ ์ฐฝ์ ์์ฒ ํ ํฐ๋ฟ์ด๋ผ ๊ธ๋ฐฉ ๋์นฉ๋๋ค. ์์ด์ ํธ๋ง๋ค ์ฐฝ์ ๋ฐ๋ก ์๋๋ค. ํ๋ฆ์ ๋ค์ ๋๋ ค๋ ์ง๋ ๋ํ๊ฐ ์์ด์ง ์๊ณ , ํฐ ๋๊ตฌ ๊ฒฐ๊ณผ๋ ์๋ ค์ ๋ค์ด๊ฐ๋๋ค. ๋์น ๋งํ ์ค์๋ ์ฝ์์ด ๋จผ์ ์ง์ด์ค๋๋ค.
-
๋ชจ๋ธ ๋ฐ ๊ธฐ์ต โ ์ฐฝ์ ๋ค ๋ด์ ์ ์๋ ๊ฒ์ ๋ธ๋ผ์ฐ์ ์ ์ฅ์์ ๋๊ณ ํ์ํ ๋๋ง ๊บผ๋ด ์๋๋ค. ๊ฐ์ ์ ์ฅ์๋ฅผ ์ฌ๋ฌ ์์ด์ ํธ์๊ฒ ๋๊ธฐ๋ฉด ๊ทธ๋๋ก ๊ณต์ ์์ ํ์ด ๋ฉ๋๋ค. ์๋ก๊ณ ์นจํด๋ ๋จ์ต๋๋ค.
-
๋ชป ์ฐ๋ ํ๊ฒฝ ์ฐํ โ Chrome ์ ์ฉ ๋ชจ๋ธ์ ์ธ์ด์๋ง๋ค, ๊ธฐ๋ฅ๋ง๋ค ์ฌ์ฉ ๊ฐ๋ฅ ์ฌ๋ถ๊ฐ ๋ค๋ฆ ๋๋ค. ์ฌ์ฏ ๊ตฐ๋ฐ๋ฅผ ์ผ์ผ์ด ํ์ธํ๋ ๋์
fallback์ ๋์ฒด ์์ด์ ํธ๋ฅผ ํ๋ ๊ฑธ์ด๋๋ฉด ๋ฉ๋๋ค.
๋ชจ๋ธ์ด ์ฌ์ฉ์ ๊ธฐ๊ธฐ์์ ๋๊ธฐ ๋๋ฌธ์, ๊ธฐ๊ธฐ ์ฌ์ ์ด ์ ๋ง์ผ๋ฉด ๊ธฐ๋ฅ ์์ฒด๊ฐ ์์ ์ผ์ง์ง ์์ต๋๋ค.
| ๋ธ๋ผ์ฐ์ | Chrome 138 ์ด์ ๋ฐ์คํฌํฑ (๋ชจ๋ฐ์ผ ๋ฏธ์ง์) |
| ์ ์ฅ ๊ณต๊ฐ | ๋ค์ด๋ก๋ ์์ ์ 22GB ์ด์ ์ฌ์ , ์ดํ 10GB ๋ฐ์ผ๋ก ๋จ์ด์ง๋ฉด ๋ชจ๋ธ ์ญ์ |
| ๊ธฐ๊ธฐ ์ฑ๋ฅ | VRAM 4GB ์ด๊ณผ, ๋๋ RAM 16GB + 4์ฝ์ด ์ด์ |
| ์ฒซ ์คํ | ๋ชจ๋ธ ์ฝ 4GB ๋ค์ด๋ก๋. ๊ทธ๋์ ๋๊ธฐ |
๋ชจ๋ธ์ ์ฌ์ดํธ๋ณ์ด ์๋๋ผ ๋ธ๋ผ์ฐ์ ์ ์ญ์ด๋ผ, ์ฌ์ฉ์๊ฐ ๋ค๋ฅธ ๊ณณ์์ ์ด๋ฏธ ํ ๋ฒ ๋ฐ์๋ค๋ฉด ๊ทธ๋๋ก ์๋๋ค.
"์์ผ๋ฉด ๋ ์ข์" ์๋ฆฌ์ ์ฐ์ธ์. ์์ผ๋ฉด ์๋น์ค๊ฐ ์ ๋์๊ฐ๋ ์๋ฆฌ์๋ ์ฐ์ง ๋ง์ธ์. ๊ธฐ๋ฅ์ ์จ๊ธฐ๊ฑฐ๋, ์๋ฒ ๊ฒฝ๋ก๋ฅผ ๋ฐ๋ก ๋๊ฑฐ๋,
fallback์ ์ง์ ํด ๋์ธ์.
pnpm add my-little-agent๋ชจ๋ธ์ Chrome์ด ์์์ ๋ด๋ ค๋ฐ๊ณ ๊ด๋ฆฌํฉ๋๋ค. ์ฑ ๋ฒ๋ค์๋ ์๋ฌด๊ฒ๋ ๋์ง ์์ต๋๋ค. ์ง๊ธ ์ํ๋ chrome://on-device-internals์์ ๋ณผ ์ ์์ต๋๋ค.
import { Agent } from 'my-little-agent'
const agent = new Agent({ instruction: 'ํ๊ตญ์ด๋ก ์งง๊ณ ๋ช
ํํ๊ฒ ๋ตํ๋ค.' })
console.log(await agent.send('์ฌ๊ท๋ฅผ ํ ๋ฌธ์ฅ์ผ๋ก ์ค๋ช
ํด์ค'))์ด ์ธ ์ค๋ง ๋๊ณ ๋ณด๋ฉด Chrome API๋ฅผ ์ง์ ์ฐ๋ ๊ฒ๊ณผ ๊ฑฐ์ ๊ฐ์ต๋๋ค. ์ฐจ์ด๋ ๋๊ตฌ๋ฅผ ๋ถ์ด๊ณ ์ฌ๋ฌ ๊ฐ๋ฅผ ์ด์ด ๋ถ์ด๋ ์๊ฐ๋ถํฐ ์๊น๋๋ค. ์๋๋ก ์ด์ด์ง๋๋ค.
Agent์ Workflow๋ ๊ฐ์ ๋ชจ์์
๋๋ค. { name, run(input) } โ ์ด๋ฆ์ด ์๊ณ , ๋ฌธ์์ด์ ๋ฐ์ ๋ฌธ์์ด์ ๋๋ ค์ค๋๋ค. ์ฝ๋์์๋ ์ด ๋ชจ์์ Runnable์ด๋ผ๊ณ ๋ถ๋ฆ
๋๋ค. ์ด๋ํฐ ์์ด ์๋ก ๋ผ์์ง๋ ์ด์ ๊ฐ ์ด๊ฒ ํ๋์
๋๋ค.
| ์์ | ๊ธฐ๋ฅ | ์์ |
|---|---|---|
| Availability | ์ด ๋ธ๋ผ์ฐ์ ์์ ๋๋ ํ์ธ | isSupported(), availability() |
| Agent | AI ๋ชจ๋ธ ํ ๋ช | new Agent({ instruction: '๋๋ ๋ฒ์ญ๊ฐ๋ค' }) |
| Tool | ๋ชจ๋ธ์ด ๋ถ๋ฅด๋ ์ปค์คํ ํจ์ | tool({ โฆ }) |
| Workflow | Agent๋ฅผ ์ด์ด ๋ถ์ | chain, parallel, router, refine |
| Memory | ๋ธ๋ผ์ฐ์ ์ ์ ์ฅ | localMemory(), memoryTools() |
Availability์ Memory๋ Runnable์ด ์๋๋๋ค. ๊ฐ๊ฐ ์์ ์ ํ์ธ๊ณผ ์ ์ฅ์์ด๊ณ , ๋๋จธ์ง๊ฐ ๋ถํ์
๋๋ค.
๋ชจ๋ ๋ฐฉ๋ฌธ์๊ฐ ๋ด์ฅ AI๋ฅผ ์ธ ์ ์๋ ๊ฑด ์๋๋๋ค. ์ ๋๋ ํ๊ฒฝ์์๋ ์์ธ๋ฅผ ๋์ง์ง ์๊ณ 'unavailable'์ ๋๋ ค์ฃผ๋, ๋ถ๊ธฐ๋ง ํด ๋๋ฉด ๋ฉ๋๋ค.
import { availability, isSupported } from 'my-little-agent'
isSupported() // boolean โ ์ ์ญ LanguageModel ์กด์ฌ ์ฌ๋ถ๋ง (๋๊ธฐ)
await availability() // ๋ชจ๋ธ๊น์ง ์ค๋น๋๋์ง (๋น๋๊ธฐ)
// โ 'unavailable' | 'downloadable' | 'downloading' | 'available'| ๊ฐ | ๋ป | ํ ์ผ |
|---|---|---|
'unavailable' |
์ด ๊ธฐ๊ธฐ์์๋ ๋ชป ์ | ๊ธฐ๋ฅ์ ์จ๊ธฐ๊ฑฐ๋ ์๋ฒ ๊ฒฝ๋ก๋ก |
'downloadable' |
์ธ ์ ์์ง๋ง ์์ง ์ ๋ฐ์ | ์ฒซ ํธ์ถ์์ ๋ฐ๊ธฐ ์์. ์งํ๋ฅ ์ ๋ณด์ฌ์ค ๊ฒ |
'downloading' |
์ง๊ธ ๋ฐ๋ ์ค | ๊ธฐ๋ค๋ฆฌ๊ฒ ํ๊ณ ์งํ๋ฅ ํ์ |
'available' |
๋ฐ๋ก ์ฌ์ฉ ๊ฐ๋ฅ | ๊ทธ๋ฅ ์ฐ๋ฉด ๋จ |
if ((await availability()) === 'downloadable') {
// ์ฒซ ํธ์ถ์์ ์ฝ 4GB๋ฅผ ๋ด๋ ค๋ฐ๋๋ค. ์งํ๋ฅ ์ ๊ผญ ๋ณด์ฌ์ฃผ์.
new Agent({ onDownloadProgress: (p) => setProgress(Math.round(p * 100)) })
}์ญํ ํ๋์ ์ธ์ ํ๋์ ๋๋ค. ์ธ์ ์ ์ฒซ ํธ์ถ ๋ ๋ง๋ค์ด์ง๋ฏ๋ก, ์ธ์คํด์ค๋ฅผ ๋ฏธ๋ฆฌ ์ฌ๋ฌ ๊ฐ ๋ง๋ค์ด ๋ฌ๋ ๋ถ๋ด์ด ์์ต๋๋ค.
const writer = new Agent({
name: 'writer',
instruction: '์ ํ ๊ด๊ณ ๋ฌธ๊ตฌ๋ฅผ ์ฐ๋ ์นดํผ๋ผ์ดํฐ.',
})
await writer.send('์ฌ๋ฆ ์ธ์ผ ๋ฐฐ๋ ๋ฌธ๊ตฌ ์ธ ๊ฐ๋ง')์ ๋ถ ์ ํ์
๋๋ค. new Agent()๋ง ํด๋ ๋์ํฉ๋๋ค.
| ์ต์ | ๊ธฐ๋ณธ๊ฐ | ์ธ์ ์ฐ๋ |
|---|---|---|
instruction |
์์ | ์ด ์์ด์ ํธ์ ์ญํ . ์์คํ ํ๋กฌํํธ๋ก ๋ค์ด๊ฐ๋๋ค. ๊ฑฐ์ ํญ์ ์๋๋ค |
tools |
[] |
๋ชจ๋ธ์๊ฒ ์ฅ์ฌ์ค ํจ์๋ค. ํ๋๋ผ๋ ์์ผ๋ฉด ํด ํธ์ถ ๋ฃจํ๋ก ๋์ํฉ๋๋ค |
stateless |
false |
true๋ฉด ํธ์ถ๋ง๋ค ๋ฐฑ์ง์์ ์์. chainยทparallel์ ๋ฃ์ ์์ด์ ํธ๋ ์ผ์ธ์ |
name |
'agent' |
๋ก๊ทธ์ parallel ๊ฒฐ๊ณผ ๋ผ๋ฒจ์ ์ฐ์
๋๋ค. ์ฌ๋ฟ์ ์ฎ์ ๋ ๋ถ์ด์ธ์ |
today |
false |
์ค๋ ๋ ์ง๋ฅผ ์์คํ ํ๋กฌํํธ์ ํ ์ค ๋ฃ์ต๋๋ค. ๋ ์งยท๊ธฐ๊ฐ์ ๋ค๋ฃจ๋ ์์ด์ ํธ๋ฉด ์ผ์ธ์ |
maxSteps |
5 |
ํด ๋ฃจํ ๋ฐ๋ณต ์ํ. ๋๊ตฌ๋ฅผ ์ฌ๋ฌ ๋ฒ ๊ฑฐ์ณ์ผ ํ๋ ์์ ์ด๋ฉด ์ฌ๋ฆฌ์ธ์ |
maxToolResultChars |
4000 |
๋๊ตฌ ๊ฒฐ๊ณผ๋ฅผ ์ด ๊ธธ์ด์์ ์๋ฆ ๋๋ค. ํฐ JSON์ ๋๋ ค์ฃผ๋ ๋๊ตฌ๊ฐ ์์ผ๋ฉด ์ค์ด์ธ์ |
history |
[] |
์ด์ ๋ํ๋ฅผ ๋ฃ์ด ๋ณต์ํฉ๋๋ค. ์๋ก๊ณ ์นจ ํ ์ด์ด๊ฐ๊ธฐ์ ์๋๋ค |
temperature / topK |
Chrome ๊ธฐ๋ณธ๊ฐ | 0์ ๊ฐ๊น์ธ์๋ก ๊ฒฐ์ ์ . ๋ ๋ค ์ฃผ๊ฑฐ๋ ๋ ๋ค ์ ์ฃผ๊ฑฐ๋๋ง ๋ฉ๋๋ค |
onEvent |
์์ | ํด ํธ์ถยท๊ฒฐ๊ณผยท์ค๋ฅยท์ปจํ ์คํธ ์ด๊ณผ๋ฅผ ํ๋ ค๋ณด๋ ๋๋ค. ๋ก๊ทธ UI์ ์ฐ๊ฒฐํ์ธ์ |
onDownloadProgress |
์์ | ๋ชจ๋ธ ๋ค์ด๋ก๋ ์งํ๋ฅ 0~1 |
signal |
์์ | AbortSignal. ์ด ์์ด์ ํธ์ ์คํ ์ ์ฒด๋ฅผ ์ทจ์ํฉ๋๋ค |
expectedInputs / expectedOutputs |
ํ ์คํธ | ๋ฉํฐ๋ชจ๋ฌ์ ์ธ ๋ ์ ์ธํฉ๋๋ค. ์: [{ type: 'image' }] |
// ์ฑ๋ด โ ๋ํ๋ฅผ ์ด์ด๊ฐ์ผ ํ๋ stateless๋ฅผ ๋๋๋ค(๊ธฐ๋ณธ๊ฐ)
const bot = new Agent({ instruction: '์น์ ํ ์๋ด์.' })
// ์ํฌํ๋ก์ฐ ๋จ๊ณ โ ๋งค๋ฒ ๋ฐฑ์ง์์ ์์ํด์ผ ํ๋ ์ผญ๋๋ค
const step = new Agent({ instruction: 'ํต์ฌ๋ง ์ธ ๋ฌธ์ฅ์ผ๋ก.', stateless: true })
// ๋๊ตฌ๋ฅผ ์ฐ๋ ์์ด์ ํธ โ ์ฌ๋ฌ ๋ฒ ๊ฑฐ์ณ์ผ ํ๋ฉด maxSteps๋ฅผ ์ฌ๋ฆฝ๋๋ค
const researcher = new Agent({
instruction: '๋๊ตฌ๋ก ์ฌ์ค์ ํ์ธํ ๋ค ๋ตํ๋ค.',
tools: [searchTool, dbTool],
maxSteps: 8,
maxToolResultChars: 1500, // ๊ฒฐ๊ณผ๊ฐ ํฌ๋ฉด ์ฐฝ์ ์๋ผ๋ ค๊ณ ์ค์
๋๋ค
onEvent: (e) => console.log(e.type, e),
})
today: true๋ฅผ ์ผ๋ฉด ์ค๋ ๋ ์ง๊ฐ ๋ค์ด๊ฐ๋๋ค. ์จ๋๋ฐ์ด์ค ๋ชจ๋ธ์ ํ์ต ์์ ์ด ๊ณ ์ ๋ผ ์๊ณ ์๊ณ๊ฐ ์์ต๋๋ค. ๋ ์ง๋ฅผ ๋ฌผ์ผ๋ฉด ํ์ ์ ์ฐฌ ์ค๋ต์ ๋ ๋๋ค. ์ผ๋ฉด ์์คํ ํ๋กฌํํธ ๋งจ ์์Today's date: 2026-08-25 (Tuesday).ํ ์ค์ด ๋ถ์ต๋๋ค. 20ํ ํฐ ๋จ์ง์ ๋๋ค.
| ๋๋ ค์ฃผ๋ ๊ฒ | ์ธ์ ์ฐ๋ | |
|---|---|---|
send(input) |
Promise<string> |
๊ธฐ๋ณธ. ์ต์ข ๋ต๋ณ ํ๋. ๋๊ตฌ๊ฐ ์์ผ๋ฉด ๋ฃจํ๋ฅผ ๋๊น์ง ๋๋ฆฐ ๋ค ๋ตํฉ๋๋ค |
stream(input) |
AsyncGenerator<string> |
ํ์ดํ ํจ๊ณผ. ๊ธ์ ์กฐ๊ฐ์ด ์์๋๋ก ๋์ต๋๋ค |
generate<T>(input, schema) |
Promise<T> |
JSON์ ๋ฐ๊ณ ์ถ์ ๋. ์คํค๋ง๋ก ์ถ๋ ฅ์ ๊ฐ์ ํ๊ณ ํ์ฑ๊น์ง ํด์ ๊ฐ์ฒด๋ก ์ค๋๋ค |
run(input) |
Promise<string> |
send()์ ๋ณ์นญ. Runnable ๊ท์ฝ์ ๋ง์ถ๋ ค๊ณ ์์ต๋๋ค |
fork(name?) |
Promise<Agent> |
์ง๊ธ ๋ํ๋ฅผ ๋ณต์ ํ ์ ์์ด์ ํธ. ๊ฐ์ ๋งฅ๋ฝ์์ ๊ฐ๋ผ์ ธ ์คํํ ๋ |
ready() |
Promise<Session> |
์ธ์ ์ ๋ฏธ๋ฆฌ ๋ง๋ค์ด ๋ก๋๋ค. ์ฒซ ์๋ต ์ง์ฐ์ ์๋น๊ธธ ๋ |
history |
PromptMessage[] |
์ง๊ธ๊น์ง์ ๋ํ. JSON์ผ๋ก ์ ์ฅํ๋ค๊ฐ history ์ต์
์ผ๋ก ๋ณต์ํฉ๋๋ค |
usage |
{ used, total } | null |
์ปจํ
์คํธ ํ ํฐ ์ฌ์ฉ๋. ์ธ์
์ด ์์ผ๋ฉด null |
stateless |
boolean | undefined |
์ค์ ๊ฐ. ์ง์ ์ ํ์ผ๋ฉด undefined (false๊ฐ ์๋๋๋ค) |
reset() |
โ | ์ธ์ ๊ณผ ๋ํ ๊ธฐ๋ก์ ๋ชจ๋ ๋ฒ๋ฆฝ๋๋ค |
destroy() |
โ | ์ธ์ ๋ง ๋ฐ๋ฉํฉ๋๋ค. ๋ค ์ด ์์ด์ ํธ๋ ๊ผญ ํธ์ถํ์ธ์ |
// send โ ๊ฐ์ฅ ํํ ์ฌ์ฉ
const answer = await agent.send('์ฌ๋ฆ ์ธ์ผ ๋ฌธ๊ตฌ ์จ์ค')
// stream โ ํ ๊ธ์์ฉ ํ๋ฉด์ ํ๋ฆฌ๊ธฐ
for await (const chunk of agent.stream('๊ธธ๊ฒ ์ค๋ช
ํด์ค')) {
setText((prev) => prev + chunk)
}
// generate โ ํ์ฑ ๊ฑฑ์ ์์ด ๊ฐ์ฒด๋ก
const parsed = await agent.generate<{ title: string; tags: string[] }>(article, {
type: 'object',
properties: {
title: { type: 'string' },
tags: { type: 'array', items: { type: 'string' } },
},
required: ['title', 'tags'],
})
// ์ ์ฅํ๊ณ ๋ณต์ํ๊ธฐ
localStorage.setItem('chat', JSON.stringify(agent.history))
const restored = new Agent({ instruction, history: JSON.parse(saved).slice(-10) })
agent.usage // { used: 812, total: 4096 }
agent.destroy()Chrome์ ํ ๊ฐ์ง ์ผ๋ง ํ๋ ์ ์ฉ ๋ชจ๋ธ์ ๋ฐ๋ก ์ค๋๋ค. ์ง์ ๋ง๋ ์์ด์ ํธ์ ๋๊ฐ์ด ์ฐ๋๋ก ๊ฐ์ธ ๋์ต๋๋ค. ์ง์๋ฌธ์ ์ธ ํ์๊ฐ ์๋, ์ด๋ฏธ ์์ฑ๋ ์์ด์ ํธ๋ผ๊ณ ๋ณด๋ฉด ๋ฉ๋๋ค.
import {
languageDetector,
proofreader,
rewriter,
summarizer,
translator,
writer,
} from 'my-little-agent'
await translator({ to: 'ko' }).run('Hello') // โ '์๋
ํ์ธ์' (์ถ๋ฐ์ด ์๋ ๊ฐ์ง)
await summarizer({ type: 'tldr', length: 'short' }).run(longText)
await languageDetector().run('Bonjour') // โ 'fr'
await writer({ tone: 'formal' }).run('ํ๋ถ ์์ฒญ ๋ฉ์ผ')
await rewriter({ tone: 'more-casual', length: 'shorter' }).run(draft)
await proofreader().run('I seen him') // โ 'I saw him'| ๋ด์ฅ Agent | ํ๋ ์ผ | ์ต์ |
|---|---|---|
translator() |
๋ฒ์ญ | to (ํ์) ยท from (์๋ตํ๋ฉด ์๋ ๊ฐ์ง) |
summarizer() |
์์ฝ | type ยท length ยท format ยท sharedContext |
languageDetector() |
๋ฌด์จ ์ธ์ด์ธ์ง ํ๋ณ. ์ธ์ด ์ฝ๋๋ฅผ ๋๋ ค์ค | โ |
writer() |
์ง์๋๋ก ์ ๊ธ ์์ฑ | tone ยท length ยท format ยท context |
rewriter() |
๊ธฐ์กด ๊ธ์ ์ด์กฐยท๊ธธ์ด ๋ณ๊ฒฝ | tone ยท length ยท format ยท context |
proofreader() |
๋ฌธ๋ฒยท๊ฐ๋ ์ฑ ๊ต์ | expectedInputLanguages |
์ ๋ถ fallback(๋ชป ์ธ ๋ ๋์ ๋๋ฆด Agent)๊ณผ signal์ ๋ฐ์ต๋๋ค. ์์ ์
์ Chrome 138๋ถํฐ ์ ์์ด๊ณ , ๋ค์ ์
์ ์์ง ์ค๋ฆฌ์ง ํธ๋ผ์ด์ผ์ด๋ผ ๋๋ถ๋ถ์ ํ๊ฒฝ์์ fallback์ ํ๋๋ค.
์ด๊ฒ ๊ฐ์ฅ ํฐ ์ ์ฝ์ ๋๋ค. ์ ์ฉ ๋ชจ๋ธ์ ๋ณ๋๋ก ๋๊ธฐ ๋๋ฌธ์ ๋ค๋ฅธ ์์ด์ ํธ์ ์ปจํ ์คํธ ์ฐฝ์ 1ํ ํฐ๋ ์ฐ์ง ์์ต๋๋ค. ์ฐฝ์ด ์์ฒ ํ ํฐ๋ฟ์ธ ํ๊ฒฝ์์, ๋ชจ๋ธ์๊ฒ ์ ์ํค๊ณ ๋๋ผ ์ ์๋ ์ผ์ ๊ณจ๋ผ๋ด๋ ๊ฒ์ด ๊ฐ์ฅ ํฌ๊ฒ ๋จ์ต๋๋ค.
// Agent์ ๋๋ํ ์์
๋๋ค
chain(analyst, summarizer(), translator({ to: 'ko' }))
// ๋ชป ์ฐ๋ ํ๊ฒฝ์ด๋ฉด ์ด ์์ด์ ํธ๊ฐ ๋์ ๋ฒ์ญํฉ๋๋ค
translator({
to: 'ko',
fallback: new Agent({ instruction: '์
๋ ฅ์ ํ๊ตญ์ด๋ก๋ง ๋ฒ์ญํด ์ถ๋ ฅํด๋ผ.' }),
})proofreader๋ง ๊ฒฐ๊ณผ๊ฐ ๋ฌธ์์ด์ด ์๋๋ผ ๊ฐ์ฒด๋ผ์ ๋๋ก ๋๋ฉ๋๋ค.
const fix = proofreader()
await fix.run('I seen him') // โ 'I saw him' (์กฐ๋ฆฝ์ฉ)
await fix.proofread('I seen him') // โ { correctedInput, corrections } (๋ฐ์ค ๊ทธ์ ๋)Tool๊ณผ ํท๊ฐ๋ฆฌ์ง ๋ง์ธ์. Tool์ ๋ชจ๋ธ์ด ํ๋จํด์ ๋ถ๋ฅด๋ ํจ์๋ผ
tools: [...]์ ๋ฃ์ต๋๋ค. ์ด์ชฝ์ Agent๋ผ์chain(...)์ ๋ฃ์ต๋๋ค. ๋ํ๋ฅผ ์ด์ด๊ฐ๋ ์์ด์ ํธ๋ ์๋๋๋ค.send()ยทhistoryยทtools๋ ์๊ณrun()๋ง ์์ต๋๋ค.
const weather = tool<{ city: string }>({
name: 'weather',
description: '๋์์ ํ์ฌ ๊ธฐ์จ์ ์กฐํํ๋ค', // ๋ชจ๋ธ์ ์ด ํ ์ค๋ง ๋ณด๊ณ ๊ณ ๋ฅธ๋ค
parameters: { type: 'object', properties: { city: { type: 'string' } } },
execute: async ({ city }) => fetch(`/api/weather?city=${city}`).then((r) => r.json()),
})
new Agent({ instruction: '๋ ์จ ๋น์', tools: [weather] })๋ชจ๋ธ์ด ์ค์ค๋ก ํ๋จํด์ ๋ถ๋ฆ
๋๋ค. ์ธ์ ๋ถ๋ฅผ์ง๋ description ํ ์ค๋ก ์ ํด์ง๋ ๊ตฌ์ฒด์ ์ผ๋ก ์ฐ์ธ์.
๋๊ตฌ๊ฐ ์์ธ๋ฅผ ๋์ ธ๋ ๋ฃจํ๋ ์ฃฝ์ง ์์ต๋๋ค. ์ค๋ฅ ๋ด์ฉ์ด ๋ชจ๋ธ์๊ฒ ์ ๋ฌ๋ผ์ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ ์๋ํฉ๋๋ค.
import { calculator, pageTools } from 'my-little-agent'
new Agent({
instruction: '์ด ํ์ด์ง๋ฅผ ๋ณด๋ฉฐ ๋ตํ๋ ๋์ฐ๋ฏธ.',
tools: [calculator(), ...pageTools()],
})| ๋ด์ฅ Tool | ํ๋ ์ผ | ์ธ์ |
|---|---|---|
calculator() |
์ ํํ ๊ณ์ฐ | ์์ ๋ฌธ์์ด |
pageTools() โ pageInfo |
ํ์ด์ง ์ ๋ชฉ, ์ฃผ์, ์ฌ์ฉ์๊ฐ ์ ํํ ํ ์คํธ | ์์ |
pageTools() โ readPage |
ํ์ด์ง ๋ณธ๋ฌธ ํ ์คํธ | ์์ |
calculator() โ ์ํ ๋ชจ๋ธ์ด ํ์คํ ๋ชปํ๋ ์ผ์ด ์ ํํ ๊ณ์ฐ์
๋๋ค. ๊ทธ ์นธ์ ๋๊ตฌ๋ก ๋ฉ์๋๋ค. ์ฌ์น์ฐ์ฐยท๋๋จธ์ง(%)ยท๊ดํธยท์์๋ฅผ ์ง์ํ๊ณ , ์๋ฆฟ์ ์ผํ(1,200)๋ ๋ฐ์์ค๋๋ค. ๋ฐฑ๋ถ์จ์ 0.15์ฒ๋ผ ์์๋ก ์๋๋ค.
pageTools() โ ์ง๊ธ ์ด๋ ค ์๋ ํ์ด์ง๋ฅผ ์ฝ์ต๋๋ค. ๋๊ตฌ ๋ ๊ฐ๊ฐ ๋์ต๋๋ค.
์๋ฒ LLM์ด ๊ตฌ์กฐ์ ์ผ๋ก ๋ชป ํ๋ ์ผ์ ๋๋ค. ์ฌ์ฉ์ ํ๋ฉด ์์ ์๋ ๊ฒ์ ๋ธ๋ผ์ฐ์ ์์์ ๋๋ ๋ชจ๋ธ๋ง ๋ณผ ์ ์์ต๋๋ค.
pageTools({
root: () => document.querySelector('article'), // ์ฝ์ ๋ฒ์. ๊ธฐ๋ณธ์ body
maxChars: 2000, // ์ ๋จ ๊ธฐ์ค
includeQuery: false, // ์ฃผ์์ ์ฟผ๋ฆฌ ๋ฌธ์์ด ํฌํจ ์ฌ๋ถ. ๊ธฐ๋ณธ false
})์ฃผ์๋ ๊ธฐ๋ณธ์ ์ผ๋ก ์ฟผ๋ฆฌ ๋ฌธ์์ด์ ๋บ๋๋ค. ์ธ์ ํ ํฐ์ด ์ค๋ฆฌ๋ ๊ฒฝ์ฐ๊ฐ ํํ๋ฐ, ๋ชจ๋ธ์ด ๋ก์ปฌ์์ ๋๋๋ผ๋ ๋ํ ๊ธฐ๋ก์ ์ ์ฅ๋ ์ ์๊ธฐ ๋๋ฌธ์ ๋๋ค.
์น ๊ฒ์์ ๋ฃ์ง ์์์ต๋๋ค. ๋ธ๋ผ์ฐ์ ์ ๊ฒ์ ๊ธฐ๋ฅ์ด ์์ด ์ 3์ API๋ฅผ ์จ์ผ ํ๋๋ฐ, ๊ทธ ์๊ฐ API ํคยทํ๋ก์ ์๋ฒยท๊ณผ๊ธยท์ธ๋ถ ์ ์ก์ด ์ ๋ถ ๋ฐ๋ผ์ต๋๋ค. ์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ ์ ๊ฐ ํต์งธ๋ก ๋ฌด๋์ง๋๋ค. ํ์ํ๋ฉด
tool()๋ก ์ง์ ๋ง๋์ธ์. ์ด ์ค์ด๋ฉด ๋ฉ๋๋ค.
| ํ๋ ์ผ | ์ฐ๋ ๊ณณ | |
|---|---|---|
chain(...steps) |
์์๋๋ก, ์ ๊ฒฐ๊ณผ๊ฐ ๋ค ์ ๋ ฅ | ์ด์ โ ๊ต์ โ ๋ฒ์ญ |
parallel(steps, opts?) |
๊ฐ์ ์ ๋ ฅ์ ๋์์ ๋๋ฆฌ๊ณ ํฉ์นจ | ์ฌ๋ฌ ๊ด์ ๋์ ๋ถ์ |
router({ classifier, routes }) |
๋ถ๋ฅํ ๋ค ํ ๊ฒฝ๋ก๋ง ์คํ | ๋ฌธ์ ์ ํ๋ณ ๋ถ๊ธฐ |
refine({ worker, evaluator }) |
๊ธฐ์ค ์ ์์ ๋ฟ์ ๋๊น์ง ๋ค์ ์ | ํ์ง์ด ์ค์ํ ๊ฒฐ๊ณผ๋ฌผ |
step(fn) |
๋ชจ๋ธ ์์ด ๋๋ ์์ ํจ์ | ์ ์ฒ๋ฆฌ, ํ์ฒ๋ฆฌ, ๋ง์คํน |
// ์ ํ๋ฒํธ๋ฅผ ์ง์ฐ๊ณ , ์ธ ๊ด์ ์ผ๋ก ๋๋ ๋ถ์ํ๊ณ , ํ๋๋ก ํฉ์น๋ค.
const flow = chain(
step((s) => s.replace(/\d{3}-\d{4}-\d{4}/g, '[์ ํ๋ฒํธ]')),
parallel([pros, cons, risks]),
summarizer(),
)๊ฒฐ๊ณผ๋ ๋ถํ์ด๋ผ ๋ค์ ์กฐ๋ฆฝํ ์ ์์ต๋๋ค.
chain(parallel([a, b, c]), router({ ... }), refine({ ... }))์ง์ ํฉ์น๋ ค๋ฉด reduce๋ฅผ ๋๊ธฐ์ธ์.
parallel([a, b], { reduce: (results) => results.join('\n---\n') })์กฐ๋ฆฝํ Agent๋
stateless: true๋ฅผ ์ผ์ธ์. ์ ์ผ๋ฉด ํ๋ฆ์ ๋ ๋ฒ์งธ ์คํํ ๋ ์ฒซ ๋ฒ์งธ ๋ํ๊ฐ ์ฐฝ์ ๊ทธ๋๋ก ๋จ์ ๊ฒฐ๊ณผ๊ฐ ์กฐ์ฉํ ๋ฌ๋ผ์ง๋๋ค. ์๋ฌ๋ ์ ๋์ ๊ฐ์ฅ ์ฐพ๊ธฐ ์ด๋ ค์ด ์ค์๋ผ, ์กฐํฉ๊ธฐ๊ฐ ์ฝ์๋ก ๊ฒฝ๊ณ ํด ์ค๋๋ค. ์ผ๋ถ๋ฌ ๋ํ๋ฅผ ์ด์ด๊ฐ ์๋๋ผ๋ฉดstateless: false๋ฅผ ๋ช ์ํ๋ฉด ๊ฒฝ๊ณ ๊ฐ ์ฌ๋ผ์ง๋๋ค.
์ธ์ ์ ์๋ก๊ณ ์นจํ๋ฉด ์ฌ๋ผ์ง๊ณ , ์ฐฝ์ ์ข์ต๋๋ค. ๊ทธ๋์ ๊ธฐ์ต์ ๋ชจ๋ธ ๋ฐ์ ๋ก๋๋ค.
const shared = localMemory('support-desk')
const tools = memoryTools(shared) // remember / recall / listMemories
new Agent({ instruction: '์์๋ธ ์ฌ์ค์ remember๋ก ์ ์ฅํ๋ค.', tools })๊ฐ์ ์ ์ฅ์๋ฅผ ์ฌ๋ฌ ์์ด์ ํธ์๊ฒ ๋๊ธฐ๋ฉด ๊ทธ๊ฒ ๊ณง ๊ณต์ ์์ ํ์ ๋๋ค. ์์ธํ ๋ด์ฉ์ ์๋์์ ์ด์ด์ง๋๋ค.
์์ด์ ํธ๋ ๊ฐ์ ์๊ธฐ ์ธ์
, ์๊ธฐ ์ฐฝ์ ์๋๋ค. ์๋ก์๊ฒ ๋์ด๊ฐ๋ ๊ฑด run()์ด ๋๋ ค์ค ๋ฌธ์์ด ํ๋๋ฟ์
๋๋ค.
[๋ถ๋ฅ๊ธฐ] [๋ถ์๊ฐ] [์์ฝ๊ฐ]
์๊ธฐ ์ฐฝ ์๊ธฐ ์ฐฝ ์๊ธฐ ์ฐฝ
โโโ ๋ฌธ์์ด โโโ โโโ ๋ฌธ์์ด โโโ
์ ์ฝ์ฒ๋ผ ๋ณด์ด์ง๋ง ๋ ธ๋ฆฐ ๊ฒ๋๋ค. ์ฐฝ์ด ์ข์์๋ก ๊ณต์ ๋ ๋ ์ด ๋ฉ๋๋ค. ํ ์์ด์ ํธ๊ฐ ๋ง๋ ์ก์์ ๋๋จธ์ง๊ฐ ๋ค ๊ฐ์ด ์ง์ด์ง๋๊น์. ๋ฐ๋ก ๋๋ฉด ์์ด์ ํธ N๊ฐ๊ฐ ๋ ๋ฆฝ๋ ์ฐฝ N๊ฐ๊ฐ ๋๊ณ , ์์คํ ์ ์ฒด๊ฐ ๋ค๋ฃจ๋ ์ ๋ณด๋์ ์คํ๋ ค ๋์ด๋ฉ๋๋ค.
| ์ํฉ | ๋ฌด์จ ์ผ์ด ์๊ธฐ๋ | ๋์ |
|---|---|---|
| ๊ฐ์ ์์ด์ ํธ๋ก ์กฐ๋ฆฝํ ํ๋ฆ์ ๋ฐ๋ณต ์คํ | ์ง๋ ์คํ์ ๋ํ๊ฐ ์ฐฝ์ ๊ทธ๋๋ก ๋จ์ | stateless: true (์ ์ผ๋ฉด ๊ฒฝ๊ณ ) |
| ๋๊ตฌ๊ฐ ํฐ JSON์ ๋๋ ค์ค | ๊ฒฐ๊ณผ ํ๋๊ฐ ๋ํ๋ฅผ ํต์งธ๋ก ๋ฐ์ด๋ | maxToolResultChars (๊ธฐ๋ณธ 4000์) |
| ์ ๋ ฅ ๋ฌธ์ ์์ฒด๊ฐ ๊น | ์ค๋๋ ๋ถ๋ถ์ด ์๋ฆฌ ์์ด ์๋ ค๋๊ฐ | step()์ผ๋ก ์ชผ๊ฐ parallel ์ฒ๋ฆฌ |
| ๋ฒ์ญยท์์ฝ์ ๋ชจ๋ธ์๊ฒ ์ํด | ์ ์จ๋ ๋ ์ฐฝ์ ์ | translator() ยท summarizer() (์ฐฝ ์ฌ์ฉ๋ 0) |
agent.usage // { used: 812, total: 4096 }
new Agent({ onEvent: (e) => e.type === 'context-overflow' && warn() })Chrome์ด ๋์คํฌ์ ๋ค๊ณ ์๋ ๊ฑด ๋ชจ๋ธ ๊ฐ์ค์น๋ฟ์
๋๋ค. ๋ํ ๊ธฐ๋ก์ ๋ฉ๋ชจ๋ฆฌ์๋ง ์์ด์ ํญ์ ๋ซ์ผ๋ฉด ์์ด์ง๋๋ค. ์ ์ฅ์ ์ฐ๋ฆฌ ๋ชซ์ด๊ณ , agent.history๊ฐ ๊ทธ ์ฐฝ๊ตฌ์
๋๋ค.
localStorage.setItem('chat', JSON.stringify(agent.history))
// ๋ณต์์ ์ต๊ทผ ๋ช ํด๋ง. ์ ๋ถ ๋ฐ์ด ๋ฃ์ผ๋ฉด ์ฐฝ์ด ๋ค์ ๊ฝ ์ฐฌ๋ค.
const saved = JSON.parse(localStorage.getItem('chat') ?? '[]')
const agent = new Agent({ instruction: '...', history: saved.slice(-10) })์ ์ฅ์ ์ง์์ฑ ๋ฌธ์ ๋ฅผ ํ์ง, ์ฉ๋ ๋ฌธ์ ๋ฅผ ํ์ง ์์ต๋๋ค. ์ ์ฅ์๊ฐ ์๋ฌด๋ฆฌ ์ปค๋ ์ฐฝ์ ๋ฃ์ ์ ์๋ ์์ ๊ทธ๋๋ก์ ๋๋ค.
์ปจํ ์คํธ ์ฐฝ์ ์์ ๋, ๋ธ๋ผ์ฐ์ ์ ์ฅ์๋ ์ฐฝ๊ณ ์ ๋๋ค. ์ฐฝ๊ณ ๋ฅผ ํต์งธ๋ก ์์ ๋์ ์ฌ๋ฆฌ์ง ์์ต๋๋ค. ํ์ํ ๊ฒ๋ง ๊ทธ๋๊ทธ๋ ๊บผ๋ด ์ต๋๋ค.
import { Agent, chain, localMemory, memoryTools } from 'my-little-agent'
const shared = localMemory('support-desk')
const tools = memoryTools(shared)
const researcher = new Agent({
instruction: '์๋ฃ๋ฅผ ์ฐพ์ ์์๋ธ ์ฌ์ค์ remember๋ก ์ ์ฅํ๋ค.',
tools: [...tools, searchTool],
stateless: true,
})
const writer = new Agent({
instruction: 'recall๋ก ํ์ํ ์ฌ์ค์ ๊บผ๋ธ ๋ค ๋ต๋ณ์ ์์ฑํ๋ค.',
tools,
stateless: true,
})
await chain(researcher, writer).run('๊ฒฝ์์ฌ ๊ฐ๊ฒฉ ์ ์ฑ
์ ๋ฆฌํด์ค')๋ ์์ด์ ํธ์ ์ฐฝ์ ๋๊น์ง ๋จ๋จ์ ๋๋ค. ์ค๊ฐ๋ ๊ฑด ์ฐฝ๊ณ ์ ๋จ์ ์งง์ ํญ๋ชฉ๋ค๋ฟ์ด๋ผ, ํ์ ์ด ๊ธธ์ด์ ธ๋ ์ฐฝ์ด ํฐ์ง์ง ์์ต๋๋ค. ์๋ก๊ณ ์นจํด๋ ์ฐฝ๊ณ ๋ ๊ทธ๋๋ก ๋จ๊ณ ์.
์ฐฝ๊ณ ๋ ๋ฉ์๋ ๋ค ๊ฐ๋ง ๊ตฌํํ๋ฉด ๊ฐ์๋ผ์ธ ์ ์์ต๋๋ค.
interface MemoryStore {
get(key: string): Promise<string | undefined>
set(key: string, value: string): Promise<void>
delete(key: string): Promise<void>
keys(): Promise<string[]>
}localMemory()๋ localStorage(์ฝ 5 MB)๋ฅผ ์๋๋ค. ๋ ํฐ ์ ์ฅ์ด ํ์ํ๋ฉด IndexedDB๋ ์์ฒด API๋ก ๊ฐ์ ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ์ธ์.
const form = await parser.generate<{ name: string; phone: string; address: string }>(
clipboardText,
{
type: 'object',
properties: {
name: { type: 'string' },
phone: { type: 'string' },
address: { type: 'string' },
},
required: ['name', 'phone', 'address'],
},
)generate()๋ ๋์ฝ๋ฉ ์์ฒด๋ฅผ ๋ฌถ์ด๋ฒ๋ฆฝ๋๋ค. ๋ชจ๋ธ์ด ์ค๋ช
์ ๋ง๋ถ์ด๊ฑฐ๋ ํ์์ ์ด๊ธธ ์๊ฐ ์์ด์, ๊ฒฐ๊ณผ๋ฅผ ๋ฐ๋ก setState์ ๋ฃ์ด๋ ๋ฉ๋๋ค.
const query = await parser.generate<{ category: string; maxPrice: number }>(
'3๋ง์ ์๋ ๋ฌ๋ํ ๋ณด์ฌ์ค',
{
type: 'object',
properties: {
category: { type: 'string', enum: ['shoes', 'clothes', 'bags'] },
maxPrice: { type: 'integer' },
},
required: ['category', 'maxPrice'],
},
)
setItems(all.filter((i) => i.category === query.category && i.price <= query.maxPrice))// ์ ๋ถ Chrome ์ ์ฉ ๋ชจ๋ธ์ด๋ผ ์ปจํ
์คํธ ์ฐฝ์ ์ฐ์ง ์๋๋ค
const digest = chain(summarizer({ length: 'short' }), translator({ to: 'ko' }))
const summaries = await Promise.all(reviews.map((r) => digest.run(r)))const assistant = new Agent({
instruction: '์ผํ๋ชฐ ๋น์. ํ์ํ๋ฉด ๋๊ตฌ๋ฅผ ์ด๋ค.',
tools: [
tool<{ keyword: string }>({
name: 'searchProducts',
description: '์ํ์ ํค์๋๋ก ๊ฒ์ํ๋ค',
parameters: { type: 'object', properties: { keyword: { type: 'string' } } },
execute: ({ keyword }) => fetch(`/api/products?q=${keyword}`).then((r) => r.json()),
}),
tool<{ id: string }>({
name: 'addToCart',
description: '์ํ์ ์ฅ๋ฐ๊ตฌ๋์ ๋ด๋๋ค',
parameters: { type: 'object', properties: { id: { type: 'string' } } },
execute: ({ id }) => cartStore.add(id),
}),
],
})
await assistant.send('์๊น ๋ณธ ๋ฌ๋ํ ์ค์ ์ ์ผ ์ผ ๊ฑฐ ์ฅ๋ฐ๊ตฌ๋์ ๋ฃ์ด์ค')const desk = router({
classifier: new Agent({ name: 'classifier', stateless: true }),
routes: { refund: refundAgent, tech: techAgent, sales: salesAgent },
descriptions: {
refund: 'ํ๋ถ, ์ทจ์, ๋ฐํ ๋ฌธ์',
tech: '์ค๋ฅ, ์ฌ์ฉ๋ฒ ๋ฌธ์',
sales: '๊ฐ๊ฒฉ, ๊ตฌ๋งค ์๋ด',
},
})const polished = refine({
worker: new Agent({
instruction: '์ ํ ๊ด๊ณ ๋ฌธ๊ตฌ๋ฅผ ์ฐ๋ ์นดํผ๋ผ์ดํฐ.',
stateless: true,
}),
evaluator: new Agent({ instruction: '๋ฌธ๊ตฌ๋ฅผ ๊น๊นํ๊ฒ ๋ณด๋ ํธ์ง์ฅ.', stateless: true }),
minScore: 85,
maxRounds: 3,
})๋ณ๋ ์ด๋ํฐ๊ฐ ํ์ ์์ต๋๋ค.
function useAgent(instruction: string) {
const ref = useRef<Agent>()
if (!ref.current) ref.current = new Agent({ instruction }) // ์ธ์
์ ์ง์ฐ ์์ฑ์ด๋ผ ๋ง๋ค์ด๋ง ๋๋ฉด ๊ณต์ง๋ค
useEffect(() => () => ref.current?.destroy(), [])
return ref.current
}
export function Summary({ text }: { text: string }) {
const agent = useAgent('ํต์ฌ๋ง ์ธ ๋ฌธ์ฅ์ผ๋ก ์ค์ธ๋ค.')
const [out, setOut] = useState('')
useEffect(() => {
let alive = true
setOut('')
;(async () => {
for await (const chunk of agent.stream(text)) {
if (!alive) return
setOut((prev) => prev + chunk)
}
})()
return () => {
alive = false
}
}, [text])
return <p>{out}</p>
}const vision = new Agent({
instruction: '์ฌ์ง์ ๋ณด์ด๋ ๊ฒ์ ์ค๋ช
ํ๋ค.',
expectedInputs: [{ type: 'image' }],
})
await vision.send([
{
role: 'user',
content: [
{ type: 'text', value: '์ด ์ฌ์ง์ ๋ญ๊ฐ ์์ด?' },
{ type: 'image', value: imageBlob },
],
},
])๊ฐ๋ฐยท์ค๊ณ ๊ท์นยท๋ก๋๋งต์ AGENTS.md์ ์์ต๋๋ค. ๋ผ์ด์ ์ค๋ MIT์ ๋๋ค.