저는 3개월 전 이커머스 플랫폼에서 AI 고객 서비스 챗봇을 개발할 때 큰壁にぶつ였습니다. 초기에는 OpenAI GPT-4로(function calling) 구현했지만, 비용 문제로 Claude와 Gemini로 교체를 검토했죠. 그런데 각 모델의 function calling 포맷이 완전히 달랐습니다. 이 경험을 계기로 어떤 AI 모델이든 동일한 코드로 동작하는 model-agnostic function calling 시스템을 구축했습니다. 이 글에서 그 방법을 상세히 공유하겠습니다.
왜 Model-Agnostic Function Calling인가?
현재 주요 AI 모델들은 function calling를 지원하지만, 구현 방식이 크게 다릅니다:
- OpenAI GPT 시리즈:
functions파라미터로 함수 정의,tool_calls로 응답 - Anthropic Claude:
tools파라미터,tool_use구조로 응답 - Google Gemini:
tools구조,function_call로 응답 - DeepSeek: OpenAI 호환 포맷 지원
HolySheep AI를 사용하면 이러한 다양한 모델들을 단일 API 키로 접근하면서, 추상화 레이어를 통해 코드 변경 없이 모델을 전환할 수 있습니다. 현재 HolySheep AI에서 지원하는 모델별 가격은 다음과 같습니다:
- GPT-4.1: $8.00/1M 토큰
- Claude Sonnet 4: $4.50/1M 토큰
- Gemini 2.5 Flash: $2.50/1M 토큰
- DeepSeek V3: $0.42/1M 토큰
핵심 구현 아키텍처
Model-agnostic function calling의 핵심은 세 가지 레이어로 분리하는 것입니다:
┌─────────────────────────────────────────────────────────┐
│ Application Layer │
│ (Business Logic - 동일한 코드 유지) │
├─────────────────────────────────────────────────────────┤
│ Function Registry Layer │
│ (함수 정의, 파라미터 검증, 응답 정규화) │
├─────────────────────────────────────────────────────────┤
│ Provider Adapter Layer │
│ (OpenAI / Claude / Gemini / DeepSeek 호환) │
└─────────────────────────────────────────────────────────┘
1단계: 범용 함수 레지스트리 정의
먼저 모든 모델에서 사용할 수 있는 범용 함수 스키마를 정의합니다:
// function-registry.ts
// HolySheep AI를 위한 범용 함수 정의 시스템
interface FunctionParameter {
type: string;
description: string;
enum?: string[];
required?: boolean;
properties?: Record<string, FunctionParameter>;
}
interface FunctionDefinition {
name: string;
description: string;
parameters: {
type: string;
properties: Record<string, FunctionParameter>;
required: string[];
};
}
class FunctionRegistry {
private functions: Map<string, FunctionDefinition> = new Map();
private handlers: Map<string, Function> = new Map();
// 함수 등록
register(
name: string,
description: string,
parameters: FunctionDefinition['parameters'],
handler: Function
): void {
this.functions.set(name, { name, description, parameters });
this.handlers.set(name, handler);
}
// OpenAI 포맷 변환
toOpenAIFormat(): any[] {
return Array.from(this.functions.values()).map(fn => ({
type: 'function',
function: {
name: fn.name,
description: fn.description,
parameters: fn.parameters
}
}));
}
// Claude 포맷 변환
toClaudeFormat(): any[] {
return Array.from(this.functions.values()).map(fn => ({
name: fn.name,
description: fn.description,
input_schema: fn.parameters
}));
}
// Gemini 포맷 변환
toGeminiFormat(): any[] {
return Array.from(this.functions.values()).map(fn => ({
functionDeclarations: [{
name: fn.name,
description: fn.description,
parameters: fn.parameters
}]
}));
}
// 함수 실행
async execute(functionName: string, arguments_: any): Promise<any> {
const handler = this.handlers.get(functionName);
if (!handler) {
throw new Error(함수 ${functionName}을 찾을 수 없습니다);
}
return await handler(arguments_);
}
getFunctionNames(): string[] {
return Array.from(this.functions.keys());
}
}
export const registry = new FunctionRegistry();
2단계: HolySheep AI 프로바이더 어댑터
이제 HolySheep AI API를 통해 다양한 모델에 접근하는 어댑터를 구현합니다:
// holysheep-adapter.ts
// HolySheep AI Model-Agnostic API 어댑터
import { registry } from './function-registry';
type ModelProvider = 'openai' | 'anthropic' | 'gemini' | 'deepseek';
interface AIClientConfig {
apiKey: string;
model: string;
provider: ModelProvider;
baseUrl?: string;
}
interface ChatMessage {
role: 'user' | 'assistant' | 'system';
content: string;
}
interface FunctionCallResult {
function_name: string;
arguments: any;
raw_response: any;
}
class HolySheepAIClient {
private apiKey: string;
private model: string;
private provider: ModelProvider;
private baseUrl = 'https://api.holysheep.ai/v1';
private messages: ChatMessage[] = [];
constructor(config: AIClientConfig) {
this.apiKey = config.apiKey;
this.model = config.model;
this.provider = config.provider;
}
// 모델별 함수 포맷 변환
private formatToolsForProvider(): any {
switch (this.provider) {
case 'openai':
return registry.toOpenAIFormat();
case 'anthropic':
return registry.toClaudeFormat();
case 'gemini':
return registry.toGeminiFormat();
case 'deepseek':
return registry.toOpenAIFormat(); // DeepSeek는 OpenAI 호환
default:
throw new Error(지원하지 않는 프로바이더: ${this.provider});
}
}
// 함수 호출 응답 파싱 (모델별 차이 처리)
private parseFunctionCalls(response: any): FunctionCallResult[] {
switch (this.provider) {
case 'openai':
case 'deepseek':
// OpenAI/DeepSeek 포맷: tool_calls
if (response.tool_calls) {
return response.tool_calls.map((tool: any) => ({
function_name: tool.function.name,
arguments: JSON.parse(tool.function.arguments),
raw_response: tool
}));
}
break;
case 'anthropic':
// Claude 포맷: tool_use
if (response.content) {
const toolUses = response.content.filter(
(c: any) => c.type === 'tool_use'
);
return toolUses.map((tool: any) => ({
function_name: tool.name,