2121)
2222from vechord .entity import GeminiEntityRecognizer
2323from vechord .errors import RequestError
24+ from vechord .evaluate import GeminiUMBRELAEvaluator
2425from vechord .extract import GeminiExtractor , LlamaParseExtractor
2526from vechord .model import (
2627 GraphEntity ,
2930 ResourceRequest ,
3031 RunAck ,
3132 RunRequest ,
33+ RunResponse ,
3234)
3335from vechord .rerank import CohereReranker
3436from vechord .spec import (
@@ -122,6 +124,7 @@ class _Relation(Table, kw_only=True):
122124 "graph" : {"gemini" : GeminiEntityRecognizer },
123125 "index" : {"vectorchord" : IndexOption },
124126 "search" : {"vectorchord" : SearchOption },
127+ "evaluate" : {"gemini" : GeminiUMBRELAEvaluator },
125128}
126129
127130
@@ -160,6 +163,7 @@ class DynamicPipeline(msgspec.Struct, kw_only=True):
160163 index : Optional [IndexOption ] = None
161164 search : Optional [SearchOption ] = None
162165 graph : Optional [GeminiEntityRecognizer ] = None
166+ evaluate : Optional [GeminiUMBRELAEvaluator ] = None
163167
164168 def __post_init__ (self ):
165169 if not (self .text_emb or self .multimodal_emb ):
@@ -195,7 +199,9 @@ def from_steps(cls, steps: list[ResourceRequest]) -> Self:
195199 calls [(step .kind ).replace ("-" , "_" )] = provider (** args )
196200 return msgspec .convert (calls , DynamicPipeline )
197201
198- async def run (self , request : RunRequest , vr : "VechordRegistry" ):
202+ async def run (
203+ self , request : RunRequest , vr : "VechordRegistry"
204+ ) -> RunAck | RunResponse :
199205 """Run the dynamic pipeline with the given request."""
200206 if self .index :
201207 return await self .run_index (request , vr )
@@ -374,7 +380,9 @@ async def graph_insert(
374380 rel .vec = await self .text_emb .vectorize_chunk (f"{ rel .description } " )
375381 await vr .insert (rel )
376382
377- async def run_search (self , request : RunRequest , vr : "VechordRegistry" ):
383+ async def run_search (
384+ self , request : RunRequest , vr : "VechordRegistry"
385+ ) -> RunResponse :
378386 query = request .data .decode ("utf-8" )
379387
380388 # for type hint and compatibility
@@ -387,32 +395,34 @@ class Entity(_Entity):
387395 class Relation (_Relation ):
388396 pass
389397
390- retrieved : list [ Chunk ] = []
398+ resp = RunResponse ()
391399 if self .search .vector :
392400 vec = (
393401 await self .text_emb .vectorize_query (query )
394402 if self .text_emb
395403 else await self .multimodal_emb .vectorize_multimodal_query (text = query )
396404 )
397- retrieved .extend (
405+ resp .extend (
398406 await vr .search_by_vector (
399407 Chunk , vec , self .search .vector .topk , probe = self .search .vector .probe
400408 )
401409 )
402410 if self .search .keyword :
403- retrieved .extend (
411+ resp .extend (
404412 await vr .search_by_keyword (Chunk , query , self .search .keyword .topk )
405413 )
406414 if self .search .graph :
407- retrieved .extend (
408- await self .graph_search (query , Chunk , Entity , Relation , vr )
409- )
415+ resp .extend (await self .graph_search (query , Chunk , Entity , Relation , vr ))
410416 if self .rerank :
411- indices = await self .rerank .rerank (
412- query , [chunk .text for chunk in retrieved ]
417+ indices = await self .rerank .rerank (query , [chunk .text for chunk in resp ])
418+ resp .reorder (indices )
419+
420+ if self .evaluate :
421+ resp .metrics = await self .evaluate .evaluate_with_estimation (
422+ query , [chunk .text for chunk in resp .chunks ]
413423 )
414- retrieved = [ retrieved [ i ] for i in indices ]
415- return retrieved
424+
425+ return resp
416426
417427 async def graph_search (
418428 self ,
0 commit comments