mirror of
https://github.com/trustgraph-ai/trustgraph.git
synced 2026-07-21 11:11:03 +02:00
Restructuring API a little
This commit is contained in:
parent
9a47915d05
commit
c49568dd34
5 changed files with 191 additions and 108 deletions
|
|
@ -118,92 +118,8 @@ class Api:
|
||||||
except:
|
except:
|
||||||
raise ProtocolException(f"Response not formatted correctly")
|
raise ProtocolException(f"Response not formatted correctly")
|
||||||
|
|
||||||
def library_add_document(
|
def library(self):
|
||||||
self, document, id, metadata, user, title, comments,
|
return Library(self)
|
||||||
kind="text/plain", tags=[],
|
|
||||||
):
|
|
||||||
|
|
||||||
if id is None:
|
|
||||||
|
|
||||||
if metadata is not None:
|
|
||||||
|
|
||||||
# Situation makes no sense. What can the metadata possibly
|
|
||||||
# mean if the caller doesn't know the document ID.
|
|
||||||
# Metadata should relate to the document by ID
|
|
||||||
raise RuntimeError("Can't specify metadata without id")
|
|
||||||
|
|
||||||
id = hash(document)
|
|
||||||
|
|
||||||
if not title: title = ""
|
|
||||||
if not comments: comments = ""
|
|
||||||
|
|
||||||
triples = []
|
|
||||||
|
|
||||||
def emit(t):
|
|
||||||
triples.append(t)
|
|
||||||
|
|
||||||
if metadata:
|
|
||||||
metadata.emit(
|
|
||||||
lambda t: triples.append({
|
|
||||||
"s": { "v": t["s"], "e": isinstance(t["s"], Uri) },
|
|
||||||
"p": { "v": t["p"], "e": isinstance(t["p"], Uri) },
|
|
||||||
"o": { "v": t["o"], "e": isinstance(t["o"], Uri) }
|
|
||||||
})
|
|
||||||
)
|
|
||||||
|
|
||||||
input = {
|
|
||||||
"operation": "add-document",
|
|
||||||
"document-metadata": {
|
|
||||||
"id": id,
|
|
||||||
"time": int(time.time()),
|
|
||||||
"kind": kind,
|
|
||||||
"title": title,
|
|
||||||
"comments": comments,
|
|
||||||
"metadata": triples,
|
|
||||||
"user": user,
|
|
||||||
"tags": tags
|
|
||||||
},
|
|
||||||
"content": base64.b64encode(document).decode("utf-8"),
|
|
||||||
}
|
|
||||||
|
|
||||||
return self.request(
|
|
||||||
f"librarian",
|
|
||||||
input
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def library_get_documents(self, user):
|
|
||||||
|
|
||||||
input = {
|
|
||||||
"operation": "list-documents",
|
|
||||||
"user": user,
|
|
||||||
}
|
|
||||||
|
|
||||||
object = self.request("librarian", input)
|
|
||||||
|
|
||||||
try:
|
|
||||||
return [
|
|
||||||
DocumentMetadata(
|
|
||||||
id = v["id"],
|
|
||||||
time = datetime.datetime.fromtimestamp(v["time"]),
|
|
||||||
kind = v["kind"],
|
|
||||||
title = v["title"],
|
|
||||||
comments = v.get("comments", ""),
|
|
||||||
metadata = [
|
|
||||||
Triple(
|
|
||||||
s = to_value(w["s"]),
|
|
||||||
p = to_value(w["p"]),
|
|
||||||
o = to_value(w["o"])
|
|
||||||
)
|
|
||||||
for w in v["metadata"]
|
|
||||||
],
|
|
||||||
user = v["user"],
|
|
||||||
tags = v["tags"]
|
|
||||||
)
|
|
||||||
for v in object["document-metadatas"]
|
|
||||||
]
|
|
||||||
except:
|
|
||||||
raise ProtocolException(f"Response not formatted correctly")
|
|
||||||
|
|
||||||
def config_get(self, keys):
|
def config_get(self, keys):
|
||||||
|
|
||||||
|
|
@ -356,12 +272,119 @@ class Api:
|
||||||
|
|
||||||
self.request("flow", input)
|
self.request("flow", input)
|
||||||
|
|
||||||
|
class Library:
|
||||||
|
|
||||||
|
def __init__(self, api):
|
||||||
|
self.api = api
|
||||||
|
|
||||||
|
def request(self, request):
|
||||||
|
return self.api.request(f"librarian", request)
|
||||||
|
|
||||||
|
def add_document(
|
||||||
|
self, document, id, metadata, user, title, comments,
|
||||||
|
kind="text/plain", tags=[],
|
||||||
|
):
|
||||||
|
|
||||||
|
if id is None:
|
||||||
|
|
||||||
|
if metadata is not None:
|
||||||
|
|
||||||
|
# Situation makes no sense. What can the metadata possibly
|
||||||
|
# mean if the caller doesn't know the document ID.
|
||||||
|
# Metadata should relate to the document by ID
|
||||||
|
raise RuntimeError("Can't specify metadata without id")
|
||||||
|
|
||||||
|
id = hash(document)
|
||||||
|
|
||||||
|
if not title: title = ""
|
||||||
|
if not comments: comments = ""
|
||||||
|
|
||||||
|
triples = []
|
||||||
|
|
||||||
|
def emit(t):
|
||||||
|
triples.append(t)
|
||||||
|
|
||||||
|
if metadata:
|
||||||
|
metadata.emit(
|
||||||
|
lambda t: triples.append({
|
||||||
|
"s": { "v": t["s"], "e": isinstance(t["s"], Uri) },
|
||||||
|
"p": { "v": t["p"], "e": isinstance(t["p"], Uri) },
|
||||||
|
"o": { "v": t["o"], "e": isinstance(t["o"], Uri) }
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
input = {
|
||||||
|
"operation": "add-document",
|
||||||
|
"document-metadata": {
|
||||||
|
"id": id,
|
||||||
|
"time": int(time.time()),
|
||||||
|
"kind": kind,
|
||||||
|
"title": title,
|
||||||
|
"comments": comments,
|
||||||
|
"metadata": triples,
|
||||||
|
"user": user,
|
||||||
|
"tags": tags
|
||||||
|
},
|
||||||
|
"content": base64.b64encode(document).decode("utf-8"),
|
||||||
|
}
|
||||||
|
|
||||||
|
return self.request(input)
|
||||||
|
|
||||||
|
def get_documents(self, user):
|
||||||
|
|
||||||
|
input = {
|
||||||
|
"operation": "list-documents",
|
||||||
|
"user": user,
|
||||||
|
}
|
||||||
|
|
||||||
|
object = self.request(input)
|
||||||
|
|
||||||
|
try:
|
||||||
|
return [
|
||||||
|
DocumentMetadata(
|
||||||
|
id = v["id"],
|
||||||
|
time = datetime.datetime.fromtimestamp(v["time"]),
|
||||||
|
kind = v["kind"],
|
||||||
|
title = v["title"],
|
||||||
|
comments = v.get("comments", ""),
|
||||||
|
metadata = [
|
||||||
|
Triple(
|
||||||
|
s = to_value(w["s"]),
|
||||||
|
p = to_value(w["p"]),
|
||||||
|
o = to_value(w["o"])
|
||||||
|
)
|
||||||
|
for w in v["metadata"]
|
||||||
|
],
|
||||||
|
user = v["user"],
|
||||||
|
tags = v["tags"]
|
||||||
|
)
|
||||||
|
for v in object["document-metadatas"]
|
||||||
|
]
|
||||||
|
except:
|
||||||
|
raise ProtocolException(f"Response not formatted correctly")
|
||||||
|
|
||||||
|
def remove_document(self, user, id):
|
||||||
|
|
||||||
|
input = {
|
||||||
|
"operation": "remove-document",
|
||||||
|
"user": user,
|
||||||
|
"document-id": id,
|
||||||
|
}
|
||||||
|
|
||||||
|
object = self.request(input)
|
||||||
|
|
||||||
|
return {}
|
||||||
|
|
||||||
class Flow:
|
class Flow:
|
||||||
|
|
||||||
def __init__(self, api, flow):
|
def __init__(self, api, flow):
|
||||||
self.api = api
|
self.api = api
|
||||||
self.flow = flow
|
self.flow = flow
|
||||||
|
|
||||||
|
def request(self, path, request):
|
||||||
|
|
||||||
|
return self.api.request(f"flow/{self.flow}/{path}", request)
|
||||||
|
|
||||||
def text_completion(self, system, prompt):
|
def text_completion(self, system, prompt):
|
||||||
|
|
||||||
# The input consists of system and prompt strings
|
# The input consists of system and prompt strings
|
||||||
|
|
@ -370,8 +393,8 @@ class Flow:
|
||||||
"prompt": prompt
|
"prompt": prompt
|
||||||
}
|
}
|
||||||
|
|
||||||
return self.api.request(
|
return self.request(
|
||||||
f"flow/{self.flow}/service/text-completion",
|
"service/text-completion",
|
||||||
input
|
input
|
||||||
)["response"]
|
)["response"]
|
||||||
|
|
||||||
|
|
@ -382,8 +405,8 @@ class Flow:
|
||||||
"question": question
|
"question": question
|
||||||
}
|
}
|
||||||
|
|
||||||
return self.api.request(
|
return self.request(
|
||||||
f"flow/{self.flow}/service/agent",
|
"service/agent",
|
||||||
input
|
input
|
||||||
)["answer"]
|
)["answer"]
|
||||||
|
|
||||||
|
|
@ -404,8 +427,8 @@ class Flow:
|
||||||
"max-path-length": max_path_length,
|
"max-path-length": max_path_length,
|
||||||
}
|
}
|
||||||
|
|
||||||
return self.api.request(
|
return self.request(
|
||||||
f"flow/{self.flow}/service/graph-rag",
|
"service/graph-rag",
|
||||||
input
|
input
|
||||||
)["response"]
|
)["response"]
|
||||||
|
|
||||||
|
|
@ -422,8 +445,8 @@ class Flow:
|
||||||
"doc-limit": doc_limit,
|
"doc-limit": doc_limit,
|
||||||
}
|
}
|
||||||
|
|
||||||
return self.api.request(
|
return self.request(
|
||||||
f"flow/{self.flow}/service/document-rag",
|
"service/document-rag",
|
||||||
input
|
input
|
||||||
)["response"]
|
)["response"]
|
||||||
|
|
||||||
|
|
@ -434,8 +457,8 @@ class Flow:
|
||||||
"text": text
|
"text": text
|
||||||
}
|
}
|
||||||
|
|
||||||
return self.api.request(
|
return self.request(
|
||||||
f"flow/{self.flow}/service/embeddings",
|
"service/embeddings",
|
||||||
input
|
input
|
||||||
)["vectors"]
|
)["vectors"]
|
||||||
|
|
||||||
|
|
@ -447,8 +470,8 @@ class Flow:
|
||||||
"variables": variables
|
"variables": variables
|
||||||
}
|
}
|
||||||
|
|
||||||
object = self.api.request(
|
object = self.request(
|
||||||
f"flow/{self.flow}/service/prompt",
|
"service/prompt",
|
||||||
input
|
input
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -496,8 +519,8 @@ class Flow:
|
||||||
raise RuntimeError("o must be Uri or Literal")
|
raise RuntimeError("o must be Uri or Literal")
|
||||||
input["o"] = { "v": str(o), "e": isinstance(o, Uri), }
|
input["o"] = { "v": str(o), "e": isinstance(o, Uri), }
|
||||||
|
|
||||||
object = self.api.request(
|
object = self.request(
|
||||||
f"flow/{self.flow}/service/triples",
|
"service/triples",
|
||||||
input
|
input
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -552,8 +575,8 @@ class Flow:
|
||||||
if collection:
|
if collection:
|
||||||
input["collection"] = collection
|
input["collection"] = collection
|
||||||
|
|
||||||
return self.api.request(
|
return self.request(
|
||||||
f"flow/{self.flow}/service/document-load",
|
"service/document-load",
|
||||||
input
|
input
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -597,8 +620,8 @@ class Flow:
|
||||||
if collection:
|
if collection:
|
||||||
input["collection"] = collection
|
input["collection"] = collection
|
||||||
|
|
||||||
return self.api.request(
|
return self.request(
|
||||||
f"flow/{self.flow}/service/text-load",
|
"service/text-load",
|
||||||
input
|
input
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ class Loader:
|
||||||
self, url, user, metadata, title, comments, kind, tags
|
self, url, user, metadata, title, comments, kind, tags
|
||||||
):
|
):
|
||||||
|
|
||||||
self.api = Api(url)
|
self.api = Api(url).library()
|
||||||
|
|
||||||
self.user = user
|
self.user = user
|
||||||
self.metadata = metadata
|
self.metadata = metadata
|
||||||
|
|
@ -57,7 +57,7 @@ class Loader:
|
||||||
|
|
||||||
self.metadata.id = id
|
self.metadata.id = id
|
||||||
|
|
||||||
self.api.library_add_document(
|
self.api.add_document(
|
||||||
document=data, id=id, metadata=self.metadata,
|
document=data, id=id, metadata=self.metadata,
|
||||||
user=self.user, kind=self.kind, title=self.title,
|
user=self.user, kind=self.kind, title=self.title,
|
||||||
comments=self.comments, tags=self.tags
|
comments=self.comments, tags=self.tags
|
||||||
|
|
|
||||||
59
trustgraph-cli/scripts/tg-remove-library-document
Executable file
59
trustgraph-cli/scripts/tg-remove-library-document
Executable file
|
|
@ -0,0 +1,59 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
"""
|
||||||
|
Remove a PDF document from the library
|
||||||
|
"""
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import os
|
||||||
|
import uuid
|
||||||
|
|
||||||
|
from trustgraph.api import Api
|
||||||
|
|
||||||
|
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
|
||||||
|
default_user = 'trustgraph'
|
||||||
|
|
||||||
|
|
||||||
|
def remove_doc(url, user, id):
|
||||||
|
|
||||||
|
api = Api(url).library()
|
||||||
|
|
||||||
|
api.remove_document(user=user, id=id)
|
||||||
|
|
||||||
|
def main():
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
prog='tg-remove-library-document',
|
||||||
|
description=__doc__,
|
||||||
|
)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
'-u', '--url',
|
||||||
|
default=default_url,
|
||||||
|
help=f'API URL (default: {default_url})',
|
||||||
|
)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
'-U', '--user',
|
||||||
|
default=default_user,
|
||||||
|
help=f'User ID (default: {default_user})'
|
||||||
|
)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
'--identifier', '--id',
|
||||||
|
required=True,
|
||||||
|
help=f'Document ID'
|
||||||
|
)
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
try:
|
||||||
|
|
||||||
|
remove_doc(args.url, args.user, args.identifier)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
|
||||||
|
print("Exception:", e, flush=True)
|
||||||
|
|
||||||
|
main()
|
||||||
|
|
||||||
|
|
@ -14,9 +14,9 @@ default_user = "trustgraph"
|
||||||
|
|
||||||
def show_docs(url, user):
|
def show_docs(url, user):
|
||||||
|
|
||||||
api = Api(url)
|
api = Api(url).library()
|
||||||
|
|
||||||
docs = api.library_get_documents(user=user)
|
docs = api.get_documents(user=user)
|
||||||
|
|
||||||
if len(docs) == 0:
|
if len(docs) == 0:
|
||||||
print("No documents.")
|
print("No documents.")
|
||||||
|
|
|
||||||
|
|
@ -72,6 +72,7 @@ setuptools.setup(
|
||||||
"scripts/tg-show-flows",
|
"scripts/tg-show-flows",
|
||||||
"scripts/tg-show-library-documents",
|
"scripts/tg-show-library-documents",
|
||||||
"scripts/tg-add-library-document",
|
"scripts/tg-add-library-document",
|
||||||
|
"scripts/tg-remove-library-document",
|
||||||
"scripts/tg-show-processor-state",
|
"scripts/tg-show-processor-state",
|
||||||
"scripts/tg-show-prompts",
|
"scripts/tg-show-prompts",
|
||||||
"scripts/tg-show-token-costs",
|
"scripts/tg-show-token-costs",
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue