diff --git a/app/services/langgraph_enhanced/agents/analysis_agent.py b/app/services/langgraph_enhanced/agents/analysis_agent.py index 199568f..a2f1230 100644 --- a/app/services/langgraph_enhanced/agents/analysis_agent.py +++ b/app/services/langgraph_enhanced/agents/analysis_agent.py @@ -355,10 +355,11 @@ async def process(self, user_query: str, query_analysis: Dict[str, Any]) -> Dict - 성장성 (매출 성장률, 이익 성장률 등) ### 📰 최신 동향 (뉴스 기반) -**위의 최신 뉴스 3개를 참고하여**: -- 최근 주요 이슈 및 이벤트 -- 호재/악재 판단 -- 시장 반응 및 전망 +**위의 최신 뉴스 3개를 참고하여 심층적으로 분석하세요**: +- **사건의 핵심**: 각 뉴스가 의미하는 핵심 사건은 무엇인가? +- **영향력 평가**: 각 사건이 주가에 미치는 영향의 **중요도(높음/중간/낮음)**와 **기간(단기/중기/장기)**을 평가하라. +- **인과관계 분석**: 왜 이 뉴스가 호재 또는 악재인가? 회사의 **펀더멘털(매출, 이익, 사용자 기반 등)**에 어떤 영향을 미치는가? +- **시장 반응 및 전망**: 이 사건에 대한 시장의 현재 반응과 향후 전망을 예측하라. ### 💡 종합 투자 의견 (Chain-of-Thought 방식) **단계별 사고 과정을 명확히 제시하세요:** @@ -367,21 +368,22 @@ async def process(self, user_query: str, query_analysis: Dict[str, Any]) -> Dict - 현재 주가: {financial_data.get('current_price', 'N/A')}원 - 밸류에이션: PER {financial_data.get('pe_ratio', 'N/A')}, PBR {financial_data.get('pbr', 'N/A')} - 재무 상태: 간단히 요약 - - 최근 뉴스: 위 3개 뉴스 제목을 언급하며 시장 분위기 파악 + - 최근 뉴스: 위 뉴스 분석을 바탕으로 현재 시장 분위기를 종합적으로 판단 2. **✅ 긍정적 요인 (호재)** - - 뉴스에서 파악된 호재 (구체적 제목 언급) + - 뉴스에서 파악된 **핵심 호재** (구체적 제목 및 중요도 언급) - 재무적으로 강한 포인트 - 성장 가능성 및 긍정적 전망 - - **각 요인마다 "왜 호재인가?" 설명** + - **각 요인마다 "왜, 그리고 얼마나 중요한 호재인가?"를 펀더멘털 관점에서 설명** 3. **⚠️ 부정적 요인 및 리스크 (악재)** - - 뉴스에서 파악된 악재 (구체적 제목 언급) + - 뉴스에서 파악된 **핵심 악재** (구체적 제목 및 중요도 언급) - 재무적 약점 - 투자 리스크 요소 - - **각 요인마다 "왜 악재인가?" 설명** + - **각 요인마다 "왜, 그리고 얼마나 중요한 악재인가?"를 펀더멘털 관점에서 설명** 4. **🎯 투자 판단 근거 (가장 중요!)** + - **긍정 vs 부정 요인 가중치 분석**: "현재 주가에 더 결정적인 영향을 미치는 요인은 무엇인가?" - "긍정 vs 부정" 요인 균형 분석 - **왜 이 회사에 투자해야 하는가? (또는 하지 말아야 하는가?)** - 구체적 판단 이유: "OO 때문에 OO하다고 판단합니다" @@ -400,15 +402,15 @@ async def process(self, user_query: str, query_analysis: Dict[str, Any]) -> Dict - 추가 확인이 필요한 사항 ## 응답 형식 -- **반드시 위의 최신 뉴스 제목을 언급**하며 분석하세요 +- **반드시 위의 최신 뉴스 제목을 언급**하며 심층적으로 분석하세요 - 각 단계마다 "왜 그렇게 판단했는지" 근거를 명확히 제시 - 숫자와 데이터를 활용하여 구체적으로 작성 - 이모지를 적절히 사용하여 가독성 향상 ## 중요 원칙 ✅ **신뢰성**: 최신 뉴스 제목을 직접 언급하여 분석의 근거 제시 -✅ **구체성**: "좋다/나쁘다"가 아닌 "OO 때문에 OO하다"로 설명 -✅ **균형성**: 호재와 악재를 모두 객관적으로 분석 +✅ **구체성**: "좋다/나쁘다"가 아닌 "**OO 때문에 OO하며, 이는 주가에 OO만큼 중요하다**"로 설명 +✅ **균형성**: 호재와 악재의 **영향력을 비교 분석**하여 종합적인 판단 제시 ✅ **실용성**: 실제 투자에 바로 활용 가능한 구체적 전략 제시""" analysis_response = self.llm.invoke(analysis_prompt) diff --git a/app/services/portfolio/financial_data_service.py b/app/services/portfolio/financial_data_service.py index ed0376f..959aa77 100644 --- a/app/services/portfolio/financial_data_service.py +++ b/app/services/portfolio/financial_data_service.py @@ -5,6 +5,9 @@ from typing import Dict, Any, List, Optional from app.services.pinecone_rag_service import search_pinecone, get_context_for_query from app.services.pinecone_config import KNOWLEDGE_NAMESPACES +from app.services.langgraph_enhanced.llm_manager import LLMManager +from app.services.pinecone_rag_service import PineconeRAGService +from app.schemas.portfolio_schema import InvestmentProfileRequest from langchain_google_genai import ChatGoogleGenerativeAI from app.config import settings diff --git a/app/utils/stock_config_loader.py b/app/utils/stock_config_loader.py index c355602..238bd2b 100644 --- a/app/utils/stock_config_loader.py +++ b/app/utils/stock_config_loader.py @@ -13,18 +13,29 @@ class StockConfigLoader: """주식 설정 로더 클래스""" - def __init__(self, config_path: str = "config/stocks.yaml"): - """ - 주식 설정 로더 초기화 - - Args: - config_path: YAML 설정 파일 경로 - """ + _instance = None + _initialized = False + + def __new__(cls, *args, **kwargs): + if cls._instance is None: + cls._instance = super().__new__(cls) + return cls._instance + + def __init__(self, config_path: str = None): + if self._initialized: + return + + if config_path is None: + # 프로젝트 루트를 기준으로 경로 설정 + base_dir = Path(__file__).resolve().parent.parent.parent + config_path = base_dir / "config" / "stocks.yaml" + self.config_path = config_path self._config = None self._stock_mapping = {} self._symbol_mapping = {} self._load_config() + self._initialized = True def _load_config(self): """YAML 설정 파일 로드"""