Victor Dibia 32d2a18bf1
[Draft] Enable File Upload/Paste as Task in AGS (#6091)
<!-- Thank you for your contribution! Please review
https://microsoft.github.io/autogen/docs/Contribute before opening a
pull request. -->

<!-- Please add a reviewer to the assignee section when you create a PR.
If you don't have the access to it, we will shortly find a reviewer and
assign them to your PR. -->

## Why are these changes needed?



https://github.com/user-attachments/assets/e160f16d-f42d-49e2-a6c6-687e4e6786f4



Enable file upload/paste as a task in AGS. Enables tasks like

- Can you research and fact check the ideas in this screenshot?
- Summarize this file

Only text and images supported for now
Underneath, it constructs TextMessage and Multimodal messages as the
task.

<!-- Please give a short summary of the change and the problem this
solves. -->

## Related issue number

<!-- For example: "Closes #1234" -->

Closes #5773 

## Checks

- [ ] I've included any doc changes needed for
<https://microsoft.github.io/autogen/>. See
<https://github.com/microsoft/autogen/blob/main/CONTRIBUTING.md> to
build and test documentation locally.
- [ ] I've added tests (if relevant) corresponding to the changes
introduced in this PR.
- [ ] I've made sure all auto checks have passed.

---------

Co-authored-by: Jack Gerrits <jackgerrits@users.noreply.github.com>
2025-04-09 02:44:45 +00:00

199 lines
6.5 KiB
Python

# defines how core data types in autogenstudio are serialized and stored in the database
from datetime import datetime
from enum import Enum
from typing import Any, Dict, List, Optional, Union
from autogen_core import ComponentModel
from pydantic import ConfigDict, SecretStr, field_validator
from sqlalchemy import ForeignKey, Integer
from sqlmodel import JSON, Column, DateTime, Field, SQLModel, func
from .eval import EvalJudgeCriteria, EvalRunResult, EvalRunStatus, EvalScore, EvalTask
from .types import (
GalleryComponents,
GalleryConfig,
GalleryMetadata,
MessageConfig,
MessageMeta,
SettingsConfig,
TeamResult,
)
class BaseDBModel(SQLModel, table=False):
"""
Base model with common fields for all database tables.
Not a table itself - meant to be inherited by concrete model classes.
"""
__abstract__ = True
# Common fields present in all database tables
id: Optional[int] = Field(default=None, primary_key=True)
created_at: datetime = Field(
default_factory=datetime.now,
sa_type=DateTime(timezone=True), # type: ignore[assignment]
sa_column_kwargs={"server_default": func.now(), "nullable": True},
)
updated_at: datetime = Field(
default_factory=datetime.now,
sa_type=DateTime(timezone=True), # type: ignore[assignment]
sa_column_kwargs={"onupdate": func.now(), "nullable": True},
)
user_id: Optional[str] = None
version: Optional[str] = "0.0.1"
class Team(BaseDBModel, table=True):
__table_args__ = {"sqlite_autoincrement": True}
component: Union[ComponentModel, dict] = Field(sa_column=Column(JSON))
class Message(BaseDBModel, table=True):
__table_args__ = {"sqlite_autoincrement": True}
config: Union[MessageConfig, dict] = Field(
default_factory=lambda: MessageConfig(source="", content=""), sa_column=Column(JSON)
)
session_id: Optional[int] = Field(
default=None, sa_column=Column(Integer, ForeignKey("session.id", ondelete="NO ACTION"))
)
run_id: Optional[int] = Field(default=None, sa_column=Column(Integer, ForeignKey("run.id", ondelete="CASCADE")))
message_meta: Optional[Union[MessageMeta, dict]] = Field(default={}, sa_column=Column(JSON))
class Session(BaseDBModel, table=True):
__table_args__ = {"sqlite_autoincrement": True}
team_id: Optional[int] = Field(default=None, sa_column=Column(Integer, ForeignKey("team.id", ondelete="CASCADE")))
name: Optional[str] = None
@field_validator("created_at", "updated_at", mode="before")
@classmethod
def parse_datetime(cls, value: Union[str, datetime]) -> datetime:
if isinstance(value, str):
return datetime.fromisoformat(value.replace("Z", "+00:00"))
return value
class RunStatus(str, Enum):
CREATED = "created"
ACTIVE = "active"
COMPLETE = "complete"
ERROR = "error"
STOPPED = "stopped"
class Run(BaseDBModel, table=True):
"""Represents a single execution run within a session"""
__table_args__ = {"sqlite_autoincrement": True}
session_id: Optional[int] = Field(
default=None, sa_column=Column(Integer, ForeignKey("session.id", ondelete="CASCADE"), nullable=False)
)
status: RunStatus = Field(default=RunStatus.CREATED)
# Store the original user task
task: Union[MessageConfig, dict] = Field(
default_factory=lambda: MessageConfig(source="", content=""), sa_column=Column(JSON)
)
# Store TeamResult which contains TaskResult
team_result: Union[TeamResult, dict] = Field(default=None, sa_column=Column(JSON))
error_message: Optional[str] = None
version: Optional[str] = "0.0.1"
messages: Union[List[Message], List[dict]] = Field(default_factory=list, sa_column=Column(JSON))
model_config = ConfigDict(json_encoders={datetime: lambda v: v.isoformat()}) # type: ignore[call-arg]
user_id: Optional[str] = None
class Gallery(BaseDBModel, table=True):
__table_args__ = {"sqlite_autoincrement": True}
config: Union[GalleryConfig, dict] = Field(
default_factory=lambda: GalleryConfig(
id="",
name="",
metadata=GalleryMetadata(author="", version=""),
components=GalleryComponents(agents=[], models=[], tools=[], terminations=[], teams=[]),
),
sa_column=Column(JSON),
)
model_config = ConfigDict(
json_encoders={
datetime: lambda v: v.isoformat(),
SecretStr: lambda v: v.get_secret_value(), # Add this line
}
) # type: ignore[call-arg]
class Settings(BaseDBModel, table=True):
__table_args__ = {"sqlite_autoincrement": True}
config: Union[SettingsConfig, dict] = Field(default_factory=SettingsConfig, sa_column=Column(JSON))
# --- Evaluation system database models ---
class EvalTaskDB(BaseDBModel, table=True):
"""Database model for storing evaluation tasks."""
__table_args__ = {"sqlite_autoincrement": True}
name: str = "Unnamed Task"
description: str = ""
config: Union[EvalTask, dict] = Field(sa_column=Column(JSON))
class EvalCriteriaDB(BaseDBModel, table=True):
"""Database model for storing evaluation criteria."""
__table_args__ = {"sqlite_autoincrement": True}
name: str = "Unnamed Criteria"
description: str = ""
config: Union[EvalJudgeCriteria, dict] = Field(sa_column=Column(JSON))
class EvalRunDB(BaseDBModel, table=True):
"""Database model for tracking evaluation runs."""
__table_args__ = {"sqlite_autoincrement": True}
name: str = "Unnamed Evaluation Run"
description: str = ""
# References to related components
task_id: Optional[int] = Field(
default=None, sa_column=Column(Integer, ForeignKey("evaltaskdb.id", ondelete="SET NULL"))
)
# Serialized configurations for runner and judge
runner_config: Union[ComponentModel, dict] = Field(sa_column=Column(JSON))
judge_config: Union[ComponentModel, dict] = Field(sa_column=Column(JSON))
# List of criteria IDs or embedded criteria configs
criteria_configs: List[Union[EvalJudgeCriteria, dict]] = Field(default_factory=list, sa_column=Column(JSON))
# Run status and timing information
status: EvalRunStatus = Field(default=EvalRunStatus.PENDING)
start_time: Optional[datetime] = Field(default=None)
end_time: Optional[datetime] = Field(default=None)
# Results (updated as they become available)
run_result: Union[EvalRunResult, dict] = Field(default=None, sa_column=Column(JSON))
score_result: Union[EvalScore, dict] = Field(default=None, sa_column=Column(JSON))
# Additional metadata
error_message: Optional[str] = None