divi 0.0.1b0__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.
- divi/__init__.py +18 -0
- divi/decorators/__init__.py +4 -0
- divi/decorators/collect.py +34 -0
- divi/decorators/obs_openai.py +48 -0
- divi/decorators/observable.py +91 -0
- divi/decorators/observe.py +47 -0
- divi/evaluation/__init__.py +4 -0
- divi/evaluation/evaluate.py +61 -0
- divi/evaluation/evaluator.py +174 -0
- divi/evaluation/prompts.py +19 -0
- divi/evaluation/scores.py +8 -0
- divi/proto/common/v1/common.proto +49 -0
- divi/proto/common/v1/common_pb2.py +43 -0
- divi/proto/common/v1/common_pb2.pyi +44 -0
- divi/proto/core/health/v1/health_service.proto +17 -0
- divi/proto/core/health/v1/health_service_pb2.py +41 -0
- divi/proto/core/health/v1/health_service_pb2.pyi +19 -0
- divi/proto/core/health/v1/health_service_pb2_grpc.py +100 -0
- divi/proto/metric/v1/metric.proto +26 -0
- divi/proto/metric/v1/metric_pb2.py +40 -0
- divi/proto/metric/v1/metric_pb2.pyi +25 -0
- divi/proto/trace/v1/trace.proto +50 -0
- divi/proto/trace/v1/trace_pb2.py +42 -0
- divi/proto/trace/v1/trace_pb2.pyi +42 -0
- divi/services/__init__.py +7 -0
- divi/services/auth/__init__.py +4 -0
- divi/services/auth/auth.py +13 -0
- divi/services/auth/init.py +22 -0
- divi/services/auth/tokman.py +42 -0
- divi/services/core/__init__.py +5 -0
- divi/services/core/core.py +35 -0
- divi/services/core/finish.py +15 -0
- divi/services/core/init.py +70 -0
- divi/services/datapark/__init__.py +4 -0
- divi/services/datapark/datapark.py +91 -0
- divi/services/datapark/init.py +21 -0
- divi/services/finish.py +9 -0
- divi/services/init.py +10 -0
- divi/services/service.py +54 -0
- divi/session/__init__.py +3 -0
- divi/session/session.py +40 -0
- divi/session/setup.py +48 -0
- divi/session/teardown.py +7 -0
- divi/signals/__init__.py +3 -0
- divi/signals/span.py +83 -0
- divi/signals/trace.py +79 -0
- divi/utils.py +49 -0
- divi-0.0.1b0.dist-info/METADATA +18 -0
- divi-0.0.1b0.dist-info/RECORD +51 -0
- divi-0.0.1b0.dist-info/WHEEL +4 -0
- divi-0.0.1b0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,91 @@
|
|
1
|
+
from typing import Any, Dict
|
2
|
+
|
3
|
+
from google.protobuf.json_format import MessageToDict
|
4
|
+
from openai import NotGiven
|
5
|
+
from openai.types.chat import ChatCompletion
|
6
|
+
from pydantic import UUID4
|
7
|
+
from typing_extensions import List, Mapping
|
8
|
+
|
9
|
+
import divi
|
10
|
+
from divi.evaluation.evaluator import EvaluationScore
|
11
|
+
from divi.proto.trace.v1.trace_pb2 import ScopeSpans
|
12
|
+
from divi.services.service import Service
|
13
|
+
from divi.session.session import SessionSignal
|
14
|
+
from divi.signals.trace import TraceSignal
|
15
|
+
|
16
|
+
|
17
|
+
class DataPark(Service):
|
18
|
+
def __init__(self, host="localhost", port=3001):
|
19
|
+
super().__init__(host, port)
|
20
|
+
if not divi._auth:
|
21
|
+
raise ValueError("No auth service")
|
22
|
+
self.token = divi._auth.token
|
23
|
+
|
24
|
+
@property
|
25
|
+
def headers(self) -> Dict[str, str]:
|
26
|
+
return {"Authorization": f"Bearer {self.token}"}
|
27
|
+
|
28
|
+
@staticmethod
|
29
|
+
def strip_not_given(obj: object | None) -> object:
|
30
|
+
"""Remove all top-level keys where their values are instances of `NotGiven`"""
|
31
|
+
if obj is None:
|
32
|
+
return None
|
33
|
+
|
34
|
+
if not isinstance(obj, Mapping):
|
35
|
+
return obj
|
36
|
+
|
37
|
+
return {
|
38
|
+
key: value
|
39
|
+
for key, value in obj.items()
|
40
|
+
if not isinstance(value, NotGiven)
|
41
|
+
}
|
42
|
+
|
43
|
+
def create_session(self, session: SessionSignal) -> None:
|
44
|
+
self.post("/api/session/", payload=session)
|
45
|
+
|
46
|
+
def upsert_traces(
|
47
|
+
self, session_id: UUID4, traces: list[TraceSignal]
|
48
|
+
) -> None:
|
49
|
+
self.post(f"/api/session/{session_id}/traces", payload=traces)
|
50
|
+
|
51
|
+
def create_spans(self, trace_id: UUID4, spans: ScopeSpans) -> None:
|
52
|
+
self.post(f"/api/trace/{trace_id}/spans", payload=MessageToDict(spans))
|
53
|
+
|
54
|
+
def create_chat_completion(
|
55
|
+
self,
|
56
|
+
span_id: bytes,
|
57
|
+
trace_id: UUID4,
|
58
|
+
inputs: Dict[str, Any],
|
59
|
+
completion: ChatCompletion,
|
60
|
+
) -> None:
|
61
|
+
hex_span_id = span_id.hex()
|
62
|
+
str_trace_id = str(trace_id)
|
63
|
+
|
64
|
+
self.post_concurrent(
|
65
|
+
{
|
66
|
+
"/api/v1/chat/completions/input": {
|
67
|
+
"span_id": hex_span_id,
|
68
|
+
"data": self.strip_not_given(inputs),
|
69
|
+
},
|
70
|
+
"/api/v1/chat/completions": {
|
71
|
+
"span_id": hex_span_id,
|
72
|
+
"trace_id": str_trace_id,
|
73
|
+
"data": completion.model_dump(),
|
74
|
+
},
|
75
|
+
}
|
76
|
+
)
|
77
|
+
|
78
|
+
def create_scores(
|
79
|
+
self,
|
80
|
+
span_id: bytes,
|
81
|
+
trace_id: UUID4,
|
82
|
+
scores: List[EvaluationScore],
|
83
|
+
) -> None:
|
84
|
+
self.post(
|
85
|
+
"/api/v1/chat/completions/scores",
|
86
|
+
payload={
|
87
|
+
"span_id": span_id.hex(),
|
88
|
+
"trace_id": str(trace_id),
|
89
|
+
"data": [score.model_dump() for score in scores],
|
90
|
+
},
|
91
|
+
)
|
@@ -0,0 +1,21 @@
|
|
1
|
+
import os
|
2
|
+
|
3
|
+
from typing_extensions import Optional
|
4
|
+
|
5
|
+
from divi.services.datapark import DataPark
|
6
|
+
|
7
|
+
DIVI_DATAPARK_HOST = "DIVI_DATAPARK_HOST"
|
8
|
+
DIVI_DATAPARK_PORT = "DIVI_DATAPARK_PORT"
|
9
|
+
|
10
|
+
|
11
|
+
def init_datapark(
|
12
|
+
host: Optional[str] = None, port: Optional[int] = None
|
13
|
+
) -> DataPark:
|
14
|
+
host = (
|
15
|
+
host
|
16
|
+
if host
|
17
|
+
else os.getenv(DIVI_DATAPARK_HOST, "datapark.divine-agent.com")
|
18
|
+
)
|
19
|
+
port = port if port else int(os.getenv(DIVI_DATAPARK_PORT, 80))
|
20
|
+
|
21
|
+
return DataPark(host=host, port=port)
|
divi/services/finish.py
ADDED
divi/services/init.py
ADDED
divi/services/service.py
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
from concurrent.futures import ThreadPoolExecutor
|
2
|
+
from typing import Any, Dict, Mapping, Sequence
|
3
|
+
|
4
|
+
import requests
|
5
|
+
|
6
|
+
|
7
|
+
class Service:
|
8
|
+
"""Service management class."""
|
9
|
+
|
10
|
+
def __init__(self, host: str, port: int):
|
11
|
+
self.host = host
|
12
|
+
self.port = port
|
13
|
+
|
14
|
+
@property
|
15
|
+
def target(self) -> str:
|
16
|
+
"""Return the target string: host:port."""
|
17
|
+
return f"{self.host}:{self.port}"
|
18
|
+
|
19
|
+
@property
|
20
|
+
def headers(self) -> Dict[str, str]:
|
21
|
+
"""Override to provide default headers."""
|
22
|
+
return {}
|
23
|
+
|
24
|
+
def post(
|
25
|
+
self,
|
26
|
+
path: str,
|
27
|
+
payload: Mapping[str, Any] | Sequence[Mapping[str, Any]],
|
28
|
+
) -> Any:
|
29
|
+
response = requests.post(
|
30
|
+
f"http://{self.target}{path}",
|
31
|
+
json=payload,
|
32
|
+
headers=self.headers,
|
33
|
+
)
|
34
|
+
if not 200 <= response.status_code < 300:
|
35
|
+
raise ValueError(
|
36
|
+
f"{path} failed: {response.json().get('message', 'Unknown error')}"
|
37
|
+
)
|
38
|
+
return response.json().get("data", response.json())
|
39
|
+
|
40
|
+
def post_concurrent(
|
41
|
+
self,
|
42
|
+
calls: Dict[str, Mapping[str, Any] | Sequence[Mapping[str, Any]]],
|
43
|
+
) -> None:
|
44
|
+
with ThreadPoolExecutor(max_workers=len(calls)) as executor:
|
45
|
+
futures = [
|
46
|
+
executor.submit(
|
47
|
+
self.post,
|
48
|
+
path,
|
49
|
+
payload,
|
50
|
+
)
|
51
|
+
for path, payload in calls.items()
|
52
|
+
]
|
53
|
+
for future in futures:
|
54
|
+
future.result()
|
divi/session/__init__.py
ADDED
divi/session/session.py
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
from typing import Optional, TypedDict
|
2
|
+
from uuid import uuid4
|
3
|
+
|
4
|
+
from divi.signals.trace import Trace
|
5
|
+
|
6
|
+
|
7
|
+
class SessionExtra(TypedDict, total=False):
|
8
|
+
"""Extra information for Session"""
|
9
|
+
|
10
|
+
session_name: Optional[str]
|
11
|
+
"""Name of the session"""
|
12
|
+
trace: Trace
|
13
|
+
"""Trace in session"""
|
14
|
+
parent_span_id: Optional[bytes]
|
15
|
+
"""Parent Span ID fixed string(8)"""
|
16
|
+
|
17
|
+
|
18
|
+
class SessionSignal(TypedDict):
|
19
|
+
"""Session request"""
|
20
|
+
|
21
|
+
id: str
|
22
|
+
"""Session ID UUID4"""
|
23
|
+
name: Optional[str]
|
24
|
+
"""Session name"""
|
25
|
+
|
26
|
+
|
27
|
+
class Session:
|
28
|
+
def __init__(
|
29
|
+
self,
|
30
|
+
name: Optional[str] = None,
|
31
|
+
):
|
32
|
+
self.id = uuid4()
|
33
|
+
self.name = name
|
34
|
+
|
35
|
+
@property
|
36
|
+
def signal(self) -> SessionSignal:
|
37
|
+
return SessionSignal(
|
38
|
+
id=str(self.id),
|
39
|
+
name=self.name,
|
40
|
+
)
|
divi/session/setup.py
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
from typing_extensions import Optional
|
2
|
+
|
3
|
+
import divi
|
4
|
+
from divi.services import init_services
|
5
|
+
from divi.session import Session, SessionExtra
|
6
|
+
from divi.signals.span import Span
|
7
|
+
from divi.signals.trace import Trace
|
8
|
+
|
9
|
+
|
10
|
+
def init_session(name: Optional[str] = None) -> Session:
|
11
|
+
"""init initializes the services and the Run"""
|
12
|
+
init_services()
|
13
|
+
session = Session(name=name)
|
14
|
+
if divi._datapark:
|
15
|
+
divi._datapark.create_session(session.signal)
|
16
|
+
return session
|
17
|
+
|
18
|
+
|
19
|
+
def setup(
|
20
|
+
span: Span,
|
21
|
+
session_extra: SessionExtra | None,
|
22
|
+
):
|
23
|
+
"""setup trace
|
24
|
+
|
25
|
+
Args:
|
26
|
+
span (Span): Span instance
|
27
|
+
session_extra (SessionExtra | None): Extra information from user input
|
28
|
+
"""
|
29
|
+
session_extra = session_extra or SessionExtra()
|
30
|
+
|
31
|
+
# init the session if not already initialized
|
32
|
+
if not divi._session:
|
33
|
+
divi._session = init_session(
|
34
|
+
name=session_extra.get("session_name") or span.name
|
35
|
+
)
|
36
|
+
|
37
|
+
# setup trace
|
38
|
+
trace = session_extra.get("trace") or Trace(divi._session.id, span.name)
|
39
|
+
parent_span_id = session_extra.get("parent_span_id")
|
40
|
+
span._add_node(trace.trace_id, parent_span_id)
|
41
|
+
|
42
|
+
# update the session_extra with the current trace and span
|
43
|
+
return SessionExtra(
|
44
|
+
session_name=divi._session.name,
|
45
|
+
trace=trace,
|
46
|
+
# set the parent_span_id to the current span_id
|
47
|
+
parent_span_id=span.span_id,
|
48
|
+
)
|
divi/session/teardown.py
ADDED
divi/signals/__init__.py
ADDED
divi/signals/span.py
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
import os
|
2
|
+
import time
|
3
|
+
from enum import Enum
|
4
|
+
from typing import Any, Mapping, Optional
|
5
|
+
|
6
|
+
from pydantic import UUID4
|
7
|
+
|
8
|
+
import divi
|
9
|
+
from divi.proto.common.v1.common_pb2 import KeyValue
|
10
|
+
from divi.proto.trace.v1.trace_pb2 import ScopeSpans
|
11
|
+
from divi.proto.trace.v1.trace_pb2 import Span as SpanProto
|
12
|
+
|
13
|
+
|
14
|
+
class Kind(int, Enum):
|
15
|
+
"""Enum for the kind of span."""
|
16
|
+
|
17
|
+
function = SpanProto.SpanKind.SPAN_KIND_FUNCTION
|
18
|
+
llm = SpanProto.SpanKind.SPAN_KIND_LLM
|
19
|
+
evaluation = SpanProto.SpanKind.SPAN_KIND_EVALUATION
|
20
|
+
|
21
|
+
|
22
|
+
class Span:
|
23
|
+
def __init__(
|
24
|
+
self,
|
25
|
+
kind: Kind = Kind.function,
|
26
|
+
name: Optional[str] = None,
|
27
|
+
metadata: Optional[Mapping[str, Any]] = None,
|
28
|
+
):
|
29
|
+
# span_id is a FixedString(8)
|
30
|
+
self.span_id: bytes = self._generate_span_id()
|
31
|
+
self.name = name
|
32
|
+
self.kind = kind
|
33
|
+
self.metadata = metadata
|
34
|
+
self.start_time_unix_nano: int | None = None
|
35
|
+
self.end_time_unix_nano: int | None = None
|
36
|
+
|
37
|
+
self.trace_id: UUID4 | None = None
|
38
|
+
self.parent_span_id: bytes | None = None
|
39
|
+
|
40
|
+
@property
|
41
|
+
def signal(self) -> SpanProto:
|
42
|
+
signal: SpanProto = SpanProto(
|
43
|
+
name=self.name,
|
44
|
+
span_id=self.span_id,
|
45
|
+
kind=SpanProto.SpanKind.Name(self.kind),
|
46
|
+
start_time_unix_nano=self.start_time_unix_nano,
|
47
|
+
end_time_unix_nano=self.end_time_unix_nano,
|
48
|
+
trace_id=self.trace_id.bytes if self.trace_id else None,
|
49
|
+
parent_span_id=self.parent_span_id,
|
50
|
+
)
|
51
|
+
signal.metadata.extend(
|
52
|
+
KeyValue(key=k, value=v)
|
53
|
+
for k, v in (self.metadata or dict()).items()
|
54
|
+
)
|
55
|
+
return signal
|
56
|
+
|
57
|
+
@classmethod
|
58
|
+
def _generate_span_id(cls) -> bytes:
|
59
|
+
return os.urandom(8)
|
60
|
+
|
61
|
+
def start(self):
|
62
|
+
"""Start the span by recording the current time in nanoseconds."""
|
63
|
+
self.start_time_unix_nano = time.time_ns()
|
64
|
+
self.upsert_span()
|
65
|
+
|
66
|
+
def end(self):
|
67
|
+
"""End the span by recording the end time in nanoseconds."""
|
68
|
+
if self.start_time_unix_nano is None:
|
69
|
+
raise ValueError("Span must be started before ending.")
|
70
|
+
self.end_time_unix_nano = time.time_ns()
|
71
|
+
self.upsert_span()
|
72
|
+
|
73
|
+
def _add_node(self, trace_id: UUID4, parent_id: Optional[bytes] = None):
|
74
|
+
"""Add node for obs tree."""
|
75
|
+
self.trace_id = trace_id
|
76
|
+
self.parent_span_id = parent_id
|
77
|
+
|
78
|
+
def upsert_span(self):
|
79
|
+
"""Upsert span with datapark."""
|
80
|
+
if divi._datapark and self.trace_id:
|
81
|
+
divi._datapark.create_spans(
|
82
|
+
self.trace_id, ScopeSpans(spans=[self.signal])
|
83
|
+
)
|
divi/signals/trace.py
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
from datetime import UTC, datetime
|
2
|
+
from typing import Optional
|
3
|
+
from uuid import uuid4
|
4
|
+
|
5
|
+
from pydantic import UUID4
|
6
|
+
from typing_extensions import TypedDict
|
7
|
+
|
8
|
+
import divi
|
9
|
+
|
10
|
+
|
11
|
+
class NullTime(TypedDict, total=False):
|
12
|
+
"""Null time"""
|
13
|
+
|
14
|
+
Time: str
|
15
|
+
"""Time in iso format"""
|
16
|
+
Valid: bool
|
17
|
+
"""Valid"""
|
18
|
+
|
19
|
+
|
20
|
+
class TraceSignal(TypedDict, total=False):
|
21
|
+
"""Trace request"""
|
22
|
+
|
23
|
+
id: str
|
24
|
+
"""Trace ID UUID4"""
|
25
|
+
start_time: str
|
26
|
+
"""Start time in iso format"""
|
27
|
+
end_time: NullTime
|
28
|
+
"""End time in iso format"""
|
29
|
+
name: Optional[str]
|
30
|
+
|
31
|
+
|
32
|
+
class Trace:
|
33
|
+
def __init__(self, session_id: UUID4, name: Optional[str] = None):
|
34
|
+
self.trace_id: UUID4 = uuid4()
|
35
|
+
self.start_time: str | None = None
|
36
|
+
self.end_time: str | None = None
|
37
|
+
self.name: Optional[str] = name
|
38
|
+
self.session_id: UUID4 = session_id
|
39
|
+
|
40
|
+
self.start()
|
41
|
+
|
42
|
+
@property
|
43
|
+
def signal(self) -> TraceSignal:
|
44
|
+
if self.start_time is None:
|
45
|
+
raise ValueError("Trace must be started.")
|
46
|
+
signal = TraceSignal(
|
47
|
+
id=str(self.trace_id),
|
48
|
+
start_time=self.start_time,
|
49
|
+
name=self.name,
|
50
|
+
)
|
51
|
+
if self.end_time is not None:
|
52
|
+
signal["end_time"] = NullTime(
|
53
|
+
Time=self.end_time,
|
54
|
+
Valid=True,
|
55
|
+
)
|
56
|
+
return signal
|
57
|
+
|
58
|
+
@staticmethod
|
59
|
+
def unix_nano_to_iso(unix_nano: int) -> str:
|
60
|
+
return datetime.utcfromtimestamp(unix_nano / 1e9).isoformat()
|
61
|
+
|
62
|
+
def start(self):
|
63
|
+
"""Start the trace by recording the current time in nanoseconds."""
|
64
|
+
self.start_time = datetime.now(UTC).isoformat()
|
65
|
+
self.upsert_trace()
|
66
|
+
|
67
|
+
def end(self):
|
68
|
+
"""End the trace by recording the end time in nanoseconds."""
|
69
|
+
if self.start_time is None:
|
70
|
+
raise ValueError("Span must be started before ending.")
|
71
|
+
self.end_time = datetime.now(UTC).isoformat()
|
72
|
+
self.upsert_trace()
|
73
|
+
|
74
|
+
def upsert_trace(self):
|
75
|
+
"""Upsert trace with datapark."""
|
76
|
+
if divi._datapark:
|
77
|
+
divi._datapark.upsert_traces(
|
78
|
+
session_id=self.session_id, traces=[self.signal]
|
79
|
+
)
|
divi/utils.py
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
import inspect
|
2
|
+
import pathlib
|
3
|
+
from typing import Any, Callable, Dict
|
4
|
+
|
5
|
+
|
6
|
+
def extract_flattened_inputs(
|
7
|
+
func: Callable, *args: Any, **kwargs: Any
|
8
|
+
) -> Dict[str, Any]:
|
9
|
+
"""
|
10
|
+
Extracts a flat dictionary of parameter names and values from a function call.
|
11
|
+
Handles default values, removes 'self' and 'cls', and flattens **kwargs.
|
12
|
+
"""
|
13
|
+
signature = inspect.signature(func)
|
14
|
+
bound_args = signature.bind_partial(*args, **kwargs)
|
15
|
+
bound_args.apply_defaults()
|
16
|
+
|
17
|
+
arguments = dict(bound_args.arguments)
|
18
|
+
arguments.pop("self", None)
|
19
|
+
arguments.pop("cls", None)
|
20
|
+
|
21
|
+
for param_name, param in signature.parameters.items():
|
22
|
+
if (
|
23
|
+
param.kind == inspect.Parameter.VAR_KEYWORD
|
24
|
+
and param_name in arguments
|
25
|
+
):
|
26
|
+
kwarg_dict = arguments.pop(param_name)
|
27
|
+
if isinstance(kwarg_dict, dict):
|
28
|
+
arguments.update(kwarg_dict)
|
29
|
+
|
30
|
+
return arguments
|
31
|
+
|
32
|
+
|
33
|
+
def get_server_path() -> str:
|
34
|
+
"""Get the path to the server binary."""
|
35
|
+
path = pathlib.Path(__file__).parent / "bin" / "core"
|
36
|
+
if not path.exists():
|
37
|
+
raise FileNotFoundError(f"Server binary not found: {path}")
|
38
|
+
|
39
|
+
return str(path)
|
40
|
+
|
41
|
+
|
42
|
+
def is_async(func: Callable) -> bool:
|
43
|
+
"""Inspect function or wrapped function to see if it is async."""
|
44
|
+
unwrapped_func = inspect.unwrap(func)
|
45
|
+
return inspect.iscoroutinefunction(unwrapped_func)
|
46
|
+
|
47
|
+
|
48
|
+
if __name__ == "__main__":
|
49
|
+
print(get_server_path())
|
@@ -0,0 +1,18 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: divi
|
3
|
+
Version: 0.0.1b0
|
4
|
+
Summary: The Agent Platform for Observability & Evaluation
|
5
|
+
License-File: LICENSE
|
6
|
+
Requires-Python: >=3.11
|
7
|
+
Requires-Dist: grpcio>=1.71.0
|
8
|
+
Requires-Dist: openai>=1.65.2
|
9
|
+
Requires-Dist: protobuf<6.0.dev0,>=5.26.1
|
10
|
+
Requires-Dist: pyjwt>=2.10.1
|
11
|
+
Requires-Dist: requests>=2.32.3
|
12
|
+
Description-Content-Type: text/markdown
|
13
|
+
|
14
|
+
# Divine Agent
|
15
|
+
|
16
|
+
Agent Platform for Observability • Evaluation • Playground
|
17
|
+
|
18
|
+
> The project is still in the development stage. 😇
|
@@ -0,0 +1,51 @@
|
|
1
|
+
divi/__init__.py,sha256=Mxu0UYIKgegwUU7gTe5jMHYZ0wf3rzwtiHfHyLcTysA,486
|
2
|
+
divi/utils.py,sha256=fXkjoyo_Lh8AZliKICOP460m0czUcNQjcEcceJbaOVA,1439
|
3
|
+
divi/decorators/__init__.py,sha256=HkyWdC1ctTsVFucCWCkj57JB4NmwONus1d2S2dUbvs4,110
|
4
|
+
divi/decorators/collect.py,sha256=5iUxAnbHYx4ISkFg64IK_4miGdrWgbOXLJxKz8lGIv8,1074
|
5
|
+
divi/decorators/obs_openai.py,sha256=ouw3GYDFg6S27tcUzY0dIqz8JX_JM8IOXttzo7HK7nk,1359
|
6
|
+
divi/decorators/observable.py,sha256=isUS3P_07wbZBj2UcRAoYNDceQTIn6zdein3-PWVsi8,2289
|
7
|
+
divi/decorators/observe.py,sha256=I2RVsp2WQep6iTLSxkAlMP8wiRsSYiiYrxR2hJzPxcI,1211
|
8
|
+
divi/evaluation/__init__.py,sha256=3qMHWu_zBh6FJa6-1dZZEWiAblQZurn5doa0OjGvDGs,93
|
9
|
+
divi/evaluation/evaluate.py,sha256=lVMCw5vHGa5sJvUyhVDZ9m3Sgl4baCjWhw2OKazhvgM,1861
|
10
|
+
divi/evaluation/evaluator.py,sha256=ulTyfSg2JXxzCCL7hRsn-EBb9UKcpQFA6rVT42mouVQ,5819
|
11
|
+
divi/evaluation/prompts.py,sha256=4oL8K8X2-zdmTDuAetc53o7Ys_vph-eWYhPmvRKYAng,960
|
12
|
+
divi/evaluation/scores.py,sha256=ZgSxfve-ZivX3WU4TGcgPOSpUQVMbG5a15IQNPeq_bQ,173
|
13
|
+
divi/proto/common/v1/common.proto,sha256=Rx8wr0_tOtQ1NseTMnsav4ApD1MDALzQDBA2IvLRTU0,1775
|
14
|
+
divi/proto/common/v1/common_pb2.py,sha256=br61OHQVAi6SI3baFcb5xJv2Xd-AZ04A19xeSjLNMXo,2442
|
15
|
+
divi/proto/common/v1/common_pb2.pyi,sha256=LmTpFFLxHg2a_qPIdNXXwGEMkbiDcTJdarR9eC-6Fq8,2133
|
16
|
+
divi/proto/core/health/v1/health_service.proto,sha256=y39MNiwYiSqxb_JPQI7AmPfNNtP6pbX-WKTseMkjWUM,369
|
17
|
+
divi/proto/core/health/v1/health_service_pb2.py,sha256=PKAxy_z7lU1HrwDNIa7AFHha9i8gICCVrcEhpOM79E0,1999
|
18
|
+
divi/proto/core/health/v1/health_service_pb2.pyi,sha256=VbYHHTcp3epUVg0lTSxo3xpG52ZGhA7KKMRL5LR5e1c,691
|
19
|
+
divi/proto/core/health/v1/health_service_pb2_grpc.py,sha256=YmlO94d-G71YBW1XZDSbYkwnHEUe6Z7R3_KAmoDWyA0,3953
|
20
|
+
divi/proto/metric/v1/metric.proto,sha256=YHRMLUW-MtakHuibR3PJ0s2w5KgV12kc4737iHw0DTk,585
|
21
|
+
divi/proto/metric/v1/metric_pb2.py,sha256=uvBhyy8QpaES3Jl82yVfsGazW5654XpRnsdGlpVgIRE,1974
|
22
|
+
divi/proto/metric/v1/metric_pb2.pyi,sha256=S7ipsojkD7QZAYefDE4b3PO99Yzc6mOdtSLxH3-b67A,1304
|
23
|
+
divi/proto/trace/v1/trace.proto,sha256=tPRIgBZB5KOKj7AoD3NoDZvLwoiJkbLiLqW53Ah-2-0,1367
|
24
|
+
divi/proto/trace/v1/trace_pb2.py,sha256=zMuQO5mN2xl11USHkhi0lLwBAPlYXRU_UG1r0Uu3mJg,2369
|
25
|
+
divi/proto/trace/v1/trace_pb2.pyi,sha256=k4dHYKAusH4I-XSW9KP3maogSWdRL7hVy8HCHhqFWzM,2231
|
26
|
+
divi/services/__init__.py,sha256=AuFqnDAhi_ZGIhEVMvTu5cUmw1tEzjQSjP6m9uB3df4,203
|
27
|
+
divi/services/finish.py,sha256=XKPKGJ5cWd5H95G_VpIOlOZOLrcf9StoTs7ayRic2jY,173
|
28
|
+
divi/services/init.py,sha256=uJi6Mma8XQgShwWB5HyoFXaeIw8iQy9TCMQ40vuARbk,249
|
29
|
+
divi/services/service.py,sha256=539MhcYfMvsVGjDdu0UtYSZnL2cloaPeYeOSMl2eUy8,1532
|
30
|
+
divi/services/auth/__init__.py,sha256=vZkOIozH_TB6CGV3IOt9NYCuj5KNHO5tfpL4YqAnZ-Y,84
|
31
|
+
divi/services/auth/auth.py,sha256=eRcE6Kq8jbBr6YL93HCGDIoga90SoZf3ogOAKeza9WY,445
|
32
|
+
divi/services/auth/init.py,sha256=ydwR70ue-0S5C5e3mhc8eeHzS8zphUkHGfvRGdEi-cI,624
|
33
|
+
divi/services/auth/tokman.py,sha256=V03wcV6TEy1k9o55teDVB9JZ3Ve2cJdwzWstQhWx4BQ,1070
|
34
|
+
divi/services/core/__init__.py,sha256=y0GAqZyYz1YuZY2PVbU3O34nldeCcZeSlkgAOUlWwGs,121
|
35
|
+
divi/services/core/core.py,sha256=PRwPtLgrgmCrejUfKf7HJNrAhGS0paFNZ7JwDToEUAk,1264
|
36
|
+
divi/services/core/finish.py,sha256=dIGQpVXcJY4-tKe7A1_VV3yoSHNCDPfOlUltvzvk6VI,231
|
37
|
+
divi/services/core/init.py,sha256=s8ZnQDu4leP8XaarpXpDttnOp7bseAJCgIPRYjj8zag,1931
|
38
|
+
divi/services/datapark/__init__.py,sha256=xDkN0GPVhVuhwMenzVnkz5qguhQIyOpbFAkS1GUe-EM,104
|
39
|
+
divi/services/datapark/datapark.py,sha256=f-qE2kmkLAniIj9mOP3nCbI3A3qkfIUnoVekwQ5w0QE,2781
|
40
|
+
divi/services/datapark/init.py,sha256=XcqVPQn5PytQo8b9fgLUQdRSFHug0ZQiiL56cn4fBus,506
|
41
|
+
divi/session/__init__.py,sha256=6lYemv21VQCIHx-xIdi7BxXcPNxVdvE60--8ArReUew,82
|
42
|
+
divi/session/session.py,sha256=QxtEezI447PbtKG2U6cxL1ACae55e8nFfTufAY8pEYI,811
|
43
|
+
divi/session/setup.py,sha256=rC1QdCxpdCOaRXmcLEQs4Yuu5UC_aRzKSaqWRPJN4Og,1390
|
44
|
+
divi/session/teardown.py,sha256=YiBz_3yCiljMFEofZ60VmRL5sb8WA5GT7EYF8nFznZ4,133
|
45
|
+
divi/signals/__init__.py,sha256=wfSkkCwkRsFP4aLj8aGHk_k6Y50P5yN44WWlO3XyW18,43
|
46
|
+
divi/signals/span.py,sha256=FQWql6ivAeXGk1HPZCsCjL5mXW6S6Nn9SmOiKH4aXik,2629
|
47
|
+
divi/signals/trace.py,sha256=IoYeTfd6x_Xmxcp4HbFSEne0d48hol4ng2Mb_AO8hZw,2144
|
48
|
+
divi-0.0.1b0.dist-info/METADATA,sha256=BW1GBcbxovWLvVJGoDylvomnBVaApGtJkTSgHIRBtuw,493
|
49
|
+
divi-0.0.1b0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
50
|
+
divi-0.0.1b0.dist-info/licenses/LICENSE,sha256=5OJuZ4wMMEV0DgF0tofhAlS_KLkaUsZwwwDS2U_GwQ0,1063
|
51
|
+
divi-0.0.1b0.dist-info/RECORD,,
|
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2025 Kaikai
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|