|
1 | 1 | import base64 |
2 | 2 | import itertools |
3 | | -from collections.abc import Callable, Iterable |
| 3 | +from collections.abc import Iterable |
4 | 4 | from contextlib import contextmanager |
5 | 5 | from os import environ |
6 | | -from typing import TYPE_CHECKING, Annotated, Any, Optional |
| 6 | +from typing import Annotated, Any, Optional |
7 | 7 | from uuid import UUID |
8 | 8 |
|
9 | 9 | import msgspec |
10 | 10 |
|
11 | 11 | from vechord.chunk import BaseChunker, GeminiChunker, RegexChunker |
12 | 12 | from vechord.client import ( |
13 | | - VechordClient, |
14 | | - limit_to_transaction_buffer_conn, |
15 | 13 | set_namespace, |
16 | 14 | ) |
17 | 15 | from vechord.embedding import ( |
|
37 | 35 | RunRequest, |
38 | 36 | RunSearchResponse, |
39 | 37 | ) |
| 38 | +from vechord.registry import VechordRegistry |
40 | 39 | from vechord.rerank import BaseReranker, CohereReranker, JinaReranker |
41 | 40 | from vechord.spec import ( |
42 | 41 | AnyOf, |
|
51 | 50 | ) |
52 | 51 | from vechord.typing import Self |
53 | 52 |
|
54 | | -if TYPE_CHECKING: |
55 | | - from vechord.registry import VechordRegistry |
56 | | - |
57 | 53 |
|
58 | 54 | class GraphIndex(msgspec.Struct): |
59 | 55 | """Graph index for entities and relations extracted from the text/image.""" |
@@ -208,7 +204,7 @@ def from_steps(cls, steps: list[ResourceRequest]) -> Self: |
208 | 204 | return msgspec.convert(calls, DynamicPipeline) |
209 | 205 |
|
210 | 206 | async def run( |
211 | | - self, request: RunRequest, vr: "VechordRegistry" |
| 207 | + self, request: RunRequest, vr: VechordRegistry |
212 | 208 | ) -> RunIngestAck | RunSearchResponse: |
213 | 209 | """Run the dynamic pipeline with the given request.""" |
214 | 210 | async with set_namespace(request.name): |
@@ -249,7 +245,7 @@ def _convert_from_extracted_graph( |
249 | 245 | return converted_ents, converted_rels |
250 | 246 |
|
251 | 247 | async def run_index( # noqa: PLR0912 |
252 | | - self, request: RunRequest, vr: "VechordRegistry" |
| 248 | + self, request: RunRequest, vr: VechordRegistry |
253 | 249 | ) -> RunIngestAck: |
254 | 250 | dim = ( |
255 | 251 | self.text_emb.get_dim() if self.text_emb else self.multimodal_emb.get_dim() |
@@ -345,7 +341,7 @@ async def graph_insert( |
345 | 341 | rels: list[_Relation], |
346 | 342 | ent_cls: type[Table], |
347 | 343 | rel_cls: type[Table], |
348 | | - vr: "VechordRegistry", |
| 344 | + vr: VechordRegistry, |
349 | 345 | ): |
350 | 346 | """Insert entities and relations into the graph index.""" |
351 | 347 | ent_map: dict[str, _Entity] = {} |
@@ -393,7 +389,7 @@ async def graph_insert( |
393 | 389 | await vr.insert(rel) |
394 | 390 |
|
395 | 391 | async def run_search( |
396 | | - self, request: RunRequest, vr: "VechordRegistry" |
| 392 | + self, request: RunRequest, vr: VechordRegistry |
397 | 393 | ) -> RunSearchResponse: |
398 | 394 | query = request.data.decode("utf-8") |
399 | 395 |
|
@@ -451,7 +447,7 @@ async def graph_search( |
451 | 447 | chunk_cls: type[Table], |
452 | 448 | ent_cls: type[Table], |
453 | 449 | rel_cls: type[Table], |
454 | | - vr: "VechordRegistry", |
| 450 | + vr: VechordRegistry, |
455 | 451 | ): |
456 | 452 | ents, rels = await self.graph.recognize_with_relations(query) |
457 | 453 | emb_func = ( |
@@ -499,40 +495,3 @@ def deduplicate_uid(uuids: Iterable[UUID], limit: Optional[int] = None) -> list[ |
499 | 495 | """Maintain the order of the occurrence of UUIDs and deduplicate them.""" |
500 | 496 | uuids = {uid: None for uid in uuids} |
501 | 497 | return list(uuids.keys())[:limit] |
502 | | - |
503 | | - |
504 | | -class VechordPipeline: |
505 | | - """Set up the pipeline to run multiple functions in a transaction. |
506 | | -
|
507 | | - Args: |
508 | | - client: :class:`VectorChordClient` to be used for the transaction. |
509 | | - steps: a list of functions to be run in the pipeline. The first function |
510 | | - will be used to accept the input, and the last function will be used |
511 | | - to return the output. The rest of the functions will be used to |
512 | | - process the data in between. The functions will be run in the order |
513 | | - they are defined in the list. |
514 | | - """ |
515 | | - |
516 | | - def __init__(self, client: VechordClient, steps: list[Callable]): |
517 | | - self.client = client |
518 | | - self.steps = steps |
519 | | - |
520 | | - async def run(self, *args, **kwargs) -> Any: |
521 | | - """Execute the pipeline in a transactional manner. |
522 | | -
|
523 | | - All the `args` and `kwargs` will be passed to the first function in the |
524 | | - pipeline. The pipeline will run in *one* transaction, and all the `inject` |
525 | | - can only see the data inserted in this transaction (to guarantee only the |
526 | | - new inserted data will be processed in this pipeline). |
527 | | -
|
528 | | - This will also return the final result of the last function in the pipeline. |
529 | | - """ |
530 | | - async with ( |
531 | | - self.client.get_connection() as conn, |
532 | | - limit_to_transaction_buffer_conn(conn), |
533 | | - ): |
534 | | - # only the 1st one can accept input (could be empty) |
535 | | - await self.steps[0](*args, **kwargs) |
536 | | - for func in self.steps[1:-1]: |
537 | | - await func() |
538 | | - return await self.steps[-1]() |
0 commit comments