랭그래프 활용한 주식 정보 도출 프로젝트

- 투자 의견 조회
ㄴ 전반적인 주식 판단 기준(ex. 채무, 리스크 등등)을 기준으로 판단하여 도출
- 투자 추천
ex)
{
  "tickers": [
    "NVDA", "GOOGL", "AAPL"
  ],
  "risk_type": "aggressive"
}
This commit is contained in:
2026-06-19 18:03:05 +09:00
parent 3be7886bfe
commit 315105cebb
19 changed files with 614 additions and 68 deletions
@@ -1,6 +1,12 @@
from backend.schemas.stock_schemas import TickerInfo
import yahooquery as yq
from fastapi import HTTPException
from backend.graph.stock_graph import build_stock_graph
from backend.repository.models import StockAnalysis, InvestmentOpinion
from fastapi.encoders import jsonable_encoder
from typing import Optional
from backend.services.score_service import evaluation, get_rating
from backend.ai.llm import hugging_llm
COMPANY_MAP = {
"NVDA": {
@@ -115,6 +121,8 @@ class StockService:
if alias.lower() in query:
return TickerInfo(ticker = ticker, company_name = info["company_name"])
return None
def _extract_company_keyword(self, query:str):
"""
query : 엔비디아 분석해줘
@@ -145,4 +153,89 @@ class StockService:
return TickerInfo(ticker=result["symbol"], company_name=result["longname"])
except Exception:
return None
return None
async def analyze(self, query: str, db):
# 티커, 회사명 추출
ticker_info = await self._extract(query)
# 그래프 실행
stock_graph = build_stock_graph()
result = await stock_graph.ainvoke(
{
"query": query,
"ticker": ticker_info.ticker,
"company_name": ticker_info.company_name
}
)
# 데이터베이스 저장
# 테이블과 관련있는 모델 객체 생성
entity = StockAnalysis(
ticker = result['ticker'],
company_name = result['company_name'],
analysis_json = jsonable_encoder(result),
report = result['report']
)
db.add(entity)
db.commit()
db.refresh(entity)
return {"analysis_id":entity.analysis_id, **result}
async def opinion_service(self, analysis_id, db):
# analysis_id 디비 조회
analysis = db.get(StockAnalysis, analysis_id)
score_result = await evaluation(analysis)
#
total_score = score_result['total_score']
rating = get_rating(total_score)
# AI 투자 의견서
opinion = await self.generate_opinion(analysis.report, total_score, rating)
entity = InvestmentOpinion(
analysis_id = analysis_id,
opinion = opinion,
rating = rating,
score = total_score,
)
db.add(entity)
db.commit()
db.refresh(entity)
return {"opinion_id":entity.opinion_id, "analysis_id":analysis_id, "opinion":opinion, "rating":rating, **score_result,}
async def generate_opinion(self, report, total_score, rating):
prompt = f"""
당신은 월가의 수석 애널리스트입니다.
종합점수 :
{total_score} / 100
투자등급 :
{rating}
다음 기업 분석 보고서를 기반으로 투자 의견서를 작성하세요.
{report}
반드시 아래 형식으로 작성하세요.
1. 투자등급
2. 투자근거
3. 핵심리스크
4. 단기전망
5. 장기전망
6. 최종의견
"""
result = await hugging_llm.ainvoke(prompt)
return result.content
# 싱글톤(객체 하나만 생성) 서비스 인스턴스
_service:Optional[StockService] = None
def get_stock_service():
global _service
if _service is None:
_service = StockService()
return _service