symbolicai 0.20.0__py3-none-any.whl → 0.20.2__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.
- symai/__init__.py +1 -1
- symai/backend/engines/search/engine_openai.py +72 -0
- {symbolicai-0.20.0.dist-info → symbolicai-0.20.2.dist-info}/METADATA +1 -1
- {symbolicai-0.20.0.dist-info → symbolicai-0.20.2.dist-info}/RECORD +8 -8
- {symbolicai-0.20.0.dist-info → symbolicai-0.20.2.dist-info}/WHEEL +0 -0
- {symbolicai-0.20.0.dist-info → symbolicai-0.20.2.dist-info}/entry_points.txt +0 -0
- {symbolicai-0.20.0.dist-info → symbolicai-0.20.2.dist-info}/licenses/LICENSE +0 -0
- {symbolicai-0.20.0.dist-info → symbolicai-0.20.2.dist-info}/top_level.txt +0 -0
symai/__init__.py
CHANGED
|
@@ -230,6 +230,8 @@ class SearchResult(Result):
|
|
|
230
230
|
|
|
231
231
|
|
|
232
232
|
class GPTXSearchEngine(Engine):
|
|
233
|
+
MAX_ALLOWED_DOMAINS = 20
|
|
234
|
+
|
|
233
235
|
def __init__(self, api_key: str | None = None, model: str | None = None):
|
|
234
236
|
super().__init__()
|
|
235
237
|
self.config = deepcopy(SYMAI_CONFIG)
|
|
@@ -250,6 +252,65 @@ class GPTXSearchEngine(Engine):
|
|
|
250
252
|
return 'search'
|
|
251
253
|
return super().id() # default to unregistered
|
|
252
254
|
|
|
255
|
+
def _extract_netloc(self, raw_domain: str | None) -> str | None:
|
|
256
|
+
if not isinstance(raw_domain, str):
|
|
257
|
+
return None
|
|
258
|
+
candidate = raw_domain.strip()
|
|
259
|
+
if not candidate:
|
|
260
|
+
return None
|
|
261
|
+
parsed = urlsplit(candidate if '://' in candidate else f"//{candidate}")
|
|
262
|
+
netloc = parsed.netloc or parsed.path
|
|
263
|
+
if not netloc:
|
|
264
|
+
return None
|
|
265
|
+
if '@' in netloc:
|
|
266
|
+
netloc = netloc.split('@', 1)[1]
|
|
267
|
+
if ':' in netloc:
|
|
268
|
+
netloc = netloc.split(':', 1)[0]
|
|
269
|
+
netloc = netloc.strip('.').strip()
|
|
270
|
+
if not netloc:
|
|
271
|
+
return None
|
|
272
|
+
return netloc.lower()
|
|
273
|
+
|
|
274
|
+
def _normalize_allowed_domains(self, domains: list[str] | None) -> list[str]:
|
|
275
|
+
if not domains or not isinstance(domains, list):
|
|
276
|
+
return []
|
|
277
|
+
|
|
278
|
+
normalized: list[str] = []
|
|
279
|
+
seen: set[str] = set()
|
|
280
|
+
for domain in domains:
|
|
281
|
+
netloc = self._extract_netloc(domain)
|
|
282
|
+
if not netloc or netloc in seen:
|
|
283
|
+
continue
|
|
284
|
+
# Validate that netloc is actually a valid domain
|
|
285
|
+
if not self._is_domain(netloc):
|
|
286
|
+
continue
|
|
287
|
+
normalized.append(netloc)
|
|
288
|
+
seen.add(netloc)
|
|
289
|
+
if len(normalized) >= self.MAX_ALLOWED_DOMAINS:
|
|
290
|
+
break
|
|
291
|
+
return normalized
|
|
292
|
+
|
|
293
|
+
def _is_domain(self, s: str) -> bool:
|
|
294
|
+
_label_re = re.compile(r"^[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?$")
|
|
295
|
+
if not s:
|
|
296
|
+
return False
|
|
297
|
+
host = s.strip().rstrip(".")
|
|
298
|
+
# If the input might be a URL, extract the hostname via urllib:
|
|
299
|
+
if "://" in host or "/" in host or "@" in host:
|
|
300
|
+
host = urlsplit(host if "://" in host else f"//{host}").hostname or ""
|
|
301
|
+
if not host:
|
|
302
|
+
return False
|
|
303
|
+
try:
|
|
304
|
+
host_ascii = host.encode("idna").decode("ascii")
|
|
305
|
+
except Exception:
|
|
306
|
+
return False
|
|
307
|
+
if len(host_ascii) > 253:
|
|
308
|
+
return False
|
|
309
|
+
labels = host_ascii.split(".")
|
|
310
|
+
if len(labels) < 2: # require a dot (reject "google")
|
|
311
|
+
return False
|
|
312
|
+
return all(_label_re.fullmatch(lbl or "") for lbl in labels)
|
|
313
|
+
|
|
253
314
|
def command(self, *args, **kwargs):
|
|
254
315
|
super().command(*args, **kwargs)
|
|
255
316
|
if 'SEARCH_ENGINE_API_KEY' in kwargs:
|
|
@@ -266,7 +327,14 @@ class GPTXSearchEngine(Engine):
|
|
|
266
327
|
if user_location:
|
|
267
328
|
tool_definition['user_location'] = user_location
|
|
268
329
|
|
|
330
|
+
allowed_domains = self._normalize_allowed_domains(kwargs.get('allowed_domains'))
|
|
331
|
+
if allowed_domains:
|
|
332
|
+
tool_definition['filters'] = {
|
|
333
|
+
'allowed_domains': allowed_domains
|
|
334
|
+
}
|
|
335
|
+
|
|
269
336
|
self.model = kwargs.get('model', self.model) # Important for MetadataTracker to work correctly
|
|
337
|
+
|
|
270
338
|
payload = {
|
|
271
339
|
"model": self.model,
|
|
272
340
|
"input": messages,
|
|
@@ -274,6 +342,10 @@ class GPTXSearchEngine(Engine):
|
|
|
274
342
|
"tool_choice": {"type": "web_search"} if self.model not in OPENAI_REASONING_MODELS else "auto" # force the use of web search tool for non-reasoning models
|
|
275
343
|
}
|
|
276
344
|
|
|
345
|
+
if self.model in OPENAI_REASONING_MODELS:
|
|
346
|
+
reasoning = kwargs.get('reasoning', { "effort": "low", "summary": "auto" })
|
|
347
|
+
payload['reasoning'] = reasoning
|
|
348
|
+
|
|
277
349
|
try:
|
|
278
350
|
res = self.client.responses.create(**payload)
|
|
279
351
|
res = SearchResult(res.dict())
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: symbolicai
|
|
3
|
-
Version: 0.20.
|
|
3
|
+
Version: 0.20.2
|
|
4
4
|
Summary: A Neurosymbolic Perspective on Large Language Models
|
|
5
5
|
Author-email: Marius-Constantin Dinu <marius@extensity.ai>, Leoveanu-Condrei Claudiu <leo@extensity.ai>
|
|
6
6
|
License: BSD 3-Clause License
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
symai/TERMS_OF_SERVICE.md,sha256=HN42UXVI_wAVDHjMShzy_k7xAsbjXaATNeMKcIte_eg,91409
|
|
2
|
-
symai/__init__.py,sha256=
|
|
2
|
+
symai/__init__.py,sha256=dck_yV4T5x8FzfK8twOpiqLPfBMDxqYL24EXmgF7Mug,16464
|
|
3
3
|
symai/chat.py,sha256=vqEe7NqSWdzr9ixkko_094SR1LIbgPLcZxQ8W7782N4,12775
|
|
4
4
|
symai/components.py,sha256=vgIq-cC8rqZG9PAPUB52Y5RGFEKrxFUCWzqzrPzLNvw,52232
|
|
5
5
|
symai/constraints.py,sha256=S1ywLB8nFQy4-beDoJz6IvLTiZHGR8Fu5RNTY4v5zG0,1641
|
|
@@ -56,7 +56,7 @@ symai/backend/engines/neurosymbolic/engine_openai_gptX_completion.py,sha256=YgxR
|
|
|
56
56
|
symai/backend/engines/neurosymbolic/engine_openai_gptX_reasoning.py,sha256=QVbyZybUPSAQHiA66V6we2W2dAsk52g1kJ7kMdGqb9I,22951
|
|
57
57
|
symai/backend/engines/ocr/engine_apilayer.py,sha256=hZo4lk0ECRIzaGEpmCSNjR5Xrh8mwkKMD2ddpdgioVU,2399
|
|
58
58
|
symai/backend/engines/output/engine_stdout.py,sha256=2hhyhMHFJTfjVRaODYd_5XPnV9pT03URcpYbeMY_USU,951
|
|
59
|
-
symai/backend/engines/search/engine_openai.py,sha256=
|
|
59
|
+
symai/backend/engines/search/engine_openai.py,sha256=ps_BNwiC1K1NeBJ6oaoyRIDiYksOqi53J7gGKaobue8,14136
|
|
60
60
|
symai/backend/engines/search/engine_perplexity.py,sha256=yxuhGaA38d1FRbLv6piLll0QDxCCyBVK6eeomjYNryM,4157
|
|
61
61
|
symai/backend/engines/search/engine_serpapi.py,sha256=UqvGHs1J9BOv05C0FJUQjbz29_VuWncIkeDwlRPUilU,3698
|
|
62
62
|
symai/backend/engines/speech_to_text/engine_local_whisper.py,sha256=LRsXliCpHDFPFaE-vPky3-DLkmYwmwe2mxfF0Brz4Wg,8220
|
|
@@ -154,9 +154,9 @@ symai/ops/primitives.py,sha256=EaB2Ekx9yGNDaQa3aKS5KpuEr5awAUbO3OcBbufI-l4,11072
|
|
|
154
154
|
symai/server/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
155
155
|
symai/server/huggingface_server.py,sha256=UpSBflnQaenDjY1AAn5LUYeg5J4gJLWiMuC5DcoIV3E,8743
|
|
156
156
|
symai/server/llama_cpp_server.py,sha256=qVCldTdcQhK2YCu7sDNSYziu1p2AQieqMFfY028-yOc,2049
|
|
157
|
-
symbolicai-0.20.
|
|
158
|
-
symbolicai-0.20.
|
|
159
|
-
symbolicai-0.20.
|
|
160
|
-
symbolicai-0.20.
|
|
161
|
-
symbolicai-0.20.
|
|
162
|
-
symbolicai-0.20.
|
|
157
|
+
symbolicai-0.20.2.dist-info/licenses/LICENSE,sha256=9vRFudlJ1ghVfra5lcCUIYQCqnZSYcBLjLHbGRsrQCs,1505
|
|
158
|
+
symbolicai-0.20.2.dist-info/METADATA,sha256=HjuszeTqm_m12VU4yXwEkYVxh3ig_2CZpUqloTtdjvY,23122
|
|
159
|
+
symbolicai-0.20.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
160
|
+
symbolicai-0.20.2.dist-info/entry_points.txt,sha256=JV5sdydIfUZdDF6QBEQHiZHod6XNPjCjpWQrXh7gTAw,261
|
|
161
|
+
symbolicai-0.20.2.dist-info/top_level.txt,sha256=bOoIDfpDIvCQtQgXcwVKJvxAKwsxpxo2IL4z92rNJjw,6
|
|
162
|
+
symbolicai-0.20.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|