1- import os
21from typing import Any , ClassVar , Dict , List , Literal , Optional
32
43from loguru import logger
54from pydantic import BaseModel , Field , field_validator
65
76from open_notebook .database .repository import (
8- repo_create ,
97 repo_query ,
108)
119from open_notebook .domain .base import ObjectModel
@@ -68,6 +66,27 @@ def notes(self) -> List["Note"]:
6866 logger .exception (e )
6967 raise DatabaseOperationError (e )
7068
69+ @property
70+ def chat_sessions (self ) -> List ["ChatSession" ]:
71+ try :
72+ srcs = repo_query (f"""
73+ select * from (
74+ select
75+ <- chat_session as chat_session
76+ from refers_to
77+ where out={ self .id }
78+ fetch chat_session
79+ )
80+ order by chat_session.updated desc
81+ """ )
82+ return (
83+ [ChatSession (** src ["chat_session" ][0 ]) for src in srcs ] if srcs else []
84+ )
85+ except Exception as e :
86+ logger .error (f"Error fetching notes for notebook { self .id } : { str (e )} " )
87+ logger .exception (e )
88+ raise DatabaseOperationError (e )
89+
7190
7291class Asset (BaseModel ):
7392 file_path : Optional [str ] = None
@@ -99,6 +118,22 @@ def get_context(
99118 else :
100119 return dict (id = self .id , title = self .title , insights = self .insights )
101120
121+ @property
122+ def embedded_chunks (self ) -> int :
123+ try :
124+ result = repo_query (
125+ f"""
126+ select count() as chunks from source_embedding where source={ self .id } GROUP ALL
127+ """
128+ )
129+ if len (result ) == 0 :
130+ return 0
131+ return result [0 ]["chunks" ]
132+ except Exception as e :
133+ logger .error (f"Error fetching insights for source { self .id } : { str (e )} " )
134+ logger .exception (e )
135+ raise DatabaseOperationError (f"Failed to count chunks for source: { str (e )} " )
136+
102137 @property
103138 def insights (self ) -> List [SourceInsight ]:
104139 try :
@@ -118,24 +153,6 @@ def add_to_notebook(self, notebook_id: str) -> Any:
118153 raise InvalidInputError ("Notebook ID must be provided" )
119154 return self .relate ("reference" , notebook_id )
120155
121- def save_chunks (self , text : str ) -> None :
122- if not text :
123- raise InvalidInputError ("Text cannot be empty" )
124- try :
125- chunks = split_text (text , chunk = 500000 , overlap = 1000 )
126- logger .debug (f"Split into { len (chunks )} chunks" )
127- for i , chunk in enumerate (chunks ):
128- logger .debug (f"Saving chunk { i } " )
129- data = {"source" : self .id , "order" : i , "content" : surreal_clean (chunk )}
130- repo_create (
131- "source_chunk" ,
132- data ,
133- )
134- except Exception as e :
135- logger .exception (e )
136- logger .error (f"Error saving chunks for source { self .id } : { str (e )} " )
137- raise DatabaseOperationError (e )
138-
139156 def vectorize (self ) -> None :
140157 EMBEDDING_MODEL = model_manager .embedding_model
141158
@@ -144,8 +161,6 @@ def vectorize(self) -> None:
144161 return
145162 chunks = split_text (
146163 self .full_text ,
147- chunk = int (os .environ .get ("EMBEDDING_CHUNK_SIZE" , 1000 )),
148- overlap = int (os .environ .get ("EMBEDDING_CHUNK_OVERLAP" , 1000 )),
149164 )
150165 logger .debug (f"Split into { len (chunks )} chunks" )
151166
@@ -166,26 +181,26 @@ def vectorize(self) -> None:
166181 logger .exception (e )
167182 raise DatabaseOperationError (e )
168183
169- @classmethod
170- def search (cls , query : str ) -> List [Dict [str , Any ]]:
171- if not query :
172- raise InvalidInputError ("Search query cannot be empty" )
173- try :
174- result = repo_query (
175- """
176- SELECT * omit full_text
177- FROM source
178- WHERE string::lowercase(title) CONTAINS $query or title @@ $query
179- OR string::lowercase(summary) CONTAINS $query or summary @@ $query
180- OR string::lowercase(full_text) CONTAINS $query or full_text @@ $query
181- """ ,
182- {"query" : query },
183- )
184- return result
185- except Exception as e :
186- logger .error (f"Error searching sources: { str (e )} " )
187- logger .exception (e )
188- raise DatabaseOperationError ("Failed to search sources" )
184+ # @classmethod
185+ # def search(cls, query: str) -> List[Dict[str, Any]]:
186+ # if not query:
187+ # raise InvalidInputError("Search query cannot be empty")
188+ # try:
189+ # result = repo_query(
190+ # """
191+ # SELECT * omit full_text
192+ # FROM source
193+ # WHERE string::lowercase(title) CONTAINS $query or title @@ $query
194+ # OR string::lowercase(summary) CONTAINS $query or summary @@ $query
195+ # OR string::lowercase(full_text) CONTAINS $query or full_text @@ $query
196+ # """,
197+ # {"query": query},
198+ # )
199+ # return result
200+ # except Exception as e:
201+ # logger.error(f"Error searching sources: {str(e)}")
202+ # logger.exception(e)
203+ # raise DatabaseOperationError("Failed to search sources")
189204
190205 def add_insight (self , insight_type : str , content : str ) -> Any :
191206 EMBEDDING_MODEL = model_manager .embedding_model
@@ -246,6 +261,16 @@ def get_embedding_content(self) -> Optional[str]:
246261 return self .content
247262
248263
264+ class ChatSession (ObjectModel ):
265+ table_name : ClassVar [str ] = "chat_session"
266+ title : Optional [str ] = None
267+
268+ def relate_to_notebook (self , notebook_id : str ) -> Any :
269+ if not notebook_id :
270+ raise InvalidInputError ("Notebook ID must be provided" )
271+ return self .relate ("refers_to" , notebook_id )
272+
273+
249274def text_search (keyword : str , results : int , source : bool = True , note : bool = True ):
250275 if not keyword :
251276 raise InvalidInputError ("Search keyword cannot be empty" )
@@ -263,18 +288,6 @@ def text_search(keyword: str, results: int, source: bool = True, note: bool = Tr
263288 raise DatabaseOperationError (e )
264289
265290
266- # def hybrid_search(
267- # keyword_search: List[str],
268- # embed_search: List[str],
269- # results: int = 50,
270- # source: bool = True,
271- # note: bool = True,
272- # ):
273- # EMBEDDING_MODEL = model_manager.embedding_model
274- # embed1_vector = EMBEDDING_MODEL.embed(embed1) if embed1 else None
275-
276-
277- # todo: mover o embedding pra ca
278291def vector_search (keyword : str , results : int , source : bool = True , note : bool = True ):
279292 if not keyword :
280293 raise InvalidInputError ("Search keyword cannot be empty" )
0 commit comments