랭그래프 활용한 주식 정보 도출 프로젝트
- 투자 의견 조회
ㄴ 전반적인 주식 판단 기준(ex. 채무, 리스크 등등)을 기준으로 판단하여 도출
- 투자 추천
ex)
{
"tickers": [
"NVDA", "GOOGL", "AAPL"
],
"risk_type": "aggressive"
}
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user