From a3b2ae6f35970dc1d412be9733f68030ca076444 Mon Sep 17 00:00:00 2001 From: Hon2yB22 Date: Sat, 19 Apr 2025 17:48:46 +0900 Subject: [PATCH 1/3] fix: pre-commit README, file chore --- README.md | 9 ++-- .../focus_group_interview/modules/chains.py | 2 - agents/focus_group_interview/modules/nodes.py | 13 ++--- .../focus_group_interview/modules/prompts.py | 8 +-- agents/focus_group_interview/modules/state.py | 9 ++-- agents/focus_group_interview/modules/tools.py | 6 +-- agents/focus_group_interview/modules/utils.py | 38 +++++++------- agents/focus_group_interview/workflow.py | 6 +-- agents/main_state.py | 3 +- agents/marketing/modules/nodes.py | 12 ++--- agents/marketing/modules/prompts.py | 30 +++++------ agents/marketing/modules/state.py | 17 +++---- agents/marketing/modules/tools.py | 12 ++--- agents/marketing/modules/utils.py | 46 ++++++++--------- agents/marketing/workflow.py | 6 +-- .../source_person_interview/modules/nodes.py | 12 ++--- .../modules/prompts.py | 28 +++++------ .../source_person_interview/modules/state.py | 6 +-- .../source_person_interview/modules/tools.py | 8 +-- .../source_person_interview/modules/utils.py | 50 +++++++++---------- agents/source_person_interview/workflow.py | 11 ++-- 21 files changed, 164 insertions(+), 168 deletions(-) diff --git a/README.md b/README.md index 27248cd..9041006 100644 --- a/README.md +++ b/README.md @@ -119,17 +119,16 @@ $ uv run langgraph dev #### pre-commit 설정 -1. pre-commit 설치 및 초기화: +1. pre-commit 초기화: ```bash -$ uv pip install pre-commit -$ pre-commit install +$ uv run pre-commit install ``` 2. 모든 파일에 대해 수동으로 실행: ```bash -$ pre-commit run --all-files +$ uv run pre-commit run --all-files ``` 3. 커밋 시 자동 실행: @@ -147,4 +146,4 @@ $ git commit -m "your commit message" ### 💡 **NOTE**: - 형식 및 가이드에 맞춰서 Commit Message, Issue, Pull Request를 작성해주세요. 상세 설명은 [여기(내부 링크)](https://www.notion.so/hon2ycomb/Git-Commit-Message-Convention-1b000c82b1388185aa3cf88a7e57f24c?pvs=4)를 참조하세요 :) -- 본 프로젝트에서 PR 후 merge하는 경우, github action으로 포맷팅 검사를 진행합니다. vscode 및 cursor에서 포맷팅 세팅은 [여기](https://gamchan.notion.site/vscode-9b61026771cb4121bbb80d4d4f289bc2)를 참조하세요 :) +- 본 프로젝트에서 PR 후 merge하는 경우, github action으로 포맷팅 검사를 진행합니다. vscode 및 cursor에서 포맷팅 세팅은 [여기](https://gamchan.notion.site/vscode-9b61026771cb4121bbb80d4d4f289bc2)를 참조하세요 :) \ No newline at end of file diff --git a/agents/focus_group_interview/modules/chains.py b/agents/focus_group_interview/modules/chains.py index 6c206e2..29c78e1 100644 --- a/agents/focus_group_interview/modules/chains.py +++ b/agents/focus_group_interview/modules/chains.py @@ -4,8 +4,6 @@ 기본적으로 modules.prompt 템플릿과 modules.models 모듈을 사용하여 LangChain 체인을 생성합니다. """ -from typing import List - # from agents.focus_group_interview.modules.models import get_openai_model # from agents.focus_group_interview.modules.prompts import ( # get_question_generation_prompt, diff --git a/agents/focus_group_interview/modules/nodes.py b/agents/focus_group_interview/modules/nodes.py index c3c9550..4b29045 100644 --- a/agents/focus_group_interview/modules/nodes.py +++ b/agents/focus_group_interview/modules/nodes.py @@ -7,13 +7,14 @@ """ from agents.base_node import BaseNode + # from agents.focus_group_interview.modules.chains import set_question_generation_chain, set_response_analysis_chain # class QuestionGenerationNode(BaseNode): # """ # 인터뷰 주제와 대상 청중에 적합한 질문을 생성하는 노드 -# +# # 이 노드는 LangChain의 질문 생성 체인을 활용하여 포커스 그룹 인터뷰에 적합한 질문을 생성합니다. # 주어진 인터뷰 주제와 대상 청중에 맞게 질문을 생성하여 Workflow의 다음 단계로 전달합니다. # """ @@ -26,10 +27,10 @@ # def execute(self, state) -> dict: # """ # 주어진 상태(state)에서 필요한 정보를 추출하여 질문을 생성하고 결과를 반환합니다. -# +# # Args: # state (dict): Workflow의 현재 상태. interview_topic과 target_audience 정보를 포함함. -# +# # Returns: # dict: 새로 생성된 질문들을 포함한 상태 업데이트 # """ @@ -48,7 +49,7 @@ # class ResponseAnalysisNode(BaseNode): # """ # 인터뷰 응답을 분석하는 노드 -# +# # 이 노드는 LangChain의 응답 분석 체인을 활용하여 포커스 그룹 인터뷰에서 수집된 응답들을 분석합니다. # 응답을 분석하여 주요 통찰과 패턴을 추출하고, 이를 Workflow의 다음 단계로 전달합니다. # """ @@ -61,10 +62,10 @@ # def execute(self, state) -> dict: # """ # 주어진 상태(state)에서 인터뷰 응답을 추출하여 분석하고 결과를 반환합니다. -# +# # Args: # state (dict): Workflow의 현재 상태. responses, interview_topic, target_audience 정보를 포함함. -# +# # Returns: # dict: 분석된 결과를 포함한 상태 업데이트 # """ diff --git a/agents/focus_group_interview/modules/prompts.py b/agents/focus_group_interview/modules/prompts.py index e95c62f..6aaa1aa 100644 --- a/agents/focus_group_interview/modules/prompts.py +++ b/agents/focus_group_interview/modules/prompts.py @@ -19,20 +19,20 @@ # template = """ # 당신은 교육 분야의 포커스 그룹 인터뷰 전문가입니다. # 아래 주제와 대상 청중에 맞는 효과적인 포커스 그룹 인터뷰 질문 목록을 생성해주세요. - + # # 인터뷰 주제 # {interview_topic} - + # # 대상 청중 # {target_audience} - + # # 지침 # - 개방형 질문을 사용하여 참가자들이 자유롭게 의견을 표현할 수 있도록 합니다. # - 교육적 맥락에 맞는 질문을 구성합니다. # - 최소 5개, 최대 10개의 질문을 생성합니다. # - 질문은 논리적 순서로 배열되어야 합니다. # - 질문은 명확하고 이해하기 쉬워야 합니다. - + # 다음 JSON 형식으로 질문 목록을 반환해주세요: # ```json # { diff --git a/agents/focus_group_interview/modules/state.py b/agents/focus_group_interview/modules/state.py index 8c45484..98fdd4b 100644 --- a/agents/focus_group_interview/modules/state.py +++ b/agents/focus_group_interview/modules/state.py @@ -1,11 +1,10 @@ from __future__ import annotations -from typing import Annotated, TypedDict, List +from dataclasses import dataclass +from typing import Annotated, List, TypedDict +from langchain_core.messages import AIMessage, HumanMessage from langgraph.graph.message import add_messages -from langchain_core.messages import HumanMessage, AIMessage - -from dataclasses import dataclass @dataclass @@ -15,7 +14,7 @@ class FocusGroupInterviewState(TypedDict): 포커스 그룹 인터뷰를 위한 Workflow에서 사용되는 상태 정보를 정의합니다. LangGraph의 상태 관리를 위한 클래스로, Workflow 내에서 처리되는 데이터의 형태와 구조를 지정합니다. - + 아래는 예시 상태 변수들입니다. 실제 구현 시 필요에 따라 수정해서 사용해주세요! """ diff --git a/agents/focus_group_interview/modules/tools.py b/agents/focus_group_interview/modules/tools.py index 317a4cc..2aa2008 100644 --- a/agents/focus_group_interview/modules/tools.py +++ b/agents/focus_group_interview/modules/tools.py @@ -26,12 +26,12 @@ # """ # 포커스 그룹 인터뷰 녹취록을 분석합니다. # -# 이 함수는 자연어 처리 기술을 사용하여 인터뷰 녹취록에서 주요 테마, +# 이 함수는 자연어 처리 기술을 사용하여 인터뷰 녹취록에서 주요 테마, # 감정 분석, 키워드 빈도 등을 추출합니다. # """ # # 실제 구현에서는 NLP 라이브러리를 사용하여 분석 수행 # # 예: spaCy, NLTK, HuggingFace Transformers 등 -# +# # # 예시 결과 # return { # "themes": ["학습 경험", "교육 콘텐츠 품질", "상호작용성"], @@ -50,7 +50,7 @@ # 응답 데이터를 가져옵니다. # """ # # 실제 구현에서는 설문조사 플랫폼 API를 호출하여 데이터 수집 -# +# # # 예시 결과 # return { # "response_count": 42, diff --git a/agents/focus_group_interview/modules/utils.py b/agents/focus_group_interview/modules/utils.py index 2c9540c..d195e54 100644 --- a/agents/focus_group_interview/modules/utils.py +++ b/agents/focus_group_interview/modules/utils.py @@ -28,81 +28,81 @@ # def extract_themes_from_responses(responses: List[str]) -> List[str]: # """ # 인터뷰 응답에서 주요 테마를 추출합니다. -# -# 이 함수는 간단한 키워드 빈도 분석을 사용하여 응답에서 +# +# 이 함수는 간단한 키워드 빈도 분석을 사용하여 응답에서 # 반복적으로 언급되는 주요 테마를 식별합니다. -# +# # Args: # responses: 인터뷰 응답 목록 -# +# # Returns: # 추출된 주요 테마 목록 # """ # # 실제 구현에서는 더 정교한 NLP 기법을 사용할 수 있음 # # 예시 구현 # all_text = " ".join(responses).lower() -# +# # # 불용어 제거 및 단어 빈도 계산 로직 # # ... -# +# # # 예시 결과 # return ["학습 경험", "교육 콘텐츠 품질", "상호작용성"] # def format_interview_report( -# themes: List[str], -# insights: List[str], +# themes: List[str], +# insights: List[str], # recommendations: List[str] # ) -> str: # """ # 포커스 그룹 인터뷰 결과를 보고서 형식으로 포맷팅합니다. -# +# # Args: # themes: 식별된 주요 테마 목록 # insights: 도출된 통찰 목록 # recommendations: 권장사항 목록 -# +# # Returns: # 포맷팅된 보고서 문자열 # """ # report = "# 포커스 그룹 인터뷰 결과 보고서\n\n" -# +# # report += "## 주요 테마\n" # for i, theme in enumerate(themes, 1): # report += f"{i}. {theme}\n" -# +# # report += "\n## 주요 통찰\n" # for i, insight in enumerate(insights, 1): # report += f"{i}. {insight}\n" -# +# # report += "\n## 권장사항\n" # for i, recommendation in enumerate(recommendations, 1): # report += f"{i}. {recommendation}\n" -# +# # return report # def parse_structured_response(response: str) -> Dict[str, Any]: # """ # LLM의 구조화된 응답을 파싱합니다. -# +# # 이 함수는 LLM이 생성한 텍스트에서 JSON 형식의 데이터를 추출합니다. -# +# # Args: # response: LLM의 응답 텍스트 -# +# # Returns: # 파싱된 구조화 데이터 # """ # # JSON 블록 찾기 # json_match = re.search(r"```json\s*([\s\S]*?)\s*```", response) -# +# # if json_match: # try: # return json.loads(json_match.group(1)) # except json.JSONDecodeError: # # JSON 파싱 실패 시 빈 딕셔너리 반환 # return {} -# +# # # JSON 블록을 찾지 못한 경우 빈 딕셔너리 반환 # return {} diff --git a/agents/focus_group_interview/workflow.py b/agents/focus_group_interview/workflow.py index a0a512d..212da32 100644 --- a/agents/focus_group_interview/workflow.py +++ b/agents/focus_group_interview/workflow.py @@ -28,11 +28,11 @@ def build(self): CompiledStateGraph: 컴파일된 상태 그래프 객체 """ builder = StateGraph(self.state) - + # 노드 추가 예시 # builder.add_node("generate_questions", QuestionGenerationNode()) # builder.add_node("analyze_responses", ResponseAnalysisNode()) - + # 에지 추가 예시 - 아래 코드는 참고용이며 실제 구현 시 주석을 해제하고 사용할 수 있습니다 # 1. 단순 에지: 시작 노드에서 need_more_questions 함수로 연결 # builder.add_edge("__start__", need_more_questions) @@ -57,4 +57,4 @@ def build(self): # 포커스 그룹 인터뷰 Workflow 인스턴스 생성 -focus_group_interview_workflow = FocusGroupInterviewWorkflow(FocusGroupInterviewState) \ No newline at end of file +focus_group_interview_workflow = FocusGroupInterviewWorkflow(FocusGroupInterviewState) diff --git a/agents/main_state.py b/agents/main_state.py index 5c6bd2e..4dd0078 100644 --- a/agents/main_state.py +++ b/agents/main_state.py @@ -1,11 +1,10 @@ - from __future__ import annotations +from dataclasses import dataclass from typing import Annotated, TypedDict from langgraph.graph.message import add_messages -from dataclasses import dataclass @dataclass class MainState(TypedDict): diff --git a/agents/marketing/modules/nodes.py b/agents/marketing/modules/nodes.py index d966f80..a719e16 100644 --- a/agents/marketing/modules/nodes.py +++ b/agents/marketing/modules/nodes.py @@ -15,7 +15,7 @@ # class CampaignGenerationNode(BaseNode): # """ # 교육 제품/서비스에 적합한 마케팅 캠페인을 생성하는 노드 -# +# # 이 노드는 LangChain의 캠페인 생성 체인을 활용하여 교육 제품이나 서비스에 적합한 마케팅 전략을 생성합니다. # 대상 청중, 제품 정보, 캠페인 목표 등을 고려하여 전략을 수립하고 Workflow의 다음 단계로 전달합니다. # """ @@ -28,10 +28,10 @@ # def execute(self, state) -> dict: # """ # 주어진 상태(state)에서 필요한 정보를 추출하여 캠페인 전략을 생성하고 결과를 반환합니다. -# +# # Args: # state (dict): Workflow의 현재 상태. target_audience, product_name, product_description 등의 정보를 포함함. -# +# # Returns: # dict: 생성된 캠페인 전략을 포함한 상태 업데이트 # """ @@ -53,7 +53,7 @@ # class ContentCreationNode(BaseNode): # """ # 마케팅 캠페인에 필요한 콘텐츠를 생성하는 노드 -# +# # 이 노드는 LangChain의 콘텐츠 생성 체인을 활용하여 마케팅 캠페인에 필요한 다양한 콘텐츠를 생성합니다. # 이전 단계에서 생성된 캠페인 전략을 기반으로 각 마케팅 채널에 적합한 콘텐츠를 생성하여 Workflow의 다음 단계로 전달합니다. # """ @@ -66,10 +66,10 @@ # def execute(self, state) -> dict: # """ # 주어진 상태(state)에서 필요한 정보를 추출하여 마케팅 콘텐츠를 생성하고 결과를 반환합니다. -# +# # Args: # state (dict): Workflow의 현재 상태. target_audience, product_name, marketing_channels, messages 등의 정보를 포함함. -# +# # Returns: # dict: 생성된 마케팅 콘텐츠를 포함한 상태 업데이트 # """ diff --git a/agents/marketing/modules/prompts.py b/agents/marketing/modules/prompts.py index 32b079a..5636830 100644 --- a/agents/marketing/modules/prompts.py +++ b/agents/marketing/modules/prompts.py @@ -21,27 +21,27 @@ # template = """ # 당신은 교육 분야의 마케팅 전략 전문가입니다. # 아래 정보를 바탕으로 효과적인 교육 마케팅 캠페인을 개발해주세요. -# +# # # 대상 청중 # {target_audience} -# +# # # 제품/서비스 정보 # 이름: {product_name} # 설명: {product_description} -# +# # # 마케팅 채널 # {marketing_channels} -# +# # # 캠페인 목표 # {campaign_goals} -# +# # # 지침 # - 교육적 가치와 학습 효과를 강조하는 캠페인을 개발하세요. # - 대상 청중의 요구와 관심사에 맞춘 전략을 구성하세요. # - 지정된 마케팅 채널에 적합한 접근 방식을 제안하세요. # - 캠페인 목표를 달성하기 위한 구체적인 전략을 포함하세요. # - 교육 분야의 최신 트렌드를 고려하세요. -# +# # 다음 JSON 형식으로 캠페인 정보를 반환해주세요: # ```json # { @@ -69,35 +69,35 @@ # template = """ # 당신은 교육 분야의 마케팅 콘텐츠 전문가입니다. # 아래 정보를 바탕으로 효과적인 마케팅 콘텐츠를 생성해주세요. -# +# # # 대상 청중 # {target_audience} -# +# # # 제품/서비스 정보 # 이름: {product_name} # 설명: {product_description} -# +# # # 마케팅 채널 # {marketing_channels} -# +# # # 캠페인 전략 # {messages} -# +# # # 지침 # - 각 마케팅 채널에 적합한 형식과 톤으로 콘텐츠를 작성하세요. # - 교육적 가치와 학습 효과를 강조하는 메시지를 포함하세요. # - 대상 청중의 요구와 관심사에 맞춘 콘텐츠를 개발하세요. # - 행동 유도(Call to Action)를 명확하게 포함하세요. # - 교육 분야의 전문성을 보여주는 언어와 표현을 사용하세요. -# +# # 다음 구조로 각 마케팅 채널별 콘텐츠를 작성해주세요: -# +# # ## [채널 이름] 콘텐츠 # (해당 채널에 적합한 콘텐츠) -# +# # ## [채널 이름] 콘텐츠 # (해당 채널에 적합한 콘텐츠) -# +# # ... # """ # return PromptTemplate.from_template(template) diff --git a/agents/marketing/modules/state.py b/agents/marketing/modules/state.py index da09aa4..307afd3 100644 --- a/agents/marketing/modules/state.py +++ b/agents/marketing/modules/state.py @@ -1,11 +1,10 @@ from __future__ import annotations -from typing import Annotated, TypedDict, List +from dataclasses import dataclass +from typing import Annotated, List, TypedDict +from langchain_core.messages import AIMessage, HumanMessage from langgraph.graph.message import add_messages -from langchain_core.messages import HumanMessage, AIMessage - -from dataclasses import dataclass @dataclass @@ -15,17 +14,17 @@ class MarketingState(TypedDict): 교육 콘텐츠 마케팅을 위한 Workflow에서 사용되는 상태 정보를 정의합니다. LangGraph의 상태 관리를 위한 클래스로, Workflow 내에서 처리되는 데이터의 형태와 구조를 지정합니다. - + 아래는 예시 상태 변수들입니다. 실제 구현 시 필요에 따라 수정해서 사용해주세요! """ target_audience: str # 대상 청중 (예: "고등학생", "대학생", "직장인") product_name: str # 교육 제품/서비스 이름 product_description: str # 교육 제품/서비스 설명 - marketing_channels: List[str] # 마케팅 채널 목록 (예: "소셜 미디어", "이메일", "블로그") + marketing_channels: List[ + str + ] # 마케팅 채널 목록 (예: "소셜 미디어", "이메일", "블로그") campaign_goals: List[str] # 캠페인 목표 목록 - messages: Annotated[ - List[HumanMessage | AIMessage], add_messages - ] # 메시지 목록 + messages: Annotated[List[HumanMessage | AIMessage], add_messages] # 메시지 목록 # Annotated는 Python 타입 어노테이션으로, add_messages는 LangGraph에서 사용하는 특별한 함수입니다. # add_messages는 메시지 목록에 새로운 메시지를 추가할 때 이전 메시지를 유지하면서 추가하는 기능을 자동으로 처리합니다. diff --git a/agents/marketing/modules/tools.py b/agents/marketing/modules/tools.py index b31194d..c98e870 100644 --- a/agents/marketing/modules/tools.py +++ b/agents/marketing/modules/tools.py @@ -26,11 +26,11 @@ # """ # 교육 시장 트렌드를 분석합니다. # -# 이 함수는 지정된 키워드를 사용하여 교육 시장의 최신 트렌드, +# 이 함수는 지정된 키워드를 사용하여 교육 시장의 최신 트렌드, # 인기 주제, 경쟁사 활동 등을 분석합니다. # """ # # 실제 구현에서는 시장 조사 API 또는 웹 스크래핑을 사용하여 데이터 수집 -# +# # # 예시 결과 # return { # "trending_topics": ["AI 기반 학습", "맞춤형 교육", "마이크로 러닝"], @@ -51,11 +51,11 @@ # """ # 소셜 미디어 플랫폼에 맞는 마케팅 콘텐츠를 생성합니다. # -# 이 함수는 지정된 플랫폼, 주제, 대상 청중에 맞는 +# 이 함수는 지정된 플랫폼, 주제, 대상 청중에 맞는 # 소셜 미디어 콘텐츠를 생성합니다. # """ # # 실제 구현에서는 LLM을 사용하여 콘텐츠 생성 -# +# # # 예시 결과 # return { # "platform": platform, @@ -71,11 +71,11 @@ # """ # 마케팅 캠페인 성과를 분석합니다. # -# 이 함수는 지정된 캠페인 ID를 사용하여 마케팅 캠페인의 +# 이 함수는 지정된 캠페인 ID를 사용하여 마케팅 캠페인의 # 성과 지표를 수집하고 분석합니다. # """ # # 실제 구현에서는 마케팅 분석 API를 호출하여 데이터 수집 -# +# # # 예시 결과 # return { # "impressions": 15000, diff --git a/agents/marketing/modules/utils.py b/agents/marketing/modules/utils.py index d5677a6..f3ce638 100644 --- a/agents/marketing/modules/utils.py +++ b/agents/marketing/modules/utils.py @@ -27,18 +27,18 @@ # def format_marketing_content( -# content: str, -# platform: str, +# content: str, +# platform: str, # character_limit: int = None # ) -> str: # """ # 마케팅 콘텐츠를 특정 플랫폼에 맞게 포맷팅합니다. -# +# # Args: # content: 원본 마케팅 콘텐츠 # platform: 대상 플랫폼 (예: "twitter", "instagram", "facebook", "linkedin") # character_limit: 문자 수 제한 (기본값: None) -# +# # Returns: # 포맷팅된 콘텐츠 # """ @@ -50,13 +50,13 @@ # "linkedin": 3000, # "email": 10000 # } -# +# # # 문자 제한 설정 # limit = character_limit or platform_limits.get(platform.lower(), None) -# +# # # 콘텐츠 포맷팅 # formatted_content = content -# +# # # 플랫폼별 특수 포맷팅 # if platform.lower() == "twitter": # # 해시태그 추출 및 최적화 @@ -68,17 +68,17 @@ # clean_content = clean_content[:limit - len(" ".join(hashtags)) - 4] + "..." # # 해시태그 추가 # formatted_content = clean_content + "\n\n" + " ".join(hashtags) -# +# # elif platform.lower() == "instagram": # # 해시태그 최적화 및 줄바꿈 추가 # hashtags = re.findall(r'#\w+', content) # clean_content = re.sub(r'#\w+', '', content).strip() # formatted_content = clean_content + "\n\n" + "\n".join(hashtags) -# +# # # 문자 제한 적용 # if limit and len(formatted_content) > limit: # formatted_content = formatted_content[:limit - 3] + "..." -# +# # return formatted_content @@ -87,10 +87,10 @@ # ) -> Dict[str, Any]: # """ # 마케팅 콘텐츠 성과를 분석합니다. -# +# # Args: # content_metrics: 콘텐츠 성과 지표 목록 -# +# # Returns: # 분석 결과 # """ @@ -98,16 +98,16 @@ # total_impressions = sum(item.get("impressions", 0) for item in content_metrics) # total_engagements = sum(item.get("engagements", 0) for item in content_metrics) # total_clicks = sum(item.get("clicks", 0) for item in content_metrics) -# +# # # 평균 참여율 계산 # avg_engagement_rate = (total_engagements / total_impressions) if total_impressions > 0 else 0 -# +# # # 클릭률(CTR) 계산 # ctr = (total_clicks / total_impressions) if total_impressions > 0 else 0 -# +# # # 최고 성과 콘텐츠 찾기 # best_performing = max(content_metrics, key=lambda x: x.get("engagements", 0), default={}) -# +# # return { # "total_impressions": total_impressions, # "total_engagements": total_engagements, @@ -125,35 +125,35 @@ # ) -> str: # """ # 마케팅 캠페인 보고서를 생성합니다. -# +# # Args: # campaign_data: 캠페인 데이터 # content_performance: 콘텐츠 성과 데이터 -# +# # Returns: # 포맷팅된 보고서 문자열 # """ # report = f"# {campaign_data.get('campaign_name', '마케팅 캠페인')} 보고서\n\n" # report += f"기간: {campaign_data.get('start_date', '')} ~ {campaign_data.get('end_date', '')}\n\n" -# +# # report += "## 캠페인 개요\n" # report += f"{campaign_data.get('description', '')}\n\n" -# +# # report += "## 주요 성과\n" # report += f"- 총 노출 수: {content_performance.get('total_impressions', 0):,}\n" # report += f"- 총 참여 수: {content_performance.get('total_engagements', 0):,}\n" # report += f"- 총 클릭 수: {content_performance.get('total_clicks', 0):,}\n" # report += f"- 평균 참여율: {content_performance.get('average_engagement_rate', 0):.2%}\n" # report += f"- 클릭률(CTR): {content_performance.get('ctr', 0):.2%}\n\n" -# +# # report += "## 채널별 성과\n" # for channel, metrics in campaign_data.get('channel_performance', {}).items(): # report += f"### {channel}\n" # report += f"- 노출 수: {metrics.get('impressions', 0):,}\n" # report += f"- 참여 수: {metrics.get('engagements', 0):,}\n" # report += f"- 전환 수: {metrics.get('conversions', 0):,}\n\n" -# +# # report += "## 결론 및 권장사항\n" # report += f"{campaign_data.get('conclusions', '')}\n\n" -# +# # return report diff --git a/agents/marketing/workflow.py b/agents/marketing/workflow.py index 1dffce8..03d6533 100644 --- a/agents/marketing/workflow.py +++ b/agents/marketing/workflow.py @@ -28,11 +28,11 @@ def build(self): CompiledStateGraph: 컴파일된 상태 그래프 객체 """ builder = StateGraph(self.state) - + # 노드 추가 예시 # builder.add_node("generate_campaign", CampaignGenerationNode()) # builder.add_node("create_content", ContentCreationNode()) - + # 에지 추가 예시 - 아래 코드는 참고용이며 실제 구현 시 주석을 해제하고 사용할 수 있습니다 # 1. 단순 에지: 시작 노드에서 need_campaign_strategy 함수로 연결 # builder.add_edge("__start__", need_campaign_strategy) @@ -57,4 +57,4 @@ def build(self): # 마케팅 Workflow 인스턴스 생성 -marketing_workflow = MarketingWorkflow(MarketingState) \ No newline at end of file +marketing_workflow = MarketingWorkflow(MarketingState) diff --git a/agents/source_person_interview/modules/nodes.py b/agents/source_person_interview/modules/nodes.py index d455c8a..551235f 100644 --- a/agents/source_person_interview/modules/nodes.py +++ b/agents/source_person_interview/modules/nodes.py @@ -15,7 +15,7 @@ # class QuestionPreparationNode(BaseNode): # """ # Source Person Interview를 위한 질문을 준비하는 노드 -# +# # 이 노드는 LangChain의 질문 준비 체인을 활용하여 Source Person Interview에 적합한 질문을 생성합니다. # 인터뷰 주제, 인터뷰 대상자, 전문 분야에 맞게 질문을 생성하여 Workflow의 다음 단계로 전달합니다. # """ @@ -28,10 +28,10 @@ # def execute(self, state) -> dict: # """ # 주어진 상태(state)에서 필요한 정보를 추출하여 인터뷰 질문을 준비하고 결과를 반환합니다. -# +# # Args: # state (dict): Workflow의 현재 상태. interview_topic, source_person, expertise_area 정보를 포함함. -# +# # Returns: # dict: 준비된 질문들을 포함한 상태 업데이트 # """ @@ -51,7 +51,7 @@ # class InsightExtractionNode(BaseNode): # """ # 인터뷰 응답에서 통찰을 추출하는 노드 -# +# # 이 노드는 LangChain의 통찰 추출 체인을 활용하여 Source Person Interview에서 수집된 응답에서 중요한 통찰을 추출합니다. # 인터뷰 질문과 응답을 분석하여 교육 콘텐츠 제작에 활용할 수 있는 핵심 통찰을 추출하고, 이를 Workflow의 다음 단계로 전달합니다. # """ @@ -64,10 +64,10 @@ # def execute(self, state) -> dict: # """ # 주어진 상태(state)에서 인터뷰 응답과 관련 정보를 추출하여 통찰을 추출하고 결과를 반환합니다. -# +# # Args: # state (dict): Workflow의 현재 상태. responses, questions, interview_topic, expertise_area 정보를 포함함. -# +# # Returns: # dict: 추출된 통찰을 포함한 상태 업데이트 # """ diff --git a/agents/source_person_interview/modules/prompts.py b/agents/source_person_interview/modules/prompts.py index 3a03a9f..e5dfb83 100644 --- a/agents/source_person_interview/modules/prompts.py +++ b/agents/source_person_interview/modules/prompts.py @@ -21,16 +21,16 @@ # template = """ # 당신은 교육 분야의 전문가 인터뷰 전문가입니다. # 아래 정보를 바탕으로 효과적인 Source Person Interview 질문 목록을 생성해주세요. -# +# # # 인터뷰 주제 # {interview_topic} -# +# # # 인터뷰 대상자 정보 # {source_person} -# +# # # 전문 분야 # {expertise_area} -# +# # # 지침 # - 개방형 질문을 사용하여 대상자가 자유롭게 의견을 표현할 수 있도록 합니다. # - 대상자의 전문성과 경험을 끌어낼 수 있는 질문을 구성합니다. @@ -38,7 +38,7 @@ # - 최소 5개, 최대 10개의 질문을 생성합니다. # - 질문은 논리적 순서로 배열되어야 합니다. # - 질문은 명확하고 이해하기 쉬워야 합니다. -# +# # 다음 JSON 형식으로 질문 목록을 반환해주세요: # ```json # { @@ -66,38 +66,38 @@ # template = """ # 당신은 교육 분야의 인터뷰 분석 전문가입니다. # 아래 인터뷰 내용을 분석하고 주요 통찰을 추출해주세요. -# +# # # 인터뷰 주제 # {interview_topic} -# +# # # 전문 분야 # {expertise_area} -# +# # # 인터뷰 질문 # {questions} -# +# # # 인터뷰 응답 # {responses} -# +# # # 지침 # - 주요 통찰과 핵심 아이디어를 식별하세요. # - 교육적 맥락에서 중요한 개념과 원칙을 추출하세요. # - 실용적인 조언과 적용 가능한 전략을 찾아내세요. # - 데이터에 기반한 객관적인 분석을 제공하세요. # - 교육 콘텐츠 개발에 활용할 수 있는 요소를 강조하세요. -# +# # 다음 구조로 통찰 목록을 작성해주세요: -# +# # ## 주요 통찰 # 1. [첫 번째 통찰] # 2. [두 번째 통찰] # ... -# +# # ## 핵심 개념 # - [개념 1]: [설명] # - [개념 2]: [설명] # ... -# +# # ## 실용적 적용 # - [적용 방안 1] # - [적용 방안 2] diff --git a/agents/source_person_interview/modules/state.py b/agents/source_person_interview/modules/state.py index 269a9d2..1d54f5e 100644 --- a/agents/source_person_interview/modules/state.py +++ b/agents/source_person_interview/modules/state.py @@ -1,14 +1,12 @@ from __future__ import annotations +from dataclasses import dataclass from typing import Annotated, List, TypedDict from langchain_core.messages import AIMessage, HumanMessage from langgraph.graph.message import add_messages -from dataclasses import dataclass - - @dataclass class SourcePersonInterviewState(TypedDict): """ @@ -16,7 +14,7 @@ class SourcePersonInterviewState(TypedDict): 교육 콘텐츠 제작을 위한 Source Person Interview Workflow에서 사용되는 상태 정보를 정의합니다. LangGraph의 상태 관리를 위한 클래스로, Workflow 내에서 처리되는 데이터의 형태와 구조를 지정합니다. - + 아래는 예시 상태 변수들입니다. 실제 구현 시 필요에 따라 수정해서 사용해주세요! """ diff --git a/agents/source_person_interview/modules/tools.py b/agents/source_person_interview/modules/tools.py index 5f12c92..d4a566b 100644 --- a/agents/source_person_interview/modules/tools.py +++ b/agents/source_person_interview/modules/tools.py @@ -26,11 +26,11 @@ # """ # 특정 교육 분야의 전문가를 검색합니다. # -# 이 함수는 지정된 전문 분야에서 인터뷰할 수 있는 +# 이 함수는 지정된 전문 분야에서 인터뷰할 수 있는 # 전문가 목록을 검색합니다. # """ # # 실제 구현에서는 전문가 데이터베이스 API를 호출하여 검색 -# +# # # 예시 결과 # return [ # { @@ -61,7 +61,7 @@ # """ # # 실제 구현에서는 음성 인식 API를 호출하여 변환 # # 예: OpenAI Whisper API, Google Speech-to-Text 등 -# +# # # 예시 결과 # return { # "transcript": "이것은 인터뷰 녹취록의 예시입니다. 실제 구현에서는 음성 인식 API를 통해 변환된 텍스트가 포함됩니다.", @@ -81,7 +81,7 @@ # 핵심 통찰, 주요 개념, 중요 인용구 등을 추출합니다. # """ # # 실제 구현에서는 NLP 기술을 사용하여 분석 -# +# # # 예시 결과 # return { # "key_insights": [ diff --git a/agents/source_person_interview/modules/utils.py b/agents/source_person_interview/modules/utils.py index 613f38f..a8298be 100644 --- a/agents/source_person_interview/modules/utils.py +++ b/agents/source_person_interview/modules/utils.py @@ -29,79 +29,79 @@ # def clean_transcript(transcript: str) -> str: # """ # 인터뷰 녹취록을 정리합니다. -# -# 이 함수는 녹취록에서 불필요한 요소(반복, 말더듬, 채움말 등)를 +# +# 이 함수는 녹취록에서 불필요한 요소(반복, 말더듬, 채움말 등)를 # 제거하고 텍스트를 정리합니다. -# +# # Args: # transcript: 원본 인터뷰 녹취록 -# +# # Returns: # 정리된 녹취록 # """ # # 채움말 제거 (예: 음, 그, 저, 어, 그래서 등) # cleaned = re.sub(r'\b(음|그|저|어|그래서|그러니까|뭐랄까|뭐지)\b', '', transcript) -# +# # # 반복 제거 # cleaned = re.sub(r'(\b\w+\b)(\s+\1\b)+', r'\1', cleaned) -# +# # # 여러 공백을 하나로 통합 # cleaned = re.sub(r'\s+', ' ', cleaned) -# +# # return cleaned.strip() # def segment_by_speaker(transcript: str, speakers: List[str]) -> List[Dict[str, str]]: # """ # 녹취록을 화자별로 분할합니다. -# +# # Args: # transcript: 인터뷰 녹취록 # speakers: 화자 목록 -# +# # Returns: # 화자별로 분할된 녹취록 세그먼트 목록 # """ # segments = [] -# +# # # 실제 구현에서는 더 정교한 화자 분할 알고리즘 사용 # # 예시 구현 (간단한 패턴 매칭) # for speaker in speakers: # pattern = rf'{speaker}:\s*(.*?)(?=\b(?:{"|".join(speakers)}):|$)' # matches = re.findall(pattern, transcript, re.DOTALL) -# +# # for match in matches: # segments.append({ # "speaker": speaker, # "text": match.strip() # }) -# +# # # 세그먼트를 원래 순서대로 정렬 (실제 구현에서는 타임스탬프 사용) # # 여기서는 간단한 예시만 제공 -# +# # return segments # def extract_quotes(transcript: str, min_length: int = 20, max_length: int = 200) -> List[str]: # """ # 인터뷰 녹취록에서 인용할 만한 문장을 추출합니다. -# +# # Args: # transcript: 인터뷰 녹취록 # min_length: 최소 문장 길이 # max_length: 최대 문장 길이 -# +# # Returns: # 추출된 인용구 목록 # """ # # 문장 분할 # sentences = re.split(r'(?<=[.!?])\s+', transcript) -# +# # # 길이 조건에 맞는 문장 필터링 # quotes = [s for s in sentences if min_length <= len(s) <= max_length] -# +# # # 실제 구현에서는 더 정교한 필터링 (중요도, 관련성 등) 적용 -# +# # return quotes @@ -114,35 +114,35 @@ # ) -> str: # """ # 인터뷰 통찰을 보고서 형식으로 포맷팅합니다. -# +# # Args: # insights: 주요 통찰 목록 # key_concepts: 핵심 개념 사전 # quotes: 주요 인용구 목록 # source_person: 인터뷰 대상자 정보 # expertise_area: 전문 분야 -# +# # Returns: # 포맷팅된 보고서 문자열 # """ # report = f"# {source_person} 인터뷰 통찰 보고서\n\n" # report += f"전문 분야: {expertise_area}\n" # report += f"날짜: {datetime.now().strftime('%Y-%m-%d')}\n\n" -# +# # report += "## 주요 통찰\n" # for i, insight in enumerate(insights, 1): # report += f"{i}. {insight}\n" -# +# # report += "\n## 핵심 개념\n" # for concept, description in key_concepts.items(): # report += f"**{concept}**: {description}\n\n" -# +# # report += "## 주요 인용구\n" # for quote in quotes: # report += f"> {quote}\n\n" -# +# # report += "## 교육적 적용\n" # report += "이 인터뷰에서 얻은 통찰은 다음과 같은 교육적 맥락에서 적용할 수 있습니다:\n\n" # # 실제 구현에서는 LLM을 사용하여 교육적 적용 사항 생성 -# +# # return report diff --git a/agents/source_person_interview/workflow.py b/agents/source_person_interview/workflow.py index 7688ac6..f3a08c2 100644 --- a/agents/source_person_interview/workflow.py +++ b/agents/source_person_interview/workflow.py @@ -1,6 +1,7 @@ +from langgraph.graph import StateGraph + from agents.base_workflow import BaseWorkflow from agents.source_person_interview.modules.state import SourcePersonInterviewState -from langgraph.graph import StateGraph class SourcePersonInterviewWorkflow(BaseWorkflow): @@ -27,11 +28,11 @@ def build(self): CompiledStateGraph: 컴파일된 상태 그래프 객체 """ builder = StateGraph(self.state) - + # 노드 추가 예시 # builder.add_node("prepare_questions", QuestionPreparationNode()) # builder.add_node("extract_insights", InsightExtractionNode()) - + # 에지 추가 예시 - 아래 코드는 참고용이며 실제 구현 시 주석을 해제하고 사용할 수 있습니다 # 1. 단순 에지: 시작 노드에서 need_questions 함수로 연결 # builder.add_edge("__start__", need_questions) @@ -56,4 +57,6 @@ def build(self): # Source Person Interview Workflow 인스턴스 생성 -source_person_interview_workflow = SourcePersonInterviewWorkflow(SourcePersonInterviewState) \ No newline at end of file +source_person_interview_workflow = SourcePersonInterviewWorkflow( + SourcePersonInterviewState +) From aefb436adcd7a1545f5971192ead8e3783250caf Mon Sep 17 00:00:00 2001 From: Hon2yB22 Date: Sat, 19 Apr 2025 17:50:29 +0900 Subject: [PATCH 2/3] fix: file code fix --- agents/focus_group_interview/modules/nodes.py | 2 +- agents/focus_group_interview/modules/prompts.py | 2 +- agents/marketing/modules/chains.py | 2 -- agents/marketing/modules/nodes.py | 2 +- agents/source_person_interview/modules/chains.py | 2 -- agents/source_person_interview/modules/nodes.py | 2 +- agents/source_person_interview/modules/prompts.py | 2 +- 7 files changed, 5 insertions(+), 9 deletions(-) diff --git a/agents/focus_group_interview/modules/nodes.py b/agents/focus_group_interview/modules/nodes.py index 4b29045..9a7f27b 100644 --- a/agents/focus_group_interview/modules/nodes.py +++ b/agents/focus_group_interview/modules/nodes.py @@ -6,7 +6,7 @@ 각 노드는 execute 메서드를 구현하여 상태(state)를 입력받아 처리하고, 처리 결과를 새로운 상태 업데이트로 반환합니다. """ -from agents.base_node import BaseNode +# from agents.base_node import BaseNode # from agents.focus_group_interview.modules.chains import set_question_generation_chain, set_response_analysis_chain diff --git a/agents/focus_group_interview/modules/prompts.py b/agents/focus_group_interview/modules/prompts.py index 6aaa1aa..a74e0fe 100644 --- a/agents/focus_group_interview/modules/prompts.py +++ b/agents/focus_group_interview/modules/prompts.py @@ -4,7 +4,7 @@ 각 함수는 특정 작업에 맞는 프롬프트 템플릿을 생성합니다. """ -from langchain_core.prompts import PromptTemplate +# from langchain_core.prompts import PromptTemplate # def get_question_generation_prompt() -> PromptTemplate: # """ diff --git a/agents/marketing/modules/chains.py b/agents/marketing/modules/chains.py index 5ac4687..7c32d31 100644 --- a/agents/marketing/modules/chains.py +++ b/agents/marketing/modules/chains.py @@ -4,8 +4,6 @@ 기본적으로 modules.prompt 템플릿과 modules.models 모듈을 사용하여 LangChain 체인을 생성합니다. """ -from typing import List - # from langchain.schema.runnable import RunnablePassthrough, RunnableSerializable # from langchain_core.output_parsers import JsonOutputParser, StrOutputParser # from langchain_core.pydantic_v1 import BaseModel, Field diff --git a/agents/marketing/modules/nodes.py b/agents/marketing/modules/nodes.py index a719e16..2987c17 100644 --- a/agents/marketing/modules/nodes.py +++ b/agents/marketing/modules/nodes.py @@ -6,7 +6,7 @@ 각 노드는 execute 메서드를 구현하여 상태(state)를 입력받아 처리하고, 처리 결과를 새로운 상태 업데이트로 반환합니다. """ -from agents.base_node import BaseNode +# from agents.base_node import BaseNode # from agents.marketing.modules.chains import set_campaign_generation_chain, set_content_creation_chain diff --git a/agents/source_person_interview/modules/chains.py b/agents/source_person_interview/modules/chains.py index dd28152..f94ea9c 100644 --- a/agents/source_person_interview/modules/chains.py +++ b/agents/source_person_interview/modules/chains.py @@ -4,8 +4,6 @@ 기본적으로 modules.prompt 템플릿과 modules.models 모듈을 사용하여 LangChain 체인을 생성합니다. """ -from typing import List - # from langchain.schema.runnable import RunnablePassthrough, RunnableSerializable # from langchain_core.output_parsers import JsonOutputParser, StrOutputParser # from langchain_core.pydantic_v1 import BaseModel, Field diff --git a/agents/source_person_interview/modules/nodes.py b/agents/source_person_interview/modules/nodes.py index 551235f..6691d94 100644 --- a/agents/source_person_interview/modules/nodes.py +++ b/agents/source_person_interview/modules/nodes.py @@ -6,7 +6,7 @@ 각 노드는 execute 메서드를 구현하여 상태(state)를 입력받아 처리하고, 처리 결과를 새로운 상태 업데이트로 반환합니다. """ -from agents.base_node import BaseNode +# from agents.base_node import BaseNode # from agents.source_person_interview.modules.chains import set_question_preparation_chain, set_insight_extraction_chain diff --git a/agents/source_person_interview/modules/prompts.py b/agents/source_person_interview/modules/prompts.py index e5dfb83..a2a2d24 100644 --- a/agents/source_person_interview/modules/prompts.py +++ b/agents/source_person_interview/modules/prompts.py @@ -4,7 +4,7 @@ 각 함수는 특정 작업에 맞는 프롬프트 템플릿을 생성합니다. """ -from langchain_core.prompts import PromptTemplate +# from langchain_core.prompts import PromptTemplate # 예시 프롬프트 함수들입니다. 참고용으로 남겨둡니다. From b408d38bf7122c657c42e6598e0e33474f3f725f Mon Sep 17 00:00:00 2001 From: Hon2yB22 Date: Sat, 19 Apr 2025 17:50:54 +0900 Subject: [PATCH 3/3] =?UTF-8?q?fix:=20=EC=9D=B4=EC=A0=84=20fix=20=EC=97=B0?= =?UTF-8?q?=EA=B3=84=EA=B3=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- agents/marketing/modules/prompts.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/agents/marketing/modules/prompts.py b/agents/marketing/modules/prompts.py index 5636830..6d2b119 100644 --- a/agents/marketing/modules/prompts.py +++ b/agents/marketing/modules/prompts.py @@ -4,7 +4,7 @@ 각 함수는 특정 작업에 맞는 프롬프트 템플릿을 생성합니다. """ -from langchain_core.prompts import PromptTemplate +# from langchain_core.prompts import PromptTemplate # 예시 함수들입니다. 참고용으로 남겨둡니다.