projectdavid 1.32.0__tar.gz → 1.32.2__tar.gz

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.

Files changed (69) hide show
  1. {projectdavid-1.32.0 → projectdavid-1.32.2}/CHANGELOG.md +14 -0
  2. {projectdavid-1.32.0/src/projectdavid.egg-info → projectdavid-1.32.2}/PKG-INFO +1 -1
  3. {projectdavid-1.32.0 → projectdavid-1.32.2}/pyproject.toml +1 -1
  4. {projectdavid-1.32.0 → projectdavid-1.32.2}/src/projectdavid/clients/synchronous_inference_wrapper.py +17 -13
  5. {projectdavid-1.32.0 → projectdavid-1.32.2}/src/projectdavid/utils/function_call_suppressor.py +6 -7
  6. projectdavid-1.32.2/src/projectdavid/utils/peek_gate.py +71 -0
  7. {projectdavid-1.32.0 → projectdavid-1.32.2/src/projectdavid.egg-info}/PKG-INFO +1 -1
  8. projectdavid-1.32.0/src/projectdavid/utils/peek_gate.py +0 -49
  9. {projectdavid-1.32.0 → projectdavid-1.32.2}/LICENSE +0 -0
  10. {projectdavid-1.32.0 → projectdavid-1.32.2}/MANIFEST.in +0 -0
  11. {projectdavid-1.32.0 → projectdavid-1.32.2}/README.md +0 -0
  12. {projectdavid-1.32.0 → projectdavid-1.32.2}/docs/assistants.md +0 -0
  13. {projectdavid-1.32.0 → projectdavid-1.32.2}/docs/code_interpretation.md +0 -0
  14. {projectdavid-1.32.0 → projectdavid-1.32.2}/docs/database.md +0 -0
  15. {projectdavid-1.32.0 → projectdavid-1.32.2}/docs/database_assistant_example.md +0 -0
  16. {projectdavid-1.32.0 → projectdavid-1.32.2}/docs/docker_comtainers.md +0 -0
  17. {projectdavid-1.32.0 → projectdavid-1.32.2}/docs/file_search.md +0 -0
  18. {projectdavid-1.32.0 → projectdavid-1.32.2}/docs/files.md +0 -0
  19. {projectdavid-1.32.0 → projectdavid-1.32.2}/docs/function_call_definition.md +0 -0
  20. {projectdavid-1.32.0 → projectdavid-1.32.2}/docs/function_calls.md +0 -0
  21. {projectdavid-1.32.0 → projectdavid-1.32.2}/docs/handling_function_calls.md +0 -0
  22. {projectdavid-1.32.0 → projectdavid-1.32.2}/docs/inference.md +0 -0
  23. {projectdavid-1.32.0 → projectdavid-1.32.2}/docs/messages.md +0 -0
  24. {projectdavid-1.32.0 → projectdavid-1.32.2}/docs/runs.md +0 -0
  25. {projectdavid-1.32.0 → projectdavid-1.32.2}/docs/streams.md +0 -0
  26. {projectdavid-1.32.0 → projectdavid-1.32.2}/docs/threads.md +0 -0
  27. {projectdavid-1.32.0 → projectdavid-1.32.2}/docs/tools.md +0 -0
  28. {projectdavid-1.32.0 → projectdavid-1.32.2}/docs/users.md +0 -0
  29. {projectdavid-1.32.0 → projectdavid-1.32.2}/docs/vector_store.md +0 -0
  30. {projectdavid-1.32.0 → projectdavid-1.32.2}/docs/versioning.md +0 -0
  31. {projectdavid-1.32.0 → projectdavid-1.32.2}/setup.cfg +0 -0
  32. {projectdavid-1.32.0 → projectdavid-1.32.2}/src/projectdavid/__init__.py +0 -0
  33. {projectdavid-1.32.0 → projectdavid-1.32.2}/src/projectdavid/_version.py +0 -0
  34. {projectdavid-1.32.0 → projectdavid-1.32.2}/src/projectdavid/clients/actions_client.py +0 -0
  35. {projectdavid-1.32.0 → projectdavid-1.32.2}/src/projectdavid/clients/api_key_client.py +0 -0
  36. {projectdavid-1.32.0 → projectdavid-1.32.2}/src/projectdavid/clients/assistants_client.py +0 -0
  37. {projectdavid-1.32.0 → projectdavid-1.32.2}/src/projectdavid/clients/base_client.py +0 -0
  38. {projectdavid-1.32.0 → projectdavid-1.32.2}/src/projectdavid/clients/base_vector_store.py +0 -0
  39. {projectdavid-1.32.0 → projectdavid-1.32.2}/src/projectdavid/clients/event_handler.py +0 -0
  40. {projectdavid-1.32.0 → projectdavid-1.32.2}/src/projectdavid/clients/file_processor.py +0 -0
  41. {projectdavid-1.32.0 → projectdavid-1.32.2}/src/projectdavid/clients/file_search.py +0 -0
  42. {projectdavid-1.32.0 → projectdavid-1.32.2}/src/projectdavid/clients/files_client.py +0 -0
  43. {projectdavid-1.32.0 → projectdavid-1.32.2}/src/projectdavid/clients/inference_client.py +0 -0
  44. {projectdavid-1.32.0 → projectdavid-1.32.2}/src/projectdavid/clients/messages_client.py +0 -0
  45. {projectdavid-1.32.0 → projectdavid-1.32.2}/src/projectdavid/clients/runs.py +0 -0
  46. {projectdavid-1.32.0 → projectdavid-1.32.2}/src/projectdavid/clients/threads_client.py +0 -0
  47. {projectdavid-1.32.0 → projectdavid-1.32.2}/src/projectdavid/clients/tools_client.py +0 -0
  48. {projectdavid-1.32.0 → projectdavid-1.32.2}/src/projectdavid/clients/users_client.py +0 -0
  49. {projectdavid-1.32.0 → projectdavid-1.32.2}/src/projectdavid/clients/vector_store_manager.py +0 -0
  50. {projectdavid-1.32.0 → projectdavid-1.32.2}/src/projectdavid/clients/vectors.py +0 -0
  51. {projectdavid-1.32.0 → projectdavid-1.32.2}/src/projectdavid/constants/platform.py +0 -0
  52. {projectdavid-1.32.0 → projectdavid-1.32.2}/src/projectdavid/entity.py +0 -0
  53. {projectdavid-1.32.0 → projectdavid-1.32.2}/src/projectdavid/events.py +0 -0
  54. {projectdavid-1.32.0 → projectdavid-1.32.2}/src/projectdavid/serializers.py +0 -0
  55. {projectdavid-1.32.0 → projectdavid-1.32.2}/src/projectdavid/services/logging_service.py +0 -0
  56. {projectdavid-1.32.0 → projectdavid-1.32.2}/src/projectdavid/synthesis/__init__.py +0 -0
  57. {projectdavid-1.32.0 → projectdavid-1.32.2}/src/projectdavid/synthesis/llm_synthesizer.py +0 -0
  58. {projectdavid-1.32.0 → projectdavid-1.32.2}/src/projectdavid/synthesis/prompt.py +0 -0
  59. {projectdavid-1.32.0 → projectdavid-1.32.2}/src/projectdavid/synthesis/reranker.py +0 -0
  60. {projectdavid-1.32.0 → projectdavid-1.32.2}/src/projectdavid/synthesis/retriever.py +0 -0
  61. {projectdavid-1.32.0 → projectdavid-1.32.2}/src/projectdavid/utils/__init__.py +0 -0
  62. {projectdavid-1.32.0 → projectdavid-1.32.2}/src/projectdavid/utils/monitor_launcher.py +0 -0
  63. {projectdavid-1.32.0 → projectdavid-1.32.2}/src/projectdavid/utils/run_monitor.py +0 -0
  64. {projectdavid-1.32.0 → projectdavid-1.32.2}/src/projectdavid/utils/vector_search_formatter.py +0 -0
  65. {projectdavid-1.32.0 → projectdavid-1.32.2}/src/projectdavid.egg-info/SOURCES.txt +0 -0
  66. {projectdavid-1.32.0 → projectdavid-1.32.2}/src/projectdavid.egg-info/dependency_links.txt +0 -0
  67. {projectdavid-1.32.0 → projectdavid-1.32.2}/src/projectdavid.egg-info/requires.txt +0 -0
  68. {projectdavid-1.32.0 → projectdavid-1.32.2}/src/projectdavid.egg-info/top_level.txt +0 -0
  69. {projectdavid-1.32.0 → projectdavid-1.32.2}/tests/test_clients.py +0 -0
@@ -1,3 +1,17 @@
1
+ ## [1.32.2](https://github.com/frankie336/projectdavid/compare/v1.32.1...v1.32.2) (2025-06-08)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * supress mode code_interpreter_calls ([d7862d8](https://github.com/frankie336/projectdavid/commit/d7862d87234d1647ab7e4ba700971ed24d4a228e))
7
+
8
+ ## [1.32.1](https://github.com/frankie336/projectdavid/compare/v1.32.0...v1.32.1) (2025-06-08)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * supress mode suppressing all content ([657ab23](https://github.com/frankie336/projectdavid/commit/657ab23668337133ce93995a6acce4b503d12fce))
14
+
1
15
  # [1.32.0](https://github.com/frankie336/projectdavid/compare/v1.31.1...v1.32.0) (2025-06-08)
2
16
 
3
17
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: projectdavid
3
- Version: 1.32.0
3
+ Version: 1.32.2
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
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "projectdavid"
7
- version = "1.32.0"
7
+ version = "1.32.2"
8
8
  description = "Python SDK for interacting with the Entities Assistant API."
9
9
  readme = "README.md"
10
10
  authors = [
@@ -49,15 +49,14 @@ class SynchronousInferenceStream:
49
49
  self,
50
50
  provider: str,
51
51
  model: str,
52
- *, # keyword-only from here
52
+ *,
53
53
  api_key: Optional[str] = None,
54
54
  timeout_per_chunk: float = 280.0,
55
- suppress_fc: bool = True, # ← NEW switch
55
+ suppress_fc: bool = True,
56
56
  ) -> Generator[dict, None, None]:
