divi 0.0.1.dev21__py3-none-any.whl → 0.0.1.dev23__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 CHANGED
@@ -12,5 +12,5 @@ _core: Optional[Core] = None
12
12
  _auth: Optional[Auth] = None
13
13
  _datapark: Optional[DataPark] = None
14
14
 
15
- __version__ = "0.0.1.dev21"
15
+ __version__ = "0.0.1.dev23"
16
16
  __all__ = ["proto", "obs_openai", "observable"]
@@ -18,7 +18,6 @@ def _get_observable_create(create: Callable) -> Callable:
18
18
  return decorator(create)(*args, stream=stream, **kwargs)
19
19
 
20
20
  # TODO Async Observable Create
21
- print("Is async", is_async(create))
22
21
  return observable_create if not is_async(create) else create
23
22
 
24
23
 
@@ -85,7 +85,11 @@ def observable(
85
85
  # recover parent context
86
86
  _SESSION_EXTRA.reset(token)
87
87
 
88
- # TODO: collect inputs and outputs
88
+ # get the trace to collect data
89
+ trace = session_extra.get("trace")
90
+ if not trace:
91
+ raise ValueError("Trace not found in session_extra")
92
+ # TODO: collect inputs and outputs for SPAN_KIND_FUNCTION
89
93
  inputs = extract_flattened_inputs(func, *args, **kwargs)
90
94
  # create the span if it is the root span
91
95
  if divi._datapark and span.trace_id:
@@ -94,43 +98,18 @@ def observable(
94
98
  )
95
99
  # end the trace if it is the root span
96
100
  if divi._datapark and not span.parent_span_id:
97
- trace = session_extra.get("trace")
98
- if trace:
99
- trace.end()
100
- divi._datapark.upsert_traces(
101
- session_id=trace.session_id, traces=[trace.signal]
102
- )
101
+ trace.end()
103
102
  # create the chat completion if it is a chat completion
104
103
  if divi._datapark and isinstance(result, ChatCompletion):
105
104
  divi._datapark.create_chat_completion(
106
- span_id=span.span_id, inputs=inputs, completion=result
105
+ span_id=span.span_id,
106
+ trace_id=trace.trace_id,
107
+ inputs=inputs,
108
+ completion=result,
107
109
  )
108
- return result
109
110
 
110
- @functools.wraps(func)
111
- def generator_wrapper(
112
- *args, session_extra: Optional[SessionExtra] = None, **kwargs
113
- ):
114
- span = Span(
115
- kind=kind, name=name or func.__name__, metadata=metadata
116
- )
117
- session_extra = setup(span, _SESSION_EXTRA.get() or session_extra)
118
- # set current context
119
- token = _SESSION_EXTRA.set(session_extra)
120
- # execute the function
121
- results: List[Any] = []
122
- span.start()
123
- for item in func(*args, **kwargs):
124
- results.append(item)
125
- yield item
126
- span.end()
127
-
128
- # recover parent context
129
- _SESSION_EXTRA.reset(token)
130
- # TODO: collect results
111
+ return result
131
112
 
132
- if inspect.isgeneratorfunction(func):
133
- return generator_wrapper
134
113
  return wrapper
135
114
 
136
115
  # Function Decorator
@@ -1,16 +1,16 @@
1
- from typing import Any, Dict, TYPE_CHECKING
2
- from typing_extensions import Mapping
1
+ from typing import Any, Dict
3
2
 
4
3
  from google.protobuf.json_format import MessageToDict
4
+ from openai import NotGiven
5
5
  from openai.types.chat import ChatCompletion
6
6
  from pydantic import UUID4
7
+ from typing_extensions import Mapping
7
8
 
8
9
  import divi
9
10
  from divi.proto.trace.v1.trace_pb2 import ScopeSpans
10
11
  from divi.services.service import Service
11
12
  from divi.session.session import SessionSignal
12
13
  from divi.signals.trace.trace import TraceSignal
13
- from openai import NotGiven
14
14
 
15
15
 
16
16
  class DataPark(Service):
@@ -33,7 +33,11 @@ class DataPark(Service):
33
33
  if not isinstance(obj, Mapping):
34
34
  return obj
35
35
 
36
- return {key: value for key, value in obj.items() if not isinstance(value, NotGiven)}
36
+ return {
37
+ key: value
38
+ for key, value in obj.items()
39
+ if not isinstance(value, NotGiven)
40
+ }
37
41
 
38
42
  def create_session(self, session: SessionSignal) -> None:
39
43
  self.post("/api/session/", payload=session)
@@ -49,6 +53,7 @@ class DataPark(Service):
49
53
  def create_chat_completion(
50
54
  self,
51
55
  span_id: bytes,
56
+ trace_id: UUID4,
52
57
  inputs: Dict[str, Any],
53
58
  completion: ChatCompletion,
54
59
  ) -> None:
@@ -61,6 +66,7 @@ class DataPark(Service):
61
66
  },
