From a4dd1c8fa39c5fabd3522594304609766cf94b1b Mon Sep 17 00:00:00 2001 From: Cyber MacGeddon Date: Fri, 29 Nov 2024 17:18:00 +0000 Subject: [PATCH] Starting to hack a lookup service --- trustgraph-base/trustgraph/schema/__init__.py | 2 + trustgraph-base/trustgraph/schema/lookup.py | 34 ++++++ .../trustgraph/external/__init__.py | 0 .../trustgraph/external/wikipedia/__init__.py | 0 .../trustgraph/external/wikipedia/service.py | 100 ++++++++++++++++++ 5 files changed, 136 insertions(+) create mode 100644 trustgraph-base/trustgraph/schema/lookup.py create mode 100644 trustgraph-flow/trustgraph/external/__init__.py create mode 100644 trustgraph-flow/trustgraph/external/wikipedia/__init__.py create mode 100644 trustgraph-flow/trustgraph/external/wikipedia/service.py diff --git a/trustgraph-base/trustgraph/schema/__init__.py b/trustgraph-base/trustgraph/schema/__init__.py index 3196691b..be41b670 100644 --- a/trustgraph-base/trustgraph/schema/__init__.py +++ b/trustgraph-base/trustgraph/schema/__init__.py @@ -9,4 +9,6 @@ from . graph import * from . retrieval import * from . metadata import * from . agent import * +from . lookup import * + diff --git a/trustgraph-base/trustgraph/schema/lookup.py b/trustgraph-base/trustgraph/schema/lookup.py new file mode 100644 index 00000000..f8aaf5fc --- /dev/null +++ b/trustgraph-base/trustgraph/schema/lookup.py @@ -0,0 +1,34 @@ + +from pulsar.schema import Record, Bytes, String, Boolean, Integer, Array, Double + +from . types import Error, Value, Triple +from . topic import topic +from . metadata import Metadata + +############################################################################ + +# Lookups + +class LookupRequest(Record): + kind = String() + term = String() + +class LookupResponse(Record): + text = String() + +wikipedia_lookup_request_queue = topic( + 'encyclopedia', kind='non-persistent', namespace='request' +) +wikipedia_lookup_response_queue = topic( + 'encyclopedia', kind='non-persistent', namespace='response', +) + +internet_search_request_queue = topic( + 'internet-search', kind='non-persistent', namespace='request' +) +internet_search_response_queue = topic( + 'internet-search', kind='non-persistent', namespace='response', +) + +############################################################################ + diff --git a/trustgraph-flow/trustgraph/external/__init__.py b/trustgraph-flow/trustgraph/external/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/trustgraph-flow/trustgraph/external/wikipedia/__init__.py b/trustgraph-flow/trustgraph/external/wikipedia/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/trustgraph-flow/trustgraph/external/wikipedia/service.py b/trustgraph-flow/trustgraph/external/wikipedia/service.py new file mode 100644 index 00000000..4b3b39c1 --- /dev/null +++ b/trustgraph-flow/trustgraph/external/wikipedia/service.py @@ -0,0 +1,100 @@ + +""" +Embeddings service, applies an embeddings model selected from HuggingFace. +Input is text, output is embeddings vector. +""" + +from langchain_huggingface import HuggingFaceEmbeddings + +from trustgraph.schema import EmbeddingsRequest, EmbeddingsResponse, Error +from trustgraph.schema import embeddings_request_queue +from trustgraph.schema import embeddings_response_queue +from trustgraph.log_level import LogLevel +from trustgraph.base import ConsumerProducer + +module = ".".join(__name__.split(".")[1:-1]) + +default_input_queue = embeddings_request_queue +default_output_queue = embeddings_response_queue +default_subscriber = module +default_model="all-MiniLM-L6-v2" + +class Processor(ConsumerProducer): + + def __init__(self, **params): + + input_queue = params.get("input_queue", default_input_queue) + output_queue = params.get("output_queue", default_output_queue) + subscriber = params.get("subscriber", default_subscriber) + model = params.get("model", default_model) + + super(Processor, self).__init__( + **params | { + "input_queue": input_queue, + "output_queue": output_queue, + "subscriber": subscriber, + "input_schema": EmbeddingsRequest, + "output_schema": EmbeddingsResponse, + } + ) + + self.embeddings = HuggingFaceEmbeddings(model_name=model) + + def handle(self, msg): + + v = msg.value() + + # Sender-produced ID + id = msg.properties()["id"] + + print(f"Handling input {id}...", flush=True) + + try: + + text = v.text + embeds = self.embeddings.embed_documents([text]) + + print("Send response...", flush=True) + r = EmbeddingsResponse(vectors=embeds, error=None) + self.producer.send(r, properties={"id": id}) + + print("Done.", flush=True) + + + except Exception as e: + + print(f"Exception: {e}") + + print("Send error response...", flush=True) + + r = EmbeddingsResponse( + error=Error( + type = "llm-error", + message = str(e), + ), + response=None, + ) + + self.producer.send(r, properties={"id": id}) + + self.consumer.acknowledge(msg) + + + @staticmethod + def add_args(parser): + + ConsumerProducer.add_args( + parser, default_input_queue, default_subscriber, + default_output_queue, + ) + + parser.add_argument( + '-m', '--model', + default="all-MiniLM-L6-v2", + help=f'LLM model (default: all-MiniLM-L6-v2)' + ) + +def run(): + + Processor.start(module, __doc__) +