nucliadb 6.2.1.post2949__py3-none-any.whl → 6.2.1.post2971__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.
@@ -21,7 +21,7 @@ import json
21
21
  import os
22
22
  import random
23
23
  from enum import Enum
24
- from typing import Any, AsyncIterator, Optional
24
+ from typing import Any, AsyncGenerator, Optional
25
25
  from unittest.mock import AsyncMock, Mock
26
26
 
27
27
  import aiohttp
@@ -121,12 +121,14 @@ class AnswerStatusCode(str, Enum):
121
121
  SUCCESS = "0"
122
122
  ERROR = "-1"
123
123
  NO_CONTEXT = "-2"
124
+ NO_RETRIEVAL_DATA = "-3"
124
125
 
125
126
  def prettify(self) -> str:
126
127
  return {
127
128
  AnswerStatusCode.SUCCESS: "success",
128
129
  AnswerStatusCode.ERROR: "error",
129
130
  AnswerStatusCode.NO_CONTEXT: "no_context",
131
+ AnswerStatusCode.NO_RETRIEVAL_DATA: "no_retrieval_data",
130
132
  }[self]
131
133
 
132
134
 
@@ -266,7 +268,7 @@ class PredictEngine:
266
268
  @predict_observer.wrap({"type": "chat_ndjson"})
267
269
  async def chat_query_ndjson(
268
270
  self, kbid: str, item: ChatModel
269
- ) -> tuple[str, str, AsyncIterator[GenerativeChunk]]:
271
+ ) -> tuple[str, str, AsyncGenerator[GenerativeChunk, None]]:
270
272
  """
271
273
  Chat query using the new stream format
272
274
  Format specs: https://github.com/ndjson/ndjson-spec
@@ -442,7 +444,7 @@ class DummyPredictEngine(PredictEngine):
442
444
 
443
445
  async def chat_query_ndjson(
444
446
  self, kbid: str, item: ChatModel
445
- ) -> tuple[str, str, AsyncIterator[GenerativeChunk]]:
447
+ ) -> tuple[str, str, AsyncGenerator[GenerativeChunk, None]]:
446
448
  self.calls.append(("chat_query_ndjson", item))
447
449
 
448
450
  async def generate():
@@ -553,7 +555,7 @@ def get_answer_generator(response: aiohttp.ClientResponse):
553
555
 
554
556
  def get_chat_ndjson_generator(
555
557
  response: aiohttp.ClientResponse,
556
- ) -> AsyncIterator[GenerativeChunk]:
558
+ ) -> AsyncGenerator[GenerativeChunk, None]:
557
559
  async def _parse_generative_chunks(gen):
558
560
  async for chunk in gen:
559
561
  try:
@@ -49,6 +49,7 @@ from nucliadb.search.search.chat.query import (
49
49
  ChatAuditor,
50
50
  get_find_results,
51
51
  get_relations_results,
52
+ maybe_audit_chat,
52
53
  rephrase_query,
53
54
  sorted_prompt_context_list,
54
55
  tokens_to_chars,
@@ -128,7 +129,7 @@ class AskResult:
128
129
  main_results: KnowledgeboxFindResults,
129
130
  prequeries_results: Optional[list[PreQueryResult]],
130
131
  nuclia_learning_id: Optional[str],
131
- predict_answer_stream: AsyncGenerator[GenerativeChunk, None],
132
+ predict_answer_stream: Optional[AsyncGenerator[GenerativeChunk, None]],
132
133
  prompt_context: PromptContext,
133
134
  prompt_context_order: PromptContextOrder,
134
135
  auditor: ChatAuditor,
@@ -395,6 +396,9 @@ class AskResult:
395
396
  This method does not assume any order in the stream of items, but it assumes that at least
396
397
  the answer text is streamed in order.
397
398
  """
399
+ if self.predict_answer_stream is None:
400
+ # In some cases, clients may want to skip the answer generation step
401
+ return
398
402
  async for generative_chunk in self.predict_answer_stream:
399
403
  item = generative_chunk.chunk
400
404
  if isinstance(item, TextGenerativeResponse):