62
67
  "/api/v1/chat/completions": {
63
68
  "span_id": hex_span_id,
69
+ "trace_id": str(trace_id),
64
70
  "data": completion.model_dump(),
65
71
  },
66
72
  }
divi/session/session.py CHANGED
@@ -9,13 +9,13 @@ class SessionExtra(TypedDict, total=False):
9
9
 
10
10
  session_name: Optional[str]
11
11
  """Name of the session"""
12
- trace: Optional[Trace]
13
- """Trace ID UUID4"""
12
+ trace: Trace
13
+ """Trace in session"""
14
14
  parent_span_id: Optional[bytes]
15
15
  """Parent Span ID fixed string(8)"""
16
16
 
17
17
 
18
- class SessionSignal(TypedDict, total=False):
18
+ class SessionSignal(TypedDict):
19
19
  """Session request"""
20
20
 
21
21
  id: str
divi/session/setup.py CHANGED
@@ -1,3 +1,4 @@
1
+ from typing_extensions import Optional
1
2
  import divi
2
3
  from divi.services import init as init_services
3
4
  from divi.session import Session, SessionExtra
@@ -5,10 +6,10 @@ from divi.signals.trace import Span
5
6
  from divi.signals.trace.trace import Trace
6
7
 
7
8
 
8
- def init(session_extra: SessionExtra) -> Session:
9
+ def init_session(name: Optional[str]=None) -> Session:
9
10
  """init initializes the services and the Run"""
10
11
  init_services()
11
- session = Session(name=session_extra.get("session_name"))
12
+ session = Session(name=name)
12
13
  if divi._datapark:
13
14
  divi._datapark.create_session(session.signal)
14
15
  return session
