nosible 0.3.5__py3-none-any.whl → 0.3.9__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.
nosible/classes/result.py CHANGED
@@ -36,6 +36,8 @@ class Result:
36
36
  The author of the content.
37
37
  content : str, optional
38
38
  The main content or body of the search result.
39
+ best_chunk : str, optional
40
+ The best snippet of text that matches your question from the search result.
39
41
  language : str, optional
40
42
  The language code of the content (e.g., 'en' for English).
41
43
  similarity : float, optional
@@ -105,6 +107,8 @@ class Result:
105
107
  """The author of the content."""
106
108
  content: str | None = None
107
109
  """The main content or body of the search result."""
110
+ best_chunk: str | None = None
111
+ """The best snippet of text that matches your question from the search result."""
108
112
  language: str | None = None
109
113
  """The language code of the content (e.g., 'en' for English)."""
110
114
  similarity: float | None = None
@@ -150,23 +154,14 @@ class Result:
150
154
  >>> result = Result(title="Example Domain", similarity=0.9876)
151
155
  >>> print(str(result))
152
156
  0.99 | Example Domain
153
- >>> result = Result(title=None, similarity=None)
154
- >>> print(str(result))
155
- {
156
- "url": null,
157
- "title": null,
158
- "description": null,
159
- "netloc": null,
160
- "published": null,
161
- "visited": null,
162
- "author": null,
163
- "content": null,
164
- "language": null,
165
- "similarity": null,
166
- "url_hash": null
167
- }
168
157
  """
169
- return print_dict(self.to_dict())
158
+ # Get the full dictionary
159
+ data = self.to_dict()
160
+
161
+ # Create a new dictionary excluding keys where the value is None
162
+ clean_data = {k: v for k, v in data.items() if v is not None}
163
+
164
+ return print_dict(clean_data)
170
165
 
171
166
  def __getitem__(self, key: str) -> str | float | bool | None:
172
167
  """
@@ -519,6 +514,11 @@ class Result:
519
514
  try:
520
515
  from nosible import Search
521
516
 
