아래 예제에서는 Windows Server에 Qdrant 실행 파일(qdrant.exe)을 설치하고, C# 콘솔 애플리케이션에서 벡터 데이터를 삽입(upsert)한 뒤, 벡터 검색 결과를 ChatGPT API로 전달하여 답변을 얻는 전체 흐름을 설명합니다.
1. Qdrant 설치 및 실행
다운로드
Qdrant GitHub 릴리즈 페이지에서 Windows용qdrant.exe를 내려받습니다.ruby복사편집https://github.com/qdrant/qdrant/releases실행
다운로드한qdrant.exe를 원하는 폴더(예:C:\qdrant)에 복사한 뒤, 관리자 권한으로 명령 프롬프트에서 다음을 실행합니다.bat복사편집cd C:\qdrant qdrant.exe serve --host 0.0.0.0 --port 6333기본적으로 메모리 모드로 실행되며,
--storage-config옵션을 주면 디스크에 영구 저장할 수 있습니다.
2. C#으로 벡터 데이터 삽입하기
아래 코드는
OpenAI Embeddings API로 텍스트를 벡터로 변환
Qdrant REST API에 컬렉션을 생성하고, 벡터 포인트를 upsert
하는 예제입니다.
csharp복사편집using System;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
namespace QdrantDemo
{
class Program
{
// TODO: 환경 변수나 설정 파일에서 읽어올 것
const string OPENAI_API_KEY = "sk-…";
const string QDRANT_URL = "http://localhost:6333";
const string COLLECTION_NAME= "my_collection";
static async Task Main(string[] args)
{
using var http = new HttpClient();
// 1. OpenAI Embeddings API 호출
var text = "안녕하세요, Qdrant 벡터 DB 테스트 문장입니다.";
var embedReq = new
{
model = "text-embedding-ada-002",
input = text
};
http.DefaultRequestHeaders.Add("Authorization", $"Bearer {OPENAI_API_KEY}");
var embedRes = await http.PostAsync(
"https://api.openai.com/v1/embeddings",
new StringContent(JsonSerializer.Serialize(embedReq), Encoding.UTF8, "application/json")
);
embedRes.EnsureSuccessStatusCode();
using var embedJson = await JsonDocument.ParseAsync(await embedRes.Content.ReadAsStreamAsync());
var vector = embedJson.RootElement
.GetProperty("data")[0]
.GetProperty("embedding")
.EnumerateArray()
.Select(v => v.GetDouble())
.ToArray();
// 2. Qdrant 컬렉션 생성 (한 번만 실행)
var createColl = new
{
vectors = new { size = vector.Length, distance = "Cosine" }
};
var createRes = await http.PutAsync(
$"{QDRANT_URL}/collections/{COLLECTION_NAME}",
new StringContent(JsonSerializer.Serialize(createColl), Encoding.UTF8, "application/json")
);
createRes.EnsureSuccessStatusCode();
// 3. 벡터 포인트 upsert
var upsertPayload = new
{
points = new[]
{
new {
id = 1,
vector = vector,
payload = new { text = text }
}
}
};
var upsertRes = await http.PutAsync(
$"{QDRANT_URL}/collections/{COLLECTION_NAME}/points",
new StringContent(JsonSerializer.Serialize(upsertPayload), Encoding.UTF8, "application/json")
);
upsertRes.EnsureSuccessStatusCode();
Console.WriteLine("벡터 데이터 삽입 완료!");
}
}
}
3. 벡터 검색 및 ChatGPT에 질의하기
다음 예제는
사용자의 질의를 Embedding으로 변환
Qdrant에서 상위 3개 유사도 검색
검색된 텍스트를 ChatGPT에 컨텍스트로 전달하여 답변 받기
를 보여줍니다.
csharp복사편집using System;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
namespace QdrantChatGPT
{
class Program
{
const string OPENAI_API_KEY = "sk-…";
const string QDRANT_URL = "http://localhost:6333";
const string COLLECTION_NAME= "my_collection";
static async Task Main(string[] args)
{
Console.Write("질문을 입력하세요: ");
var userQuestion = Console.ReadLine();
using var http = new HttpClient();
http.DefaultRequestHeaders.Add("Authorization", $"Bearer {OPENAI_API_KEY}");
// 1. 질문을 벡터로 변환
var embedReq = new { model = "text-embedding-ada-002", input = userQuestion };
var embedRes = await http.PostAsync(
"https://api.openai.com/v1/embeddings",
new StringContent(JsonSerializer.Serialize(embedReq), Encoding.UTF8, "application/json")
);
embedRes.EnsureSuccessStatusCode();
using var embedJson = await JsonDocument.ParseAsync(await embedRes.Content.ReadAsStreamAsync());
var queryVector = embedJson.RootElement
.GetProperty("data")[0]
.GetProperty("embedding")
.EnumerateArray()
.Select(v => v.GetDouble())
.ToArray();
// 2. Qdrant에서 유사도 검색
var searchPayload = new
{
vector = queryVector,
top = 3
};
var searchRes = await http.PostAsync(
$"{QDRANT_URL}/collections/{COLLECTION_NAME}/points/search",
new StringContent(JsonSerializer.Serialize(searchPayload), Encoding.UTF8, "application/json")
);
searchRes.EnsureSuccessStatusCode();
using var searchJson = await JsonDocument.ParseAsync(await searchRes.Content.ReadAsStreamAsync());
var hits = searchJson.RootElement.GetProperty("result")
.EnumerateArray()
.Select(e => e.GetProperty("payload").GetProperty("text").GetString())
.ToList();
// 3. ChatGPT에 컨텍스트와 함께 질문
var systemMsg = "다음 컨텍스트를 참고하여 사용자의 질문에 답변해주세요.";
var userMsg = $"컨텍스트:\n- {string.Join("\n- ", hits)}\n\n질문: {userQuestion}";
var chatReq = new
{
model = "gpt-3.5-turbo",
messages = new[]
{
new { role = "system", content = systemMsg },
new { role = "user", content = userMsg }
}
};
var chatRes = await http.PostAsync(
"https://api.openai.com/v1/chat/completions",
new StringContent(JsonSerializer.Serialize(chatReq), Encoding.UTF8, "application/json")
);
chatRes.EnsureSuccessStatusCode();
using var chatJson = await JsonDocument.ParseAsync(await chatRes.Content.ReadAsStreamAsync());
var answer = chatJson.RootElement
.GetProperty("choices")[0]
.GetProperty("message")
.GetProperty("content")
.GetString();
Console.WriteLine("\n===== ChatGPT 응답 =====");
Console.WriteLine(answer);
}
}
}
요약
Qdrant 실행:
qdrant.exe serve로 로컬에서 HTTP API(포트 6333) 제공데이터 삽입: OpenAI Embeddings → Qdrant 컬렉션 생성 → points upsert
검색 & 질의: 질문 Embedding → Qdrant 검색(top-k) → ChatGPT에 컨텍스트 포함해 질문
이 구조를 통해 사용자의 질의에 대해 벡터 DB에서 관련 문서를 찾아, 보다 정교한 답변을 ChatGPT로부터 받아올 수 있습니다.