update readme
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
"metadata": {
|
||||
"dependency_versions": {
|
||||
"python": "3.13",
|
||||
"dspy": "3.0.4b1",
|
||||
"dspy": "3.0.4",
|
||||
"cloudpickle": "3.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{
|
||||
"AutoConfig": "src.index.CodexAgentConfig",
|
||||
"AutoAgent": "src.index.CodexAgent"
|
||||
"AutoConfig": "src.codex_dspy.agent.CodexAgentConfig",
|
||||
"AutoAgent": "src.codex_dspy.agent.CodexModule"
|
||||
}
|
||||
4
main.py
4
main.py
@@ -1,6 +1,6 @@
|
||||
from src.index import CodexAgent, CodexAgentConfig
|
||||
from src.codex_dspy.agent import CodexModule, CodexAgentConfig
|
||||
|
||||
codex_agent = CodexAgent(CodexAgentConfig())
|
||||
codex_agent = CodexModule(CodexAgentConfig())
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
@@ -12,7 +12,7 @@ from pydantic import BaseModel
|
||||
import dspy
|
||||
from dspy.primitives.prediction import Prediction
|
||||
from dspy.signatures.signature import Signature, ensure_signature
|
||||
|
||||
from modaic import PrecompiledAgent, PrecompiledConfig
|
||||
from ..codex import Codex, CodexOptions, SandboxMode, ThreadOptions, TurnOptions
|
||||
|
||||
|
||||
@@ -38,7 +38,18 @@ def _is_str_type(annotation: Any) -> bool:
|
||||
return False
|
||||
|
||||
|
||||
class CodexModule(dspy.Module):
|
||||
class CodexAgentConfig(PrecompiledConfig):
|
||||
signature: str | type[Signature] = "message:str -> answer:str"
|
||||
working_directory: str = "."
|
||||
model: Optional[str] = "gpt-4o"
|
||||
sandbox_mode: Optional[SandboxMode] = None
|
||||
skip_git_repo_check: bool = False
|
||||
api_key: Optional[str] = None
|
||||
base_url: Optional[str] = None
|
||||
codex_path_override: Optional[str] = "/opt/homebrew/bin/codex"
|
||||
|
||||
|
||||
class CodexModule(PrecompiledAgent):
|
||||
"""DSPy module for Codex SDK integration.
|
||||
|
||||
Creates a stateful agent where each instance maintains one conversation thread.
|
||||
@@ -72,21 +83,13 @@ class CodexModule(dspy.Module):
|
||||
>>> print(result.report.severity) # typed access
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
signature: str | type[Signature],
|
||||
working_directory: str,
|
||||
model: Optional[str] = None,
|
||||
sandbox_mode: Optional[SandboxMode] = None,
|
||||
skip_git_repo_check: bool = False,
|
||||
api_key: Optional[str] = None,
|
||||
base_url: Optional[str] = None,
|
||||
codex_path_override: Optional[str] = None,
|
||||
):
|
||||
super().__init__()
|
||||
config: CodexAgentConfig
|
||||
|
||||
def __init__(self, config: CodexAgentConfig, **kwargs):
|
||||
super().__init__(config, **kwargs)
|
||||
|
||||
# Ensure signature is valid
|
||||
self.signature = ensure_signature(signature)
|
||||
self.signature = ensure_signature(config.signature)
|
||||
|
||||
# Validate: exactly 1 input field, 1 output field
|
||||
if len(self.signature.input_fields) != 1:
|
||||
@@ -112,19 +115,19 @@ class CodexModule(dspy.Module):
|
||||
# Create Codex client
|
||||
self.client = Codex(
|
||||
options=CodexOptions(
|
||||
api_key=api_key,
|
||||
base_url=base_url,
|
||||
codex_path_override=codex_path_override,
|
||||
api_key=config.api_key,
|
||||
base_url=config.base_url,
|
||||
codex_path_override=config.codex_path_override,
|
||||
)
|
||||
)
|
||||
|
||||
# Start thread (1 agent instance = 1 stateful thread)
|
||||
self.thread = self.client.start_thread(
|
||||
options=ThreadOptions(
|
||||
working_directory=working_directory,
|
||||
model=model,
|
||||
sandbox_mode=sandbox_mode,
|
||||
skip_git_repo_check=skip_git_repo_check,
|
||||
working_directory=config.working_directory,
|
||||
model=config.model,
|
||||
sandbox_mode=config.sandbox_mode,
|
||||
skip_git_repo_check=config.skip_git_repo_check,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
51
src/index.py
51
src/index.py
@@ -1,51 +0,0 @@
|
||||
import dspy
|
||||
from modaic import PrecompiledAgent, PrecompiledConfig
|
||||
from .codex_dspy import CodexModule
|
||||
from .codex import Codex, CodexOptions, SandboxMode, ThreadOptions, TurnOptions
|
||||
from dspy.signatures.signature import Signature
|
||||
from dspy.primitives.prediction import Prediction
|
||||
from typing import Optional
|
||||
|
||||
|
||||
class CodexAgentConfig(PrecompiledConfig):
|
||||
signature: str | type[Signature] = "message:str -> answer:str"
|
||||
working_directory: str = "."
|
||||
model: Optional[str] = "gpt-4o"
|
||||
sandbox_mode: Optional[SandboxMode] = None
|
||||
skip_git_repo_check: bool = False
|
||||
api_key: Optional[str] = None
|
||||
base_url: Optional[str] = None
|
||||
codex_path_override: Optional[str] = "/opt/homebrew/bin/codex"
|
||||
|
||||
|
||||
class CodexAgent(PrecompiledAgent):
|
||||
config: CodexAgentConfig
|
||||
|
||||
def __init__(self, config: CodexAgentConfig, **kwargs):
|
||||
super().__init__(config, **kwargs)
|
||||
|
||||
self.codex_module = CodexModule(
|
||||
signature=config.signature,
|
||||
working_directory=config.working_directory,
|
||||
model=config.model,
|
||||
sandbox_mode=config.sandbox_mode,
|
||||
skip_git_repo_check=config.skip_git_repo_check,
|
||||
api_key=config.api_key,
|
||||
base_url=config.base_url,
|
||||
codex_path_override=config.codex_path_override,
|
||||
)
|
||||
|
||||
def forward(self, **kwargs) -> Prediction:
|
||||
return self.codex_module(**kwargs)
|
||||
|
||||
@property
|
||||
def thread_id(self) -> Optional[str]:
|
||||
"""Get thread ID for this agent instance.
|
||||
|
||||
The thread ID is assigned after the first forward() call.
|
||||
Useful for debugging and visibility into the conversation state.
|
||||
|
||||
Returns:
|
||||
Thread ID string, or None if no forward() calls have been made yet
|
||||
"""
|
||||
return self.codex_module.thread.id
|
||||
Reference in New Issue
Block a user