11import os
2- from typing import List , Dict , Tuple , Any , Union
2+ from typing import List , Dict , Tuple , Any , Union , Optional
33from urllib import request
44
55from pydantic import BaseModel
66
77from chatbees .client_models .chat import Chat
88from chatbees .server_models .doc_api import (
99 CrawlStatus ,
10- IngestionStatus ,
11- AnswerReference ,
10+ AskResponse ,
1211 SearchReference ,
1312)
14- from chatbees .server_models .chat import ConfigureChatRequest , ChatAttributes
13+ from chatbees .server_models .chat import ConfigureChatRequest
1514from chatbees .server_models .ingestion_type import (
1615 IngestionType ,
16+ IngestionStatus ,
17+ ScheduleSpec ,
1718 ConfluenceSpec ,
1819 GDriveSpec ,
1920 NotionSpec ,
3435 DeleteCrawlRequest ,
3536)
3637from chatbees .server_models .collection_api import (
38+ ChatAttributes ,
39+ PeriodicIngest ,
3740 DescribeCollectionResponse ,
3841)
3942from chatbees .server_models .ingestion_api import (
4346 GetIngestionResponse ,
4447 IndexIngestionRequest ,
4548 DeleteIngestionRequest ,
49+ UpdatePeriodicIngestionRequest ,
50+ DeletePeriodicIngestionRequest ,
4651)
4752from chatbees .server_models .search_api import SearchRequest , SearchResponse
53+ from chatbees .server_models .feedback_api import (
54+ UnregisteredUser ,
55+ CreateOrUpdateFeedbackRequest ,
56+ )
4857from chatbees .utils .ask import ask
4958from chatbees .utils .config import Config
5059from chatbees .utils .file_upload import (
@@ -70,6 +79,10 @@ class Collection(BaseModel):
7079 # If true, collection can be read without an API key
7180 public_read : bool = False
7281
82+ chat_attributes : Optional [ChatAttributes ] = None
83+
84+ periodic_ingests : Optional [List [PeriodicIngest ]] = None
85+
7386 def upload_document (self , path_or_url : str ):
7487 """
7588 Uploads a local or web document into this collection.
@@ -146,7 +159,7 @@ def summarize_document(self, doc_name: str) -> str:
146159
147160 def ask (
148161 self , question : str , top_k : int = 5 , doc_name : str = None ,
149- ) -> ( str , List [ AnswerReference ]) :
162+ ) -> AskResponse :
150163 """
151164 Ask a question within the context of this collection.
152165
@@ -205,7 +218,11 @@ def chat(self, doc_name: str = None) -> Chat:
205218 doc_name = doc_name
206219 )
207220
208- def create_crawl (self , root_url : str , max_urls_to_crawl : int ) -> str :
221+ # TODO support update ScheduleSpec for periodic crawl.
222+ # TODO deprecate crawl apis and switch to ingest apis.
223+ def create_crawl (
224+ self , root_url : str , max_urls_to_crawl : int , schedule : ScheduleSpec = None ,
225+ ) -> str :
209226 """
210227 Create a crawl task to crawl the root_url.
211228
@@ -219,6 +236,7 @@ def create_crawl(self, root_url: str, max_urls_to_crawl: int) -> str:
219236 collection_name = self .name ,
220237 root_url = root_url ,
221238 max_urls_to_crawl = max_urls_to_crawl ,
239+ schedule = schedule ,
222240 )
223241 resp = Config .post (url = url , data = req .model_dump_json ())
224242 crawl_resp = CreateCrawlResponse .model_validate (resp .json ())
@@ -227,7 +245,7 @@ def create_crawl(self, root_url: str, max_urls_to_crawl: int) -> str:
227245 def create_ingestion (
228246 self ,
229247 ingestion_type : IngestionType ,
230- ingestion_spec : Union [ConfluenceSpec , GDriveSpec , NotionSpec ]
248+ ingestion_spec : Union [ConfluenceSpec , GDriveSpec , NotionSpec ],
231249 ) -> str :
232250 """
233251 Create an Ingestion task
@@ -249,6 +267,29 @@ def create_ingestion(
249267 ingest_resp = CreateIngestionResponse .model_validate (resp .json ())
250268 return ingest_resp .ingestion_id
251269
270+ def update_periodic_ingestion (
271+ self ,
272+ ingestion_type : IngestionType ,
273+ ingestion_spec : Union [ConfluenceSpec , GDriveSpec , NotionSpec ]
274+ ):
275+ """
276+ Update the periodic ingestion.
277+
278+ :param ingestion_type: the ingestion type
279+ :param ingestion_spec: the spec for the ingestion. Currently, supports
280+ - ConfluenceSpec
281+ - GDriveSpec
282+ - NotionSpec
283+ :return: the id of the ingestion
284+ """
285+ url = f'{ Config .get_base_url ()} /docs/update_periodic_ingestion'
286+ req = UpdatePeriodicIngestionRequest (
287+ namespace_name = Config .namespace ,
288+ collection_name = self .name ,
289+ type = ingestion_type ,
290+ spec = ingestion_spec .model_dump ())
291+ Config .post (url = url , data = req .model_dump_json ())
292+
252293 def get_ingestion (self , ingestion_id : str ) -> IngestionStatus :
253294 """
254295 Gets the Ingestion task status
@@ -294,6 +335,20 @@ def delete_ingestion(self, ingestion_type: IngestionType):
294335 type = ingestion_type )
295336 Config .post (url = url , data = req .model_dump_json ())
296337
338+ def delete_periodic_ingestion (self , ingestion_type : IngestionType ):
339+ """
340+ Delete the periodic ingestion for an ingestion type, e.g. a data source.
341+ This does not delete the ingested data.
342+
343+ :param ingestion_type: the ingestion type
344+ """
345+ url = f'{ Config .get_base_url ()} /docs/delete_periodic_ingestion'
346+ req = DeletePeriodicIngestionRequest (
347+ namespace_name = Config .namespace ,
348+ collection_name = self .name ,
349+ type = ingestion_type )
350+ Config .post (url = url , data = req .model_dump_json ())
351+
297352 def get_crawl (
298353 self , crawl_id : str ,
299354 ) -> Tuple [CrawlStatus , Dict [str , PageStats ]]:
@@ -373,6 +428,36 @@ def configure_chat(
373428 url = f'{ Config .get_base_url ()} /docs/configure_chat'
374429 Config .post (url = url , data = req .model_dump_json ())
375430
431+ # update the local chat attributes
432+ self .chat_attributes = req .chat_attributes
433+
434+ def create_or_update_feedback (
435+ self ,
436+ request_id : str ,
437+ thumb_down : bool ,
438+ text_feedback : str = "" ,
439+ unregistered_user : UnregisteredUser = None ,
440+ ):
441+ """
442+ Provides feedback for the ask or search.
443+
444+ :param request_id: the request_id of the ask or search
445+ :param thumb_down: thumb up or down
446+ :param text_feedback: optional text feedback
447+ :param unregistered_user: optional information of the unregistered user
448+ """
449+ url = f'{ Config .get_base_url ()} /feedback/create_or_update'
450+ req = CreateOrUpdateFeedbackRequest (
451+ namespace_name = Config .namespace ,
452+ collection_name = self .name ,
453+ request_id = request_id ,
454+ thumb_down = thumb_down ,
455+ text_feedback = text_feedback ,
456+ unregistered_user = unregistered_user ,
457+ )
458+ print (req .model_dump_json ())
459+ Config .post (url = url , data = req .model_dump_json ())
460+
376461def describe_response_to_collection (
377462 collection_name : str ,
378463 resp : DescribeCollectionResponse
@@ -386,5 +471,7 @@ def describe_response_to_collection(
386471 return Collection (
387472 name = collection_name ,
388473 description = description ,
389- public_read = public_read
474+ public_read = public_read ,
475+ chat_attributes = resp .chat_attributes ,
476+ periodic_ingests = resp .periodic_ingests ,
390477 )
0 commit comments