@@ -24,39 +25,21 @@ def setup(
24
25
  span (Span): Span instance
25
26
  session_extra (SessionExtra | None): Extra information from user input
26
27
  """
27
- # TOOD: merge run_extra input by user with the one from the context
28
- # temp solution: Priority: run_extra_context.get() > run_extra
29
28
  session_extra = session_extra or SessionExtra()
30
29
 
31
30
  # init the session if not already initialized
32
31
  if not divi._session:
33
- divi._session = init(session_extra=session_extra)
32
+ divi._session = init_session(name=session_extra.get('session_name') or span.name)
34
33
 
35
34
  # setup trace
36
- # init current span
37
- trace = session_extra.get("trace")
35
+ trace = session_extra.get("trace") or Trace(divi._session.id, span.name)
38
36
  parent_span_id = session_extra.get("parent_span_id")
39
- if trace and parent_span_id:
40
- span._add_parent(trace.trace_id, parent_span_id)
41
- else:
42
- trace = Trace(divi._session.id)
43
- trace.start()
44
- span._as_root(trace.trace_id)
45
- # create the trace
46
- if divi._datapark:
47
- divi._datapark.upsert_traces(
48
- session_id=divi._session.id, traces=[trace.signal]
49
- )
50
-
51
- # update the session_extra with the current span
52
- # session_extra["trace_id"] = span.trace_id
53
- # session_extra["parent_span_id"] = span.span_id
54
- session_extra = SessionExtra(
37
+ span._add_node(trace.trace_id, parent_span_id)
38
+
39
+ # update the session_extra with the current trace and span
40
+ return SessionExtra(
55
41
  session_name=divi._session.name,
56
42
  trace=trace,
57
43
  # set the parent_span_id to the current span_id
58
44
  parent_span_id=span.span_id,
59
45
  )
60
-
61
- # offer end hook to collect data at whe end of the span ?
62
- return session_extra
@@ -7,6 +7,7 @@ from uuid import uuid4
7
7
  from pydantic import UUID4
8
8
  from typing_extensions import TypedDict
9
9
 
10
+ import divi
10
11
  from divi.proto.common.v1.common_pb2 import KeyValue
11
12
  from divi.proto.trace.v1.trace_pb2 import Span as SpanProto
12
13
 
@@ -29,15 +30,19 @@ class TraceSignal(TypedDict, total=False):
29
30
  """Start time in iso format"""
30
31
  end_time: NullTime
31
32
  """End time in iso format"""
33
+ name: Optional[str]
32
34
 
33
35
 
34
36
  class Trace:
35
- def __init__(self, session_id: UUID4):
37
+ def __init__(self, session_id: UUID4, name: Optional[str] = None):
36
38
  self.trace_id: UUID4 = uuid4()
37
39
  self.start_time: str | None = None
38
40
  self.end_time: str | None = None
41
+ self.name: Optional[str] = name
39
42
  self.session_id: UUID4 = session_id
40
43
 
44
+ self.start()
45
+
41
46
  @property
42
47
  def signal(self) -> TraceSignal:
43
48
  if self.start_time is None:
@@ -45,6 +50,7 @@ class Trace:
45
50
  signal = TraceSignal(
46
51
  id=str(self.trace_id),
47
52
  start_time=self.start_time,
53
+ name=self.name,
48
54
  )
49
55
  if self.end_time is not None:
50
56
  signal["end_time"] = NullTime(
@@ -60,12 +66,21 @@ class Trace:
60
66
  def start(self):
61
67
  """Start the trace by recording the current time in nanoseconds."""
62
68
  self.start_time = datetime.now(UTC).isoformat()
69
+ self.upsert_trace()
63
70
 
64
71
  def end(self):
65
72
  """End the trace by recording the end time in nanoseconds."""
66
73
  if self.start_time is None:
67
74
  raise ValueError("Span must be started before ending.")
68
75
  self.end_time = datetime.now(UTC).isoformat()
76
+ self.upsert_trace()
77
+
78
+ def upsert_trace(self):
79
+ """Upsert trace with datapark."""
80
+ if divi._datapark:
81
+ divi._datapark.upsert_traces(
82
+ session_id=self.session_id, traces=[self.signal]
83
+ )
69
84
 
70
85
 
71
86
  class Span:
@@ -102,7 +117,6 @@ class Span:
102
117
  trace_id=self.trace_id.bytes if self.trace_id else None,
103
118
  parent_span_id=self.parent_span_id,
104
119
  )
105
- print(self.kind)
106
120
  signal.metadata.extend(
107
121
  KeyValue(key=k, value=v)
108
122
  for k, v in (self.metadata or dict()).items()
@@ -131,21 +145,7 @@ class Span:
131
145
  raise ValueError("Span must be started before ending.")
132
146
  self.end_time_unix_nano = time.time_ns()
133
147
 
134
- def _as_root(self, trace_id: UUID4):
135
- """Set the span as a root span."""
136
- self.trace_id = trace_id
137
- print("as root")
138
- print(f"name: {self.name}")
139
- print(f"trace_id: {self.trace_id}")
140
- print(f"span_id: {self.span_id}")
141
-
142
- def _add_parent(self, trace_id: UUID4, parent_id: bytes):
143
- """Set the parent span ID."""
148
+ def _add_node(self, trace_id: UUID4, parent_id: Optional[bytes] = None):
149
+ """Add node for obs tree."""
144
150
  self.trace_id = trace_id
145
151
  self.parent_span_id = parent_id
146
-
147
- print("add parent")
148
- print(f"name: {self.name}")
149
- print(f"trace_id: {trace_id}")
150
- print(f"span_id: {self.span_id}")
151
- print(f"parent_span_id: {parent_id}")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: divi
3
- Version: 0.0.1.dev21
3
+ Version: 0.0.1.dev23
4
4
  Summary: The Agent Platform for Observability & Evaluation
5
5
  License-File: LICENSE
6
6
  Requires-Python: >=3.11
@@ -1,9 +1,9 @@
1
- divi/__init__.py,sha256=-XjMcUmlsDSB_v0_rf5owoldPj1mXFoAgUaVZpyfwqk,396
1
+ divi/__init__.py,sha256=lcpSVEjIcXy-e9CuJB8V1izwaoEK8YpH8FtkzH0IqJc,396
2
2
  divi/utils.py,sha256=fXkjoyo_Lh8AZliKICOP460m0czUcNQjcEcceJbaOVA,1439
3
3
  divi/config/config.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  divi/decorators/__init__.py,sha256=HkyWdC1ctTsVFucCWCkj57JB4NmwONus1d2S2dUbvs4,110
5
- divi/decorators/obs_openai.py,sha256=4LtQPRgJPPyTOw1318Fi04WYqjIwGX8EP0YiWrTW0dk,1003
6
- divi/decorators/observable.py,sha256=OZ0Ry6Q2sdZPAT_T5j2wSsM7g0nwDroxeSbP3nLMDvA,4250
5
+ divi/decorators/obs_openai.py,sha256=GI9c6gFArA6pTfa3EPednMtRqV2zIlofuTDdUYtS_x4,963
6
+ divi/decorators/observable.py,sha256=xKapTyHL50mUyIDhDSYIXR1yZIdHTuw6WtI4H0j1xDE,3464
7
7
  divi/proto/common/v1/common.proto,sha256=Rx8wr0_tOtQ1NseTMnsav4ApD1MDALzQDBA2IvLRTU0,1775
8
8
  divi/proto/common/v1/common_pb2.py,sha256=br61OHQVAi6SI3baFcb5xJv2Xd-AZ04A19xeSjLNMXo,2442
9
9
  divi/proto/common/v1/common_pb2.pyi,sha256=LmTpFFLxHg2a_qPIdNXXwGEMkbiDcTJdarR9eC-6Fq8,2133
@@ -30,16 +30,16 @@ divi/services/core/core.py,sha256=PRwPtLgrgmCrejUfKf7HJNrAhGS0paFNZ7JwDToEUAk,12
30
30
  divi/services/core/finish.py,sha256=dIGQpVXcJY4-tKe7A1_VV3yoSHNCDPfOlUltvzvk6VI,231
31
31
  divi/services/core/init.py,sha256=e7-fgpOPglBXyEoPkgOAnpJk2ApdFbo7LPupxOb8N-w,1966
32
32
  divi/services/datapark/__init__.py,sha256=GbV1mwHE07yutgOlCIYHykSEL5KJ-ApgLutGMzu2eUE,86
33
- divi/services/datapark/datapark.py,sha256=1CoWJI2embzvijCmIIPwTLnliU4kSolUginGuSWHsBw,2182
33
+ divi/services/datapark/datapark.py,sha256=d2pbrzVJtR3mNW1eQpbm-Wca-SvcfJqT7IuaQy7yHT0,2285
34
34
  divi/services/datapark/init.py,sha256=C32f9t3eLsxcYNqEyheh6nW455G2oR0YhhdqBcbN3ec,92
35
35
  divi/session/__init__.py,sha256=6lYemv21VQCIHx-xIdi7BxXcPNxVdvE60--8ArReUew,82
36
- divi/session/session.py,sha256=ID7bQ4CuRPUcZ9S-DSjndiduslYFJukRLuCtChYm3wk,838
37
- divi/session/setup.py,sha256=jlc3ICR5hRDdrcxoSxi66FYS2TYxqrIJOMgI4i1tEJs,1972
36
+ divi/session/session.py,sha256=LlB2W2qGo0Vf-0L0CTQoXfzg_gCGpf0MTFsXQW7E6i4,817
37
+ divi/session/setup.py,sha256=NeCxCb-uYhkKnOEiw8dBQHz0DEL8j1oxzQY3cBAmHbo,1380
38
38
  divi/session/teardown.py,sha256=YiBz_3yCiljMFEofZ60VmRL5sb8WA5GT7EYF8nFznZ4,133
39
39
  divi/signals/__init__.py,sha256=K1PaTAMwyBDsK6jJUg4QWy0xVJ_5MA6dlWiUyJeiSQA,44
40
40
  divi/signals/trace/__init__.py,sha256=K1PaTAMwyBDsK6jJUg4QWy0xVJ_5MA6dlWiUyJeiSQA,44
41
- divi/signals/trace/trace.py,sha256=y8Xio8Tp_e1tO8l_DAkUuzMrmENNKfIdklF0iWrjGYk,4547
42
- divi-0.0.1.dev21.dist-info/METADATA,sha256=xyAsE6Uj3sA8T7I83LVLtCEyum_hMQT4ULien2Q-0NU,497
43
- divi-0.0.1.dev21.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
44
- divi-0.0.1.dev21.dist-info/licenses/LICENSE,sha256=5OJuZ4wMMEV0DgF0tofhAlS_KLkaUsZwwwDS2U_GwQ0,1063
45
- divi-0.0.1.dev21.dist-info/RECORD,,
41
+ divi/signals/trace/trace.py,sha256=OsfrZPHp241_NN8W79U4O69HsHQajez_d3rz6yJRN9s,4508
42
+ divi-0.0.1.dev23.dist-info/METADATA,sha256=KdspT1iEra11ixCEtl94Mz_fCziMVOOER08rDE4yCWU,497
43
+ divi-0.0.1.dev23.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
44
+ divi-0.0.1.dev23.dist-info/licenses/LICENSE,sha256=5OJuZ4wMMEV0DgF0tofhAlS_KLkaUsZwwwDS2U_GwQ0,1063
45
+ divi-0.0.1.dev23.dist-info/RECORD,,