Ollama, Gemma4 e4b, MS Agent Framework, MCP Client ์˜ˆ์ œ

์˜ค๋Š˜ ์•„์นจ ์ƒˆ๋กญ๊ฒŒ ์ถœ์‹œ๋œ Google์˜ ์ƒˆ ์˜คํ”ˆ ์†Œ์Šค LLM์ธ Gemma 4๋ฅผ ๋ฐ”๋กœ ํ…Œ์ŠคํŠธํ•ด๋ณด๊ณ  ์‹ถ์–ด์„œ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด๋ดค์Šต๋‹ˆ๋‹ค.

MS Agent Framework, Ollama, ๊ทธ๋ฆฌ๊ณ  MS Learn MCP ์„œ๋ฒ„ ํˆด ์ฝœ๋ง๊นŒ์ง€ ํ•ฉ์นœ ์˜จ์ „ํ•œ ์˜ˆ์ œ๋ฅผ ์†์‰ฝ๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ์—ˆ๊ณ  ๋กœ์ปฌ์—์„œ๋„ ๊ฝค ์˜๋ฏธ์žˆ๋Š” ๊ฒฐ๊ณผ๋ฅผ ๋‚ผ ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. Edge ๋””๋ฐ”์ด์Šค ์šฉ์œผ๋กœ ๊ฒฝ๋Ÿ‰ํ™”๋œ ํ™˜๊ฒฝ, ๊ทธ๋ฆฌ๊ณ  ์• ํ”Œ M2 Air ์ •๋„ ๋˜๋Š” ์‚ฌ์–‘์—์„œ๋„ ๊ทธ๋Ÿญ์ €๋Ÿญ ์“ธ๋งŒํ•œ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์™€์„œ ํฅ๋ฏธ๋กœ์› ์Šต๋‹ˆ๋‹ค. :smiley: (์ด๋ฏธ ์ž˜ ์•„์‹œ๊ฒ ์ง€๋งŒ, .NET์€ ์• ํ”Œ ์‹ค๋ฆฌ์ฝ˜ ๋งฅ์—์„œ๋„ ๋„ˆ๋ฌด๋‚˜ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์ž˜ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.)

์•„๋ž˜ ์ฝ”๋“œ๋ฅผ gemma4.cs ๋กœ ์ €์žฅํ•˜๊ณ  dotnet run gemma4.cs ํ˜น์€ chmod +x gemma4.cs; ./gemma4.cs ๋กœ Ollama๊ฐ€ ๋–  ์žˆ๋Š” ์ƒํƒœ์—์„œ ์‹คํ–‰ํ•˜์‹œ๋ฉด Model Pull๋ถ€ํ„ฐ ํˆด ์ฝœ๋ง๊นŒ์ง€ ํ•œ ๋ฒˆ์— ์ „๊ฐœ๋˜๋Š” ๊ฒƒ์„ ๋ณด์‹ค ์ˆ˜ ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. :smiley:

#!/usr/bin/env dotnet
#:package Microsoft.Agents.AI@1.*
#:package Microsoft.Extensions.AI@10.*
#:package OllamaSharp@5.*
#:package ModelContextProtocol@1.*
#:property PublishAot=false

using Microsoft.Extensions.AI;
using Microsoft.Agents.AI;
using OllamaSharp;
using ModelContextProtocol.Client;

var ollamaEndpoint = "http://localhost:11434";
var modelId = "gemma4";
var systemCard = "๋‹น์‹ ์€ Ollama ์•ˆ์—์„œ ์‹คํ–‰๋˜๋Š” ์œ ๋Šฅํ•˜๊ณ  ์œ ์šฉํ•œ ๋กœ์ปฌ AI ์–ด์‹œ์Šคํ„ดํŠธ์ž…๋‹ˆ๋‹ค. ๋ชจ๋“  ๋ฉ”์‹œ์ง€๋Š” ํ•œ๊ตญ์–ด๋กœ ๋‹ตํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.";
var prompt = "Windows Sandbox๋ฅผ XML ๋ฐฉ์‹์œผ๋กœ ์ œ์–ดํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ๊ถ๊ธˆํ•ฉ๋‹ˆ๋‹ค.";

