Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions packages/sdk/server-ai/src/ldai/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
AIAgentConfig, AIAgentConfigDefault, AIAgentConfigRequest,
AIAgentGraphConfig, AIAgents, AICompletionConfig,
AICompletionConfigDefault, AIConfig, AIJudgeConfig, AIJudgeConfigDefault,
Edge, JudgeConfiguration, LDAIAgent, LDAIAgentConfig, LDAIAgentDefaults,
LDMessage, ModelConfig, ProviderConfig)
AITool, Edge, JudgeConfiguration, LDAIAgent, LDAIAgentConfig,
LDAIAgentDefaults, LDMessage, ModelConfig, ProviderConfig)
from ldai.providers.types import EvalScore, JudgeResponse
from ldai.tracker import AIGraphTracker

Expand All @@ -23,6 +23,7 @@
'AIAgents',
'AIAgentGraphConfig',
'AIGraphTracker',
'AITool',
'Edge',
'AICompletionConfig',
'AICompletionConfigDefault',
Expand Down
38 changes: 35 additions & 3 deletions packages/sdk/server-ai/src/ldai/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from ldai.models import (AIAgentConfig, AIAgentConfigDefault,
AIAgentConfigRequest, AIAgentGraphConfig, AIAgents,
AICompletionConfig, AICompletionConfigDefault,
AIJudgeConfig, AIJudgeConfigDefault, Edge,
AIJudgeConfig, AIJudgeConfigDefault, AITool, Edge,
JudgeConfiguration, LDMessage, ModelConfig,
ProviderConfig)
from ldai.providers.ai_provider_factory import AIProviderFactory
Expand Down Expand Up @@ -52,15 +52,31 @@ def _completion_config(
default: AICompletionConfigDefault,
variables: Optional[Dict[str, Any]] = None,
) -> AICompletionConfig:
model, provider, messages, instructions, tracker, enabled, judge_configuration, _ = self.__evaluate(
model, provider, messages, instructions, tracker, enabled, judge_configuration, variation = self.__evaluate(
key, context, default.to_dict(), variables
)

# Parse tools from variation data
tools = None
if 'tools' in variation and isinstance(variation['tools'], list):
tools = [
AITool(
key=tool['key'],
version=tool.get('version', 0),
instructions=tool.get('instructions'),
examples=tool.get('examples'),
custom_parameters=tool.get('customParameters'),
)
for tool in variation['tools']
if isinstance(tool, dict) and 'key' in tool
]

config = AICompletionConfig(
key=key,
enabled=bool(enabled),
model=model,
messages=messages,
tools=tools if tools is not None else default.tools,
provider=provider,
tracker=tracker,
judge_configuration=judge_configuration,
Expand Down Expand Up @@ -706,19 +722,35 @@ def __evaluate_agent(
:param variables: Variables for interpolation.
:return: Configured AIAgentConfig instance.
"""
model, provider, messages, instructions, tracker, enabled, judge_configuration, _ = self.__evaluate(
model, provider, messages, instructions, tracker, enabled, judge_configuration, variation = self.__evaluate(
key, context, default.to_dict(), variables
)

# For agents, prioritize instructions over messages
final_instructions = instructions if instructions is not None else default.instructions

# Parse tools from variation data
tools = None
if 'tools' in variation and isinstance(variation['tools'], list):
tools = [
AITool(
key=tool['key'],
version=tool.get('version', 0),
instructions=tool.get('instructions'),
examples=tool.get('examples'),
custom_parameters=tool.get('customParameters'),
)
for tool in variation['tools']
if isinstance(tool, dict) and 'key' in tool
]

return AIAgentConfig(
key=key,
enabled=bool(enabled) if enabled is not None else (default.enabled or False),
model=model or default.model,
provider=provider or default.provider,
instructions=final_instructions,
tools=tools if tools is not None else default.tools,
tracker=tracker,
judge_configuration=judge_configuration or default.judge_configuration,
)
Expand Down
44 changes: 44 additions & 0 deletions packages/sdk/server-ai/src/ldai/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,38 @@ def to_dict(self) -> dict:
}


# ============================================================================
# Tool Types
# ============================================================================

@dataclass(frozen=True)
class AITool:
"""
Configuration for an AI tool.
"""
key: str
version: int
instructions: Optional[str] = None
examples: Optional[str] = None
custom_parameters: Optional[Dict[str, Any]] = None

def to_dict(self) -> dict:
"""
Render the tool as a dictionary object.
"""
result: Dict[str, Any] = {
'key': self.key,
'version': self.version,
}
if self.instructions is not None:
result['instructions'] = self.instructions
if self.examples is not None:
result['examples'] = self.examples
if self.custom_parameters is not None:
result['customParameters'] = self.custom_parameters
return result


# ============================================================================
# Base AI Config Types
# ============================================================================
Expand Down Expand Up @@ -207,6 +239,7 @@ class AICompletionConfigDefault(AIConfigDefault):
Default Completion AI Config (default mode).
"""
messages: Optional[List[LDMessage]] = None
tools: Optional[List[AITool]] = None
judge_configuration: Optional[JudgeConfiguration] = None

def to_dict(self) -> dict:
Expand All @@ -215,6 +248,8 @@ def to_dict(self) -> dict:
"""
result = self._base_to_dict()
result['messages'] = [message.to_dict() for message in self.messages] if self.messages else None
if self.tools is not None:
result['tools'] = [tool.to_dict() for tool in self.tools]
if self.judge_configuration is not None:
result['judgeConfiguration'] = self.judge_configuration.to_dict()
return result
Expand All @@ -226,6 +261,7 @@ class AICompletionConfig(AIConfig):
Completion AI Config (default mode).
"""
messages: Optional[List[LDMessage]] = None
tools: Optional[List[AITool]] = None
judge_configuration: Optional[JudgeConfiguration] = None

def to_dict(self) -> dict:
Expand All @@ -234,6 +270,8 @@ def to_dict(self) -> dict:
"""
result = self._base_to_dict()
result['messages'] = [message.to_dict() for message in self.messages] if self.messages else None
if self.tools is not None:
result['tools'] = [tool.to_dict() for tool in self.tools]
if self.judge_configuration is not None:
result['judgeConfiguration'] = self.judge_configuration.to_dict()
return result
Expand All @@ -249,6 +287,7 @@ class AIAgentConfigDefault(AIConfigDefault):
Default Agent-specific AI Config with instructions.
"""
instructions: Optional[str] = None
tools: Optional[List[AITool]] = None
judge_configuration: Optional[JudgeConfiguration] = None

def to_dict(self) -> Dict[str, Any]:
Expand All @@ -258,6 +297,8 @@ def to_dict(self) -> Dict[str, Any]:
result = self._base_to_dict()
if self.instructions is not None:
result['instructions'] = self.instructions
if self.tools is not None:
result['tools'] = [tool.to_dict() for tool in self.tools]
if self.judge_configuration is not None:
result['judgeConfiguration'] = self.judge_configuration.to_dict()
return result
Expand All @@ -269,6 +310,7 @@ class AIAgentConfig(AIConfig):
Agent-specific AI Config with instructions.
"""
instructions: Optional[str] = None
tools: Optional[List[AITool]] = None
judge_configuration: Optional[JudgeConfiguration] = None

def to_dict(self) -> Dict[str, Any]:
Expand All @@ -278,6 +320,8 @@ def to_dict(self) -> Dict[str, Any]:
result = self._base_to_dict()
if self.instructions is not None:
result['instructions'] = self.instructions
if self.tools is not None:
result['tools'] = [tool.to_dict() for tool in self.tools]
if self.judge_configuration is not None:
result['judgeConfiguration'] = self.judge_configuration.to_dict()
return result
Expand Down
Loading
Loading