| | |
| | from __future__ import annotations |
| | from typing import Any, Optional, List, Dict, Callable |
| | from datetime import datetime, timezone |
| | from pydantic import BaseModel, Field, ConfigDict |
| | from dataclasses import dataclass |
| | from zoneinfo import ZoneInfo |
| | import secrets |
| | import string |
| |
|
| |
|
| |
|
| | |
| | _ALPHABET = string.ascii_letters + string.digits |
| | def _nanoid(size: int = 21) -> str: |
| | return "".join(secrets.choice(_ALPHABET) for _ in range(size)) |
| |
|
| |
|
| | |
| | class CloudEvent(BaseModel): |
| | specversion: str = "1.0" |
| | id: str |
| | type: str |
| | source: str |
| | time: datetime |
| | datacontenttype: str = "application/json" |
| | data: Optional[Any] = None |
| |
|
| | @staticmethod |
| | def now_utc() -> datetime: |
| | return datetime.now(timezone.utc) |
| |
|
| | @classmethod |
| | def wrap(cls, *, event_id: str, event_type: str, source: str, data: Any) -> "CloudEvent": |
| | return cls( |
| | id=event_id, |
| | type=event_type or ("NullOrEmpty" if data is None else type(data).__name__), |
| | source=source, |
| | time=cls.now_utc(), |
| | data=data, |
| | ) |
| |
|
| |
|
| | |
| | class FunctionCallData(BaseModel): |
| | function: Optional[str] = None |
| | name: Optional[str] = None |
| | arguments: Optional[Dict[str, Any]] = None |
| | parameters: Optional[Dict[str, Any]] = None |
| |
|
| | def copy_from(self, other: "FunctionCallData") -> None: |
| | if other is None: |
| | return |
| | self.function = other.function |
| | self.name = other.name |
| | self.arguments = None if other.arguments is None else dict(other.arguments) |
| | self.parameters = None if other.parameters is None else dict(other.parameters) |
| |
|
| |
|
| | |
| | class FunctionState(BaseModel): |
| | IsFunctionCall: bool = False |
| | IsFunctionCallResponse: bool = False |
| | IsFunctionCallError: bool = False |
| | IsFunctionCallStatus: bool = False |
| | IsFunctionStillRunning: bool = False |
| |
|
| | |
| | def SetAsCall(self) -> "FunctionState": |
| | self.IsFunctionCall = True |
| | self.IsFunctionCallResponse = False |
| | self.IsFunctionCallError = False |
| | self.IsFunctionCallStatus = False |
| | self.IsFunctionStillRunning = False |
| | return self |
| |
|
| | |
| | def SetAsCallError(self) -> "FunctionState": |
| | return self.SetAsCall() |
| |
|
| | def SetAsNotCall(self) -> "FunctionState": |
| | self.IsFunctionCall = False |
| | self.IsFunctionCallResponse = False |
| | self.IsFunctionCallError = False |
| | self.IsFunctionCallStatus = False |
| | self.IsFunctionStillRunning = False |
| | return self |
| |
|
| | def SetAsResponseComplete(self) -> "FunctionState": |
| | self.IsFunctionCall = False |
| | self.IsFunctionCallResponse = True |
| | self.IsFunctionCallError = False |
| | self.IsFunctionCallStatus = False |
| | self.IsFunctionStillRunning = False |
| | return self |
| |
|
| | def SetOnlyResponse(self) -> "FunctionState": |
| | |
| | self.IsFunctionCall = False |
| | self.IsFunctionCallResponse = True |
| | self.IsFunctionCallError = False |
| | self.IsFunctionCallStatus = False |
| | |
| | return self |
| |
|
| | def SetAsResponseRunning(self) -> "FunctionState": |
| | self.IsFunctionCall = False |
| | self.IsFunctionCallResponse = False |
| | self.IsFunctionCallError = False |
| | self.IsFunctionCallStatus = False |
| | self.IsFunctionStillRunning = True |
| | return self |
| |
|
| | def SetAsResponseStatus(self) -> "FunctionState": |
| | self.IsFunctionCall = False |
| | self.IsFunctionCallResponse = False |
| | self.IsFunctionCallError = False |
| | self.IsFunctionCallStatus = True |
| | self.IsFunctionStillRunning = True |
| | return self |
| |
|
| | def SetAsResponseStatusOnly(self) -> "FunctionState": |
| | self.IsFunctionCall = False |
| | self.IsFunctionCallResponse = False |
| | self.IsFunctionCallError = False |
| | self.IsFunctionCallStatus = True |
| | self.IsFunctionStillRunning = False |
| | return self |
| |
|
| | def SetAsResponseError(self) -> "FunctionState": |
| | self.IsFunctionCall = False |
| | self.IsFunctionCallResponse = False |
| | self.IsFunctionCallError = True |
| | self.IsFunctionCallStatus = False |
| | self.IsFunctionStillRunning = False |
| | return self |
| |
|
| | def SetAsResponseErrorComplete(self) -> "FunctionState": |
| | |
| | self.IsFunctionCall = False |
| | self.IsFunctionCallResponse = True |
| | self.IsFunctionCallError = True |
| | self.IsFunctionCallStatus = False |
| | self.IsFunctionStillRunning = False |
| | return self |
| |
|
| | def SetFunctionState( |
| | self, |
| | functionCall: bool, |
| | functionCallResponse: bool, |
| | functionCallError: bool, |
| | functionCallStatus: bool, |
| | functionStillRunning: bool, |
| | ) -> "FunctionState": |
| | self.IsFunctionCall = functionCall |
| | self.IsFunctionCallResponse = functionCallResponse |
| | self.IsFunctionCallError = functionCallError |
| | self.IsFunctionCallStatus = functionCallStatus |
| | self.IsFunctionStillRunning = functionStillRunning |
| | return self |
| |
|
| | def StatesString(self) -> str: |
| | return ( |
| | f"IsFunctionCall={self.IsFunctionCall}, " |
| | f"IsFunctionCallResponse={self.IsFunctionCallResponse}, " |
| | f"IsFunctionCallError={self.IsFunctionCallError}, " |
| | f"IsFunctionCallStatus={self.IsFunctionCallStatus}, " |
| | f"IsFunctionStillRunning={self.IsFunctionStillRunning}" |
| | ) |
| |
|
| |
|
| | |
| | class UserInfo(BaseModel): |
| | UserID: Optional[str] = None |
| | DateCreated: datetime = Field(default_factory=lambda: datetime.now(timezone.utc)) |
| | HostLimit: int = 0 |
| | DisableEmail: bool = False |
| | Status: Optional[str] = "" |
| | Name: Optional[str] = "" |
| | Given_name: Optional[str] = "" |
| | Family_name: Optional[str] = "" |
| | Nickname: Optional[str] = "" |
| | Sub: Optional[str] = "" |
| | Enabled: bool = True |
| | MonitorAlertEnabled: bool = True |
| | PredictAlertEnabled: bool = False |
| | AccountType: Optional[str] = "Default" |
| | Email: Optional[str] = "" |
| | Email_verified: bool = False |
| | Picture: Optional[str] = "" |
| | Updated_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc)) |
| | LastLoginDate: datetime = Field(default_factory=lambda: datetime.now(timezone.utc)) |
| | CustomerId: Optional[str] = "" |
| | CancelAt: Optional[datetime] = None |
| | TokensUsed: int = 0 |
| | LoadServer: Dict[str, Any] = Field(default_factory=dict) |
| |
|
| | def copy_from(self, other: "UserInfo") -> None: |
| | if other is None: |
| | return |
| | for k, v in other.model_dump().items(): |
| | setattr(self, k, v) |
| |
|
| |
|
| | class LLMServiceObj(BaseModel): |
| | """ |
| | Python port of NetworkMonitor.Objects.ServiceMessage.LLMServiceObj |
| | – same JSON/wire names via aliases, no Pydantic forward-ref clash. |
| | """ |
| | model_config = ConfigDict(populate_by_name=True) |
| | |
| | |
| | |
| | |
| | def __getattr__(self, name): |
| | if name == "FunctionCallData": |
| | return super().__getattribute__("function_call_data") |
| | if name == "UserInfo": |
| | return super().__getattribute__("user_info") |
| | raise AttributeError(f"{type(self).__name__} has no attribute {name!r}") |
| |
|
| | def __setattr__(self, name, value): |
| | if name == "FunctionCallData": |
| | return super().__setattr__("function_call_data", value) |
| | if name == "UserInfo": |
| | return super().__setattr__("user_info", value) |
| | return super().__setattr__(name, value) |
| |
|
| | |
| | MessageID: str = Field(default_factory=_nanoid) |
| | RequestSessionId: str = "" |
| | SessionId: str = "" |
| | UserInput: str = "" |
| | JsonFunction: str = "" |
| | FunctionName: str = "" |
| | SwapFunctionName: str = "" |
| | LLMRunnerType: str = "TurboLLM" |
| | SourceLlm: str = "" |
| | DestinationLlm: str = "" |
| | TimeZone: str = "" |
| | LlmMessage: str = "" |
| | ResultMessage: str = "" |
| | LlmSessionStartName: str = "" |
| | ChatAgentLocation: str = "" |
| | ToolsDefinitionId: Optional[str] = None |
| | JsonToolsBuilderSpec: Optional[str] = None |
| |
|
| | |
| | TokensUsed: int = 0 |
| | IsUserLoggedIn: bool = False |
| | ResultSuccess: bool = False |
| | IsFuncAck: bool = False |
| | IsProcessed: bool = False |
| | IsSystemLlm: bool = False |
| | Timeout: Optional[int] = None |
| |
|
| | |
| | FunctionCallId: str = "" |
| | function_call_data: FunctionCallData = Field(default_factory=FunctionCallData, alias="FunctionCallData") |
| | user_info: UserInfo = Field(default_factory=UserInfo, alias="UserInfo") |
| |
|
| | |
| | LlmStack: List[str] = Field(default_factory=list) |
| | FunctionCallIdStack: List[str] = Field(default_factory=list) |
| | FunctionNameStack: List[str] = Field(default_factory=list) |
| | MessageIDStack: List[str] = Field(default_factory=list) |
| | IsProcessedStack: List[bool] = Field(default_factory=list) |
| |
|
| | |
| | functionState: FunctionState = Field(default_factory=FunctionState) |
| |
|
| | |
| | StartTimeUTC: datetime = Field(default_factory=lambda: datetime.now(timezone.utc)) |
| |
|
| | |
| | @classmethod |
| | def from_other(cls, other: "LLMServiceObj") -> "LLMServiceObj": |
| | inst = cls() |
| | inst.copy_from(other) |
| | return inst |
| |
|
| | @classmethod |
| | def from_other_with_state(cls, other: "LLMServiceObj", configure: Callable[[FunctionState], None]) -> "LLMServiceObj": |
| | inst = cls() |
| | inst.functionState = FunctionState() |
| | inst.copy_from(other) |
| | if configure: |
| | configure(inst.functionState) |
| | return inst |
| |
|
| | def copy_from(self, other: "LLMServiceObj") -> None: |
| | if other is None: |
| | return |
| | |
| | self.RequestSessionId = other.RequestSessionId |
| | self.SessionId = other.SessionId |
| | self.UserInput = other.UserInput |
| | self.IsUserLoggedIn = other.IsUserLoggedIn |
| | self.JsonFunction = other.JsonFunction |
| |
|
| | |
| | self.functionState = FunctionState().SetFunctionState( |
| | other.IsFunctionCall, |
| | other.IsFunctionCallResponse, |
| | other.IsFunctionCallError, |
| | other.IsFunctionCallStatus, |
| | other.IsFunctionStillRunning, |
| | ) |
| |
|
| | |
| | self.FunctionName = other.FunctionName |
| | self.FunctionCallId = other.FunctionCallId |
| | self.LLMRunnerType = other.LLMRunnerType |
| | self.SourceLlm = other.SourceLlm |
| | self.DestinationLlm = other.DestinationLlm |
| | self.TokensUsed = other.TokensUsed |
| | self.LlmMessage = other.LlmMessage |
| | self.IsSystemLlm = other.IsSystemLlm |
| | self.ResultSuccess = other.ResultSuccess |
| | self.ResultMessage = other.ResultMessage |
| | self.TimeZone = other.TimeZone |
| | self.LlmSessionStartName = other.LlmSessionStartName |
| | self.MessageID = other.MessageID |
| | self.StartTimeUTC = other.StartTimeUTC |
| | self.ChatAgentLocation = other.ChatAgentLocation |
| | self.ToolsDefinitionId = other.ToolsDefinitionId |
| | self.JsonToolsBuilderSpec = other.JsonToolsBuilderSpec |
| | self.Timeout = other.Timeout |
| | self.SwapFunctionName = other.SwapFunctionName |
| | self.IsFuncAck = other.IsFuncAck |
| | self.IsProcessed = other.IsProcessed |
| |
|
| | |
| | self.function_call_data = other.function_call_data.model_copy(deep=True) |
| | self.user_info = other.user_info.model_copy(deep=True) |
| |
|
| | self.LlmStack = list(other.LlmStack) |
| | self.FunctionCallIdStack = list(other.FunctionCallIdStack) |
| | self.FunctionNameStack = list(other.FunctionNameStack) |
| | self.MessageIDStack = list(other.MessageIDStack) |
| | self.IsProcessedStack = list(other.IsProcessedStack) |
| |
|
| | |
| | def GetFunctionStateString(self) -> str: |
| | return self.functionState.StatesString() |
| |
|
| | def SetAsCall(self) -> None: self.functionState.SetAsCall() |
| | def SetAsCallError(self) -> None: self.functionState.SetAsCallError() |
| | def SetAsNotCall(self) -> None: self.functionState.SetAsNotCall() |
| | def SetAsResponseComplete(self) -> None: self.functionState.SetAsResponseComplete() |
| | def SetOnlyResponse(self) -> None: self.functionState.SetOnlyResponse() |
| | def SetAsResponseRunning(self) -> None: self.functionState.SetAsResponseRunning() |
| | def SetAsResponseStatus(self) -> None: self.functionState.SetAsResponseStatus() |
| | def SetAsResponseStatusOnly(self) -> None: self.functionState.SetAsResponseStatusOnly() |
| | def SetAsResponseError(self) -> None: self.functionState.SetAsResponseError() |
| | def SetAsResponseErrorComplete(self) -> None: self.functionState.SetAsResponseErrorComplete() |
| | def SetFunctionState(self, a: bool, b: bool, c: bool, d: bool, e: bool) -> None: |
| | self.functionState.SetFunctionState(a, b, c, d, e) |
| |
|
| | |
| | @property |
| | def IsFunctionCall(self) -> bool: return self.functionState.IsFunctionCall |
| | @IsFunctionCall.setter |
| | def IsFunctionCall(self, v: bool) -> None: self.functionState.IsFunctionCall = v |
| |
|
| | @property |
| | def IsFunctionCallResponse(self) -> bool: return self.functionState.IsFunctionCallResponse |
| | @IsFunctionCallResponse.setter |
| | def IsFunctionCallResponse(self, v: bool) -> None: self.functionState.IsFunctionCallResponse = v |
| |
|
| | @property |
| | def IsFunctionCallError(self) -> bool: return self.functionState.IsFunctionCallError |
| | @IsFunctionCallError.setter |
| | def IsFunctionCallError(self, v: bool) -> None: self.functionState.IsFunctionCallError = v |
| |
|
| | @property |
| | def IsFunctionCallStatus(self) -> bool: return self.functionState.IsFunctionCallStatus |
| | @IsFunctionCallStatus.setter |
| | def IsFunctionCallStatus(self, v: bool) -> None: self.functionState.IsFunctionCallStatus = v |
| |
|
| | @property |
| | def IsFunctionStillRunning(self) -> bool: return self.functionState.IsFunctionStillRunning |
| | @IsFunctionStillRunning.setter |
| | def IsFunctionStillRunning(self, v: bool) -> None: self.functionState.IsFunctionStillRunning = v |
| |
|
| | |
| | def PopLlm(self) -> None: |
| | if self.LlmStack: |
| | self.SourceLlm = self.LlmStack.pop() |
| | self.DestinationLlm = self.SourceLlm |
| | self.PopMessageID() |
| | self.PopFunctionCallId() |
| | self.PopFunctionName() |
| | self.PopIsProcessed() |
| |
|
| | def PushLmm(self, llmName: str, newFunctionCallId: str, newFunctionName: str, newMessageID: str, newIsProcessed: bool) -> None: |
| | if self.SourceLlm: |
| | self.LlmStack.append(self.SourceLlm) |
| | self.SourceLlm = self.DestinationLlm |
| | self.DestinationLlm = llmName |
| | self.PushMessageID(newMessageID) |
| | self.PushFunctionCallId(newFunctionCallId) |
| | self.PushFunctionName(newFunctionName) |
| | self.PushIsProcessed(newIsProcessed) |
| |
|
| | @property |
| | def LlmChainStartName(self) -> str: |
| | return self.SourceLlm if not self.LlmStack else self.LlmStack[0] |
| |
|
| | @property |
| | def RootMessageID(self) -> str: |
| | return self.MessageID if not self.MessageIDStack else self.MessageIDStack[0] |
| |
|
| | @property |
| | def FirstFunctionName(self) -> str: |
| | return self.FunctionName if not self.FunctionNameStack else self.FunctionNameStack[0] |
| |
|
| | @property |
| | def IsPrimaryLlm(self) -> bool: |
| | return False if self.IsSystemLlm else (self.SourceLlm == self.DestinationLlm) |
| |
|
| | def PopMessageID(self) -> None: |
| | if self.MessageIDStack: |
| | self.MessageID = self.MessageIDStack.pop() |
| |
|
| | def PushMessageID(self, newMessageID: str) -> None: |
| | if self.MessageID: |
| | self.MessageIDStack.append(self.MessageID) |
| | self.MessageID = newMessageID |
| |
|
| | def PopFunctionCallId(self) -> None: |
| | if self.FunctionCallIdStack: |
| | self.FunctionCallId = self.FunctionCallIdStack.pop() |
| |
|
| | def PushFunctionCallId(self, newFunctionCallId: str) -> None: |
| | if self.FunctionCallId: |
| | self.FunctionCallIdStack.append(self.FunctionCallId) |
| | self.FunctionCallId = newFunctionCallId |
| |
|
| | def PopFunctionName(self) -> None: |
| | if self.FunctionNameStack: |
| | self.FunctionName = self.FunctionNameStack.pop() |
| |
|
| | def PushFunctionName(self, newFunctionName: str) -> None: |
| | if self.FunctionName: |
| | self.FunctionNameStack.append(self.FunctionName) |
| | self.FunctionName = newFunctionName |
| |
|
| | def PushIsProcessed(self, newIsProcessed: bool) -> None: |
| | self.IsProcessedStack.append(self.IsProcessed) |
| | self.IsProcessed = newIsProcessed |
| |
|
| | def PopIsProcessed(self) -> None: |
| | if self.IsProcessedStack: |
| | self.IsProcessed = self.IsProcessedStack.pop() |
| |
|
| | |
| | def _tz(self) -> ZoneInfo: |
| | try: |
| | return ZoneInfo(self.TimeZone) if self.TimeZone else ZoneInfo("UTC") |
| | except Exception: |
| | return ZoneInfo("UTC") |
| |
|
| | def GetClientCurrentTime(self) -> datetime: |
| | try: |
| | return datetime.now(timezone.utc).astimezone(self._tz()) |
| | except Exception: |
| | return datetime.now(timezone.utc) |
| |
|
| | def GetClientStartTime(self) -> datetime: |
| | try: |
| | return self.StartTimeUTC.astimezone(self._tz()) |
| | except Exception: |
| | return datetime.now(timezone.utc) |
| |
|
| | def GetClientCurrentUnixTime(self) -> int: |
| | try: |
| | return int(self.GetClientCurrentTime().timestamp()) |
| | except Exception: |
| | return int(datetime.now(timezone.utc).timestamp()) |
| |
|
| | def GetClientStartUnixTime(self) -> int: |
| | try: |
| | return int(self.GetClientStartTime().timestamp()) |
| | except Exception: |
| | return int(datetime.now(timezone.utc).timestamp()) |
| |
|
| | |
| |
|
| | |
| | class ResultObj(BaseModel): |
| | Message: str = "" |
| | Success: bool = False |
| | Data: Optional[Any] = None |
| |
|
| |
|
| |
|