๋ฉ”์ธ ์ฝ˜ํ…์ธ ๋กœ ๊ฑด๋„ˆ๋›ฐ๊ธฐ
Sonamu๋Š” Vercel AI SDK๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ AI ์—์ด์ „ํŠธ๋ฅผ ๊ตฌ์ถ•ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. OpenAI, Anthropic ๋“ฑ ๋‹ค์–‘ํ•œ LLM ํ”„๋กœ๋ฐ”์ด๋”๋ฅผ ์ง€์›ํ•˜๋ฉฐ, ์ปค์Šคํ…€ ๋„๊ตฌ(tools)๋ฅผ ์ •์˜ํ•˜์—ฌ ์—์ด์ „ํŠธ๊ฐ€ ํŠน์ • ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋„๋ก ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

AI ์—์ด์ „ํŠธ๋ž€?

AI ์—์ด์ „ํŠธ๋Š” ๋Œ€ํ™”ํ˜• AI ๋ชจ๋ธ(LLM)์— **๋„๊ตฌ(tools)**๋ฅผ ์ œ๊ณตํ•˜์—ฌ ๋ณต์žกํ•œ ์ž‘์—…์„ ์ž๋™์œผ๋กœ ์ˆ˜ํ–‰ํ•˜๋„๋ก ํ•˜๋Š” ์‹œ์Šคํ…œ์ž…๋‹ˆ๋‹ค. ํŠน์ง•:
  • LLM์ด ์ƒํ™ฉ์— ๋งž๋Š” ๋„๊ตฌ๋ฅผ ์„ ํƒํ•˜์—ฌ ์‹คํ–‰
  • ์—ฌ๋Ÿฌ ๋‹จ๊ณ„์˜ ์ž‘์—…์„ ์ž๋™์œผ๋กœ ์ˆ˜ํ–‰
  • ์ปจํ…์ŠคํŠธ๋ฅผ ์œ ์ง€ํ•˜๋ฉฐ ๋Œ€ํ™”

ํ•„์ˆ˜ ํŒจํ‚ค์ง€ ์„ค์น˜

AI ์—์ด์ „ํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด Vercel AI SDK์™€ LLM ํ”„๋กœ๋ฐ”์ด๋” ํŒจํ‚ค์ง€๋ฅผ ์„ค์น˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

OpenAI ์‚ฌ์šฉ

pnpm add ai @ai-sdk/openai

Anthropic ์‚ฌ์šฉ

pnpm add ai @ai-sdk/anthropic

๋‘˜ ๋‹ค ์‚ฌ์šฉ

pnpm add ai @ai-sdk/openai @ai-sdk/anthropic

๊ธฐ๋ณธ ์„ค์ •

ํ™˜๊ฒฝ๋ณ€์ˆ˜ ์„ค์ •

# OpenAI
OPENAI_API_KEY=sk-...

# Anthropic
ANTHROPIC_API_KEY=sk-ant-...

LLM ๋ชจ๋ธ ์ดˆ๊ธฐํ™”

import { openai } from '@ai-sdk/openai';

const model = openai('gpt-4o');  // GPT-4 Optimized
์ง€์› ๋ชจ๋ธ:
  • gpt-4o: GPT-4 Optimized (์ตœ์‹ )
  • gpt-4-turbo: GPT-4 Turbo
  • gpt-4: GPT-4
  • gpt-3.5-turbo: GPT-3.5 Turbo

AgentConfig

์—์ด์ „ํŠธ ์„ค์ • ๊ฐ์ฒด์ž…๋‹ˆ๋‹ค.
import type { AgentConfig } from "sonamu/ai";

const config: AgentConfig = {
  model: openai('gpt-4o'),
  instructions: "๋‹น์‹ ์€ ํ˜ธํ…” ์˜ˆ์•ฝ ๋„์šฐ๋ฏธ์ž…๋‹ˆ๋‹ค.",
  toolChoice: 'auto',
  temperature: 0.7,
  maxOutputTokens: 1000,
};

์ฃผ์š” ์˜ต์…˜

LLM ๋ชจ๋ธ (ํ•„์ˆ˜)
import { openai } from '@ai-sdk/openai';
import { anthropic } from '@ai-sdk/anthropic';

config: {
  model: openai('gpt-4o'),
  // model: anthropic('claude-3-5-sonnet-20241022'),
}

์ถ”๊ฐ€ ์˜ต์…˜

const config: AgentConfig = {
  model: openai('gpt-4o'),
  
  // ํ† ํฐ ์ œํ•œ
  maxOutputTokens: 1000,
  
  // ๊ณ ๊ธ‰ ํŒŒ๋ผ๋ฏธํ„ฐ
  topP: 0.9,                    // ์ƒ์œ„ P ์ƒ˜ํ”Œ๋ง
  topK: 50,                     // ์ƒ์œ„ K ์ƒ˜ํ”Œ๋ง
  presencePenalty: 0.0,         // ์ฃผ์ œ ๋ฐ˜๋ณต ์–ต์ œ
  frequencyPenalty: 0.0,        // ๋‹จ์–ด ๋ฐ˜๋ณต ์–ต์ œ
  
  // ์ •์ง€ ์กฐ๊ฑด
  stopSequences: ['\n\n'],      // ์ •์ง€ ์‹œํ€€์Šค
  
  // ์žฌํ˜„์„ฑ
  seed: 12345,                  // ๊ณ ์ • ์‹œ๋“œ
  
  // HTTP ํ—ค๋”
  headers: {
    'X-Custom-Header': 'value',
  },
};

์‹ค์ „ ์„ค์ • ์˜ˆ์ œ

1. ๊ณ ๊ฐ ์ง€์› ์ฑ—๋ด‡

import { openai } from '@ai-sdk/openai';
import type { AgentConfig } from "sonamu/ai";

const config: AgentConfig = {
  model: openai('gpt-4o'),
  instructions: `
    ๋‹น์‹ ์€ ์ „์ž์ƒ๊ฑฐ๋ž˜ ๊ณ ๊ฐ ์ง€์› ์ฑ—๋ด‡์ž…๋‹ˆ๋‹ค.
    - ์ฃผ๋ฌธ ์กฐํšŒ, ๋ฐฐ์†ก ์ถ”์ , ํ™˜๋ถˆ ์ฒ˜๋ฆฌ๋ฅผ ๋„์™€์ค๋‹ˆ๋‹ค.
    - ํ•ญ์ƒ ์ •์ค‘ํ•˜๊ณ  ๋ช…ํ™•ํ•˜๊ฒŒ ๋‹ต๋ณ€ํ•˜์„ธ์š”.
    - ํ•„์š”ํ•œ ๊ฒฝ์šฐ ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ •ํ™•ํ•œ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•˜์„ธ์š”.
  `,
  toolChoice: 'auto',
  temperature: 0.3,  // ์ผ๊ด€๋œ ๋‹ต๋ณ€
  maxOutputTokens: 500,
};

2. ์ฐฝ์˜์  ์ฝ˜ํ…์ธ  ์ƒ์„ฑ

import { anthropic } from '@ai-sdk/anthropic';
import type { AgentConfig } from "sonamu/ai";

const config: AgentConfig = {
  model: anthropic('claude-3-5-sonnet-20241022'),
  instructions: `
    ๋‹น์‹ ์€ ๋ธ”๋กœ๊ทธ ๊ธ€ ์ž‘์„ฑ ๋„์šฐ๋ฏธ์ž…๋‹ˆ๋‹ค.
    - ์ฃผ์ œ์— ๋งž๋Š” ์ฐฝ์˜์ ์ธ ๊ธ€์„ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค.
    - SEO ์ตœ์ ํ™”๋ฅผ ๊ณ ๋ คํ•˜์„ธ์š”.
    - ํ•„์š” ์‹œ ๊ด€๋ จ ์ •๋ณด๋ฅผ ๊ฒ€์ƒ‰ํ•˜์„ธ์š”.
  `,
  toolChoice: 'auto',
  temperature: 1.0,  // ์ฐฝ์˜์ 
  maxOutputTokens: 2000,
};

