projectdavid 1.32.5__py3-none-any.whl → 1.32.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.
Potentially problematic release.
This version of projectdavid might be problematic. Click here for more details.
- projectdavid/clients/synchronous_inference_wrapper.py +57 -13
- {projectdavid-1.32.5.dist-info → projectdavid-1.32.6.dist-info}/METADATA +1 -1
- {projectdavid-1.32.5.dist-info → projectdavid-1.32.6.dist-info}/RECORD +6 -6
- {projectdavid-1.32.5.dist-info → projectdavid-1.32.6.dist-info}/WHEEL +0 -0
- {projectdavid-1.32.5.dist-info → projectdavid-1.32.6.dist-info}/licenses/LICENSE +0 -0
- {projectdavid-1.32.5.dist-info → projectdavid-1.32.6.dist-info}/top_level.txt +0 -0
|
@@ -11,12 +11,14 @@ LOG = UtilsInterface.LoggingUtility()
|
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
class SynchronousInferenceStream:
|
|
14
|
+
"""Wrap an async streaming generator and expose it synchronously."""
|
|
15
|
+
|
|
14
16
|
_GLOBAL_LOOP = asyncio.new_event_loop()
|
|
15
17
|
asyncio.set_event_loop(_GLOBAL_LOOP)
|
|
16
18
|
|
|
17
|
-
#
|
|
18
|
-
#
|
|
19
|
-
#
|
|
19
|
+
# ------------------------------------------------------------------ #
|
|
20
|
+
# construction / setup
|
|
21
|
+
# ------------------------------------------------------------------ #
|
|
20
22
|
def __init__(self, inference) -> None:
|
|
21
23
|
self.inference_client = inference
|
|
22
24
|
self.user_id: Optional[str] = None
|
|
@@ -42,9 +44,9 @@ class SynchronousInferenceStream:
|
|
|
42
44
|
self.run_id = run_id
|
|
43
45
|
self.api_key = api_key
|
|
44
46
|
|
|
45
|
-
#
|
|
47
|
+
# ------------------------------------------------------------------ #
|
|
46
48
|
# main streaming entry-point
|
|
47
|
-
#
|
|
49
|
+
# ------------------------------------------------------------------ #
|
|
48
50
|
def stream_chunks(
|
|
49
51
|
self,
|
|
50
52
|
provider: str,
|
|
@@ -54,6 +56,13 @@ class SynchronousInferenceStream:
|
|
|
54
56
|
timeout_per_chunk: float = 280.0,
|
|
55
57
|
suppress_fc: bool = True,
|
|
56
58
|
) -> Generator[dict, None, None]:
|
|
59
|
+
"""
|
|
60
|
+
Yield provider chunks synchronously. When *suppress_fc* is True we
|
|
61
|
+
|
|
62
|
+
1. completely drop top-level `type="function_call"` chunks, and
|
|
63
|
+
2. scrub inline `<fc> … </fc>` sections inside text using the
|
|
64
|
+
PeekGate + FunctionCallSuppressor chain.
|
|
65
|
+
"""
|
|
57
66
|
|
|
58
67
|
resolved_api_key = api_key or self.api_key
|
|
59
68
|
|
|
@@ -71,33 +80,68 @@ class SynchronousInferenceStream:
|
|
|
71
80
|
|
|
72
81
|
agen = _stream_chunks_async().__aiter__()
|
|
73
82
|
|
|
83
|
+
# ---------- build inline filter --------------------------------
|
|
84
|
+
if suppress_fc:
|
|
85
|
+
suppressor = FunctionCallSuppressor()
|
|
86
|
+
peek_gate = PeekGate(suppressor)
|
|
87
|
+
|
|
88
|
+
def _filter_text(txt: str) -> str:
|
|
89
|
+
return peek_gate.feed(txt)
|
|
90
|
+
|
|
91
|
+
else:
|
|
92
|
+
|
|
93
|
+
def _filter_text(txt: str) -> str: # no-op
|
|
94
|
+
return txt
|
|
95
|
+
|
|
96
|
+
# ---------- main loop ------------------------------------------
|
|
74
97
|
while True:
|
|
75
98
|
try:
|
|
76
99
|
chunk = self._GLOBAL_LOOP.run_until_complete(
|
|
77
100
|
asyncio.wait_for(agen.__anext__(), timeout=timeout_per_chunk)
|
|
78
101
|
)
|
|
79
102
|
|
|
80
|
-
#
|
|
103
|
+
# ① drop provider-labelled function_call objects
|
|
81
104
|
if suppress_fc and chunk.get("type") == "function_call":
|
|
82
|
-
LOG.debug("[SUPPRESSOR]
|
|
105
|
+
LOG.debug("[SUPPRESSOR] stripped top-level function_call chunk")
|
|
83
106
|
continue
|
|
84
107
|
|
|
85
|
-
#
|
|
108
|
+
# ② never touch hot-code or code-interpreter file previews
|
|
109
|
+
if chunk.get("type") == "hot_code":
|
|
110
|
+
yield chunk
|
|
111
|
+
continue
|
|
112
|
+
|
|
113
|
+
if (
|
|
114
|
+
chunk.get("stream_type") == "code_execution"
|
|
115
|
+
and chunk.get("chunk", {}).get("type") == "code_interpreter_stream"
|
|
116
|
+
):
|
|
117
|
+
yield chunk
|
|
118
|
+
continue
|
|
119
|
+
|
|
120
|
+
# ③ filter inline text (<fc> blocks) *only* when content is str
|
|
121
|
+
if isinstance(chunk.get("content"), str):
|
|
122
|
+
chunk["content"] = _filter_text(chunk["content"])
|
|
123
|
+
if chunk["content"] == "":
|
|
124
|
+
# Either the text is still in PeekGate’s buffer
|
|
125
|
+
# or it was fully suppressed – skip for now.
|
|
126
|
+
continue
|
|
127
|
+
|
|
86
128
|
yield chunk
|
|
87
129
|
|
|
88
130
|
except StopAsyncIteration:
|
|
89
131
|
LOG.info("Stream completed normally.")
|
|
90
132
|
break
|
|
91
133
|
except asyncio.TimeoutError:
|
|
92
|
-
LOG.error(
|
|
134
|
+
LOG.error(
|
|
135
|
+
"[Timeout] chunk wait exceeded %.1f s – aborting", timeout_per_chunk
|
|
136
|
+
)
|
|
93
137
|
break
|
|
94
|
-
except Exception as
|
|
95
|
-
LOG.error("Unexpected
|
|
138
|
+
except Exception as exc: # pylint: disable=broad-except
|
|
139
|
+
LOG.error("Unexpected streaming error: %s", exc, exc_info=True)
|
|
96
140
|
break
|
|
97
141
|
|
|
98
|
-
#
|
|
142
|
+
# ------------------------------------------------------------------ #
|
|
99
143
|
# housekeeping
|
|
100
|
-
#
|
|
144
|
+
# ------------------------------------------------------------------ #
|
|
101
145
|
@classmethod
|
|
102
146
|
def shutdown_loop(cls) -> None:
|
|
103
147
|
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.32.
|
|
3
|
+
Version: 1.32.6
|
|
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
|
|
@@ -15,7 +15,7 @@ projectdavid/clients/files_client.py,sha256=XkIDzbQFGDrd88taf0Kouc_4YJOPIYEHiIyW
|
|
|
15
15
|
projectdavid/clients/inference_client.py,sha256=xz4ACPv5Tkis604QxO5mJX1inH_TGDfQP-31geETYpE,6609
|
|
16
16
|
projectdavid/clients/messages_client.py,sha256=467xeIt3VYs6cG8-bl-eDRi_auWOPmfd5tSJDmQSJUI,17232
|
|
17
17
|
projectdavid/clients/runs.py,sha256=-fXOq5L9w2efDPmZkNxb0s2yjl6oN0XN4_aLXqaeceo,25270
|
|
18
|
-
projectdavid/clients/synchronous_inference_wrapper.py,sha256=
|
|
18
|
+
projectdavid/clients/synchronous_inference_wrapper.py,sha256=msshrx_sJxi0Zn-RJpLTPF1HImK7FFHNBTF9m-g2kKE,5463
|
|
19
19
|
projectdavid/clients/threads_client.py,sha256=ekzU5w14zftmtmFkiec3NC90Of-_KVSUY1qH9cmfSFg,6771
|
|
20
20
|
projectdavid/clients/tools_client.py,sha256=GkCVOmwpAoPqVt6aYmH0G1HIFha3iEwR9IIf9teR0j8,11487
|
|
21
21
|
projectdavid/clients/users_client.py,sha256=eCuUb9qvyH1GUFhZu6TRL9zdoK-qzHSs8-Vmrk_0mmg,13729
|
|
@@ -34,8 +34,8 @@ projectdavid/utils/monitor_launcher.py,sha256=3YAgJdeuaUvq3JGvpA4ymqFsAnk29nH5q9
|
|
|
34
34
|
projectdavid/utils/peek_gate.py,sha256=5whMRnDOQjATRpThWDJkvY9ScXuJ7Sd_-9rvGgXeTAQ,2532
|
|
35
35
|
projectdavid/utils/run_monitor.py,sha256=F_WkqIP-qnWH-4llIbileWWLfRj2Q1Cg-ni23SR1rec,3786
|
|
36
36
|
projectdavid/utils/vector_search_formatter.py,sha256=YTe3HPGec26qGY7uxY8_GS8lc4QaN6aNXMzkl29nZpI,1735
|
|
37
|
-
projectdavid-1.32.
|
|
38
|
-
projectdavid-1.32.
|
|
39
|
-
projectdavid-1.32.
|
|
40
|
-
projectdavid-1.32.
|
|
41
|
-
projectdavid-1.32.
|
|
37
|
+
projectdavid-1.32.6.dist-info/licenses/LICENSE,sha256=_8yjiEGttpS284BkfhXxfERqTRZW_tUaHiBB0GTJTMg,4563
|
|
38
|
+
projectdavid-1.32.6.dist-info/METADATA,sha256=pz7BV3J79Ot0hDnTo0jEBPSARuUo-ohc3FAVEZh2-3Q,10781
|
|
39
|
+
projectdavid-1.32.6.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
40
|
+
projectdavid-1.32.6.dist-info/top_level.txt,sha256=kil8GU4s7qYRfNnzGnFHhZnSNRSxgNG-J4HLgQMmMtw,13
|
|
41
|
+
projectdavid-1.32.6.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|