Skip to content

Commit 2256aff

Browse files
committed
inital logger interface
1 parent e83d039 commit 2256aff

File tree

6 files changed

+704
-7
lines changed

6 files changed

+704
-7
lines changed

src/codegen/agents/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+

src/codegen/agents/code_agent.py

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@
33
from uuid import uuid4
44

55
from langchain.tools import BaseTool
6-
from langchain_core.messages import AIMessage
76
from langsmith import Client
8-
7+
from langchain_core.messages import AIMessage
8+
from codegen.agents.loggers import ExternalLogger
9+
from codegen.agents.tracer import MessageStreamTracer
910
from codegen.extensions.langchain.agent import create_codebase_agent
1011
from codegen.extensions.langchain.utils.get_langsmith_url import find_and_print_langsmith_run_url
1112

@@ -42,7 +43,7 @@ def __init__(self, codebase: "Codebase", model_provider: str = "anthropic", mode
4243
self.project_name = os.environ.get("LANGCHAIN_PROJECT", "RELACE")
4344
print(f"Using LangSmith project: {self.project_name}")
4445

45-
def run(self, prompt: str, thread_id: Optional[str] = None) -> str:
46+
def run(self, prompt: str, thread_id: Optional[str] = None, logger: Optional[ExternalLogger] = None) -> str:
4647
"""Run the agent with a prompt.
4748
4849
Args:
@@ -55,20 +56,32 @@ def run(self, prompt: str, thread_id: Optional[str] = None) -> str:
5556
if thread_id is None:
5657
thread_id = str(uuid4())
5758

59+
60+
5861
# this message has a reducer which appends the current message to the existing history
5962
# see more https://langchain-ai.github.io/langgraph/concepts/low_level/#reducers
6063
input = {"messages": [("user", prompt)]}
6164

6265
# we stream the steps instead of invoke because it allows us to access intermediate nodes
63-
stream = self.agent.stream(input, config={"configurable": {"thread_id": thread_id, "metadata": {"project": self.project_name}}, "recursion_limit": 100}, stream_mode="values")
66+
stream = self.agent.stream(input, config={"configurable": {"thread_id": thread_id, "metadata": {"project": self.project_name}}, "recursion_limit": 100}, stream_mode="values")
67+
# Get the stream from the graph
68+
# Create the external logger (optional)
69+
# Create the tracer
70+
_tracer = MessageStreamTracer(logger=logger)
71+
72+
# Process the stream with the tracer
73+
traced_stream = _tracer.process_stream(stream)
6474

6575
# Keep track of run IDs from the stream
6676
run_ids = []
6777

68-
for s in stream:
78+
for s in traced_stream:
6979
message = s["messages"][-1]
80+
message.pretty_print()
81+
7082
if isinstance(message, tuple):
71-
print(message)
83+
# print(message)
84+
pass
7285
else:
7386
if isinstance(message, AIMessage) and isinstance(message.content, list) and "text" in message.content[0]:
7487
AIMessage(message.content[0]["text"]).pretty_print()
@@ -82,7 +95,7 @@ def run(self, prompt: str, thread_id: Optional[str] = None) -> str:
8295
# Get the last message content
8396
result = s["messages"][-1].content
8497

85-
# Try to find run IDs in the LangSmith client's recent runs
98+
# # Try to find run IDs in the LangSmith client's recent runs
8699
try:
87100
# Find and print the LangSmith run URL
88101
find_and_print_langsmith_run_url(self.langsmith_client, self.project_name)

src/codegen/agents/data.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
from typing import List, Optional
2+
from dataclasses import dataclass, field
3+
from datetime import datetime
4+
5+
# Base dataclass for all message types
6+
@dataclass
7+
class BaseMessage:
8+
"""Base class for all message types."""
9+
type: str
10+
timestamp: str = field(default_factory=lambda: datetime.now().isoformat())
11+
content: str = ""
12+
13+
@dataclass
14+
class UserMessage(BaseMessage):
15+
"""Represents a message from the user."""
16+
type: str = field(default="user")
17+
18+
@dataclass
19+
class SystemMessageData(BaseMessage):
20+
"""Represents a system message."""
21+
type: str = field(default="system")
22+
23+
@dataclass
24+
class ToolCall:
25+
"""Represents a tool call within an assistant message."""
26+
name: Optional[str] = None
27+
arguments: Optional[str] = None
28+
id: Optional[str] = None
29+
30+
@dataclass
31+
class AssistantMessage(BaseMessage):
32+
"""Represents a message from the assistant."""
33+
type: str = field(default="assistant")
34+
tool_calls: List[ToolCall] = field(default_factory=list)
35+
36+
@dataclass
37+
class ToolMessageData(BaseMessage):
38+
"""Represents a tool response message."""
39+
type: str = field(default="tool")
40+
tool_name: Optional[str] = None
41+
tool_response: Optional[str] = None
42+
tool_id: Optional[str] = None
43+
44+
@dataclass
45+
class FunctionMessageData(BaseMessage):
46+
"""Represents a function message."""
47+
type: str = field(default="function")
48+
49+
@dataclass
50+
class UnknownMessage(BaseMessage):
51+
"""Represents an unknown message type."""
52+
type: str = field(default="unknown")

src/codegen/agents/loggers.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import json
2+
from typing import Dict, List, Any, Union, Protocol
3+
from dataclasses import asdict
4+
from .data import BaseMessage
5+
6+
# Define the interface for ExternalLogger
7+
class ExternalLogger(Protocol):
8+
"""Protocol defining the interface for external loggers."""
9+
10+
def log(self, data: Union[Dict[str, Any], BaseMessage]) -> None:
11+
"""
12+
Log structured data to an external system.
13+
14+
Args:
15+
data: The structured data to log, either as a dictionary or a BaseMessage
16+
"""
17+
pass

0 commit comments

Comments
 (0)