3. ๋ฐ์ดํ„ฐ ๋ถ„์„ ์—์ด์ „ํŠธ

import { openai } from '@ai-sdk/openai';
import type { AgentConfig } from "sonamu/ai";

const config: AgentConfig = {
  model: openai('gpt-4o'),
  instructions: `
    ๋‹น์‹ ์€ ๋ฐ์ดํ„ฐ ๋ถ„์„ ์ „๋ฌธ๊ฐ€์ž…๋‹ˆ๋‹ค.
    - SQL ์ฟผ๋ฆฌ๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.
    - ๋ฐ์ดํ„ฐ๋ฅผ ๋ถ„์„ํ•˜๊ณ  ์ธ์‚ฌ์ดํŠธ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
    - ์‹œ๊ฐํ™” ์ฐจํŠธ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
  `,
  toolChoice: 'required',  // ํ•ญ์ƒ ๋„๊ตฌ ์‚ฌ์šฉ
  temperature: 0.0,  // ์ •ํ™•ํ•œ ์ฟผ๋ฆฌ
  maxOutputTokens: 1500,
};

4. ๋ฉ€ํ‹ฐ๋ชจ๋‹ฌ ์—์ด์ „ํŠธ

import { openai } from '@ai-sdk/openai';
import type { AgentConfig } from "sonamu/ai";

const config: AgentConfig = {
  model: openai('gpt-4o'),  // ์ด๋ฏธ์ง€ ์ง€์›
  instructions: `
    ๋‹น์‹ ์€ ์ด๋ฏธ์ง€ ๋ถ„์„ ๋ฐ ์„ค๋ช… ์ „๋ฌธ๊ฐ€์ž…๋‹ˆ๋‹ค.
    - ์ด๋ฏธ์ง€๋ฅผ ๋ถ„์„ํ•˜๊ณ  ์ž์„ธํžˆ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.
    - ํ•„์š” ์‹œ ๊ด€๋ จ ์ •๋ณด๋ฅผ ๊ฒ€์ƒ‰ํ•ฉ๋‹ˆ๋‹ค.
  `,
  toolChoice: 'auto',
  temperature: 0.5,
  maxOutputTokens: 1000,
};

ํ™˜๊ฒฝ๋ณ„ ์„ค์ •

๊ฐœ๋ฐœ ํ™˜๊ฒฝ

const isDevelopment = process.env.NODE_ENV === 'development';

const config: AgentConfig = {
  model: isDevelopment
    ? openai('gpt-3.5-turbo')  // ๋น ๋ฅด๊ณ  ์ €๋ ด
    : openai('gpt-4o'),        // ํ”„๋กœ๋•์…˜์šฉ
  
  instructions: "...",
  
  temperature: isDevelopment ? 0.0 : 0.7,  // ๊ฐœ๋ฐœ: ์ผ๊ด€์„ฑ
  maxOutputTokens: isDevelopment ? 500 : 2000,
};

ํ”„๋กœ๋•์…˜ ํ™˜๊ฒฝ

const config: AgentConfig = {
  model: openai('gpt-4o', {
    apiKey: process.env.OPENAI_API_KEY,
  }),
  
  instructions: "...",
  
  // ์•ˆ์ •์ ์ธ ์„ค์ •
  temperature: 0.5,
  maxOutputTokens: 1000,
  
  // ์žฌํ˜„์„ฑ
  seed: parseInt(process.env.AGENT_SEED || '0'),
  
  // ๋ชจ๋‹ˆํ„ฐ๋ง ํ—ค๋”
  headers: {
    'X-Environment': 'production',
    'X-Version': process.env.APP_VERSION,
  },
};

๋น„์šฉ ์ตœ์ ํ™”

๋ชจ๋ธ ์„ ํƒ