57
57
 
58
58
  resolved_api_key = api_key or self.api_key
59
59
 
60
- # ------------- build async generator ----------------------
61
60
  async def _stream_chunks_async():
62
61
  async for chk in self.inference_client.stream_inference_response(
63
62
  provider=provider,
@@ -72,10 +71,10 @@ class SynchronousInferenceStream:
72
71
 
73
72
  agen = _stream_chunks_async().__aiter__()
74
73
 
75
- # ------------- optional suppression chain -----------------
74
+ # ---------- suppression chain ----------
76
75
  if suppress_fc:
77
76
  _suppressor = FunctionCallSuppressor()
78
- _peek_gate = PeekGate(_suppressor) # 2 KB default
77
+ _peek_gate = PeekGate(_suppressor)
79
78
 
80
79
  def _filter_text(txt: str) -> str:
81
80
  return _peek_gate.feed(txt)
@@ -85,7 +84,7 @@ class SynchronousInferenceStream:
85
84
  def _filter_text(txt: str) -> str: # no-op
86
85
  return txt
87
86
 
88
- # ----------------------------------------------------------
87
+ # ---------------------------------------
89
88
 
90
89
  while True:
91
90
  try:
@@ -93,18 +92,23 @@ class SynchronousInferenceStream:
93
92
  asyncio.wait_for(agen.__anext__(), timeout=timeout_per_chunk)
94
93
  )
95
94
 
