arbor-ai 0.1.4__py3-none-any.whl → 0.1.6__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,76 +1,81 @@
1
1
  import uuid
2
- from enum import Enum
3
- import logging
4
2
  from datetime import datetime
3
+ from typing import Literal
4
+
5
+ from arbor.server.api.models.schemas import JobStatus
6
+ from arbor.server.core.config import Settings
7
+
8
+
9
+ class JobEvent:
10
+ def __init__(
11
+ self, level: Literal["info", "warning", "error"], message: str, data: dict = {}
12
+ ):
13
+ self.level = level
14
+ self.message = message
15
+ self.data = data
16
+
17
+ self.id = str(f"ftevent-{uuid.uuid4()}")
18
+ self.created_at = datetime.now()
19
+
20
+
21
+ class JobCheckpoint:
22
+ def __init__(
23
+ self,
24
+ fine_tuned_model_checkpoint: str,
25
+ fine_tuning_job_id: str,
26
+ metrics: dict,
27
+ step_number: int,
28
+ ):
29
+ self.id = str(f"ftckpt-{uuid.uuid4()}")
30
+ self.fine_tuned_model_checkpoint = fine_tuned_model_checkpoint
31
+ self.fine_tuning_job_id = fine_tuning_job_id
32
+ self.metrics = metrics
33
+ self.step_number = step_number
34
+ self.created_at = datetime.now()
5
35
 
6
- # https://platform.openai.com/docs/api-reference/fine-tuning/object
7
- class JobStatus(Enum):
8
- PENDING = "pending" # Not in OAI
9
- VALIDATING_FILES = "validating_files"
10
- QUEUED = "queued"
11
- RUNNING = "running"
12
- SUCCEEDED = "succeeded"
13
- FAILED = "failed"
14
- CANCELLED = "cancelled"
15
-
16
- class JobLogHandler(logging.Handler):
17
- def __init__(self, job):
18
- super().__init__()
19
- self.job = job
20
-
21
- def emit(self, record):
22
- log_entry = {
23
- 'timestamp': datetime.fromtimestamp(record.created).isoformat(),
24
- 'level': record.levelname,
25
- 'message': record.getMessage()
26
- }
27
- self.job.logs.append(log_entry)
28
36
 
29
37
  class Job:
30
- def __init__(self, id: str, status: JobStatus):
31
- self.id = id
32
- self.status = status
33
- self.fine_tuned_model = None
34
- self.logs = []
35
- self.logger = None
36
- self.log_handler = None
37
-
38
- def setup_logger(self, logger_name: str = None) -> logging.Logger:
39
- """Sets up logging for the job with a dedicated handler."""
40
- if logger_name is None:
41
- logger_name = f"job_{self.id}"
42
-
43
- logger = logging.getLogger(logger_name)
44
- logger.setLevel(logging.INFO)
45
-
46
- # Create and setup handler if not already exists
47
- if self.log_handler is None:
48
- handler = JobLogHandler(self)
49
- formatter = logging.Formatter('%(message)s')
50
- handler.setFormatter(formatter)
51
- logger.addHandler(handler)
52
- self.log_handler = handler
53
-
54
- self.logger = logger
55
- return logger
56
-
57
- def cleanup_logger(self):
58
- """Removes the job's logging handler."""
59
- if self.logger and self.log_handler:
60
- self.logger.removeHandler(self.log_handler)
61
- self.log_handler = None
62
- self.logger = None
38
+ def __init__(self, status: JobStatus):
39
+ self.id = str(f"ftjob-{uuid.uuid4()}")
40
+ self.status = status
41
+ self.fine_tuned_model = None
42
+ self.events: list[JobEvent] = []
43
+ self.checkpoints: list[JobCheckpoint] = []
44
+
45
+ self.created_at = datetime.now()
46
+
47
+ def add_event(self, event: JobEvent):
48
+ self.events.append(event)
49
+
50
+ def get_events(self) -> list[JobEvent]:
51
+ return self.events
52
+
53
+ def add_checkpoint(self, checkpoint: JobCheckpoint):
54
+ self.checkpoints.append(checkpoint)
55
+
56
+ def get_checkpoints(self) -> list[JobCheckpoint]:
57
+ return self.checkpoints
58
+
63
59
 
64
60
  class JobManager:
65
- def __init__(self):
66
- self.jobs = {}
67
-
68
- def get_job(self, job_id: str):
69
- if job_id not in self.jobs:
70
- raise ValueError(f"Job {job_id} not found")
71
- return self.jobs[job_id]
72
-
73
- def create_job(self):
74
- job = Job(id=str(uuid.uuid4()), status=JobStatus.PENDING)
75
- self.jobs[job.id] = job
76
- return job
61
+ def __init__(self, settings: Settings):
62
+ self.jobs = {}
63
+
64
+ def get_job(self, job_id: str):
65
+ if job_id not in self.jobs:
66
+ raise ValueError(f"Job {job_id} not found")
67
+ return self.jobs[job_id]
68
+
69
+ def create_job(self):
70
+ job = Job(status=JobStatus.PENDING)
71
+ self.jobs[job.id] = job
72
+ return job
73
+
74
+ def get_jobs(self):
75
+ return list(self.jobs.values())
76
+
77
+ def get_active_job(self):
78
+ for job in self.jobs.values():
79
+ if job.status == JobStatus.RUNNING:
80
+ return job
81
+ return None