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>

 

결과 확인