96
- # --- provider-labelled function_call blocks -------
95
+ # provider-labelled function_call
97
96
  if suppress_fc and chunk.get("type") == "function_call":
98
- LOG.debug(
99
- "[SUPPRESSOR] blocked provider-labelled function_call chunk"
100
- )
97
+ LOG.debug("[SUPPRESSOR] blocked provider-labelled function_call")
101
98
  continue
102
99
 
103
- # --- inline content filtering --------------------
100
+ # inline content
104
101
  if isinstance(chunk.get("content"), str):
105
102
  chunk["content"] = _filter_text(chunk["content"])
106
- if not chunk["content"]:
107
- # fully suppressed skip forwarding
103
+ if chunk["content"] == "":
104
+ continue # fully suppressed (or still peeking)
105
+
106
+ # additional raw inline suppression for partial JSON
107
+ if (
108
+ '"name": "code_interpreter"' in chunk["content"]
109
+ and '"arguments": {"code"' in chunk["content"]
110
+ ):
111
+ LOG.debug("[SUPPRESSOR] inline code_interpreter match blocked")
108
112
  continue
109
113
 
110
114
  yield chunk
@@ -1,3 +1,6 @@
1
+ # ------------------------------------------------------------------
2
+ # utils.function_call_suppressor (unchanged except for logger)
3
+ # ------------------------------------------------------------------
1
4
  import re
2
5
 
3
6
  from projectdavid_common.utilities.logging_service import LoggingUtility
@@ -5,9 +8,6 @@ from projectdavid_common.utilities.logging_service import LoggingUtility
5
8
  LOG = LoggingUtility()
6
9
 
7
10
 
8
- # ─────────────────────────────────────────────────────────────────────
9
- # function-call filter helpers (unchanged except for logger)
10
- # ─────────────────────────────────────────────────────────────────────
11
11
  class FunctionCallSuppressor:
12
12
  OPEN_RE = re.compile(r"<\s*fc\s*>", re.I)
13
13
  CLOSE_RE = re.compile(r"</\s*fc\s*>", re.I)
@@ -16,10 +16,9 @@ class FunctionCallSuppressor:
16
16
  self.in_fc = False
17
17
  self.buf = ""
18
18
 
19
- def filter_chunk(self, chunk: str) -> str:
20
- self.buf += chunk
19
+ def filter_chunk(self, txt: str) -> str:
20
+ self.buf += txt
21
21
  out = ""
22
-
23
22
  while self.buf:
24
23
  if not self.in_fc:
25
24
  m = self.OPEN_RE.search(self.buf)
@@ -34,7 +33,7 @@ class FunctionCallSuppressor:
34
33
  else:
35
34
  m = self.CLOSE_RE.search(self.buf)
36
35
  if not m:
37
- break # wait for more tokens
36
+ break
38
37
  LOG.debug("[SUPPRESSOR] </fc> detected — block suppressed")
39
38
  self.buf = self.buf[m.end() :]
40
39
  self.in_fc = False
