Skip to content

Commit 0f6d8bc

Browse files
committed
gen: (GPT-5) #file:agent.py で LlmClassifier, MockClassifier を定義していますが、抽象クラスのインタフェースを作成してリファクタしてください
1 parent 38d5d0e commit 0f6d8bc

File tree

2 files changed

+87
-49
lines changed

2 files changed

+87
-49
lines changed

template_langgraph/agents/image_classifier_agent/agent.py

Lines changed: 7 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,14 @@
55
from langgraph.graph import StateGraph
66
from langgraph.types import Send
77

8+
from template_langgraph.agents.image_classifier_agent.classifiers import (
9+
BaseClassifier,
10+
LlmClassifier,
11+
MockClassifier,
12+
)
813
from template_langgraph.agents.image_classifier_agent.models import (
914
AgentState,
1015
ClassifyImageState,
11-
Result,
1216
Results,
1317
)
1418
from template_langgraph.llms.azure_openais import AzureOpenAiWrapper
@@ -28,62 +32,16 @@ def notify(self, id: str, body: dict) -> None:
2832
logger.info(f"Notification sent for request {id}: {body}")
2933

3034

31-
class MockClassifier:
32-
def predict(
33-
self,
34-
prompt: str,
35-
image: str,
36-
llm=AzureOpenAiWrapper().chat_model,
37-
) -> Result:
38-
"""Simulate image classification."""
39-
return Result(
40-
title="Mocked Image Title",
41-
summary=f"Mocked summary of the prompt: {prompt}",
42-
labels=["mocked_label_1", "mocked_label_2"],
43-
reliability=0.95,
44-
)
45-
46-
47-
class LlmClassifier:
48-
def predict(
49-
self,
50-
prompt: str,
51-
image: str,
52-
llm=AzureOpenAiWrapper().chat_model,
53-
) -> Result:
54-
"""Use the LLM to classify the image."""
55-
logger.info(f"Classifying image with LLM: {prompt}")
56-
return llm.with_structured_output(Result).invoke(
57-
input=[
58-
{
59-
"role": "user",
60-
"content": [
61-
{
62-
"type": "text",
63-
"text": prompt,
64-
},
65-
{
66-
"type": "image",
67-
"source_type": "base64",
68-
"data": image,
69-
"mime_type": "image/png",
70-
},
71-
],
72-
},
73-
]
74-
)
75-
76-
7735
class ImageClassifierAgent:
7836
def __init__(
7937
self,
8038
llm=AzureOpenAiWrapper().chat_model,
8139
notifier=MockNotifier(),
82-
classifier=MockClassifier(),
40+
classifier: BaseClassifier = MockClassifier(),
8341
):
8442
self.llm = llm
8543
self.notifier = notifier
86-
self.classifier = classifier
44+
self.classifier: BaseClassifier = classifier
8745

8846
def create_graph(self):
8947
"""Create the main graph for the agent."""
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
"""Classifier interfaces and implementations for ImageClassifierAgent.
2+
3+
This module defines an abstract base classifier interface so that different
4+
image classification strategies (mock, LLM-backed, future vision models, etc.)
5+
can be plugged into the agent without modifying the agent orchestration code.
6+
"""
7+
8+
from __future__ import annotations
9+
10+
from abc import ABC, abstractmethod
11+
from typing import Any
12+
13+
from langchain_core.language_models.chat_models import BaseChatModel
14+
15+
from template_langgraph.agents.image_classifier_agent.models import Result
16+
from template_langgraph.loggers import get_logger
17+
18+
logger = get_logger(__name__)
19+
20+
21+
class BaseClassifier(ABC):
22+
"""Abstract base class for image classifiers.
23+
24+
Implementations should return a structured ``Result`` object.
25+
The ``llm`` argument is kept generic (Any) to avoid tight coupling
26+
with a specific provider wrapper; callers supply a model instance
27+
that offers the needed interface (e.g. ``with_structured_output``).
28+
"""
29+
30+
@abstractmethod
31+
def predict(self, prompt: str, image: str, llm: BaseChatModel) -> Result: # pragma: no cover - interface
32+
"""Classify an image.
33+
34+
Args:
35+
prompt: Instruction or question guiding the classification.
36+
image: Base64-encoded image string ("data" portion only).
37+
llm: A language / vision model instance used (if needed) by the classifier.
38+
39+
Returns:
40+
Result: Structured classification output.
41+
"""
42+
raise NotImplementedError
43+
44+
45+
class MockClassifier(BaseClassifier):
46+
"""Simple mock classifier used for tests / offline development."""
47+
48+
def predict(self, prompt: str, image: str, llm: Any) -> Result: # noqa: D401
49+
import time
50+
51+
time.sleep(3) # Simulate a long-running process
52+
return Result(
53+
title="Mocked Image Title",
54+
summary=f"Mocked summary of the prompt: {prompt}",
55+
labels=["mocked_label_1", "mocked_label_2"],
56+
reliability=0.95,
57+
)
58+
59+
60+
class LlmClassifier(BaseClassifier):
61+
"""LLM-backed classifier using the provided model's structured output capability."""
62+
63+
def predict(self, prompt: str, image: str, llm: BaseChatModel) -> Result: # noqa: D401
64+
logger.info(f"Classifying image with LLM: {prompt}")
65+
return llm.with_structured_output(Result).invoke(
66+
input=[
67+
{
68+
"role": "user",
69+
"content": [
70+
{"type": "text", "text": prompt},
71+
{
72+
"type": "image",
73+
"source_type": "base64",
74+
"data": image,
75+
"mime_type": "image/png",
76+
},
77+
],
78+
}
79+
]
80+
)

0 commit comments

Comments
 (0)