model.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. from datetime import datetime
  2. from typing import TYPE_CHECKING, Literal
  3. from core_domain import ChatCompletionResponseContract
  4. from core_shared import JSONValue
  5. from pydantic import BaseModel, Field, HttpUrl
  6. if TYPE_CHECKING:
  7. from app.db.models import ModelDefinition
  8. ModelStatus = Literal["active", "disabled"]
  9. class ModelCreateRequest(BaseModel):
  10. code: str = Field(min_length=1, max_length=64)
  11. name: str = Field(min_length=1, max_length=128)
  12. provider_type: str = "openai_compatible"
  13. provider_base_url: HttpUrl | str
  14. provider_api_key: str | None = None
  15. model_name: str = Field(min_length=1, max_length=128)
  16. status: ModelStatus = "active"
  17. description: str | None = None
  18. capabilities_json: list[str] = Field(default_factory=lambda: ["chat"])
  19. context_window: int | None = Field(default=None, ge=1)
  20. max_output_tokens: int | None = Field(default=None, ge=1)
  21. default_temperature: float | None = Field(default=None, ge=0, le=2)
  22. timeout_seconds: float = Field(default=60.0, ge=1, le=300)
  23. metadata_json: dict[str, JSONValue] = Field(default_factory=dict)
  24. class ModelUpdateRequest(BaseModel):
  25. code: str | None = Field(default=None, min_length=1, max_length=64)
  26. name: str | None = Field(default=None, min_length=1, max_length=128)
  27. provider_type: str | None = None
  28. provider_base_url: HttpUrl | str | None = None
  29. provider_api_key: str | None = None
  30. model_name: str | None = Field(default=None, min_length=1, max_length=128)
  31. status: ModelStatus | None = None
  32. description: str | None = None
  33. capabilities_json: list[str] | None = None
  34. context_window: int | None = Field(default=None, ge=1)
  35. max_output_tokens: int | None = Field(default=None, ge=1)
  36. default_temperature: float | None = Field(default=None, ge=0, le=2)
  37. timeout_seconds: float | None = Field(default=None, ge=1, le=300)
  38. metadata_json: dict[str, JSONValue] | None = None
  39. class ModelStatusUpdateRequest(BaseModel):
  40. status: ModelStatus
  41. class ModelResponse(BaseModel):
  42. id: str
  43. code: str
  44. name: str
  45. provider_type: str
  46. provider_base_url: str
  47. has_provider_api_key: bool
  48. model_name: str
  49. status: ModelStatus
  50. description: str | None = None
  51. capabilities_json: list[str] = Field(default_factory=list)
  52. context_window: int | None = None
  53. max_output_tokens: int | None = None
  54. default_temperature: float | None = None
  55. timeout_seconds: float
  56. metadata_json: dict[str, JSONValue] | None = None
  57. created_time: datetime
  58. updated_time: datetime
  59. @classmethod
  60. def from_entity(cls, entity: "ModelDefinition") -> "ModelResponse":
  61. return cls(
  62. id=entity.id,
  63. code=entity.code,
  64. name=entity.name,
  65. provider_type=entity.provider_type,
  66. provider_base_url=entity.provider_base_url,
  67. has_provider_api_key=bool(entity.provider_api_key),
  68. model_name=entity.model_name,
  69. status=entity.status,
  70. description=entity.description,
  71. capabilities_json=list(entity.capabilities_json or []),
  72. context_window=entity.context_window,
  73. max_output_tokens=entity.max_output_tokens,
  74. default_temperature=entity.default_temperature,
  75. timeout_seconds=entity.timeout_seconds,
  76. metadata_json=entity.metadata_json,
  77. created_time=entity.created_time,
  78. updated_time=entity.updated_time,
  79. )
  80. class ModelTestRequest(BaseModel):
  81. prompt: str = Field(default="Reply with a short readiness check.", min_length=1)
  82. system_prompt: str | None = "You are a concise model connectivity checker."
  83. temperature: float | None = Field(default=None, ge=0, le=2)
  84. max_tokens: int | None = Field(default=128, ge=1)
  85. class ModelTestResponse(BaseModel):
  86. model: ModelResponse
  87. response: ChatCompletionResponseContract