var option = new ChatClientAgentRunOptions()
{
	ChatOptions = new()
	{
		Reasoning = new()
		{
			Effort = ReasoningEffort.High,
			Output = ReasoningOutput.Full,
		}
	},
};

using var chatClient = new OllamaApiClient(ollamaEndpoint, modelId);
await foreach (var eachFragment in chatClient.PullModelAsync(modelId))
	Console.WriteLine($"{eachFragment?.Status}: {eachFragment?.Percent}%");

var client = await McpClient.CreateAsync(new HttpClientTransport(new HttpClientTransportOptions() { Name = "microsoft_learn", Endpoint = new Uri("https://learn.microsoft.com/api/mcp"), }));

var agent = chatClient.AsAIAgent(
	instructions: systemCard,
	tools: (await client.ListToolsAsync()).Cast<AITool>().ToList());
var session = await agent.CreateSessionAsync().ConfigureAwait(false);

await foreach (var eachFragment in agent.RunStreamingAsync(prompt, session, option))
{
	foreach (var eachContent in eachFragment.Contents)
	{
		if (eachContent is TextReasoningContent reasoning)
			Console.Write(reasoning.Text);
		else if (eachContent is TextContent text)
			Console.Write(text.Text);
		else
			Console.WriteLine($"<< {eachContent.GetType()} >>");
	}
}

5๊ฐœ์˜ ์ข‹์•„์š”

๋…ธํŠธ๋ถ์— ์„ค์น˜ ํ•˜๊ณ  ๋Œ๋ฆด์ˆ˜๋Š” ์—†์ฃ  ?? ์„œ๋ฒ„๊ธ‰ ์œผ๋กœ ์„ฑ๋Šฅ ์ข‹์€๊ฑฐ์— ์„ค์น˜ ํ•ด์•ผ ํ•˜์ฃ  ?

์ž‘๋…„ ์ธ๊ฐ€ ์žฌ์ž‘๋…„์ธ๊ฐ€ LLM ๋…ธํŠธ๋ถ์— ๊น”๊ณ  ๋ญ ํ• ๋ผ๋‹ค๊ฐ€ ์ฃฝ์€์ค„ ์•Œ์•˜๋Š”๋ฐ ์•”๊ฒƒ๋„ ์•ˆ๋˜์„œ

1๊ฐœ์˜ ์ข‹์•„์š”

ํ…Œ์ŠคํŠธ์— ์‚ฌ์šฉํ•œ ๋ชจ๋ธ์€ gemma4:e4b ๋ฒ„์ „์ž…๋‹ˆ๋‹ค.

๋ชจ๋ธ ๊ตฌ๋™ ์ž์ฒด๋Š” NVIDIA GeForce RTX 4060 Laptop ์ •๋„ (์ „์šฉ GPU ๋ฉ”๋ชจ๋ฆฌ 8GB)์—์„œ ํ„ฑ๊ฑธ์ด๋กœ ๊ฐ€๋Šฅํ•˜์ง€๋งŒ, MS Learn MCP ์„œ๋ฒ„๊ฐ€ ๋˜๋Œ๋ ค์ฃผ๋Š” ๋‚ด์šฉ๊นŒ์ง€ ํ•ฉ์ณ์„œ ์ถ”๋ก ํ•˜๋Š” ๊ฒƒ์€ ์ด๊ฒƒ๋ณด๋‹ค๋Š” ์‚ฌ์–‘์ด ์ข‹์•„์•ผ ํ•  ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์ด๊ฒŒ ๋ช‡ ์„ธ๋Œ€ ์ „ NVIDIA ๊ทธ๋ž˜ํ”ฝ์นด๋“œ์ด๋‹ˆ ์š”์ฆˆ์Œ ๊ตฌํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์œผ๋กœ ํ…Œ์ŠคํŠธํ•˜์‹œ๋ฉด ์ ๋‹นํžˆ ๋Œ์•„๊ฐˆ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

