diff --git a/docs/index.md b/docs/index.md index c021af5..d361604 100644 --- a/docs/index.md +++ b/docs/index.md @@ -30,6 +30,11 @@ uv run python -m template_langgraph.tasks.draw_basic_workflow_agent_mermaid_png uv run python -m template_langgraph.tasks.run_basic_workflow_agent # KABUTOの起動時に、画面全体が紫色に点滅し、システムがフリーズします。KABUTO のマニュアルから、関連する情報を取得したり過去のシステムのトラブルシュート事例が蓄積されたデータベースから、関連する情報を取得して質問に答えてください # 天狗のいたずら という現象について KABUTO のマニュアルから、関連する情報を取得したり過去のシステムのトラブルシュート事例が蓄積されたデータベースから、関連する情報を取得して質問に答えてください + +# IssueFormatterAgent +uv run python -m template_langgraph.tasks.run_issue_formatter_agent +# KABUTOにログインできない!パスワードは合ってるはずなのに…若手社員である山田太郎は、Windows 11 を立ち上げ、日課のように自社の業務システムKABUTOのログイン画面を開きます。しかし、そこには、意味をなさない「虚無」という文字だけがただひっそりと表示されていたのです。これは質問でもあり不具合の報告でもあります。岡本太郎さんに本件調査依頼します。 + ``` ## References diff --git a/langgraph.json b/langgraph.json index 681460f..3721d5c 100644 --- a/langgraph.json +++ b/langgraph.json @@ -4,7 +4,8 @@ ], "graphs": { "basic_workflow_agent": "template_langgraph.agents.basic_workflow_agent.agent:graph", - "kabuto_helpdesk_agent": "template_langgraph.agents.kabuto_helpdesk_agent:graph" + "kabuto_helpdesk_agent": "template_langgraph.agents.kabuto_helpdesk_agent:graph", + "issue_formatter_agent": "template_langgraph.agents.issue_formatter_agent.agent:graph" }, "env": ".env" } diff --git a/template_langgraph/agents/issue_formatter_agent/__init__.py b/template_langgraph/agents/issue_formatter_agent/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/template_langgraph/agents/issue_formatter_agent/agent.py b/template_langgraph/agents/issue_formatter_agent/agent.py new file mode 100644 index 0000000..e5e5cdc --- /dev/null +++ b/template_langgraph/agents/issue_formatter_agent/agent.py @@ -0,0 +1,43 @@ +from langgraph.graph import END, StateGraph + +from template_langgraph.agents.issue_formatter_agent.models import AgentState, Issue +from template_langgraph.llms.azure_openais import AzureOpenAiWrapper +from template_langgraph.loggers import get_logger + +logger = get_logger(__name__) + + +class IssueFormatterAgent: + def __init__(self): + self.llm = AzureOpenAiWrapper().chat_model + + def create_graph(self): + """Create the main graph for the agent.""" + # Create the workflow state graph + workflow = StateGraph(AgentState) + + # Create nodes + workflow.add_node("analyze", self.analyze) + + # Create edges + workflow.set_entry_point("analyze") + workflow.add_edge("analyze", END) + + # Compile the graph + return workflow.compile() + + def analyze(self, state: AgentState) -> AgentState: + """Analyze the issue and extract relevant information.""" + logger.info(f"Analyzing issue with state: {state}") + issue = self.llm.with_structured_output(Issue).invoke( + input=state["messages"], + ) + state["issue"] = issue + return state + + def draw_mermaid_png(self) -> bytes: + """Draw the graph in Mermaid format.""" + return self.create_graph().get_graph().draw_mermaid_png() + + +graph = IssueFormatterAgent().create_graph() diff --git a/template_langgraph/agents/issue_formatter_agent/models.py b/template_langgraph/agents/issue_formatter_agent/models.py new file mode 100644 index 0000000..7b4c248 --- /dev/null +++ b/template_langgraph/agents/issue_formatter_agent/models.py @@ -0,0 +1,52 @@ +from collections.abc import Sequence +from enum import Enum +from typing import ( + Annotated, + TypedDict, +) + +from langchain_core.messages import ( + BaseMessage, +) +from langgraph.graph.message import add_messages +from pydantic import BaseModel, Field + + +class SystemInfo(BaseModel): + os: str | None = Field(None, description="Operating system of the environment") + version: str | None = Field(None, description="Version of the environment") + + +class IssueLabel(Enum): + """Enum for issue labels.""" + + BUG = "bug" + FEATURE_REQUEST = "feature_request" + DOCUMENTATION = "documentation" + ENHANCEMENT = "enhancement" + QUESTION = "question" + + +class Issue(BaseModel): + title: str = Field(..., description="Issue title") + description: str = Field(..., description="Issue description") + labels: Sequence[IssueLabel] = Field(default_factory=list, description="Labels associated with the issue") + assignee: str | None = Field(None, description="User assigned to the issue") + milestone: str | None = Field(None, description="Milestone associated with the issue") + system_info: SystemInfo | None = Field(None, description="Information about the system") + steps_to_reproduce: Sequence[str] | None = Field(None, description="Steps to reproduce the issue") + current_behavior: str | None = Field(None, description="Current behavior when the issue occurs") + expected_behavior: str | None = Field(None, description="Expected behavior when the issue is resolved") + + +class AgentInput(BaseModel): + issue: str = Field(..., description="The issue to be formatted") + + +class AgentOutput(BaseModel): + response: str = Field(..., description="The agent's response after formatting the issue") + + +class AgentState(TypedDict): + messages: Annotated[Sequence[BaseMessage], add_messages] + issue: Issue diff --git a/template_langgraph/tasks/run_issue_formatter_agent.py b/template_langgraph/tasks/run_issue_formatter_agent.py new file mode 100644 index 0000000..82f546e --- /dev/null +++ b/template_langgraph/tasks/run_issue_formatter_agent.py @@ -0,0 +1,32 @@ +import logging + +from template_langgraph.agents.issue_formatter_agent.agent import AgentState, graph +from template_langgraph.loggers import get_logger + +logger = get_logger(__name__) +logger.setLevel(logging.INFO) + + +def stream_graph_updates( + state: AgentState, +) -> dict: + for event in graph.stream(input=state): + logger.info("-" * 20) + logger.info(f"Event: {event}") + return event + + +if __name__ == "__main__": + user_input = input("User: ") + state = AgentState( + messages=[ + { + "role": "user", + "content": user_input, + } + ], + profile=None, + ) + last_event = stream_graph_updates(state) + for value in last_event.values(): + logger.info(f"Formatted issue: {value['issue']}")