projectdavid 1.33.12__py3-none-any.whl → 1.33.13__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.
Potentially problematic release.
This version of projectdavid might be problematic. Click here for more details.
- projectdavid/clients/synchronous_inference_wrapper.py +44 -9
- {projectdavid-1.33.12.dist-info → projectdavid-1.33.13.dist-info}/METADATA +1 -1
- {projectdavid-1.33.12.dist-info → projectdavid-1.33.13.dist-info}/RECORD +6 -6
- {projectdavid-1.33.12.dist-info → projectdavid-1.33.13.dist-info}/WHEEL +0 -0
- {projectdavid-1.33.12.dist-info → projectdavid-1.33.13.dist-info}/licenses/LICENSE +0 -0
- {projectdavid-1.33.12.dist-info → projectdavid-1.33.13.dist-info}/top_level.txt +0 -0
|
@@ -11,9 +11,15 @@ LOG = UtilsInterface.LoggingUtility()
|
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
class SynchronousInferenceStream:
|
|
14
|
+
# ------------------------------------------------------------ #
|
|
15
|
+
# GLOBAL EVENT LOOP (single hidden thread for sync wrapper)
|
|
16
|
+
# ------------------------------------------------------------ #
|
|
14
17
|
_GLOBAL_LOOP = asyncio.new_event_loop()
|
|
15
18
|
asyncio.set_event_loop(_GLOBAL_LOOP)
|
|
16
19
|
|
|
20
|
+
# ------------------------------------------------------------ #
|
|
21
|
+
# Init / setup
|
|
22
|
+
# ------------------------------------------------------------ #
|
|
17
23
|
def __init__(self, inference) -> None:
|
|
18
24
|
self.inference_client = inference
|
|
19
25
|
self.user_id: Optional[str] = None
|
|
@@ -32,6 +38,7 @@ class SynchronousInferenceStream:
|
|
|
32
38
|
run_id: str,
|
|
33
39
|
api_key: str,
|
|
34
40
|
) -> None:
|
|
41
|
+
"""Populate IDs once, so callers only provide provider/model."""
|
|
35
42
|
self.user_id = user_id
|
|
36
43
|
self.thread_id = thread_id
|
|
37
44
|
self.assistant_id = assistant_id
|
|
@@ -39,7 +46,10 @@ class SynchronousInferenceStream:
|
|
|
39
46
|
self.run_id = run_id
|
|
40
47
|
self.api_key = api_key
|
|
41
48
|
|
|
42
|
-
|
|
49
|
+
# ------------------------------------------------------------ #
|
|
50
|
+
# Core sync-to-async streaming wrapper
|
|
51
|
+
# ------------------------------------------------------------ #
|
|
52
|
+
def stream_chunks( # noqa: PLR0915
|
|
43
53
|
self,
|
|
44
54
|
provider: str,
|
|
45
55
|
model: str,
|
|
@@ -48,9 +58,15 @@ class SynchronousInferenceStream:
|
|
|
48
58
|
timeout_per_chunk: float = 280.0,
|
|
49
59
|
suppress_fc: bool = True,
|
|
50
60
|
) -> Generator[dict, None, None]:
|
|
61
|
+
"""
|
|
62
|
+
Sync generator that mirrors async `inference_client.stream_inference_response`
|
|
63
|
+
but (optionally) removes raw <fc> … </fc> output *and* JSON
|
|
64
|
+
`{"type": "function_call" …}` objects from the stream.
|
|
65
|
+
"""
|
|
51
66
|
|
|
52
67
|
resolved_api_key = api_key or self.api_key
|
|
53
68
|
|
|
69
|
+
# ---------- async inner generator -------------------------------- #
|
|
54
70
|
async def _stream_chunks_async():
|
|
55
71
|
async for chk in self.inference_client.stream_inference_response(
|
|
56
72
|
provider=provider,
|
|
@@ -65,6 +81,7 @@ class SynchronousInferenceStream:
|
|
|
65
81
|
|
|
66
82
|
agen = _stream_chunks_async().__aiter__()
|
|
67
83
|
|
|
84
|
+
# ---------- FC-suppressor plumbing -------------------------------- #
|
|
68
85
|
if suppress_fc:
|
|
69
86
|
_suppressor = FunctionCallSuppressor()
|
|
70
87
|
_peek_gate = PeekGate(_suppressor)
|
|
@@ -72,11 +89,15 @@ class SynchronousInferenceStream:
|
|
|
72
89
|
def _filter_text(txt: str) -> str:
|
|
73
90
|
return _peek_gate.feed(txt)
|
|
74
91
|
|
|
92
|
+
LOG.debug("[SyncStream] Function-call suppression ACTIVE")
|
|
75
93
|
else:
|
|
76
94
|
|
|
77
95
|
def _filter_text(txt: str) -> str:
|
|
78
96
|
return txt
|
|
79
97
|
|
|
98
|
+
LOG.debug("[SyncStream] Function-call suppression DISABLED")
|
|
99
|
+
|
|
100
|
+
# ---------- helper to flush residual buffered text ---------------- #
|
|
80
101
|
def _drain_filters() -> Optional[dict]:
|
|
81
102
|
if not suppress_fc:
|
|
82
103
|
return None
|
|
@@ -97,18 +118,17 @@ class SynchronousInferenceStream:
|
|
|
97
118
|
}
|
|
98
119
|
return None
|
|
99
120
|
|
|
121
|
+
# ---------- main sync loop ---------------------------------------- #
|
|
100
122
|
while True:
|
|
101
123
|
try:
|
|
102
124
|
chunk = self._GLOBAL_LOOP.run_until_complete(
|
|
103
125
|
asyncio.wait_for(agen.__anext__(), timeout=timeout_per_chunk)
|
|
104
126
|
)
|
|
105
127
|
|
|
106
|
-
# Always attach run_id
|
|
128
|
+
# Always attach run_id for front-end helpers
|
|
107
129
|
chunk["run_id"] = self.run_id
|
|
108
130
|
|
|
109
|
-
#
|
|
110
|
-
# allow status chunks to bypass suppression suppression
|
|
111
|
-
# -------------------------------------------------------
|
|
131
|
+
# ----- bypass filters for status / code-exec related -------- #
|
|
112
132
|
if chunk.get("type") == "status":
|
|
113
133
|
yield chunk
|
|
114
134
|
continue
|
|
@@ -124,9 +144,19 @@ class SynchronousInferenceStream:
|
|
|
124
144
|
yield chunk
|
|
125
145
|
continue
|
|
126
146
|
|
|
147
|
+
# ----- NEW: swallow raw JSON function_call objects ---------- #
|
|
148
|
+
if suppress_fc and chunk.get("type") == "function_call":
|
|
149
|
+
LOG.debug(
|
|
150
|
+
"[SyncStream] Swallowing JSON function_call chunk: %s",
|
|
151
|
+
chunk.get("name") or "<unnamed>",
|
|
152
|
+
)
|
|
153
|
+
continue
|
|
154
|
+
|
|
155
|
+
# ----- text-level suppression ------------------------------- #
|
|
127
156
|
if isinstance(chunk.get("content"), str):
|
|
128
157
|
chunk["content"] = _filter_text(chunk["content"])
|
|
129
158
|
if chunk["content"] == "":
|
|
159
|
+
# Entire segment was inside <fc> … </fc>
|
|
130
160
|
continue
|
|
131
161
|
|
|
132
162
|
yield chunk
|
|
@@ -134,21 +164,26 @@ class SynchronousInferenceStream:
|
|
|
134
164
|
except StopAsyncIteration:
|
|
135
165
|
if tail := _drain_filters():
|
|
136
166
|
yield tail
|
|
137
|
-
LOG.info("Stream completed normally.")
|
|
167
|
+
LOG.info("[SyncStream] Stream completed normally.")
|
|
138
168
|
break
|
|
139
169
|
|
|
140
170
|
except asyncio.TimeoutError:
|
|
141
171
|
if tail := _drain_filters():
|
|
142
172
|
yield tail
|
|
143
|
-
LOG.error("[
|
|
173
|
+
LOG.error("[SyncStream] Timeout waiting for next chunk.")
|
|
144
174
|
break
|
|
145
175
|
|
|
146
|
-
except Exception as exc:
|
|
176
|
+
except Exception as exc: # noqa: BLE001
|
|
147
177
|
if tail := _drain_filters():
|
|
148
178
|
yield tail
|
|
149
|
-
LOG.error(
|
|
179
|
+
LOG.error(
|
|
180
|
+
"[SyncStream] Unexpected streaming error: %s", exc, exc_info=True
|
|
181
|
+
)
|
|
150
182
|
break
|
|
151
183
|
|
|
184
|
+
# ------------------------------------------------------------ #
|
|
185
|
+
# House-keeping
|
|
186
|
+
# ------------------------------------------------------------ #
|
|
152
187
|
@classmethod
|
|
153
188
|
def shutdown_loop(cls) -> None:
|
|
154
189
|
if cls._GLOBAL_LOOP and not cls._GLOBAL_LOOP.is_closed():
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: projectdavid
|
|
3
|
-
Version: 1.33.
|
|
3
|
+
Version: 1.33.13
|
|
4
4
|
Summary: Python SDK for interacting with the Entities Assistant API.
|
|
5
5
|
Author-email: Francis Neequaye Armah <francis.neequaye@projectdavid.co.uk>
|
|
6
6
|
License: PolyForm Noncommercial License 1.0.0
|
|
@@ -16,7 +16,7 @@ projectdavid/clients/files_client.py,sha256=XkIDzbQFGDrd88taf0Kouc_4YJOPIYEHiIyW
|
|
|
16
16
|
projectdavid/clients/inference_client.py,sha256=xz4ACPv5Tkis604QxO5mJX1inH_TGDfQP-31geETYpE,6609
|
|
17
17
|
projectdavid/clients/messages_client.py,sha256=467xeIt3VYs6cG8-bl-eDRi_auWOPmfd5tSJDmQSJUI,17232
|
|
18
18
|
projectdavid/clients/runs.py,sha256=-fXOq5L9w2efDPmZkNxb0s2yjl6oN0XN4_aLXqaeceo,25270
|
|
19
|
-
projectdavid/clients/synchronous_inference_wrapper.py,sha256=
|
|
19
|
+
projectdavid/clients/synchronous_inference_wrapper.py,sha256=qh94rtNlLqgIxiA_ZbQ1ncOwQTi9aBj5os3sMExLh4E,7070
|
|
20
20
|
projectdavid/clients/threads_client.py,sha256=ekzU5w14zftmtmFkiec3NC90Of-_KVSUY1qH9cmfSFg,6771
|
|
21
21
|
projectdavid/clients/tools_client.py,sha256=GkCVOmwpAoPqVt6aYmH0G1HIFha3iEwR9IIf9teR0j8,11487
|
|
22
22
|
projectdavid/clients/users_client.py,sha256=eCuUb9qvyH1GUFhZu6TRL9zdoK-qzHSs8-Vmrk_0mmg,13729
|
|
@@ -35,8 +35,8 @@ projectdavid/utils/monitor_launcher.py,sha256=3YAgJdeuaUvq3JGvpA4ymqFsAnk29nH5q9
|
|
|
35
35
|
projectdavid/utils/peek_gate.py,sha256=5whMRnDOQjATRpThWDJkvY9ScXuJ7Sd_-9rvGgXeTAQ,2532
|
|
36
36
|
projectdavid/utils/run_monitor.py,sha256=F_WkqIP-qnWH-4llIbileWWLfRj2Q1Cg-ni23SR1rec,3786
|
|
37
37
|
projectdavid/utils/vector_search_formatter.py,sha256=YTe3HPGec26qGY7uxY8_GS8lc4QaN6aNXMzkl29nZpI,1735
|
|
38
|
-
projectdavid-1.33.
|
|
39
|
-
projectdavid-1.33.
|
|
40
|
-
projectdavid-1.33.
|
|
41
|
-
projectdavid-1.33.
|
|
42
|
-
projectdavid-1.33.
|
|
38
|
+
projectdavid-1.33.13.dist-info/licenses/LICENSE,sha256=_8yjiEGttpS284BkfhXxfERqTRZW_tUaHiBB0GTJTMg,4563
|
|
39
|
+
projectdavid-1.33.13.dist-info/METADATA,sha256=wFCKMGJBgK8yku6jOoE2IPsdB9-kfIGL1kBYF89yfNM,11555
|
|
40
|
+
projectdavid-1.33.13.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
41
|
+
projectdavid-1.33.13.dist-info/top_level.txt,sha256=kil8GU4s7qYRfNnzGnFHhZnSNRSxgNG-J4HLgQMmMtw,13
|
|
42
|
+
projectdavid-1.33.13.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|