๋งฅ๋ถ์˜ ๊ฒฝ์šฐ, ๋งฅ๋ถ M2 Air 16GB ์ •๋„์—์„œ MS Learn MCP ์„œ๋ฒ„๊ฐ€ ๋˜๋Œ๋ ค์ฃผ๋Š” ๋‚ด์šฉ๊นŒ์ง€ ํ•ฉ์ณ์„œ ์ถ”๋ก ํ•˜๋Š” ๊ฒƒ๋„ ์ ๋‹นํžˆ ๊ตฌ๋™๋˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

๊ฐœ์ธ์ ์ธ ๊ฐ์ƒ์œผ๋กœ, Gemma4๋Š” qwen์ด๋‚˜ kimi ๊ฐ™์€ ํ•˜์ด์—”๋“œ LLM๋ณด๋‹ค๋Š” ํ›จ์”ฌ ์—ฌ์œ ์žˆ๊ฒŒ ๋Œ์•„๊ฐ€๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

2๊ฐœ์˜ ์ข‹์•„์š”

์ ฌ๋งˆ๊ฐ€ ๋ฉ€ํ‹ฐ๋ชจ๋‹ฌ ํŽ‘์…˜์ฝœ๋„ ๋˜๋Š”์ ์ด ๊ฐ•์ ์ด๋‹ค๋ผ๊ณ  ํ•˜๋˜๊ฒŒ ,๋ผ์ดํŠธํ•œ ๋ชจ๋ธ๋กœ ์œˆ๋„์ œ์–ด์šฉ์„ ์ฐพ๋˜ ์ฐฐ๋‚˜์— ์ด ๋ฐฉ๋ฒ•์œผ๋กœ ์‹œ๋„ํ•ด๋ด์•ผ๊ฒ ์Šต๋‹ˆ๋‹ค. ํŒŒ์ด์ฌ ์„ค์น˜์— ์”จ๋ฆ„ํ•˜๋А๋ผ ์ ฌ๋งˆ์„ค์น˜ ์‹คํŒจ -ํŒŒ์ด์ฌ์ดˆ๋ณด๋ผ

๊ฒŒ์ด๋ฐ๊ธ‰ ๊ฐœ๋ฐœ๊ธ‰ ๋…น๋ถ์—๋Š” ์›ํ™œํ•˜๊ฒŒ ๋Œ์•„๊ฐˆ๊ฒƒ๊ฐ™์œผ๋ฉฐ

(ai๊ฐœ๋ฐœ ์„œํฟ๋จธ์‹ ์œผ๋กœ ์žฅ๋งŒ ํ–ˆ์œผ๋‚˜ ๊ฒœ๋Œ์ด๊ฐ€๋จ)

๋ผ์ดํŠธ๋ชจ๋ธ ํ‰์…˜์ฝœ์ด ๋˜๋‚˜ ์ƒ˜ํ”Œํ™•๋ณด์ค‘์— ์žˆ์Šต๋‹ˆ๋‹ค.

์‹œ๋„ํ•˜๊ณ ์žํ•˜๋Š”๊ฒƒ

text+์œˆ๋„์ด๋ฏธ์ง€ ์ฃผ๊ณ  => ํ‰์…˜์ฝœ

์ด๊ฑฐ ์•ˆ๋ ์‹œ text+์ด๋ฏธ์ง€ํ•ด์„ => ํ…์ŠคํŠธ๋ถ„์„ => ํ‰์…˜์ฝœ

3๊ฐœ์˜ ์ข‹์•„์š”