Skip to content

Commit 7eccc32

Browse files
authored
Merge pull request #18 from ks6088ts-labs/feature/issue-17_issue-reporting-agent
add issue formatter agent
2 parents aa69615 + 320d3ca commit 7eccc32

File tree

6 files changed

+134
-1
lines changed

6 files changed

+134
-1
lines changed

docs/index.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@ uv run python -m template_langgraph.tasks.draw_basic_workflow_agent_mermaid_png
3030
uv run python -m template_langgraph.tasks.run_basic_workflow_agent
3131
# KABUTOの起動時に、画面全体が紫色に点滅し、システムがフリーズします。KABUTO のマニュアルから、関連する情報を取得したり過去のシステムのトラブルシュート事例が蓄積されたデータベースから、関連する情報を取得して質問に答えてください
3232
# 天狗のいたずら という現象について KABUTO のマニュアルから、関連する情報を取得したり過去のシステムのトラブルシュート事例が蓄積されたデータベースから、関連する情報を取得して質問に答えてください
33+
34+
# IssueFormatterAgent
35+
uv run python -m template_langgraph.tasks.run_issue_formatter_agent
36+
# KABUTOにログインできない!パスワードは合ってるはずなのに…若手社員である山田太郎は、Windows 11 を立ち上げ、日課のように自社の業務システムKABUTOのログイン画面を開きます。しかし、そこには、意味をなさない「虚無」という文字だけがただひっそりと表示されていたのです。これは質問でもあり不具合の報告でもあります。岡本太郎さんに本件調査依頼します。
37+
3338
```
3439

3540
## References

langgraph.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
],
55
"graphs": {
66
"basic_workflow_agent": "template_langgraph.agents.basic_workflow_agent.agent:graph",
7-
"kabuto_helpdesk_agent": "template_langgraph.agents.kabuto_helpdesk_agent:graph"
7+
"kabuto_helpdesk_agent": "template_langgraph.agents.kabuto_helpdesk_agent:graph",
8+
"issue_formatter_agent": "template_langgraph.agents.issue_formatter_agent.agent:graph"
89
},
910
"env": ".env"
1011
}

template_langgraph/agents/issue_formatter_agent/__init__.py

Whitespace-only changes.
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
from langgraph.graph import END, StateGraph
2+
3+
from template_langgraph.agents.issue_formatter_agent.models import AgentState, Issue
4+
from template_langgraph.llms.azure_openais import AzureOpenAiWrapper
5+
from template_langgraph.loggers import get_logger
6+
7+
logger = get_logger(__name__)
8+
9+
10+
class IssueFormatterAgent:
11+
def __init__(self):
12+
self.llm = AzureOpenAiWrapper().chat_model
13+
14+
def create_graph(self):
15+
"""Create the main graph for the agent."""
16+
# Create the workflow state graph
17+
workflow = StateGraph(AgentState)
18+
19+
# Create nodes
20+
workflow.add_node("analyze", self.analyze)
21+
22+
# Create edges
23+
workflow.set_entry_point("analyze")
24+
workflow.add_edge("analyze", END)
25+
26+
# Compile the graph
27+
return workflow.compile()
28+
29+
def analyze(self, state: AgentState) -> AgentState:
30+
"""Analyze the issue and extract relevant information."""
31+
logger.info(f"Analyzing issue with state: {state}")
32+
issue = self.llm.with_structured_output(Issue).invoke(
33+
input=state["messages"],
34+
)
35+
state["issue"] = issue
36+
return state
37+
38+
def draw_mermaid_png(self) -> bytes:
39+
"""Draw the graph in Mermaid format."""
40+
return self.create_graph().get_graph().draw_mermaid_png()
41+
42+
43+
graph = IssueFormatterAgent().create_graph()
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
from collections.abc import Sequence
2+
from enum import Enum
3+
from typing import (
4+
Annotated,
5+
TypedDict,
6+
)
7+
8+
from langchain_core.messages import (
9+
BaseMessage,
10+
)
11+
from langgraph.graph.message import add_messages
12+
from pydantic import BaseModel, Field
13+
14+
15+
class SystemInfo(BaseModel):
16+
os: str | None = Field(None, description="Operating system of the environment")
17+
version: str | None = Field(None, description="Version of the environment")
18+
19+
20+
class IssueLabel(Enum):
21+
"""Enum for issue labels."""
22+
23+
BUG = "bug"
24+
FEATURE_REQUEST = "feature_request"
25+
DOCUMENTATION = "documentation"
26+
ENHANCEMENT = "enhancement"
27+
QUESTION = "question"
28+
29+
30+
class Issue(BaseModel):
31+
title: str = Field(..., description="Issue title")
32+
description: str = Field(..., description="Issue description")
33+
labels: Sequence[IssueLabel] = Field(default_factory=list, description="Labels associated with the issue")
34+
assignee: str | None = Field(None, description="User assigned to the issue")
35+
milestone: str | None = Field(None, description="Milestone associated with the issue")
36+
system_info: SystemInfo | None = Field(None, description="Information about the system")
37+
steps_to_reproduce: Sequence[str] | None = Field(None, description="Steps to reproduce the issue")
38+
current_behavior: str | None = Field(None, description="Current behavior when the issue occurs")
39+
expected_behavior: str | None = Field(None, description="Expected behavior when the issue is resolved")
40+
41+
42+
class AgentInput(BaseModel):
43+
issue: str = Field(..., description="The issue to be formatted")
44+
45+
46+
class AgentOutput(BaseModel):
47+
response: str = Field(..., description="The agent's response after formatting the issue")
48+
49+
50+
class AgentState(TypedDict):
51+
messages: Annotated[Sequence[BaseMessage], add_messages]
52+
issue: Issue
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import logging
2+
3+
from template_langgraph.agents.issue_formatter_agent.agent import AgentState, graph
4+
from template_langgraph.loggers import get_logger
5+
6+
logger = get_logger(__name__)
7+
logger.setLevel(logging.INFO)
8+
9+
10+
def stream_graph_updates(
11+
state: AgentState,
12+
) -> dict:
13+
for event in graph.stream(input=state):
14+
logger.info("-" * 20)
15+
logger.info(f"Event: {event}")
16+
return event
17+
18+
19+
if __name__ == "__main__":
20+
user_input = input("User: ")
21+
state = AgentState(
22+
messages=[
23+
{
24+
"role": "user",
25+
"content": user_input,
26+
}
27+
],
28+
profile=None,
29+
)
30+
last_event = stream_graph_updates(state)
31+
for value in last_event.values():
32+
logger.info(f"Formatted issue: {value['issue']}")

0 commit comments

Comments
 (0)