네, Model Context Protocol(MCP)을 사용하는 C# 예제를 만들어 드리겠습니다. MCP는 다양한 LLM 모델 간에 컨텍스트와 상태를 공유하고 관리하기 위한 프로토콜입니다.
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
namespace ModelContextProtocolExample
{
class Program
{
// Ollama API 기본 URL
private static readonly string OllamaBaseUrl = "http://localhost:11434/api";
static async Task Main(string[] args)
{
Console.WriteLine("Model Context Protocol (MCP) 사용 예제 시작");
var mcpClient = new McpClient(OllamaBaseUrl);
try
{
// 사용 가능한 모델 리스트 가져오기
Console.WriteLine("사용 가능한 모델 목록 가져오기:");
var models = await mcpClient.ListModelsAsync();
foreach (var model in models.Models)
{
Console.WriteLine($"- {model.Name} ({model.Size})");
}
Console.WriteLine();
// MCP 세션 시작하기
string modelName = "llama3"; // 사용할 모델 이름 (설치된 모델로 변경 필요)
Console.WriteLine($"'{modelName}' 모델로 MCP 세션 시작하기");
// 초기 컨텍스트 설정
var context = new McpContext
{
Messages = new List<McpMessage>
{
new McpMessage { Role = "system", Content = "당신은 한국어에 능통한 유용한 AI 비서입니다." }
}
};
// 첫 번째 메시지 처리
await SendMessageAndDisplayResponse(mcpClient, modelName, context, "안녕하세요! 당신은 누구인가요?");
// 후속 메시지 처리 (컨텍스트 유지)
await SendMessageAndDisplayResponse(mcpClient, modelName, context, "자연어 처리에 대해 간단히 설명해주세요.");
// 컨텍스트 수정 (시스템 메시지 변경)
Console.WriteLine("\n컨텍스트 수정: 시스템 메시지 변경");
context.Messages[0] = new McpMessage { Role = "system", Content = "당신은 전문적인 데이터 과학자입니다." };
// 수정된 컨텍스트로 메시지 처리
await SendMessageAndDisplayResponse(mcpClient, modelName, context, "머신러닝 알고리즘 중 랜덤 포레스트에 대해 설명해주세요.");
// 컨텍스트 리셋 예제
Console.WriteLine("\n컨텍스트 리셋하기");
context = new McpContext
{
Messages = new List<McpMessage>
{
new McpMessage { Role = "system", Content = "당신은 창의적인 스토리텔러입니다." }
}
};
await SendMessageAndDisplayResponse(mcpClient, modelName, context, "우주를 배경으로 한 짧은 이야기를 만들어주세요.");
// 함수 호출 예제
Console.WriteLine("\n함수 호출 예제 (Tool 사용)");
context = new McpContext
{
Messages = new List<McpMessage>
{
new McpMessage { Role = "system", Content = "당신은 날씨 정보를 제공하는 AI 비서입니다. get_weather 함수를 사용하여 날씨 정보를 조회할 수 있습니다." },
},
Tools = new List<McpTool>
{
new McpTool
{
Type = "function",
Function = new McpFunction
{
Name = "get_weather",
Description = "지정된 위치의 현재 날씨 정보를 가져옵니다.",
Parameters = new
{
Type = "object",
Properties = new
{
Location = new
{
Type = "string",
Description = "도시 이름, 예: 서울, 부산, 뉴욕"
}
},
Required = new[] { "location" }
}
}
}
}
};
await SendMessageAndDisplayResponse(mcpClient, modelName, context, "서울의 날씨가 어떤가요?");
// 함수 호출 결과 제공
context.Messages.Add(new McpMessage { Role = "assistant", Content = null, ToolCalls = new List<McpToolCall>
{
new McpToolCall
{
Id = "call_123",
Type = "function",
Function = new McpToolCallFunction
{
Name = "get_weather",
Arguments = "{\"location\":\"서울\"}"
}
}
}});
context.Messages.Add(new McpMessage
{
Role = "tool",
ToolCallId = "call_123",
Content = "{\"temperature\":23.5,\"condition\":\"맑음\",\"humidity\":65}"
});
await SendMessageAndDisplayResponse(mcpClient, modelName, context, "");
}
catch (Exception ex)
{
Console.WriteLine($"오류 발생: {ex.Message}");
}
Console.WriteLine("\n프로그램 종료. 아무 키나 누르세요...");
Console.ReadKey();
}
// 메시지 전송 및 응답 표시를 위한 헬퍼 메서드
private static async Task SendMessageAndDisplayResponse(McpClient client, string model, McpContext context, string userMessage)
{
if (!string.IsNullOrEmpty(userMessage))
{
Console.WriteLine($"\n사용자: {userMessage}");
// 사용자 메시지를 컨텍스트에 추가
context.Messages.Add(new McpMessage { Role = "user", Content = userMessage });
}
// 모델에 요청 전송
var response = await client.GenerateWithMcpAsync(model, context);
// 응답 표시
Console.WriteLine($"AI: {response.Message.Content}");
// 응답을 컨텍스트에 추가하여 대화 기록 유지
context.Messages.Add(response.Message);
}
}
// MCP 클라이언트 클래스
public class McpClient
{
private readonly HttpClient _httpClient;
private readonly string _baseUrl;
private readonly JsonSerializerOptions _jsonOptions;
public McpClient(string baseUrl)
{
_baseUrl = baseUrl;
_httpClient = new HttpClient();
_jsonOptions = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true,
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
};
}
// 사용 가능한 모델 목록 가져오기
public async Task<ModelsResponse> ListModelsAsync()
{
var response = await _httpClient.GetAsync($"{_baseUrl}/tags");
response.EnsureSuccessStatusCode();
var content = await response.Content.ReadAsStringAsync();
return JsonSerializer.Deserialize<ModelsResponse>(content, _jsonOptions);
}
// MCP를 사용하여 텍스트 생성
public async Task<McpResponse> GenerateWithMcpAsync(string model, McpContext context, float temperature = 0.7f)
{
var requestBody = new
{
model = model,
messages = context.Messages,
tools = context.Tools,
temperature = temperature
};
var json = JsonSerializer.Serialize(requestBody, _jsonOptions);
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await _httpClient.PostAsync($"{_baseUrl}/chat", content);
response.EnsureSuccessStatusCode();
var responseContent = await response.Content.ReadAsStringAsync();
return JsonSerializer.Deserialize<McpResponse>(responseContent, _jsonOptions);
}
}
// MCP 응답 클래스
public class McpResponse
{
public string Model { get; set; }
public long Created { get; set; }
public McpMessage Message { get; set; }
public bool Done { get; set; }
public long TotalDuration { get; set; }
public long LoadDuration { get; set; }
public long PromptEvalCount { get; set; }
public long PromptEvalDuration { get; set; }
public long EvalCount { get; set; }
public long EvalDuration { get; set; }
}
// MCP 컨텍스트 클래스
public class McpContext
{
public List<McpMessage> Messages { get; set; } = new List<McpMessage>();
public List<McpTool> Tools { get; set; } = new List<McpTool>();
}
// MCP 메시지 클래스
public class McpMessage
{
public string Role { get; set; }
public string Content { get; set; }
public List<McpToolCall> ToolCalls { get; set; }
public string ToolCallId { get; set; }
}
// MCP 도구 클래스
public class McpTool
{
public string Type { get; set; }
public McpFunction Function { get; set; }
}
// MCP 함수 클래스
public class McpFunction
{
public string Name { get; set; }
public string Description { get; set; }
public object Parameters { get; set; }
}
// MCP 도구 호출 클래스
public class McpToolCall
{
public string Id { get; set; }
public string Type { get; set; }
public McpToolCallFunction Function { get; set; }
}
// MCP 도구 호출 함수 클래스
public class McpToolCallFunction
{
public string Name { get; set; }
public string Arguments { get; set; }
}
// 모델 응답 클래스
public class ModelsResponse
{
public List<ModelInfo> Models { get; set; }
}
public class ModelInfo
{
public string Name { get; set; }
public string Modified { get; set; }
public string Size { get; set; }
public string Digest { get; set; }
}
}
위 코드는 C#에서 Model Context Protocol(MCP)을 사용하는 예제입니다. MCP는 대화형 AI 모델과의 상호작용에서 컨텍스트를 관리하는 프로토콜로, Ollama API와 같은 LLM 서비스와 함께 사용됩니다.
### 주요 기능
1. **컨텍스트 관리**: 대화 내역을 메시지 목록으로 관리하여 대화의 연속성을 유지합니다.
2. **역할 기반 메시지**: system, user, assistant, tool 등 다양한 역할의 메시지를 지원합니다.
3. **도구 호출 (Function Calling)**: 모델이 외부 함수를 호출하여 추가 정보를 얻을 수 있습니다.
4. **컨텍스트 수정**: 대화 중 시스템 메시지나 컨텍스트를 동적으로 변경할 수 있습니다.
### 예제 시나리오
이 예제는 다음과 같은 시나리오를 포함합니다:
1. **기본 대화**: 시스템 메시지 설정 후 기본적인 질의응답 대화를 진행합니다.
2. **컨텍스트 수정**: 대화 중간에 시스템 메시지를 변경하여 모델의 역할을 변경합니다.
3. **컨텍스트 리셋**: 이전 대화를 버리고 새로운 컨텍스트로 시작합니다.
4. **함수 호출**: 날씨 정보 조회와 같은 외부 함수를 정의하고 모델이 이를 호출하는 과정을 시뮬레이션합니다.
### 사용 방법
1. Ollama가 로컬에 설치되어 있고 실행 중이어야 합니다.
2. Ollama API는 기본적으로 `http://localhost:11434`에서 제공됩니다.
3. `modelName` 변수를 설치된 모델 이름(예: "llama3")으로 변경해야 합니다.
4. 코드를 실행하면 여러 시나리오에 따른 MCP 사용 예제가 순차적으로 실행됩니다.
### 참고 사항
- 이 예제는 Ollama의 `/chat` 엔드포인트를 사용하며, 이는 MCP와 호환됩니다.
- MCP는 OpenAI의 Chat Completion API와 유사한 형식을 가지고 있어, 대부분의 LLM 서비스와 호환됩니다.
- 함수 호출 결과는 실제 API 호출 대신 하드코딩된 값을 사용하고 있습니다. 실제 애플리케이션에서는 외부 서비스와 연동하여 실제 데이터를 가져와야 합니다.
이 코드는 MCP를 사용하여 대화형 AI 시스템을 구축하는 기본적인 프레임워크를 제공합니다. 필요에 따라 확장하여 다양한 애플리케이션에 활용할 수 있습니다.
카테고리 없음