@@ -433,14 +437,14 @@ class NotEnoughContextAskResult(AskResult):
433
437
  """
434
438
  yield self._ndjson_encode(RetrievalAskResponseItem(results=self.main_results))
435
439
  yield self._ndjson_encode(AnswerAskResponseItem(text=NOT_ENOUGH_CONTEXT_ANSWER))
436
- status = AnswerStatusCode.NO_CONTEXT
440
+ status = AnswerStatusCode.NO_RETRIEVAL_DATA
437
441
  yield self._ndjson_encode(StatusAskResponseItem(code=status.value, status=status.prettify()))
438
442
 
439
443
  async def json(self) -> str:
440
444
  return SyncAskResponse(
441
445
  answer=NOT_ENOUGH_CONTEXT_ANSWER,
442
446
  retrieval_results=self.main_results,
443
- status=AnswerStatusCode.NO_CONTEXT,
447
+ status=AnswerStatusCode.NO_RETRIEVAL_DATA.prettify(),
444
448
  ).model_dump_json()
445
449
 
446
450
 
@@ -487,6 +491,31 @@ async def ask(
487
491
  resource=resource,
488
492
  )
489
493
  except NoRetrievalResultsError as err:
494
+ try:
495
+ rephrase_time = metrics.elapsed("rephrase")
496
+ except KeyError:
497
+ # Not all ask requests have a rephrase step
498
+ rephrase_time = None
499
+
500
+ maybe_audit_chat(
501
+ kbid=kbid,
502
+ user_id=user_id,
503
+ client_type=client_type,
504
+ origin=origin,
505
+ generative_answer_time=0,
506
+ generative_answer_first_chunk_time=0,
507
+ rephrase_time=rephrase_time,
508
+ user_query=user_query,
509
+ rephrased_query=rephrased_query,
510
+ text_answer=b"",
511
+ status_code=AnswerStatusCode.NO_RETRIEVAL_DATA,
512
+ chat_history=chat_history,
513
+ query_context={},
514
+ query_context_order={},
515
+ learning_id=None,
516
+ model=ask_request.generative_model,
517
+ )
518
+
490
519
  # If a retrieval was attempted but no results were found,
491
520
  # early return the ask endpoint without querying the generative model
492
521
  return NotEnoughContextAskResult(
@@ -536,14 +565,18 @@ async def ask(
536
565
  rerank_context=False,
537
566
  top_k=ask_request.top_k,
538
567
  )
539
- with metrics.time("stream_start"):
540
- predict = get_predict()
541
- (
542
- nuclia_learning_id,
543
- nuclia_learning_model,
544
- predict_answer_stream,
545
- ) = await predict.chat_query_ndjson(kbid, chat_model)
546
- debug_chat_model = chat_model
568
+
569
+ nuclia_learning_id = None
570
+ nuclia_learning_model = None
571
+ predict_answer_stream = None
572
+ if ask_request.generate_answer:
573
+ with metrics.time("stream_start"):
574
+ predict = get_predict()
575
+ (
576
+ nuclia_learning_id,
577
+ nuclia_learning_model,
578
+ predict_answer_stream,
579
+ ) = await predict.chat_query_ndjson(kbid, chat_model)
547
580
 
548
581
  auditor = ChatAuditor(
549
582
  kbid=kbid,
@@ -564,13 +597,13 @@ async def ask(
564
597
  main_results=retrieval_results.main_query,
565
598
  prequeries_results=retrieval_results.prequeries,
566
599
  nuclia_learning_id=nuclia_learning_id,
567
- predict_answer_stream=predict_answer_stream, # type: ignore
600
+ predict_answer_stream=predict_answer_stream,
568
601
  prompt_context=prompt_context,
569
602
  prompt_context_order=prompt_context_order,
570
603
  auditor=auditor,
571
604
  metrics=metrics,
572
605
  best_matches=retrieval_results.best_matches,
573
- debug_chat_model=debug_chat_model,
606
+ debug_chat_model=chat_model,
574
607
  )
575
608
 
576
609
 
@@ -285,8 +285,8 @@ def maybe_audit_chat(
285
285
  chat_history: list[ChatContextMessage],
286
286
  query_context: PromptContext,
287
287
  query_context_order: PromptContextOrder,
288
- learning_id: str,
289
- model: str,
288
+ learning_id: Optional[str],
289
+ model: Optional[str],
290
290
  ):
291
291
  audit = get_audit()
292
292
  if audit is None:
@@ -324,7 +324,7 @@ def maybe_audit_chat(
324
324
 
325
325
 
326
326
  def parse_audit_answer(raw_text_answer: bytes, status_code: AnswerStatusCode) -> Optional[str]:
327
- if status_code == AnswerStatusCode.NO_CONTEXT:
327
+ if status_code == AnswerStatusCode.NO_CONTEXT or status_code == AnswerStatusCode.NO_RETRIEVAL_DATA:
328
328
  # We don't want to audit "Not enough context to answer this." and instead set a None.
329
329
  return None
330
330
  return raw_text_answer.decode()
@@ -349,7 +349,7 @@ class ChatAuditor:
349
349
  learning_id: Optional[str],
350
350
  query_context: PromptContext,
351
351
  query_context_order: PromptContextOrder,
352
- model: str,
352
+ model: Optional[str],
353
353
  ):
354
354
  self.kbid = kbid
355
355
  self.user_id = user_id
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: nucliadb
3
- Version: 6.2.1.post2949
3
+ Version: 6.2.1.post2971
4
4
  Home-page: https://docs.nuclia.dev/docs/management/nucliadb/intro
5
5
  Author: NucliaDB Community
6
6
  Author-email: nucliadb@nuclia.com
@@ -22,10 +22,10 @@ Classifier: Programming Language :: Python :: 3.12
22
22
  Classifier: Programming Language :: Python :: 3 :: Only
23
23
  Requires-Python: >=3.9, <4
24
24
  Description-Content-Type: text/markdown
25
- Requires-Dist: nucliadb-telemetry[all]>=6.2.1.post2949
26
- Requires-Dist: nucliadb-utils[cache,fastapi,storages]>=6.2.1.post2949
27
- Requires-Dist: nucliadb-protos>=6.2.1.post2949
28
- Requires-Dist: nucliadb-models>=6.2.1.post2949
25
+ Requires-Dist: nucliadb-telemetry[all]>=6.2.1.post2971
26
+ Requires-Dist: nucliadb-utils[cache,fastapi,storages]>=6.2.1.post2971
27
+ Requires-Dist: nucliadb-protos>=6.2.1.post2971
28
+ Requires-Dist: nucliadb-models>=6.2.1.post2971
29
29
  Requires-Dist: nucliadb-admin-assets>=1.0.0.post1224
30
30
  Requires-Dist: nucliadb-node-binding>=2.26.0
31
31
  Requires-Dist: nuclia-models>=0.24.2
@@ -189,7 +189,7 @@ nucliadb/search/__init__.py,sha256=tnypbqcH4nBHbGpkINudhKgdLKpwXQCvDtPchUlsyY4,1
189
189
  nucliadb/search/app.py,sha256=6UV7rO0f3w5bNFXLdQM8bwUwXayMGnM4hF6GGv7WPv4,4260
190
190
  nucliadb/search/lifecycle.py,sha256=DW8v4WUi4rZqc7xTOi3rE67W7877WG7fH9oTZbolHdE,2099
191
191
  nucliadb/search/openapi.py,sha256=t3Wo_4baTrfPftg2BHsyLWNZ1MYn7ZRdW7ht-wFOgRs,1016
192
- nucliadb/search/predict.py,sha256=AB8E5epRR_aUsfKYfWw96WsrJUAdalZE4uolkrTor8Q,20799
192
+ nucliadb/search/predict.py,sha256=EWOiWVUX9U_TE19Cl6bpCr6Mjs7hjuvCcG26C7e6KnQ,20919
193
193
  nucliadb/search/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
194
194
  nucliadb/search/run.py,sha256=aFb-CXRi_C8YMpP_ivNj8KW1BYhADj88y8K9Lr_nUPI,1402
195
195
  nucliadb/search/settings.py,sha256=vem3EcyYlTPSim0kEK-xe-erF4BZg0CT_LAb8ZRQAE8,1684
@@ -234,11 +234,11 @@ nucliadb/search/search/shards.py,sha256=mM2aCHWhl_gwkCENXDShPukS-_qnB5tFS3UAJuzM
234
234
  nucliadb/search/search/summarize.py,sha256=ksmYPubEQvAQgfPdZHfzB_rR19B2ci4IYZ6jLdHxZo8,4996
235
235
  nucliadb/search/search/utils.py,sha256=iF2tbBA56gRMJH1TlE2hMrqeXqjoeOPt4KgRdp2m9Ek,3313
236
236
  nucliadb/search/search/chat/__init__.py,sha256=cp15ZcFnHvpcu_5-aK2A4uUyvuZVV_MJn4bIXMa20ks,835
237
- nucliadb/search/search/chat/ask.py,sha256=4PHueXt4dMF6NHuBYII--reCslbAVCzAE4LgWFAiKdY,35143
237
+ nucliadb/search/search/chat/ask.py,sha256=tE1Q5V58oLMCo-T9s0N6Kko-1RWn1e4kHfbbPBsD2uU,36266
238
238
  nucliadb/search/search/chat/exceptions.py,sha256=Siy4GXW2L7oPhIR86H3WHBhE9lkV4A4YaAszuGGUf54,1356
239
239
  nucliadb/search/search/chat/images.py,sha256=PA8VWxT5_HUGfW1ULhKTK46UBsVyINtWWqEM1ulzX1E,3095
240
240
  nucliadb/search/search/chat/prompt.py,sha256=r2JTiRWH3YHPdeRAG5w6gD0g0fWVxdTjYIR86qAVa7k,47106
241
- nucliadb/search/search/chat/query.py,sha256=4cmTxnqnvQGPDKTdaNJL4Au8aop1reHLXzkGNhf4NWg,15345
241
+ nucliadb/search/search/chat/query.py,sha256=y7W5VuKl1XiZuNsxZIcxxHcFXSG6It2W5CoftZ-ekAc,15428
242
242
  nucliadb/search/search/query_parser/__init__.py,sha256=cp15ZcFnHvpcu_5-aK2A4uUyvuZVV_MJn4bIXMa20ks,835
243
243
  nucliadb/search/search/query_parser/exceptions.py,sha256=tuzl7ZyvVsRz6u0_3zMe60vx39nd3pi641prs-5nC0E,872
244
244
  nucliadb/search/search/query_parser/models.py,sha256=-VlCDXUCgOroAZw1Leqhj2VMgRv_CD2w40PXXOBLaUM,2332
@@ -340,9 +340,9 @@ nucliadb/writer/tus/local.py,sha256=7jYa_w9b-N90jWgN2sQKkNcomqn6JMVBOVeDOVYJHto,
340
340
  nucliadb/writer/tus/s3.py,sha256=vF0NkFTXiXhXq3bCVXXVV-ED38ECVoUeeYViP8uMqcU,8357
341
341
  nucliadb/writer/tus/storage.py,sha256=ToqwjoYnjI4oIcwzkhha_MPxi-k4Jk3Lt55zRwaC1SM,2903
342
342
  nucliadb/writer/tus/utils.py,sha256=MSdVbRsRSZVdkaum69_0wku7X3p5wlZf4nr6E0GMKbw,2556
343
- nucliadb-6.2.1.post2949.dist-info/METADATA,sha256=N3Z4fQUusKc5JJ5ybVTWHvLHQH7ZK7Yb8I2oNor1vT8,4689
344
- nucliadb-6.2.1.post2949.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
345
- nucliadb-6.2.1.post2949.dist-info/entry_points.txt,sha256=XqGfgFDuY3zXQc8ewXM2TRVjTModIq851zOsgrmaXx4,1268
346
- nucliadb-6.2.1.post2949.dist-info/top_level.txt,sha256=hwYhTVnX7jkQ9gJCkVrbqEG1M4lT2F_iPQND1fCzF80,20
347
- nucliadb-6.2.1.post2949.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
348
- nucliadb-6.2.1.post2949.dist-info/RECORD,,
343
+ nucliadb-6.2.1.post2971.dist-info/METADATA,sha256=Ftcrf80Q8tp56jdibzPDOdTJq2jG0aEGuC-bMD-4418,4689
344
+ nucliadb-6.2.1.post2971.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
345
+ nucliadb-6.2.1.post2971.dist-info/entry_points.txt,sha256=XqGfgFDuY3zXQc8ewXM2TRVjTModIq851zOsgrmaXx4,1268
346
+ nucliadb-6.2.1.post2971.dist-info/top_level.txt,sha256=hwYhTVnX7jkQ9gJCkVrbqEG1M4lT2F_iPQND1fCzF80,20
347
+ nucliadb-6.2.1.post2971.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
348
+ nucliadb-6.2.1.post2971.dist-info/RECORD,,