๋ชจ๋ธ์„ฑ๋Šฅ๋น„์šฉ์†๋„๊ถŒ์žฅ ์šฉ๋„
GPT-4o์ตœ๊ณ ๋†’์Œ์ค‘๊ฐ„๋ณต์žกํ•œ ์ž‘์—…
GPT-4 Turbo๋†’์Œ์ค‘๊ฐ„๋น ๋ฆ„์ผ๋ฐ˜์ ์ธ ์ž‘์—…
GPT-3.5 Turbo์ค‘๊ฐ„๋‚ฎ์Œ๋งค์šฐ ๋น ๋ฆ„๊ฐ„๋‹จํ•œ ์ž‘์—…
Claude 3.5 Sonnet์ตœ๊ณ ์ค‘๊ฐ„๋น ๋ฆ„์ฝ”๋”ฉ, ๋ถ„์„
Claude 3 Haiku๋‚ฎ์Œ๋งค์šฐ ๋‚ฎ์Œ๋งค์šฐ ๋น ๋ฆ„๊ฐ„๋‹จํ•œ ์ž‘์—…

ํ† ํฐ ์ œํ•œ

const config: AgentConfig = {
  model: openai('gpt-4o'),
  
  // ์ถœ๋ ฅ ํ† ํฐ ์ œํ•œ
  maxOutputTokens: 500,  // ๋น„์šฉ ์ ˆ์•ฝ
  
  // ๊ฐ„๊ฒฐํ•œ ์ง€์‹œ์‚ฌํ•ญ
  instructions: "๊ฐ„๋‹จํžˆ ๋‹ต๋ณ€ํ•˜์„ธ์š”.",
};

์ฃผ์˜์‚ฌํ•ญ

Agent ์„ค์ • ์‹œ ์ฃผ์˜์‚ฌํ•ญ:
  1. API ํ‚ค ๋ณด์•ˆ: ํ™˜๊ฒฝ๋ณ€์ˆ˜ ์‚ฌ์šฉ ํ•„์ˆ˜
    // โŒ ํ•˜๋“œ์ฝ”๋”ฉ
    model: openai('gpt-4o', { apiKey: 'sk-...' })
    
    // โœ… ํ™˜๊ฒฝ๋ณ€์ˆ˜
    model: openai('gpt-4o', { apiKey: process.env.OPENAI_API_KEY })
    
  2. ํ† ํฐ ์ œํ•œ: maxOutputTokens ์„ค์ •
    maxOutputTokens: 1000,  // ๋น„์šฉ ์ œ์–ด
    
  3. Temperature ๋ฒ”์œ„: 0.0 ~ 2.0
    temperature: 0.7,  // ์ ์ ˆํ•œ ๊ฐ’
    
  4. toolChoice ์„ ํƒ: ์šฉ๋„์— ๋งž๊ฒŒ ์„ค์ •
    // ๋ฐ์ดํ„ฐ ๋ถ„์„: required
    // ์ผ๋ฐ˜ ๋Œ€ํ™”: auto
    // ์ˆœ์ˆ˜ ๋Œ€ํ™”: none
    
  5. instructions ๋ช…ํ™•์„ฑ: ๊ตฌ์ฒด์ ์ธ ์ง€์‹œ
    // โŒ ๋ชจํ˜ธํ•จ
    instructions: "๋„์™€์ฃผ์„ธ์š”"
    
    // โœ… ๋ช…ํ™•ํ•จ
    instructions: "์ฃผ๋ฌธ ์กฐํšŒ, ๋ฐฐ์†ก ์ถ”์ , ํ™˜๋ถˆ ์ฒ˜๋ฆฌ๋ฅผ ๋„์™€์ฃผ๋Š” ๊ณ ๊ฐ ์ง€์› ์ฑ—๋ด‡"
    
  6. ๋น„์šฉ ๋ชจ๋‹ˆํ„ฐ๋ง: ํ”„๋กœ๋•์…˜์—์„œ ํ† ํฐ ์‚ฌ์šฉ๋Ÿ‰ ์ถ”์  ํ•„์š”

๋‹ค์Œ ๋‹จ๊ณ„