FinGraph / tests /test_retrieval.py
dev-yuje's picture
feat: implement conversational hybrid RAG fallback routing and optimize presentation layout
79ef842
import os
import pytest
from src.retrieval.finRetrieval import graphrag
# API ํ‚ค์™€ Neo4j ์—ฐ๊ฒฐ์ •๋ณด๊ฐ€ ์—†์„ ๊ฒฝ์šฐ ํ…Œ์ŠคํŠธ๋ฅผ ๊ฑด๋„ˆ๋œ๋‹ˆ๋‹ค.
has_credentials = (
os.getenv("OPENAI_API_KEY") is not None and
os.getenv("NEO4J_URI") is not None
)
@pytest.mark.skipif(
not has_credentials,
reason="OpenAI API Key ๋˜๋Š” Neo4j ์—ฐ๊ฒฐ ํ™˜๊ฒฝ๋ณ€์ˆ˜๊ฐ€ ์—†์œผ๋ฏ€๋กœ ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ๋ฅผ ๊ฑด๋„ˆ๋œ๋‹ˆ๋‹ค."
)
def test_portfolio_showcase_aggregation_query():
"""
[ํฌํŠธํด๋ฆฌ์˜ค ํ•ต์‹ฌ ์‹œ๋‚˜๋ฆฌ์˜ค]
ํŠน์ • ๊ธฐ์—…์„ ์ง€์ •ํ•˜์ง€ ์•Š๊ณ , ๊ธˆ์œตAI ๋ถ„์•ผ์˜ ์ตœ์‹  ํŠธ๋ Œ๋“œ ๊ธฐ์—… TOP 3์™€ ๋Œ€ํ‘œ ์„œ๋น„์Šค๋ฅผ
๋™์ ์œผ๋กœ ๊ทธ๋ž˜ํ”„ ํƒ์ƒ‰(GraphRAG)ํ•˜์—ฌ ์˜ฌ๋ฐ”๋ฅธ ํ˜•์‹์œผ๋กœ ๋‹ต๋ณ€ํ•˜๋Š”์ง€ ๊ฒ€์ฆํ•ฉ๋‹ˆ๋‹ค.
"""
showcase_query = (
"์ตœ๊ทผ ์ˆ˜์ง‘๋œ ๋‰ด์Šค์—์„œ ๊ธˆ์œตAI(AIField) ๋ถ„์•ผ์— ๊ฐ€์žฅ ์ ๊ทน์ ์œผ๋กœ ๊ธฐ์ˆ ์„ ๊ฐœ๋ฐœํ•˜๊ณ  ์žˆ๋Š” "
"๊ธฐ์—… TOP 3์™€ ๊ทธ ๊ธฐ์—…๋“ค์ด ๊ฐœ๋ฐœํ•œ ๋Œ€ํ‘œ ์„œ๋น„์Šค๋ฅผ ์•Œ๋ ค์ค˜."
)
# GraphRAG ๊ฒ€์ƒ‰ ๋ฐ ์ƒ์„ฑ ์‹คํ–‰
response = graphrag.search(query_text=showcase_query)
# 1. ์‘๋‹ต ๊ฐ์ฒด ๋ฐ ์†์„ฑ ์กด์žฌ ์—ฌ๋ถ€ ๊ฒ€์ฆ
assert response is not None
assert hasattr(response, "answer")
# 2. ๋‹ต๋ณ€ ํ…์ŠคํŠธ ์œ ํšจ์„ฑ ๊ฒ€์ฆ
answer = response.answer
assert len(answer.strip()) > 0
# 3. ๋‹ต๋ณ€ ํ˜•์‹ ๊ฒ€์ฆ (์ˆœ์œ„ ๊ตฌ์กฐ๋‚˜ ์ถœ์ฒ˜ ์ง€์นจ ์ค€์ˆ˜ ์—ฌ๋ถ€)
assert any(indicator in answer for indicator in ["1.", "์ฒซ์งธ", "TOP", "๊ธฐ์‚ฌ", "์ถœ์ฒ˜"])
print(f"\nโœจ [ํฌํŠธํด๋ฆฌ์˜ค ์‡ผ์ผ€์ด์Šค RAG ๊ฒฐ๊ณผ]\n{answer}")
@pytest.mark.skipif(
not has_credentials,
reason="OpenAI API Key ๋˜๋Š” Neo4j ์—ฐ๊ฒฐ ํ™˜๊ฒฝ๋ณ€์ˆ˜๊ฐ€ ์—†์œผ๋ฏ€๋กœ ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ๋ฅผ ๊ฑด๋„ˆ๋œ๋‹ˆ๋‹ค."
)
def test_hybrid_fallback_general_query():
"""
[ํ•˜์ด๋ธŒ๋ฆฌ๋“œ RAG Fallback ์‹œ๋‚˜๋ฆฌ์˜ค]
์ง€์‹ ๊ทธ๋ž˜ํ”„(๋‰ด์Šค ๋ฐ์ดํ„ฐ)์— ์ „ํ˜€ ์ˆ˜์ง‘๋˜์ง€ ์•Š์€ ์ผ๋ฐ˜ ๊ณผํ•™/์—ญ์‚ฌ ์งˆ๋ฌธ์— ๋Œ€ํ•ด
๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ๊ฐ€ ์ž„๊ณ„์น˜ ๋ฏธ๋งŒ์ž„์„ ๊ฐ์ง€ํ•˜๊ณ  ์ž๋™์œผ๋กœ GPT-4o ์ผ๋ฐ˜ ์ง€์‹ ๋ชจ๋“œ(general)๋กœ ๋ผ์šฐํŒ…ํ•˜๋Š”์ง€ ๊ฒ€์ฆํ•ฉ๋‹ˆ๋‹ค.
"""
general_query = "ํ”ผํƒ€๊ณ ๋ผ์Šค ์ •๋ฆฌ์™€ ๊ทธ ์‹ค์ƒํ™œ ํ™œ์šฉ ์˜ˆ์‹œ๋ฅผ ๊ฐ„๋‹จํžˆ ์„ค๋ช…ํ•ด์ค˜."
# search_with_fallback์„ ํ†ตํ•œ ๋ผ์šฐํŒ… ๊ฒ€์ƒ‰ ์ˆ˜ํ–‰
result = graphrag.search_with_fallback(query_text=general_query, history=[])
# 1. ๋ฐ˜ํ™˜ ํƒ€์ž… ๋ฐ ๋ชจ๋“œ ๊ฒ€์ฆ
assert result is not None
assert result.mode == "general"
# 2. GPT-4o ์ผ๋ฐ˜ ์ง€์‹ ๋‹ต๋ณ€ ์œ ํšจ์„ฑ ๊ฒ€์ฆ
assert len(result.answer.strip()) > 0
assert "ํ”ผํƒ€๊ณ ๋ผ์Šค" in result.answer
print(f"\nโœจ [์ผ๋ฐ˜ ์ง€์‹ Fallback ๋ผ์šฐํŒ… ๊ฒฐ๊ณผ]\n{result.answer}")