@@ -0,0 +1,71 @@
1
+ # ------------------------------------------------------------------
2
+ # utils.peek_gate (progressive flush version)
3
+ # ------------------------------------------------------------------
4
+ import re
5
+
6
+ from projectdavid_common.utilities.logging_service import LoggingUtility
7
+
8
+ from .function_call_suppressor import FunctionCallSuppressor
9
+
10
+ LOG = LoggingUtility()
11
+
12
+
13
+ class PeekGate:
14
+ """
15
+ • Streams *most* text immediately while the gate decides whether
16
+ a <fc> block will appear.
17
+ • Keeps only SAFETY_MARGIN bytes back so a tag split across two
18
+ chunks can still be caught.
19
+ """
20
+
21
+ SAFETY_MARGIN = 8 # enough to hold "<fc>" + whitespace
22
+
23
+ def __init__(self, downstream: FunctionCallSuppressor, peek_limit: int = 2048):
24
+ self.downstream = downstream
25
+ self.peek_limit = peek_limit
26
+ self.buf = ""
27
+ self.mode = "peeking" # → "normal" after decision
28
+ self.suppressing = False
29
+
30
+ # ----------------------------------------------------------
31
+ def _safe_flush(self, new_txt: str = "") -> str:
32
+ """
33
+ Return everything except the last SAFETY_MARGIN chars,
34
+ which are kept for tag-boundary safety.
35
+ """
36
+ self.buf += new_txt
37
+ if len(self.buf) <= self.SAFETY_MARGIN:
38
+ return ""
39
+ flush_len = len(self.buf) - self.SAFETY_MARGIN
40
+ head, self.buf = self.buf[:flush_len], self.buf[flush_len:]
41
+ return head
42
+
43
+ # ----------------------------------------------------------
44
+ def feed(self, txt: str) -> str:
45
+ # decision already taken
46
+ if self.mode == "normal":
47
+ return self.downstream.filter_chunk(txt) if self.suppressing else txt
48
+
49
+ # still peeking …
50
+ self.buf += txt
51
+ m = re.search(r"<\s*fc\s*>", self.buf, flags=re.I)
52
+ if m: # tag found
53
+ head = self.buf[: m.start()]
54
+ LOG.debug("[PEEK] <fc> located – engaging suppressor")
55
+ self.suppressing = True
56
+ self.mode = "normal"
57
+ tail, self.buf = self.buf[m.start() :], ""
58
+ return head + self.downstream.filter_chunk(tail)
59
+
60
+ # no tag yet – overflow?
61
+ if len(self.buf) >= self.peek_limit:
62
+ LOG.debug(
63
+ "[PEEK] no <fc> tag within first %d chars – " "streaming normally",
64
+ self.peek_limit,
65
+ )
66
+ flush, self.mode = self.buf, "normal"
67
+ self.buf = ""
68
+ return flush
69
+
70
+ # still undecided → flush safe part
71
+ return self._safe_flush()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: projectdavid
3
- Version: 1.32.0
3
+ Version: 1.32.2
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
@@ -1,49 +0,0 @@
1
- import re
2
-
3
- from projectdavid_common.utilities.logging_service import LoggingUtility
4
-
5
- from .function_call_suppressor import FunctionCallSuppressor
6
-
7
- LOG = LoggingUtility()
8
-
9
-
10
- class PeekGate:
11
- """
12
- Turns the suppressor on only if a <fc> block appears in the first
13
- `peek_limit` characters; otherwise passes text through unchanged.
14
- """
15
-
16
- def __init__(self, downstream: FunctionCallSuppressor, peek_limit: int = 2048):
17
- self.downstream = downstream
18
- self.peek_limit = peek_limit
19
- self.buf = ""
20
- self.mode = "peeking" # -> "normal" after decision
21
- self.suppressing = False
22
-
23
- def feed(self, txt: str) -> str:
24
- # decision already taken
25
- if self.mode == "normal":
26
- return self.downstream.filter_chunk(txt) if self.suppressing else txt
27
-
28
- # still peeking …
29
- self.buf += txt
30
- m = re.search(r"<\s*fc\s*>", self.buf, flags=re.I)
31
- if m: # found a tag
32
- head = self.buf[: m.start()]
33
- LOG.debug("[PEEK] <fc> located after leading text – engaging suppressor")
34
- self.suppressing = True
35
- self.mode = "normal"
36
- tail = self.buf[m.start() :]
37
- self.buf = ""
38
- return head + self.downstream.filter_chunk(tail)
39
-
40
- if len(self.buf) >= self.peek_limit: # give up
41
- LOG.debug(
42
- "[PEEK] no <fc> tag within first %d chars – no suppression",
43
- self.peek_limit,
44
- )
45
- self.mode = "normal"
46
- self.suppressing = False
47
- out, self.buf = self.buf, ""
48
- return out
49
- return ""
File without changes
File without changes
File without changes
File without changes