Lab
[side-1] 웹 화면에서 사용자 쿼리 받아 유사한 값 출력 보여주기
돌돌찐
2025. 2. 19. 21:41
개요
사용자 쿼리를 화면 상에서 받고, 검색 시 유사한 값을 화면에 출력해보기 위해 작업해보았다.
환경
FastAPI 컨테이너 내에서 작업.
작업
1. 데이터 검색을 위한 코드 함수화
테스트로 유사도 검색 작업을 했던 파일을 다듬어 함수화하였다.
from dotenv import load_dotenv
import os
from langchain_openai import OpenAIEmbeddings
from pymilvus import connections, MilvusClient
from openai import OpenAI
load_dotenv()
# 환경 변수 가져오기
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
MILVUS_HOST = os.getenv("MILVUS_HOST")
MILVUS_PORT = os.getenv("MILVUS_PORT")
COLLECTION_NAME = "lost_items"
# Milvus 연결 테스트
try:
connections.connect("default", host=MILVUS_HOST, port=MILVUS_PORT)
print("Milvus에 성공적으로 연결되었습니다.")
except Exception as e:
print(f"Milvus 연결 실패: {e}")
exit(1)
openai_client = OpenAI(api_key=OPENAI_API_KEY)
embeddings = OpenAIEmbeddings(model='text-embedding-3-large')
milvus_client = MilvusClient(uri="http://milvus-standalone:19530")
def search_similar_items(query:str):
response = openai_client.embeddings.create(input=[query], model='text-embedding-3-large',dimensions=384)
query_vector = response.data[0].embedding
res = milvus_client.search(
collection_name=COLLECTION_NAME,
data=[query_vector],
limit=3,
output_fields=["item_id", "name", "description"],
)
results = []
for result in res[0]:
results.append(
{"item_id": result.get("entity")["item_id"],
"name": result.get("entity")["name"],
"description": result.get("entity")["description"]}
)
return results
2. 라우팅 설정 및 html 작성
'/'로 진입 시 index.html 을 보여주고, 유저가 검색할 항목을 입력하고 검색 버튼을 누르면 '/search'에서 검색 결과를 보여주는 구조로 코드를 작성하였다.
- main.py
from fastapi import FastAPI, Request, Form
from fastapi.responses import HTMLResponse
from fastapi.templating import Jinja2Templates
from milvus_search import search_similar_items
app = FastAPI()
templates = Jinja2Templates(directory="templates")
# 메인 페이지. 검색 입력 값을 받음.
@app.get("/", response_class=HTMLResponse)
async def get_home(request: Request):
return templates.TemplateResponse("index.html", {"request": request})
# 검색을 처리하고 결과 값을 보여줌
@app.post("/search", response_class=HTMLResponse)
async def post_search(request: Request, user_input: str = Form(...)):
try:
results = search_similar_items(user_input)
return templates.TemplateResponse(
"index.html", {"request": request, "results": results}
)
except Exception as e:
return templates.TemplateResponse(
"index.html", {"request": request, "error": str(e)}
)
- templates/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>검색</title>
</head>
<body>
<h1>유사 항목 검색</h1>
<!-- 검색 폼 -->
<form action="/search" method="post">
<input type="text" name="user_input" placeholder="검색어 입력" required>
<button type="submit">검색</button>
</form>
<!-- 결과 -->
{% if results %}
<h2>검색 결과</h2>
<ul>
{% for result in results %}
<li>
<strong>{{ result.name }}</strong> (ID: {{ result.item_id }})<br>
<em>{{ result.description }}</em>
</li>
{% endfor %}
</ul>
{% elif error %}
<p>오류: {{ error }}</p>
{% endif %}
</body>
</html>