update readme
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
"metadata": {
|
"metadata": {
|
||||||
"dependency_versions": {
|
"dependency_versions": {
|
||||||
"python": "3.13",
|
"python": "3.13",
|
||||||
"dspy": "3.0.4b1",
|
"dspy": "3.0.4",
|
||||||
"cloudpickle": "3.1"
|
"cloudpickle": "3.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
{
|
{
|
||||||
"AutoConfig": "src.index.CodexAgentConfig",
|
"AutoConfig": "src.codex_dspy.agent.CodexAgentConfig",
|
||||||
"AutoAgent": "src.index.CodexAgent"
|
"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():
|
def main():
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ from pydantic import BaseModel
|
|||||||
import dspy
|
import dspy
|
||||||
from dspy.primitives.prediction import Prediction
|
from dspy.primitives.prediction import Prediction
|
||||||
from dspy.signatures.signature import Signature, ensure_signature
|
from dspy.signatures.signature import Signature, ensure_signature
|
||||||
|
from modaic import PrecompiledAgent, PrecompiledConfig
|
||||||
from ..codex import Codex, CodexOptions, SandboxMode, ThreadOptions, TurnOptions
|
from ..codex import Codex, CodexOptions, SandboxMode, ThreadOptions, TurnOptions
|
||||||
|
|
||||||
|
|
||||||
@@ -38,7 +38,18 @@ def _is_str_type(annotation: Any) -> bool:
|
|||||||
return False
|
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.
|
"""DSPy module for Codex SDK integration.
|
||||||
|
|
||||||
Creates a stateful agent where each instance maintains one conversation thread.
|
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
|
>>> print(result.report.severity) # typed access
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(
|
config: CodexAgentConfig
|
||||||
self,
|
|
||||||
signature: str | type[Signature],
|
def __init__(self, config: CodexAgentConfig, **kwargs):
|
||||||
working_directory: str,
|
super().__init__(config, **kwargs)
|
||||||
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__()
|
|
||||||
|
|
||||||
# Ensure signature is valid
|
# Ensure signature is valid
|
||||||
self.signature = ensure_signature(signature)
|
self.signature = ensure_signature(config.signature)
|
||||||
|
|
||||||
# Validate: exactly 1 input field, 1 output field
|
# Validate: exactly 1 input field, 1 output field
|
||||||
if len(self.signature.input_fields) != 1:
|
if len(self.signature.input_fields) != 1:
|
||||||
@@ -112,19 +115,19 @@ class CodexModule(dspy.Module):
|
|||||||
# Create Codex client
|
# Create Codex client
|
||||||
self.client = Codex(
|
self.client = Codex(
|
||||||
options=CodexOptions(
|
options=CodexOptions(
|
||||||
api_key=api_key,
|
api_key=config.api_key,
|
||||||
base_url=base_url,
|
base_url=config.base_url,
|
||||||
codex_path_override=codex_path_override,
|
codex_path_override=config.codex_path_override,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
# Start thread (1 agent instance = 1 stateful thread)
|
# Start thread (1 agent instance = 1 stateful thread)
|
||||||
self.thread = self.client.start_thread(
|
self.thread = self.client.start_thread(
|
||||||
options=ThreadOptions(
|
options=ThreadOptions(
|
||||||
working_directory=working_directory,
|
working_directory=config.working_directory,
|
||||||
model=model,
|
model=config.model,
|
||||||
sandbox_mode=sandbox_mode,
|
sandbox_mode=config.sandbox_mode,
|
||||||
skip_git_repo_check=skip_git_repo_check,
|
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