Skip to content

Commit 0a5d669

Browse files
committed
move notifier modules to internals
1 parent 29a5fb4 commit 0a5d669

File tree

3 files changed

+83
-42
lines changed

3 files changed

+83
-42
lines changed

scripts/agent_operator.py

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,13 @@
99
from template_langgraph.agents.image_classifier_agent.models import Results
1010
from template_langgraph.agents.issue_formatter_agent.agent import graph as issue_formatter_agent_graph
1111
from template_langgraph.agents.kabuto_helpdesk_agent.agent import graph as kabuto_helpdesk_agent_graph
12-
from template_langgraph.agents.news_summarizer_agent.agent import MockNotifier, NewsSummarizerAgent
13-
from template_langgraph.agents.news_summarizer_agent.agent import (
14-
graph as news_summarizer_agent_graph,
15-
)
12+
from template_langgraph.agents.news_summarizer_agent.agent import graph as news_summarizer_agent_graph
1613
from template_langgraph.agents.news_summarizer_agent.models import (
1714
AgentInputState,
1815
AgentState,
1916
Article,
2017
)
2118
from template_langgraph.agents.task_decomposer_agent.agent import graph as task_decomposer_agent_graph
22-
from template_langgraph.internals.scrapers import get_scraper
23-
from template_langgraph.internals.summarizers import (
24-
get_summarizer,
25-
)
2619
from template_langgraph.loggers import get_logger
2720

2821
# Initialize the Typer application
@@ -154,11 +147,7 @@ def news_summarizer_agent(
154147
if verbose:
155148
logger.setLevel(logging.DEBUG)
156149

157-
graph = NewsSummarizerAgent(
158-
notifier=MockNotifier(),
159-
scraper=get_scraper(),
160-
summarizer=get_summarizer(),
161-
).create_graph()
150+
graph = news_summarizer_agent_graph
162151
for event in graph.stream(
163152
input=AgentState(
164153
input=AgentInputState(

template_langgraph/agents/news_summarizer_agent/agent.py

Lines changed: 12 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -8,40 +8,27 @@
88
StructuredArticle,
99
SummarizeWebContentState,
1010
)
11-
from template_langgraph.internals.scrapers import (
12-
BaseScraper,
13-
HttpxScraper,
14-
MockScraper,
15-
)
16-
from template_langgraph.internals.summarizers import (
17-
BaseSummarizer,
18-
LlmSummarizer,
19-
MockSummarizer,
20-
)
11+
from template_langgraph.internals.notifiers import get_notifier
12+
from template_langgraph.internals.scrapers import get_scraper
13+
from template_langgraph.internals.summarizers import get_summarizer
2114
from template_langgraph.llms.azure_openais import AzureOpenAiWrapper
2215
from template_langgraph.loggers import get_logger
2316

2417
logger = get_logger(__name__)
2518

2619

27-
class MockNotifier:
28-
def notify(self, id: str, body: dict) -> None:
29-
"""Simulate sending a notification to the user."""
30-
logger.info(f"Notification sent for request {id}: {body}")
31-
32-
3320
class NewsSummarizerAgent:
3421
def __init__(
3522
self,
3623
llm=AzureOpenAiWrapper().chat_model,
37-
notifier=MockNotifier(),
38-
scraper: BaseScraper = MockScraper(),
39-
summarizer: BaseSummarizer = MockSummarizer(),
24+
notifier=get_notifier(),
25+
scraper=get_scraper(),
26+
summarizer=get_summarizer(),
4027
):
4128
self.llm = llm
4229
self.notifier = notifier
43-
self.scraper: BaseScraper = scraper
44-
self.summarizer: BaseSummarizer = summarizer
30+
self.scraper = scraper
31+
self.summarizer = summarizer
4532

4633
def create_graph(self):
4734
"""Create the main graph for the agent."""
@@ -133,17 +120,13 @@ def notify(self, state: AgentState) -> AgentState:
133120
for i, article in enumerate(state.articles):
134121
summary[i] = article.model_dump()
135122
self.notifier.notify(
136-
id=state.input.id,
137-
body=summary,
123+
text=summary.__str__(),
138124
)
139125
return state
140126

141127

142-
# For testing
143-
# graph = NewsSummarizerAgent().create_graph()
144-
145128
graph = NewsSummarizerAgent(
146-
notifier=MockNotifier(),
147-
scraper=HttpxScraper(),
148-
summarizer=LlmSummarizer(),
129+
notifier=get_notifier(),
130+
scraper=get_scraper(),
131+
summarizer=get_summarizer(),
149132
).create_graph()
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
"""Scraper interfaces and implementations for NewsSummarizerAgent.
2+
3+
This module defines an abstract base scraper so different scraping strategies
4+
(mock, httpx-based, future headless browser, etc.) can be plugged into the agent
5+
without changing orchestration logic.
6+
"""
7+
8+
from __future__ import annotations
9+
10+
from abc import ABC, abstractmethod
11+
from enum import Enum
12+
from functools import lru_cache
13+
14+
from pydantic_settings import BaseSettings, SettingsConfigDict
15+
16+
from template_langgraph.loggers import get_logger
17+
18+
logger = get_logger(__name__)
19+
20+
21+
class NotifierType(str, Enum):
22+
MOCK = "mock"
23+
24+
25+
class Settings(BaseSettings):
26+
notifier_type: NotifierType = NotifierType.MOCK
27+
28+
model_config = SettingsConfigDict(
29+
env_file=".env",
30+
env_ignore_empty=True,
31+
extra="ignore",
32+
)
33+
34+
35+
@lru_cache
36+
def get_notifier_settings() -> Settings:
37+
"""Get notifier settings."""
38+
return Settings()
39+
40+
41+
class BaseNotifier(ABC):
42+
"""Abstract base notifier."""
43+
44+
@abstractmethod
45+
def notify(self, text: str):
46+
"""Send a notification with the given text.
47+
48+
Args:
49+
text: The text to include in the notification.
50+
51+
"""
52+
raise NotImplementedError
53+
54+
55+
class MockNotifier(BaseNotifier):
56+
"""Deterministic notifier for tests / offline development."""
57+
58+
def notify(self, text: str):
59+
logger.info(f"Mock notify with text: {text}")
60+
61+
62+
def get_notifier(settings: Settings = None) -> BaseNotifier:
63+
if settings is None:
64+
settings = get_notifier_settings()
65+
66+
if settings.notifier_type == NotifierType.MOCK:
67+
return MockNotifier()
68+
else:
69+
raise ValueError(f"Unknown notifier type: {settings.notifier_type}")

0 commit comments

Comments
 (0)