517
+ # Exclude the original doc from the new search.
518
+ exclude_docs_list = list(exclude_docs) if exclude_docs else []
519
+ if self.url_hash and self.url_hash not in exclude_docs_list:
520
+ exclude_docs_list.append(self.url_hash)
521
+
522
522
  s = Search(
523
523
  question=self.title,
524
524
  expansions=[],
@@ -537,7 +537,7 @@ class Result:
537
537
  include_companies=include_companies,
538
538
  exclude_companies=exclude_companies,
539
539
  include_docs=include_docs,
540
- exclude_docs=exclude_docs,
540
+ exclude_docs=exclude_docs_list,
541
541
  brand_safety=brand_safety,
542
542
  language=language,
543
543
  continent=continent,
@@ -54,6 +54,7 @@ class ResultSet(Iterator[Result]):
54
54
  "visited",
55
55
  "author",
56
56
  "content",
57
+ "best_chunk",
57
58
  "language",
58
59
  "similarity",
59
60
  "url_hash",
@@ -1004,6 +1005,7 @@ class ResultSet(Iterator[Result]):
1004
1005
  visited=row.get("visited"),
1005
1006
  author=row.get("author"),
1006
1007
  content=row.get("content"),
1008
+ best_chunk=row.get("best_chunk"),
1007
1009
  language=row.get("language"),
1008
1010
  similarity=row.get("similarity"),
1009
1011
  url_hash=row.get("url_hash"),
@@ -1113,6 +1115,7 @@ class ResultSet(Iterator[Result]):
1113
1115
  visited=row.get("visited"),
1114
1116
  author=row.get("author"),
1115
1117
  content=row.get("content"),
1118
+ best_chunk=row.get("best_chunk"),
1116
1119
  language=row.get("language"),
1117
1120
  similarity=row.get("semantics", {}).get("similarity", row.get("similarity")),
1118
1121
  url_hash=row.get("url_hash"),
@@ -1212,6 +1215,7 @@ class ResultSet(Iterator[Result]):
1212
1215
  visited=data.get("visited"),
1213
1216
  author=data.get("author"),
1214
1217
  content=data.get("content"),
1218
+ best_chunk=data.get("best_chunk"),
1215
1219
  language=data.get("language"),
1216
1220
  similarity=data.get("similarity"),
1217
1221
  url_hash=data.get("url_hash"),
@@ -1449,6 +1453,7 @@ class ResultSet(Iterator[Result]):
1449
1453
  visited=d.get("visited"),
1450
1454
  author=d.get("author"),
1451
1455
  content=d.get("content"),
1456
+ best_chunk=d.get("best_chunk"),
1452
1457
  language=d.get("language"),
1453
1458
  similarity=d.get("similarity", d.get("semantics", {}).get("similarity")),
1454
1459
  url_hash=d.get("url_hash"),
@@ -30,18 +30,13 @@ class Snippet:
30
30
  The words in the snippet.
31
31
  links : list or None
32
32
  List of links associated with the snippet.
33
- companies : list or None
34
- List of companies mentioned in the snippet.
35
-
36
33
 
37
34
  Examples
38
35
  --------
39
36
  >>> snippet = Snippet(content="Example snippet", language="en")
40
37
  >>> print(snippet.content)
41
38
  Example snippet
42
-
43
39
  """
44
-
45
40
  content: str = field(default=None, repr=True, compare=True)
46
41
  """The text content of the snippet."""
47
42
  images: list = field(default=None, repr=True, compare=False)
@@ -62,8 +57,6 @@ class Snippet:
62
57
  """The words in the snippet."""
63
58
  links: list = field(default=None, repr=False, compare=False)
64
59
  """List of links associated with the snippet."""
65
- companies: list = field(default=None, repr=False, compare=False)
66
- """List of companies mentioned in the snippet."""
67
60
 
68
61
  def __str__(self):
69
62
  """
@@ -40,8 +40,6 @@ class WebPageData:
40
40
  {'description': 'Example'}
41
41
  """
42
42
 
43
- companies: list = None
44
- """A list of companies mentioned in the webpage, if applicable. (GKIDS)"""
45
43
  full_text: str = None
46
44
  """The full text content of the webpage."""
47
45
  languages: dict = None
nosible/nosible_client.py CHANGED
@@ -1522,7 +1522,6 @@ class Nosible:
1522
1522
 
1523
1523
  response_data = data["response"]
1524
1524
  return WebPageData(
1525
- companies=response_data.get("companies"),
1526
1525
  full_text=response_data.get("full_text"),
1527
1526
  languages=response_data.get("languages"),
1528
1527
  metadata=response_data.get("metadata"),
@@ -2039,13 +2038,13 @@ class Nosible:
2039
2038
 
2040
2039
  if include_docs:
2041
2040
  # Assume these are URL hashes, e.g. "ENNmqkF1mGNhVhvhmbUEs4U2"
2042
- doc_hashes = ", ".join(f"'{doc}'" for doc in include_docs)
2043
- clauses.append(f"doc_hash IN ({doc_hashes})")
2041
+ docs = ", ".join(f"'{doc}'" for doc in include_docs)
2042
+ clauses.append(f"doc IN ({docs})")
2044
2043
 
2045
2044
  if exclude_docs:
2046
2045
  # Assume these are URL hashes, e.g. "ENNmqkF1mGNhVhvhmbUEs4U2"
2047
- doc_hashes = ", ".join(f"'{doc}'" for doc in exclude_docs)
2048
- clauses.append(f"doc_hash NOT IN ({doc_hashes})")
2046
+ docs = ", ".join(f"'{doc}'" for doc in exclude_docs)
2047
+ clauses.append(f"doc NOT IN ({docs})")
2049
2048
 
2050
2049
  # Join everything
2051
2050
  if clauses:
@@ -2092,7 +2091,7 @@ class Nosible:
2092
2091
  "netloc",
2093
2092
  "language",
2094
2093
  "companies"
2095
- "doc_hash",
2094
+ "doc",
2096
2095
  ]
2097
2096
  import polars as pl # Lazy import
2098
2097
 
@@ -4,7 +4,7 @@ import time
4
4
 
5
5
  from pyrate_limiter import Limiter, Rate
6
6
  from pyrate_limiter.buckets.in_memory_bucket import InMemoryBucket
7
- from pyrate_limiter.exceptions import BucketFullException
7
+ from pyrate_limiter.exceptions import BucketFullException, LimiterDelayException
8
8
 
9
9
  log = logging.getLogger(__name__)
10
10
 
@@ -133,7 +133,7 @@ class RateLimiter:
133
133
 
134
134
  # Build our bucket
135
135
  bucket = InMemoryBucket([Rate(max_calls, period_ms)])
136
- self._limiter = Limiter(bucket)
136
+ self._limiter = Limiter(bucket, max_delay=1000)
137
137
 
138
138
  def acquire(self) -> None:
139
139
  """
@@ -177,7 +177,7 @@ class RateLimiter:
177
177
  # Ensure at least a small sleep if rounding to zero
178
178
  time.sleep(wait_s)
179
179
 
180
- def try_acquire(self) -> bool:
180
+ def try_acquire(self, name: str = None) -> bool:
181
181
  """
182
182
  Attempt to acquire a slot without blocking.
183
183
 
@@ -196,8 +196,11 @@ class RateLimiter:
196
196
  >>> rl.try_acquire()
197
197
  False
198
198
  """
199
+ key = name if name else self._GLOBAL_KEY
200
+
199
201
  try:
200
- self._limiter.try_acquire(self._GLOBAL_KEY)
202
+ self._limiter.try_acquire(key)
201
203
  return True
202
- except BucketFullException:
203
- return False
204
+ except (BucketFullException, LimiterDelayException):
205
+ # Return False instead of crashing when the limit is hit
206
+ return False
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nosible
3
- Version: 0.3.5
3
+ Version: 0.3.9
4
4
  Summary: Python client for the NOSIBLE Search API
5
5
  Home-page: https://github.com/NosibleAI/nosible-py
6
6
  Author: Stuart Reid, Matthew Dicks, Richard Taylor, Gareth Warburton
@@ -146,6 +146,24 @@ with Nosible(nosible_api_key="YOUR API KEY") as client:
146
146
  print(results)
147
147
  ```
148
148
 
149
+ ### 🤖 Cybernaut 1
150
+
151
+ An AI agent with unrestricted access to everything in NOSIBLE including every shard, algorithm, selector,
152
+ reranker, and signal. It knows what these things are and can tune them on the fly to find better results.
153
+
154
+ ```python
155
+ from nosible import Nosible
156
+
157
+ with Nosible(nosible_api_key="YOUR API KEY") as client:
158
+
159
+ results = client.search(
160
+ # search() gives you access to Cybernaut 1
161
+ question="Find me interesting technical blogs about Monte Carlo Tree Search."
162
+ )
163
+
164
+ print(results)
165
+ ```
166
+
149
167
  ### 📄 Documentation
150
168
 
151
169
  You can find the full NOSIBLE Search Client documentation
@@ -0,0 +1,16 @@
1
+ nosible/__init__.py,sha256=11QmG9Wjprp_zB0VnPxGjqKwHmaoB0hoT8AGO6cGVMM,1426
2
+ nosible/nosible_client.py,sha256=tTnDts1XaxaqGRW4ymcwYsZlbzg2i_1Qw9GfD3PCRmA,88572
3
+ nosible/classes/result.py,sha256=DvUUt4hiZ8PJBGTIwkq5GFB4ors_2L9dApNlawSLesA,22978
4
+ nosible/classes/result_set.py,sha256=9xuACJVp5n3pKECBjhkzNMb7PAQd4P1HmtkZH3KFAyo,52911
5
+ nosible/classes/search.py,sha256=VrpuAsS4pxcirR6l6WStJN0gPIfahZ_9Cx3YdNKczSw,13860
6
+ nosible/classes/search_set.py,sha256=VvtKXQ1_Ws_W-0p0C-wUvvdskeuXAyr65tpfvexAVw0,9895
7
+ nosible/classes/snippet.py,sha256=K0o4aQbbvsnNzgnhZIu7RXLASkVO-R3iBIY7sCpNpLw,4787
8
+ nosible/classes/snippet_set.py,sha256=0jPMDhJNCO02WhvY1QR1HedvADvBxRcN6x3FItEgSiI,5099
9
+ nosible/classes/web_page.py,sha256=gAOBnqaK59f5erdRERxhvKmcwRVSXvhwJwyHIjPyeek,5732
10
+ nosible/utils/json_tools.py,sha256=PcSMjcLEhbA626jAIn0SuD_1-4QDduapZUenTSt3N2E,4569
11
+ nosible/utils/rate_limiter.py,sha256=X1-X5ykU9NKpp1vZJQj1oXEEBUQvur7PSG_o4Yidp4k,6657
12
+ nosible-0.3.9.dist-info/licenses/LICENSE,sha256=8ifsV4DrsiKi8KVBFy8SBb3KXPXhofE3pYq07q1TSCQ,1117
13
+ nosible-0.3.9.dist-info/METADATA,sha256=8O3piycx24IomgyZhErKfDHyiH3DeY91iHOPC4l0GcQ,6032
14
+ nosible-0.3.9.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
15
+ nosible-0.3.9.dist-info/top_level.txt,sha256=mOconHuKcNJ1jTAj3DapQP_xB8YOmjTMyHg5txKH3uA,8
16
+ nosible-0.3.9.dist-info/RECORD,,
@@ -1,16 +0,0 @@
1
- nosible/__init__.py,sha256=11QmG9Wjprp_zB0VnPxGjqKwHmaoB0hoT8AGO6cGVMM,1426
2
- nosible/nosible_client.py,sha256=VOwc2nYOL-OtO9Xp3yyUOdJ3aUzr9_9lxDHJoCiADio,88665
3
- nosible/classes/result.py,sha256=c1YOFdhZOnSjdcNqpc3YjXxKcoJ2c0ik6wgfIsXTAP0,22697
4
- nosible/classes/result_set.py,sha256=8XrnnpGdm5lskqE0E7qSRR_mofPZfEHxtOFrkmfpbEM,52662
5
- nosible/classes/search.py,sha256=VrpuAsS4pxcirR6l6WStJN0gPIfahZ_9Cx3YdNKczSw,13860
6
- nosible/classes/search_set.py,sha256=VvtKXQ1_Ws_W-0p0C-wUvvdskeuXAyr65tpfvexAVw0,9895
7
- nosible/classes/snippet.py,sha256=m2qxgnMxIxx4ZOIMqUAViGLf7C1Y4NCGaioyEKw2-Zg,4994
8
- nosible/classes/snippet_set.py,sha256=0jPMDhJNCO02WhvY1QR1HedvADvBxRcN6x3FItEgSiI,5099
9
- nosible/classes/web_page.py,sha256=cvwQspxS0pU2nFgPLqnDtDWlLONHp1KwxerflHueLJ8,5838
10
- nosible/utils/json_tools.py,sha256=PcSMjcLEhbA626jAIn0SuD_1-4QDduapZUenTSt3N2E,4569
11
- nosible/utils/rate_limiter.py,sha256=zbzEGtVnHooknEbwQSK2dtk_afsmbM0diz5t9JF68Bw,6470
12
- nosible-0.3.5.dist-info/licenses/LICENSE,sha256=8ifsV4DrsiKi8KVBFy8SBb3KXPXhofE3pYq07q1TSCQ,1117
13
- nosible-0.3.5.dist-info/METADATA,sha256=C4STEONiV1xeNydUKV3ZrHIlzFXDwQslGp2W99BN03w,5503
14
- nosible-0.3.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
15
- nosible-0.3.5.dist-info/top_level.txt,sha256=mOconHuKcNJ1jTAj3DapQP_xB8YOmjTMyHg5txKH3uA,8
16
- nosible-0.3.5.dist-info/RECORD,,