Source code for smarter.apps.prompt.contract.history

"""
Pydantic models of the prompt history's REST api responses (``/api/v1/prompts/history/``).

The prompt history is the chat sessions (:class:`PromptHistoryApiSession`) of the users whose
resources the requesting user may manage, the tool calls that the LLMs made in them
(:class:`PromptHistoryApiToolCall`), and the plugins that they used
(:class:`PromptHistoryApiPluginUsage`).

The models are the outputs of the serializers of :mod:`smarter.apps.prompt.api.v1.serializers`,
which the REST api returned before it was modeled, and which clients already read. Their keys are
snake_case, unlike the rest of the REST api's, for the same reason. A plugin is a
:class:`smarter.apps.plugin.contract.models.PluginApiPluginMeta`, in camelCase.

The models forbid extra fields: the api returns exactly what they declare.
"""

from datetime import datetime
from typing import TYPE_CHECKING, Optional

from pydantic import BaseModel, ConfigDict, Field, JsonValue

from smarter.apps.account.contract.models import MetaDataApiAnnotations
from smarter.apps.plugin.contract.models import PluginApiPluginMeta

if TYPE_CHECKING:
    from smarter.apps.prompt.models import Prompt, PromptPluginUsage, PromptToolCall


[docs] class PromptHistoryApiModel(BaseModel): """Base class of the prompt history's models: the fields of a row, and a TimestampedModel's.""" model_config = ConfigDict(extra="forbid") id: int = Field(..., description="The row's primary key.") created_at: Optional[datetime] = Field(None, description="TimestampedModel.created_at.") updated_at: Optional[datetime] = Field(None, description="TimestampedModel.updated_at.")
[docs] class PromptHistoryApiSession(PromptHistoryApiModel): """A chat session: one conversation with an LLMClient, a :class:`smarter.apps.prompt.models.Prompt`.""" name: str = Field("", description="MetaDataModel.name.") description: Optional[str] = Field(None, description="MetaDataModel.description.") version: Optional[str] = Field(None, description="MetaDataModel.version, e.g. 1.0.0.") annotations: MetaDataApiAnnotations = Field(None, description="MetaDataModel.annotations.") session_key: str = Field(..., max_length=255, description="Prompt.session_key, which identifies the session.") ip_address: str = Field(..., description="Prompt.ip_address: the client's IP address.") user_agent: str = Field(..., max_length=255, description="Prompt.user_agent: the client's user agent.") url: str = Field(..., description="Prompt.url: the url that the session's chat was configured with.") user_profile: int = Field(..., description="Prompt.user_profile: the user profile's id.") llmclient: int = Field(..., description="Prompt.llmclient: the LLMClient's id.")
[docs] @classmethod def from_model(cls, prompt: "Prompt") -> "PromptHistoryApiSession": """ The contract's model of a chat session. :param prompt: The row. :type prompt: smarter.apps.prompt.models.Prompt :returns: The model. :rtype: PromptHistoryApiSession """ return cls( id=prompt.pk, created_at=prompt.created_at, updated_at=prompt.updated_at, name=prompt.name, description=prompt.description, version=prompt.version, annotations=prompt.annotations, session_key=prompt.session_key, ip_address=prompt.ip_address, user_agent=prompt.user_agent, url=prompt.url, user_profile=prompt.user_profile_id, # type: ignore[attr-defined] llmclient=prompt.llmclient_id, # type: ignore[attr-defined] )
[docs] class PromptHistoryApiToolCall(PromptHistoryApiModel): """A tool call that the LLM made in a chat session: a :class:`smarter.apps.prompt.models.PromptToolCall`.""" prompt: PromptHistoryApiSession = Field(..., description="PromptToolCall.prompt: the chat session.") plugin: Optional[int] = Field(None, description="PromptToolCall.plugin: the PluginMeta's id, for a plugin.") function_name: Optional[str] = Field(None, max_length=255, description="PromptToolCall.function_name.") function_args: Optional[str] = Field(None, max_length=255, description="PromptToolCall.function_args.") request: Optional[JsonValue] = Field(None, description="PromptToolCall.request: the tool's input.") response: Optional[JsonValue] = Field(None, description="PromptToolCall.response: the tool's result.")
[docs] @classmethod def from_model(cls, row: "PromptToolCall") -> "PromptHistoryApiToolCall": """ The contract's model of a tool call. :param row: The row, whose ``prompt`` should be fetched with it. :type row: smarter.apps.prompt.models.PromptToolCall :returns: The model. :rtype: PromptHistoryApiToolCall """ return cls( id=row.pk, created_at=row.created_at, updated_at=row.updated_at, prompt=PromptHistoryApiSession.from_model(row.prompt), plugin=row.plugin_id, # type: ignore[attr-defined] function_name=row.function_name, function_args=row.function_args, request=row.request, response=row.response, )
[docs] class PromptHistoryApiPluginUsage(PromptHistoryApiModel): """A use of a plugin in a chat session: a :class:`smarter.apps.prompt.models.PromptPluginUsage`.""" prompt: PromptHistoryApiSession = Field(..., description="PromptPluginUsage.prompt: the chat session.") plugin: PluginApiPluginMeta = Field(..., description="PromptPluginUsage.plugin: the plugin.") input_text: Optional[str] = Field(None, description="PromptPluginUsage.input_text.")
[docs] @classmethod def from_model(cls, row: "PromptPluginUsage", user: object = None) -> "PromptHistoryApiPluginUsage": """ The contract's model of a use of a plugin. :param row: The row, whose ``prompt`` and ``plugin`` should be fetched with it. :type row: smarter.apps.prompt.models.PromptPluginUsage :param user: The requesting user, for the plugin's ``canDelete``. None may delete nothing. :type user: object :returns: The model. :rtype: PromptHistoryApiPluginUsage """ return cls( id=row.pk, created_at=row.created_at, updated_at=row.updated_at, prompt=PromptHistoryApiSession.from_model(row.prompt), plugin=PluginApiPluginMeta.from_model(row.plugin, user), input_text=row.input_text, )
PROMPT_HISTORY_API_MODELS = (PromptHistoryApiSession, PromptHistoryApiToolCall, PromptHistoryApiPluginUsage) """The models whose JSON Schemas the Smarter api's OpenAPI document includes.""" __all__ = [ "PROMPT_HISTORY_API_MODELS", "PromptHistoryApiModel", "PromptHistoryApiPluginUsage", "PromptHistoryApiSession", "PromptHistoryApiToolCall", ]