[C#/COMMON/.NET8] 대용량 CSV 파일 병합하기
■ 대용량 CSV 파일을 병합하는 방법을 보여준다. ※ CSV 파일에 헤더 라인이 있어야 합니다. ※ 병합하는 CSV 파일은 동일한 헤더 라인을 갖고
■ 대용량 CSV 파일을 병합하는 방법을 보여준다. ※ CSV 파일에 헤더 라인이 있어야 합니다. ※ 병합하는 CSV 파일은 동일한 헤더 라인을 갖고
■ 엑셀에서 OLLAMA에게 질문을 하는 사용자 함수를 추가하는 방법을 보여준다. ▶ TestLibrary.csproj
1 2 3 4 5 6 7 8 9 10 11 12 |
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>net6.0-windows</TargetFramework> <ImplicitUsings>disable</ImplicitUsings> <Nullable>disable</Nullable> </PropertyGroup> <ItemGroup> <PackageReference Include="ExcelDna.AddIn" Version="1.8.0" /> </ItemGroup> </Project> |
▶ launchSettings.json
1 2 3 4 5 6 7 8 9 10 11 |
{ "profiles": { "Excel": { "commandName": "Executable", "executablePath": "C:\\Program Files\\Microsoft Office\\root\\Office16\\EXCEL.EXE", "commandLineArgs": "/x \"TestLibrary-AddIn64.xll\"" } } } |
▶ OllamaClient.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
using System.Net.Http; using System.Text; using System.Text.Json; namespace TestLibrary; /// <summary> /// OLLAMA 클라이언트 /// </summary> public class OllamaClient { //////////////////////////////////////////////////////////////////////////////////////////////////// Field ////////////////////////////////////////////////////////////////////////////////////////// Private #region Field /// <summary> /// 기본 URL /// </summary> private readonly string baseURL; /// <summary> /// 모델명 /// </summary> private readonly string modelName; /// <summary> /// HTTP 클라이언트 /// </summary> private readonly HttpClient client; #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor ////////////////////////////////////////////////////////////////////////////////////////// Public #region 생성자 - OllamaClient(baseURL, modelName) /// <summary> /// 생성자 /// </summary> /// <param name="baseURL">기본 URL</param> /// <param name="modelName">모델명</param> public OllamaClient(string baseURL = "http://localhost:11434", string modelName = "bnksys/eeve-yanolja-v1:latest") { this.baseURL = baseURL; this.modelName = modelName; this.client = new HttpClient(); } #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Public #region 질문하기 - Ask(question) /// <summary> /// 질문하기 /// </summary> /// <param name="question">질문</param> /// <returns>답변</returns> public string Ask(string question) { var requestContent = new { model = this.modelName, prompt = question, stream = false, raw = false }; string json = JsonSerializer.Serialize(requestContent); StringContent stringContent = new StringContent(json, Encoding.UTF8, "application/json"); using(HttpResponseMessage httpResponseMessage = client.PostAsync($"{baseURL}/api/generate", stringContent).Result) { httpResponseMessage.EnsureSuccessStatusCode(); string respnseJSON = httpResponseMessage.Content.ReadAsStringAsync().Result; using(JsonDocument jsonElement = JsonDocument.Parse(respnseJSON)) { JsonElement rootJSONElement = jsonElement.RootElement; if(rootJSONElement.TryGetProperty("response", out JsonElement responseElement)) { return responseElement.GetString() ?? string.Empty; } return string.Empty; } } } #endregion } |
▶ CustomFunction.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
using ExcelDna.Integration; namespace TestLibrary; /// <summary> /// 커스텀 함수 /// </summary> public static class CustomFunction { //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Public #region OLLAMA 질문하기 - AskOllama(question) /// <summary> /// OLLAMA 질문하기 /// </summary> /// <param name="question">질문</param> /// <returns>답변</returns> [ExcelFunction(Description = "Ollama에게 질문을 합니다.")] public static string AskOllama(string question) { OllamaClient ollamaClient = new OllamaClient(); string answer = ollamaClient.Ask(question); return answer; } #endregion } |
■ ExcelDna.AddIn 누겟을 설치하는 방법을 보여준다. 1. Visual Studio를 실행한다. 2. [도구] / [NuGet 패키지 관리자] / [패키지 관리자 콘솔] 메뉴를 실행한다.
■ HttpClient 클래스를 사용해 OLLAMA 서버와 통신하는 방법을 보여준다. ▶ OllamaRequest.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
using System.Text.Json.Serialization; namespace TestProject; /// <summary> /// OLLAMA 요청 /// </summary> public class OllamaRequest { //////////////////////////////////////////////////////////////////////////////////////////////////// Property ////////////////////////////////////////////////////////////////////////////////////////// Public #region 모델 - Model /// <summary> /// 모델 /// </summary> [JsonPropertyName("model")] public string Model { get; set; } #endregion #region 프롬프트 - Prompt /// <summary> /// 프롬프트 /// </summary> [JsonPropertyName("prompt")] public string Prompt { get; set; } #endregion #region 스트림 여부 - Stream /// <summary> /// 스트림 여부 /// </summary> [JsonPropertyName("stream")] public bool Stream { get; set; } #endregion } |
▶ OllamaResponse.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
using System.Text.Json.Serialization; namespace TestProject; /// <summary> /// OLLAMA 응답 /// </summary> public class OllamaResponse { //////////////////////////////////////////////////////////////////////////////////////////////////// Property ////////////////////////////////////////////////////////////////////////////////////////// Public #region 모델 - Model /// <summary> /// 모델 /// </summary> [JsonPropertyName("model")] public string Model { get; set; } #endregion #region 응답 - Response /// <summary> /// 응답 /// </summary> [JsonPropertyName("response")] public string Response { get; set; } #endregion #region 완료 여부 - Done /// <summary> /// 완료 여부 /// </summary> [JsonPropertyName("done")] public bool Done { get; set; } #endregion } |
▶ Program.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
using System; using System.Net.Http; using System.Text; using System.Text.Json; using System.Threading.Tasks; namespace TestProject; /// <summary> /// 프로그램 /// </summary> public class Program { //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Static //////////////////////////////////////////////////////////////////////////////// Private #region OLLAMA 요청 보내기 (비동기) - SendOllamaRequestAsync(httpClient, ollamaRequest) /// <summary> /// OLLAMA 요청 보내기 (비동기) /// </summary> /// <param name="httpClient">HTTP 클라이언트</param> /// <param name="ollamaRequest">OLLAMA 요청</param> /// <returns>OLLAMA 응답 태스크</returns> private static async Task<OllamaResponse> SendOllamaRequestAsync(HttpClient httpClient, OllamaRequest ollamaRequest) { string json = JsonSerializer.Serialize ( ollamaRequest, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase } ); StringContent stringContent = new StringContent(json, Encoding.UTF8, "application/json"); HttpResponseMessage response = await httpClient.PostAsync("/api/generate", stringContent); response.EnsureSuccessStatusCode(); string responseBody = await response.Content.ReadAsStringAsync(); return JsonSerializer.Deserialize<OllamaResponse> ( responseBody, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase } ); } #endregion #region 프로그램 시작하기 - Main() /// <summary> /// 프로그램 시작하기 /// </summary> /// <returns>태스크</returns> private static async Task Main() { string baseURL = "http://localhost:11434"; using var httpClient = new HttpClient(); httpClient.BaseAddress = new Uri(baseURL); OllamaRequest ollamaRequest = new() { Model = "bnksys/eeve-yanolja-v1:latest", Prompt = "여기어때와 야놀자의 차이점을 알려주세요.", Stream = false }; try { OllamaResponse ollamaResponse = await SendOllamaRequestAsync(httpClient, ollamaRequest); Console.WriteLine($"질문 : {ollamaRequest.Prompt }"); Console.WriteLine($"응답 : {ollamaResponse.Response}"); } catch(Exception exception) { Console.WriteLine($"오류 발생 : {exception.Message}"); } } #endregion } |
TestProject.zip
■ RegistryKey 클래스를 사용해 CUDA 설치 여부 및 CUDA 버전을 구하는 방법을 보여준다. ▶ CUDAHelper.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
using Microsoft.Win32; namespace TestProject; /// <summary> /// CUDA 헬퍼 /// </summary> public class CUDAHelper { //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Static //////////////////////////////////////////////////////////////////////////////// Public #region CUDA 설치 여부 구하기 - IsCUDAInstalled() /// <summary> /// CUDA 설치 여부 구하기 /// </summary> /// <returns>CUDA 설치 여부</returns> public static bool IsCUDAInstalled() { try { #pragma warning disable CA1416 // 플랫폼 호환성 유효성 검사 using(RegistryKey registryKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\NVIDIA Corporation\GPU Computing Toolkit\CUDA")) { if(registryKey != null) { string[] subkeyNameArray = registryKey.GetSubKeyNames(); if(subkeyNameArray.Length > 0) { return true; } } } #pragma warning restore CA1416 // 플랫폼 호환성 유효성 검사 return false; } catch { return false; } } #endregion #region CUDA 버전 구하기 - GetGUDAVersion() /// <summary> /// CUDA 버전 구하기 /// </summary> /// <returns>CUDA 버전</returns> public static string GetGUDAVersion() { if(IsCUDAInstalled()) { #pragma warning disable CA1416 // 플랫폼 호환성 유효성 검사 using(RegistryKey registryKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\NVIDIA Corporation\GPU Computing Toolkit\CUDA")) { if(registryKey != null) { string[] subkeyNameArray = registryKey.GetSubKeyNames(); if(subkeyNameArray.Length > 0) { string version = string.Join(", ", subkeyNameArray); return version; } } } #pragma warning restore CA1416 // 플랫폼 호환성 유효성 검사 return null; } else { return null; } } #endregion } |
▶ Program.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
using System; namespace TestProject; /// <summary> /// 프로그램 /// </summary> class Program { //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Static //////////////////////////////////////////////////////////////////////////////// Private #region 프로그램 시작하기 - Main() /// <summary> /// 프로그램 시작하기 /// </summary> static void Main() { bool isCUDAInstalled = CUDAHelper.IsCUDAInstalled(); if(isCUDAInstalled) { Console.WriteLine("CUDA가 설치되어 있습니다."); string version = CUDAHelper.GetGUDAVersion(); Console.WriteLine($"CUDA 버전 : {version}"); } else { Console.WriteLine("CUDA가 설치되어 있지 않습니다."); } } #endregion } |
TestProject.zip
■ String 클래스에서 문자열을 정규화하는 방법을 보여준다. ▶ 예제 코드 (C#)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
using System; using System.Linq; using System.Text.RegularExpressions; #region 문자열 정규화하기 - NormalizeString(sourceString) /// <summary> /// 문자열 정규화하기 /// </summary> /// <param name="sourceString">소스 문자열</param> /// <returns>정규화 문자열</returns> /// <remarks> /// 1. 각 줄의 문자열의 앞뒤 공백을 제거한다. /// 2. 빈줄이 반복되는 경우 1개의 빈줄로 만든다. /// </remarks> public string NormalizeString(string sourceString) { string[] sourceLineArray = sourceString.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None); string[] targetLineArray = sourceLineArray.Select(line => line.Trim()).ToArray(); string joinedString = string.Join(Environment.NewLine, targetLineArray); string targetString = Regex.Replace(joinedString, @"(\r\n|\n){2,}", Environment.NewLine + Environment.NewLine); return targetString; } #endregion |
■ String 클래스에서 문자열을 정규화하는 방법을 보여준다. ▶ 예제 코드 (C#)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
using System; using System.Collections.Generic; #region 텍스트 정규화하기 - NormalizeText(sourceString) /// <summary> /// 텍스트 정규화하기 /// </summary> /// <param name="sourceString">소스 문자열</param> /// <returns>정규화 텍스트</returns> /// <remarks> /// 1. 각 줄의 문자열의 앞뒤 공백을 제거한다. /// 2. 빈줄이 반복되면 1개의 빈줄로 만든다. /// 3. 문자열이 있는 줄들 사이에 빈줄을 추가한다. /// </remarks> public string NormalizeText(string sourceString) { string[] sourceLineArray = sourceString.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None); List<string> targetList = new List<string>(); bool previousLineWasEmpty = false; foreach(string sourceLine in sourceLineArray) { string targetLine = sourceLine.Trim(); if (string.IsNullOrEmpty(targetLine)) { if(!previousLineWasEmpty) { targetList.Add(string.Empty); previousLineWasEmpty = true; } } else { targetList.Add(targetLine); previousLineWasEmpty = false; } } return string.Join(Environment.NewLine, targetList); } #endregion |
■ ManagementObjectSearcher 클래스를 사용해 NVIDIA GPU 설치 여부를 구하는 방법을 보여준다. ▶ Program.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
using System; using System.Management; namespace TestProject; /// <summary> /// 프로그램 /// </summary> class Program { //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Static //////////////////////////////////////////////////////////////////////////////// Private #region NVIDIA GPU 설치 여부 구하기 - IsInstalledNvidiaGPU() /// <summary> /// NVIDIA GPU 설치 여부 구하기 /// </summary> /// <returns>NVIDIA GPU 설치 여부</returns> private static bool IsInstalledNvidiaGPU() { using ManagementObjectSearcher managementObjectSearcher = new("SELECT * FROM Win32_VideoController"); foreach(ManagementObject managementObject in managementObjectSearcher.Get()) { string name = managementObject["Name"] as string; if(!string.IsNullOrEmpty(name) && name.ToLower().Contains("nvidia")) { return true; } } return false; } #endregion #region 프로그램 시작하기 - Main() /// <summary> /// 프로그램 시작하기 /// </summary> private static void Main() { bool isInstalledNvidiaGPU = IsInstalledNvidiaGPU(); Console.WriteLine(isInstalledNvidiaGPU ? "NVIDIA GPU가 설치되어 있습니다." : "NVIDIA GPU가 설치되어 있지 않습니다."); } #endregion } |
TestProject.zip
■ RuntimeInformation 클래스의 IsOSPlatform 정적 메소드를 사용해 윈도우즈 운영 체제가 아닌 경우 실행을 중단하는 방법을 보여준다. ▶ Program.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
using System; using System.Runtime.InteropServices; namespace TestProject; /// <summary> /// 프로그램 /// </summary> class Program { //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Static //////////////////////////////////////////////////////////////////////////////// Private #region 프로그램 시작하기 - Main() /// <summary> /// 프로그램 시작하기 /// </summary> private static void Main() { if(!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { Console.WriteLine("이 프로그램은 Windows에서만 실행할 수 있습니다."); return; } } #endregion } |
TestProject.zip
■ HttpClient 클래스를 사용해 Ollama 연동 파이썬 LLM 서버와 통신하는 방법을 보여준다. ▶ AdditionalKeywordArgument.cs
1 2 3 4 5 6 7 8 9 10 |
namespace TestProject; /// <summary> /// 부가적 키워드 인자 /// </summary> public class AdditionalKeywordArgument { } |
▶ AIMessageChunk.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 |
using Newtonsoft.Json; namespace TestProject; /// <summary> /// AI 메시지 청크 /// </summary> public class AIMessageChunk { //////////////////////////////////////////////////////////////////////////////////////////////////// Property ////////////////////////////////////////////////////////////////////////////////////////// Public #region 컨텐트 - Content /// <summary> /// 컨텐트 /// </summary> [JsonProperty("content")] public string Content { get; set; } #endregion #region 부가적 키워드 인자 - AdditionalKeywordArgument /// <summary> /// 부가적 키워드 인자 /// </summary> [JsonProperty("additional_kwargs")] public AdditionalKeywordArgument AdditionalKeywordArgument { get; set; } #endregion #region 응답 메타 데이터 - ResponseMetadata /// <summary> /// 응답 메타 데이터 /// </summary> [JsonProperty("response_metadata")] public ResponseMetadata ResponseMetadata { get; set; } #endregion #region 타입 - Type /// <summary> /// 타입 /// </summary> [JsonProperty("type")] public string Type { get; set; } #endregion #region 명칭 - Name /// <summary> /// 명칭 /// </summary> [JsonProperty("name")] public string Name { get; set; } #endregion #region ID - ID /// <summary> /// ID /// </summary> [JsonProperty("id")] public string ID { get; set; } #endregion #region 예제 여부 - Example /// <summary> /// 예제 여부 /// </summary> [JsonProperty("example")] public bool Example { get; set; } #endregion #region 도구 호출 리스트 - ToolCallList /// <summary> /// 도구 호출 리스트 /// </summary> [JsonProperty("tool_calls")] public ToolCallList ToolCallList { get; set; } #endregion #region 무효 도구 호출 리스트 - InvalidToolCallList /// <summary> /// 무효 도구 호출 리스트 /// </summary> [JsonProperty("invalid_tool_calls")] public InvalidToolCallList InvalidToolCallList { get; set; } #endregion #region 사용 메타 데이터 - UsageMetadata /// <summary> /// 사용 메타 데이터 /// </summary> [JsonProperty("usage_metadata")] public UsageMetadata UsageMetadata { get; set; } #endregion #region 도구 호출 청크 리스트 - ToolCallChunkList /// <summary> /// 도구 호출 청크 리스트 /// </summary> [JsonProperty("tool_call_chunks")] public ToolCallChunkList ToolCallChunkList { get; set; } #endregion } |
▶ InvalidToolCallList.cs
1 2 3 4 5 6 7 8 9 10 11 12 |
using System.Collections.Generic; namespace TestProject; /// <summary> /// 무효 도구 호출 리스트 /// </summary> public class InvalidToolCallList : List<object> { } |
▶
■ Marshal 클래스의 SizeOf 정적 메소드를 사용해 특정 타입의 크기를 구하는 방법을 보여준다. ▶ DataStruct.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
using System.Runtime.InteropServices; namespace TestProject; /// <summary> /// 데이터 구조체 /// </summary> [StructLayout(LayoutKind.Sequential)] public struct DataStruct { //////////////////////////////////////////////////////////////////////////////////////////////////// Field ////////////////////////////////////////////////////////////////////////////////////////// Public #region Field /// <summary> /// 정수 값 /// </summary> public int IntegerValue; /// <summary> /// 배정도 실수 값 /// </summary> public double DoubleValue; /// <summary> /// 문자 값 /// </summary> public char CharacterValue; #endregion } |
▶ Program.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
using System.Runtime.InteropServices; using System; namespace TestProject; /// <summary> /// 프로그램 /// </summary> class Program { //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Static //////////////////////////////////////////////////////////////////////////////// Private #region 프로그램 시작하기 - Main() /// <summary> /// 프로그램 시작하기 /// </summary> static void Main() { int size = Marshal.SizeOf<DataStruct>(); Console.WriteLine($"DataStruct 크기 : {size} 바이트"); } #endregion } |
TestProject.zip
■ HttpClient 클래스를 사용해 네이버 HyperCLOVA X와 통신하는 방법을 보여준다. (IAsyncEnumerable<T> 객체) ▶ AIFilter.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
using Newtonsoft.Json; namespace TestProject; /// <summary> /// AI 필터 /// </summary> public class AIFilter { //////////////////////////////////////////////////////////////////////////////////////////////////// Property ////////////////////////////////////////////////////////////////////////////////////////// Public #region 그룹명 - GroupName /// <summary> /// 그룹명 /// </summary> [JsonProperty("groupName")] public string GroupName { get; set; } #endregion #region 명칭 - Name /// <summary> /// 명칭 /// </summary> [JsonProperty("name")] public string Name { get; set; } #endregion #region 점수 - Score /// <summary> /// 점수 /// </summary> [JsonProperty("score")] public string Score { get; set; } #endregion #region 결과 - Result /// <summary> /// 결과 /// </summary> [JsonProperty("result")] public string Result { get; set; } #endregion } |
▶ Message.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
using Newtonsoft.Json; namespace TestProject; /// <summary> /// 메시지 /// </summary> public class Message { //////////////////////////////////////////////////////////////////////////////////////////////////// Property ////////////////////////////////////////////////////////////////////////////////////////// Public #region 역할 - Role /// <summary> /// 역할 /// </summary> [JsonProperty("role")] public string Role { get; set; } #endregion #region 내용 - Content /// <summary> /// 내용 /// </summary> [JsonProperty("content")] public string Content { get; set; } #endregion } |
▶ RequestMessage.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
using Newtonsoft.Json; namespace TestProject; /// <summary> /// 요청 메시지 /// </summary> public class RequestMessage { //////////////////////////////////////////////////////////////////////////////////////////////////// Property ////////////////////////////////////////////////////////////////////////////////////////// Public #region 메시지 리스트 - MessageList /// <summary> /// 메시지 리스트 /// </summary> [JsonProperty("messages")] public List<Message> MessageList { get; set; } #endregion #region Top P - TopP /// <summary> /// TopP /// </summary> [JsonProperty("topP")] public double TopP { get; set; } #endregion #region Top K - TopK /// <summary> /// TopK /// </summary> [JsonProperty("topK")] public int TopK { get; set; } #endregion #region 최대 토큰 카운트 - MaximumTokenCount /// <summary> /// 최대 토큰 카운트 /// </summary> [JsonProperty("maxTokens")] public int MaximumTokenCount { get; set; } #endregion #region 온도 - Temperature /// <summary> /// 온도 /// </summary> [JsonProperty("temperature")] public double Temperature { get; set; } #endregion #region 반복 패널티 - RepeatPenalty /// <summary> /// 반복 패널티 /// </summary> [JsonProperty("repeatPenalty")] public double RepeatPenalty { get; set; } #endregion #region Stop Before - StopBefore /// <summary> /// Stop Before /// </summary> [JsonProperty("stopBefore")] public List<string> StopBefore { get; set; } #endregion #region AI 필터 포함 여부 - IncludeAIFilters /// <summary> /// AI 필터 포함 여부 /// </summary> [JsonProperty("includeAiFilters")] public bool IncludeAIFilters { get; set; } #endregion #region 시드 - Seed /// <summary> /// 시드 /// </summary> [JsonProperty("seed")] public int Seed { get; set; } #endregion } |
▶
■ ManagementObjectSearcher 클래스를 사용해 시스템 정보를 구하는 방법을 보여준다. ▶ Program.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
#pragma warning disable CA1416 using System.Management; namespace TestProject; /// <summary> /// 프로그램 /// </summary> class Program { //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Static //////////////////////////////////////////////////////////////////////////////// Private #region 프로그램 시작하기 - Main() /// <summary> /// 프로그램 시작하기 /// </summary> private static void Main() { try { ManagementObjectSearcher searcher; // PC 모델 및 제조업체 정보 searcher = new ManagementObjectSearcher("SELECT * FROM Win32_ComputerSystem"); foreach(ManagementObject mo in searcher.Get()) { Console.WriteLine($"PC 모델 : {mo["Model" ]}"); Console.WriteLine($"제조업체 : {mo["Manufacturer"]}"); } // 제조번호(시리얼 넘버) 정보 searcher = new ManagementObjectSearcher("SELECT * FROM Win32_BIOS"); foreach(ManagementObject mo in searcher.Get()) { Console.WriteLine($"제조번호(시리얼 넘버) : {mo["SerialNumber"]}"); } // CPU 정보 searcher = new ManagementObjectSearcher("SELECT * FROM Win32_Processor"); foreach(ManagementObject mo in searcher.Get()) { Console.WriteLine($"CPU : {mo["Name"]}"); } // 메인보드 정보 searcher = new ManagementObjectSearcher("SELECT * FROM Win32_BaseBoard"); foreach(ManagementObject mo in searcher.Get()) { Console.WriteLine($"메인보드 제조사 : {mo["Manufacturer"]}"); Console.WriteLine($"메인보드 제품 ID : {mo["Product" ]}"); Console.WriteLine($"메인보드 시리얼 번호 : {mo["SerialNumber"]}"); } // 메모리 용량 정보 searcher = new ManagementObjectSearcher("SELECT * FROM Win32_ComputerSystem"); foreach(ManagementObject mo in searcher.Get()) { ulong totalPhysicalMemory = Convert.ToUInt64(mo["TotalPhysicalMemory"]); Console.WriteLine($"메모리 용량 : {(totalPhysicalMemory / (1024 * 1024 * 1024))} GB"); } } catch (Exception exception) { Console.WriteLine("오류 발생 : " + exception.Message); } Console.WriteLine("아무 키나 누르면 종료됩니다..."); Console.ReadKey(false); } #endregion } |
TestProject.zip
■ Segoe UI Emoji 폰트에서 이모지 문자 여부를 구하는 방법을 보여준다. ▶ Segoe UI Emoji 폰트에서 이모지 문자 여부 구하기 예제 (C#)
■ Typeface 클래스를 사용해 이모지 타입 페이스 객체를 만드는 방법을 보여준다. ▶ 예제 코드 (C#)
1 2 3 4 5 6 7 8 9 10 11 12 |
using System.Windows; using System.Windows.Media; Typeface emojiTypeface = new Typeface ( new FontFamily("Segoe UI Emoji"), FontStyles.Normal, FontWeights.Normal, FontStretches.Normal ); |
■ char 구조체의 ConvertToUtf32 정적 메소드를 사용해 이모지 문자에서 UTF-32 문자 코드를 구하는 방법을 보여준다. ▶ 예제 코드 (C#)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
string smileString = char.ConvertFromUtf32(0x1f600); // 반환값: "😀" (웃는 얼굴 이모지) string dragonString = char.ConvertFromUtf32(0x1f409); // 반환값: "🐉" (용 이모지) int smileCode = char.ConvertToUtf32(smileString , 0); int dragonCode = char.ConvertToUtf32(dragonString, 0); Console.WriteLine($"0x{smileCode :x}"); Console.WriteLine($"0x{dragonCode:x}"); /* 0x1f600 0x1f409 */ |
■ char 구조체의 ConvertFromUtf32 정적 메소드를 사용해 이모지 문자를 구하는 방법을 보여준다. ▶ 예제 코드 (C#)
1 2 3 4 |
string smileString = char.ConvertFromUtf32(0x1f600); // 반환값: "😀" (웃는 얼굴 이모지) string dragonString = char.ConvertFromUtf32(0x1f409); // 반환값: "🐉" (용 이모지) |
■ HttpClient 클래스의 GetAsync 메소드를 사용해 파일을 다운로드하는 방법을 보여준다. ▶ 예제 코드 (C#)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
using System.IO; using System.Net.Http; using System.Threading.Tasks; #region 파일 다운로드하기 (비동기) - DownloadFileAsync(url, filePath) /// <summary> /// 파일 다운로드하기 (비동기) /// </summary> /// <param name="url">URL</param> /// <param name="filePath">파일 경로</param> /// <returns>처리 결과</returns> public async Task<bool> DownloadFileAsync(string url, string filePath) { using HttpClient client = new HttpClient(); try { using HttpResponseMessage response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead); response.EnsureSuccessStatusCode(); using Stream stream = await response.Content.ReadAsStreamAsync(); using FileStream fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None); await stream.CopyToAsync(fileStream); return true; } catch(HttpRequestException) { return false; } } #endregion |
■ Python 프로그램을 자동 설치하는 방법을 보여준다. ▶ Program.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
using System; using System.Diagnostics; using System.IO; using System.Net.Http; using System.Threading.Tasks; namespace TestProject; /// <summary> /// 프로그램 /// </summary> class Program { //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Static //////////////////////////////////////////////////////////////////////////////// Private #region 프로그램 시작하기 - Main() /// <summary> /// 프로그램 시작하기 /// </summary> /// <returns>태스크</returns> static async Task Main() { string installerURL = "https://www.python.org/ftp/python/3.12.4/python-3.12.4-amd64.exe"; string installerFilePath = @"C:\temp\python_installer.exe"; if(!Directory.Exists(@"C:\temp")) { Directory.CreateDirectory(@"C:\temp"); } Console.WriteLine($"[{DateTime.Now.ToString("HH:mm:ss")}] 파이썬 설치 프로그램 다운로드를 시작합니다."); await DownloadFileAsync(installerURL, installerFilePath); Console.WriteLine($"[{DateTime.Now.ToString("HH:mm:ss")}] 파이썬 설치 프로그램 다운로드를 종료합니다."); Console.WriteLine($"[{DateTime.Now.ToString("HH:mm:ss")}] 파이썬 프로그램 설치를 시작합니다."); ProcessStartInfo processStartInfo = new() { FileName = installerFilePath, Arguments = "/quiet InstallAllUsers=1 PrependPath=1", // 자동 설치를 위한 인자 UseShellExecute = false }; Process process = new() { StartInfo = processStartInfo }; process.Start(); process.WaitForExit(); Console.WriteLine($"[{DateTime.Now.ToString("HH:mm:ss")}] 파이썬 프로그램 설치를 종료합니다."); string pythonFilePath = @"C:\Program Files\Python312\python.exe"; if(File.Exists(pythonFilePath)) { Console.WriteLine("Python이 성공적으로 설치되었습니다."); } else { Console.WriteLine("Python 설치에 실패했습니다."); } Console.WriteLine("프로그램을 종료하기 위해 아무 키나 눌러 주세요."); Console.ReadKey(false); } #endregion #region 파일 다운로드하기 (비동기) - DownloadFileAsync(url, filePath) /// <summary> /// 파일 다운로드하기 (비동기) /// </summary> /// <param name="url">URL</param> /// <param name="filePath">파일 경로</param> /// <returns>처리 결과</returns> private static async Task<bool> DownloadFileAsync(string url, string filePath) { using HttpClient client = new HttpClient(); try { using HttpResponseMessage response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead); response.EnsureSuccessStatusCode(); using Stream stream = await response.Content.ReadAsStreamAsync(); using FileStream fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None); await stream.CopyToAsync(fileStream); return true; } catch(HttpRequestException) { return false; } } #endregion } |
TestProject.zip
■ HttpClient 클래스를 사용해 OLLAMA에게 LLAMA 3 로컬 LLM 통신하는 방법을 보여준다. (스트림) ▶ RequestMessage.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
using Newtonsoft.Json; namespace TestProject; /// <summary> /// 요청 메시지 /// </summary> public class RequestMessage { //////////////////////////////////////////////////////////////////////////////////////////////////// Property ////////////////////////////////////////////////////////////////////////////////////////// Public #region 모델 - Model /// <summary> /// 모델 /// </summary> [JsonProperty("model")] public string Model { get; set; } #endregion #region 프롬프트 - Prompt /// <summary> /// 프롬프트 /// </summary> [JsonProperty("prompt")] public string Prompt { get; set; } #endregion } |
▶ ResponseMessage.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
using Newtonsoft.Json; namespace TestProject; /// <summary> /// 응답 메시지 /// </summary> public class ResponseMessage { //////////////////////////////////////////////////////////////////////////////////////////////////// Property ////////////////////////////////////////////////////////////////////////////////////////// Public #region 모델 - Model /// <summary> /// 모델 /// </summary> [JsonProperty("model")] public string Model { get; set; } #endregion #region 생성 시간 - CreateTime /// <summary> /// 생성 시간 /// </summary> [JsonProperty("created_at")] public string CreateTime { get; set; } #endregion #region 응답 - Response /// <summary> /// 응답 /// </summary> [JsonProperty("response")] public string Response { get; set; } #endregion #region 완료 여부 - Done /// <summary> /// 완료 여부 /// </summary> [JsonProperty("done")] public bool Done { get; set; } #endregion } |
▶ APIClient.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 |
using System.Text; using System.Net.Http.Headers; using Newtonsoft.Json; namespace TestProject; /// <summary> /// API 클라이언트 /// </summary> public class APIClient : IDisposable { //////////////////////////////////////////////////////////////////////////////////////////////////// Event ////////////////////////////////////////////////////////////////////////////////////////// Public #region 메시지 도착시 이벤트 - MessageArrived /// <summary> /// 메시지 도착시 이벤트 /// </summary> public event EventHandler<ResponseMessage> MessageArrived; #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Field ////////////////////////////////////////////////////////////////////////////////////////// Private #region Field /// <summary> /// 리소스 해제 여부 /// </summary> private bool disposed = false; /// <summary> /// BASE URL /// </summary> private const string BASE_URL = "http://localhost:11434"; /// <summary> /// HTTP 클라이언트 /// </summary> private HttpClient client; /// <summary> /// 품질을 갖는 스트림 미디어 타입 헤더 값 /// </summary> private MediaTypeWithQualityHeaderValue streamMediaTypeWithQualityHeaderValue; #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Property ////////////////////////////////////////////////////////////////////////////////////////// Public #region HTTP 클라이언트 - Client /// <summary> /// HTTP 클라이언트 /// </summary> public HttpClient Client { get { return this.client; } } #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor ////////////////////////////////////////////////////////////////////////////////////////// Public #region API 클라이언트 - APIClient() /// <summary> /// API 클라이언트 /// </summary> public APIClient() { this.client = new HttpClient(); this.streamMediaTypeWithQualityHeaderValue = new MediaTypeWithQualityHeaderValue("text/event-stream"); } #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Public #region 채팅 요청하기 (비동기) - RequestChatAsync(requestMessage) /// <summary> /// 채팅 요청하기 (비동기) /// </summary> /// <param name="requestMessage">요청 메시지</param> /// <returns>응답 메시지 태스크</returns> public async Task<List<ResponseMessage>> RequestChatAsync(RequestMessage requestMessage) { if(this.client.DefaultRequestHeaders.Accept.Contains(this.streamMediaTypeWithQualityHeaderValue)) { this.client.DefaultRequestHeaders.Accept.Remove(this.streamMediaTypeWithQualityHeaderValue); } string requestJSON = JsonConvert.SerializeObject(requestMessage); StringContent content = new StringContent(requestJSON, Encoding.UTF8, "application/json"); HttpResponseMessage responseMessage = await this.client.PostAsync($"{BASE_URL}/api/generate", content); responseMessage.EnsureSuccessStatusCode(); string responseString = await responseMessage.Content.ReadAsStringAsync(); return JsonConvert.DeserializeObject<List<ResponseMessage>>($"[{responseString}]"); } #endregion #region 채팅 요청하기 (스트림) (비동기) - RequestChatStreamAsync(requestMessage) /// <summary> /// 채팅 요청하기 (스트림) (비동기) /// </summary> /// <param name="requestMessage">요청 메시지</param> /// <returns>스트리밍 메시지 리스트 태스크</returns> public async Task<List<ResponseMessage>> RequestChatStreamAsync(RequestMessage requestMessage) { if(!this.client.DefaultRequestHeaders.Accept.Contains(this.streamMediaTypeWithQualityHeaderValue)) { this.client.DefaultRequestHeaders.Accept.Add(this.streamMediaTypeWithQualityHeaderValue); } string requestJSON = JsonConvert.SerializeObject(requestMessage); StringContent content = new StringContent(requestJSON, Encoding.UTF8, "application/json"); using var request = new HttpRequestMessage(HttpMethod.Post, $"{BASE_URL}/api/generate"); request.Content = content; using HttpResponseMessage httpResponseMessage = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead); httpResponseMessage.EnsureSuccessStatusCode(); using Stream stream = await httpResponseMessage.Content.ReadAsStreamAsync(); using StreamReader reader = new StreamReader(stream); List<ResponseMessage> responseMessageList = new List<ResponseMessage>(); while(!reader.EndOfStream) { string line = await reader.ReadLineAsync(); if(string.IsNullOrWhiteSpace(line)) { continue; } ResponseMessage responseMessage = JsonConvert.DeserializeObject<ResponseMessage>(line); responseMessageList.Add(responseMessage); MessageArrived?.Invoke(this, responseMessage); } return responseMessageList; } #endregion #region 리소스 해제하기 - Dispose() /// <summary> /// 리소스 해제하기 /// </summary> public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } #endregion ////////////////////////////////////////////////////////////////////////////////////////// Protected #region 리소스 해제하기 - Dispose(disposing) /// <summary> /// 리소스 해제하기 /// </summary> /// <param name="disposing">리소스 해제 여부</param> protected virtual void Dispose(bool disposing) { if(!this.disposed) { if(disposing) { if(this.client != null) { this.client.Dispose(); } this.client = null; this.disposed = true; } } } #endregion } |
■ HttpClient 클래스를 사용해 OLLAMA에게 LLAMA 3 로컬 LLM 통신하는 방법을 보여준다. ▶ RequestMessage.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
using Newtonsoft.Json; namespace TestProject; /// <summary> /// 요청 메시지 /// </summary> public class RequestMessage { //////////////////////////////////////////////////////////////////////////////////////////////////// Property ////////////////////////////////////////////////////////////////////////////////////////// Public #region 모델 - Model /// <summary> /// 모델 /// </summary> [JsonProperty("model")] public string Model { get; set; } #endregion #region 프롬프트 - Prompt /// <summary> /// 프롬프트 /// </summary> [JsonProperty("prompt")] public string Prompt { get; set; } #endregion } |
▶ Program.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
using System.Text; using Newtonsoft.Json; namespace TestProject; /// <summary> /// 프로그램 /// </summary> class Program { //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Static //////////////////////////////////////////////////////////////////////////////// Private #region 프로그램 시작하기 - Main() /// <summary> /// 프로그램 시작하기 /// </summary> /// <returns>태스크</returns> static async Task Main() { using HttpClient httpClient = new HttpClient(); httpClient.BaseAddress = new Uri("http://localhost:11434"); RequestMessage requestMessage = new() { Model = "llama3", Prompt = "Hello, how are you?" }; StringContent stringContent = new ( JsonConvert.SerializeObject(requestMessage), Encoding.UTF8, "application/json" ); HttpResponseMessage httpResponseMessage = await httpClient.PostAsync("/api/generate", stringContent); string responseString = await httpResponseMessage.Content.ReadAsStringAsync(); Console.WriteLine(responseString); } #endregion } |
TestProject.zip
■ HttpClient 클래스를 사용해 네이버 HyperCLOVA X와 통신하는 방법을 보여준다. (이벤트) ▶ AIFilter.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
using Newtonsoft.Json; namespace TestProject; /// <summary> /// AI 필터 /// </summary> public class AIFilter { //////////////////////////////////////////////////////////////////////////////////////////////////// Property ////////////////////////////////////////////////////////////////////////////////////////// Public #region 그룹명 - GroupName /// <summary> /// 그룹명 /// </summary> [JsonProperty("groupName")] public string GroupName { get; set; } #endregion #region 명칭 - Name /// <summary> /// 명칭 /// </summary> [JsonProperty("name")] public string Name { get; set; } #endregion #region 점수 - Score /// <summary> /// 점수 /// </summary> [JsonProperty("score")] public string Score { get; set; } #endregion #region 결과 - Result /// <summary> /// 결과 /// </summary> [JsonProperty("result")] public string Result { get; set; } #endregion } |
▶ Message.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
using Newtonsoft.Json; namespace TestProject; /// <summary> /// 메시지 /// </summary> public class Message { //////////////////////////////////////////////////////////////////////////////////////////////////// Property ////////////////////////////////////////////////////////////////////////////////////////// Public #region 역할 - Role /// <summary> /// 역할 /// </summary> [JsonProperty("role")] public string Role { get; set; } #endregion #region 내용 - Content /// <summary> /// 내용 /// </summary> [JsonProperty("content")] public string Content { get; set; } #endregion } |
▶ RequestMessage.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
using Newtonsoft.Json; namespace TestProject; /// <summary> /// 요청 메시지 /// </summary> public class RequestMessage { //////////////////////////////////////////////////////////////////////////////////////////////////// Property ////////////////////////////////////////////////////////////////////////////////////////// Public #region 메시지 리스트 - MessageList /// <summary> /// 메시지 리스트 /// </summary> [JsonProperty("messages")] public List<Message> MessageList { get; set; } #endregion #region Top P - TopP /// <summary> /// TopP /// </summary> [JsonProperty("topP")] public double TopP { get; set; } #endregion #region Top K - TopK /// <summary> /// TopK /// </summary> [JsonProperty("topK")] public int TopK { get; set; } #endregion #region 최대 토큰 카운트 - MaximumTokenCount /// <summary> /// 최대 토큰 카운트 /// </summary> [JsonProperty("maxTokens")] public int MaximumTokenCount { get; set; } #endregion #region 온도 - Temperature /// <summary> /// 온도 /// </summary> [JsonProperty("temperature")] public double Temperature { get; set; } #endregion #region 반복 패널티 - RepeatPenalty /// <summary> /// 반복 패널티 /// </summary> [JsonProperty("repeatPenalty")] public double RepeatPenalty { get; set; } #endregion #region Stop Before - StopBefore /// <summary> /// Stop Before /// </summary> [JsonProperty("stopBefore")] public List<string> StopBefore { get; set; } #endregion #region AI 필터 포함 여부 - IncludeAIFilters /// <summary> /// AI 필터 포함 여부 /// </summary> [JsonProperty("includeAiFilters")] public bool IncludeAIFilters { get; set; } #endregion #region 시드 - Seed /// <summary> /// 시드 /// </summary> [JsonProperty("seed")] public int Seed { get; set; } #endregion } |
▶ ResponseMessage.cs
■ HttpClient 클래스를 사용해 네이버 HyperCLOVA X와 통신하는 방법을 보여준다. ▶ AIFilter.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
using Newtonsoft.Json; namespace TestProject; /// <summary> /// AI 필터 /// </summary> public class AIFilter { //////////////////////////////////////////////////////////////////////////////////////////////////// Property ////////////////////////////////////////////////////////////////////////////////////////// Public #region 그룹명 - GroupName /// <summary> /// 그룹명 /// </summary> [JsonProperty("groupName")] public string GroupName { get; set; } #endregion #region 명칭 - Name /// <summary> /// 명칭 /// </summary> [JsonProperty("name")] public string Name { get; set; } #endregion #region 점수 - Score /// <summary> /// 점수 /// </summary> [JsonProperty("score")] public string Score { get; set; } #endregion #region 결과 - Result /// <summary> /// 결과 /// </summary> [JsonProperty("result")] public string Result { get; set; } #endregion } |
▶ Message.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
using Newtonsoft.Json; namespace TestProject; /// <summary> /// 메시지 /// </summary> public class Message { //////////////////////////////////////////////////////////////////////////////////////////////////// Property ////////////////////////////////////////////////////////////////////////////////////////// Public #region 역할 - Role /// <summary> /// 역할 /// </summary> [JsonProperty("role")] public string Role { get; set; } #endregion #region 내용 - Content /// <summary> /// 내용 /// </summary> [JsonProperty("content")] public string Content { get; set; } #endregion } |
▶ RequestMessage.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
using Newtonsoft.Json; namespace TestProject; /// <summary> /// 요청 메시지 /// </summary> public class RequestMessage { //////////////////////////////////////////////////////////////////////////////////////////////////// Property ////////////////////////////////////////////////////////////////////////////////////////// Public #region 메시지 리스트 - MessageList /// <summary> /// 메시지 리스트 /// </summary> [JsonProperty("messages")] public List<Message> MessageList { get; set; } #endregion #region Top P - TopP /// <summary> /// TopP /// </summary> [JsonProperty("topP")] public double TopP { get; set; } #endregion #region Top K - TopK /// <summary> /// TopK /// </summary> [JsonProperty("topK")] public int TopK { get; set; } #endregion #region 최대 토큰 카운트 - MaximumTokenCount /// <summary> /// 최대 토큰 카운트 /// </summary> [JsonProperty("maxTokens")] public int MaximumTokenCount { get; set; } #endregion #region 온도 - Temperature /// <summary> /// 온도 /// </summary> [JsonProperty("temperature")] public double Temperature { get; set; } #endregion #region 반복 패널티 - RepeatPenalty /// <summary> /// 반복 패널티 /// </summary> [JsonProperty("repeatPenalty")] public double RepeatPenalty { get; set; } #endregion #region Stop Before - StopBefore /// <summary> /// Stop Before /// </summary> [JsonProperty("stopBefore")] public List<string> StopBefore { get; set; } #endregion #region AI 필터 포함 여부 - IncludeAIFilters /// <summary> /// AI 필터 포함 여부 /// </summary> [JsonProperty("includeAiFilters")] public bool IncludeAIFilters { get; set; } #endregion #region 시드 - Seed /// <summary> /// 시드 /// </summary> [JsonProperty("seed")] public int Seed { get; set; } #endregion } |
▶ ResponseMessage.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
using Newtonsoft.Json; namespace TestProject; /// <summary> /// 응답 메시지 /// </summary> public class ResponseMessage { //////////////////////////////////////////////////////////////////////////////////////////////////// Property ////////////////////////////////////////////////////////////////////////////////////////// Public #region 상태 - Status /// <summary> /// 상태 /// </summary> [JsonProperty("status")] public ResponseStatus Status { get; set; } #endregion #region 결과 - Result /// <summary> /// 결과 /// </summary> [JsonProperty("result")] public ResponseResult Result { get; set; } #endregion } |
■ MemberNotNullWhenAttribute 클래스를 사용해 특정 멤버가 NOT NULL인 것을 보장하는 방법을 보여준다. ※ 조건부 not null 보장 : 특정 조건이 참일 때
■ HttpClient 클래스의 PostAsJsonAsync/GetFromJsonAsync/GetAsync/PutAsJsonAsync/DeleteAsync 메소드를 사용해 REST API를 호출하는 방법을 보여준다. ※ REST API 서버는 파이썬 서버를 사용했다 : https://icodebroker.com/archives/107331 ▶ TodoItem.cs