mirror of
https://github.com/trustgraph-ai/trustgraph.git
synced 2026-07-24 04:31:02 +02:00
Phase 2
This commit is contained in:
parent
d87f244872
commit
561f7f1dda
5 changed files with 274 additions and 421 deletions
|
|
@ -5,12 +5,10 @@ Uses the agent service to answer a question
|
||||||
import argparse
|
import argparse
|
||||||
import os
|
import os
|
||||||
import textwrap
|
import textwrap
|
||||||
import uuid
|
from trustgraph.api import Api
|
||||||
import asyncio
|
|
||||||
import json
|
|
||||||
from websockets.asyncio.client import connect
|
|
||||||
|
|
||||||
default_url = os.getenv("TRUSTGRAPH_URL", 'ws://localhost:8088/')
|
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
|
||||||
|
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
|
||||||
default_user = 'trustgraph'
|
default_user = 'trustgraph'
|
||||||
default_collection = 'default'
|
default_collection = 'default'
|
||||||
|
|
||||||
|
|
@ -99,79 +97,47 @@ def output(text, prefix="> ", width=78):
|
||||||
)
|
)
|
||||||
print(out)
|
print(out)
|
||||||
|
|
||||||
async def question(
|
def question(
|
||||||
url, question, flow_id, user, collection,
|
url, question, flow_id, user, collection,
|
||||||
plan=None, state=None, group=None, verbose=False, streaming=True
|
plan=None, state=None, group=None, verbose=False, streaming=True,
|
||||||
|
token=None
|
||||||
):
|
):
|
||||||
|
|
||||||
if not url.endswith("/"):
|
|
||||||
url += "/"
|
|
||||||
|
|
||||||
url = url + "api/v1/socket"
|
|
||||||
|
|
||||||
if verbose:
|
if verbose:
|
||||||
output(wrap(question), "\U00002753 ")
|
output(wrap(question), "\U00002753 ")
|
||||||
print()
|
print()
|
||||||
|
|
||||||
# Track last chunk type and current outputter for streaming
|
# Create API client
|
||||||
last_chunk_type = None
|
api = Api(url=url, token=token)
|
||||||
current_outputter = None
|
socket = api.socket()
|
||||||
|
flow = socket.flow(flow_id)
|
||||||
|
|
||||||
def think(x):
|
# Prepare request parameters
|
||||||
if verbose:
|
request_params = {
|
||||||
output(wrap(x), "\U0001f914 ")
|
"question": question,
|
||||||
print()
|
"user": user,
|
||||||
|
"streaming": streaming,
|
||||||
|
}
|
||||||
|
|
||||||
def observe(x):
|
# Only add optional fields if they have values
|
||||||
if verbose:
|
if state is not None:
|
||||||
output(wrap(x), "\U0001f4a1 ")
|
request_params["state"] = state
|
||||||
print()
|
if group is not None:
|
||||||
|
request_params["group"] = group
|
||||||
|
|
||||||
mid = str(uuid.uuid4())
|
try:
|
||||||
|
# Call agent
|
||||||
|
response = flow.agent(**request_params)
|
||||||
|
|
||||||
async with connect(url) as ws:
|
# Handle streaming response
|
||||||
|
if streaming:
|
||||||
|
# Track last chunk type and current outputter for streaming
|
||||||
|
last_chunk_type = None
|
||||||
|
current_outputter = None
|
||||||
|
|
||||||
req = {
|
for chunk in response:
|
||||||
"id": mid,
|
chunk_type = chunk.chunk_type
|
||||||
"service": "agent",
|
content = chunk.content
|
||||||
"flow": flow_id,
|
|
||||||
"request": {
|
|
||||||
"question": question,
|
|
||||||
"user": user,
|
|
||||||
"history": [],
|
|
||||||
"streaming": streaming
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Only add optional fields if they have values
|
|
||||||
if state is not None:
|
|
||||||
req["request"]["state"] = state
|
|
||||||
if group is not None:
|
|
||||||
req["request"]["group"] = group
|
|
||||||
|
|
||||||
req = json.dumps(req)
|
|
||||||
|
|
||||||
await ws.send(req)
|
|
||||||
|
|
||||||
while True:
|
|
||||||
|
|
||||||
msg = await ws.recv()
|
|
||||||
|
|
||||||
obj = json.loads(msg)
|
|
||||||
|
|
||||||
if "error" in obj:
|
|
||||||
raise RuntimeError(obj["error"])
|
|
||||||
|
|
||||||
if obj["id"] != mid:
|
|
||||||
print("Ignore message")
|
|
||||||
continue
|
|
||||||
|
|
||||||
response = obj["response"]
|
|
||||||
|
|
||||||
# Handle streaming format (new format with chunk_type)
|
|
||||||
if "chunk_type" in response:
|
|
||||||
chunk_type = response["chunk_type"]
|
|
||||||
content = response.get("content", "")
|
|
||||||
|
|
||||||
# Check if we're switching to a new message type
|
# Check if we're switching to a new message type
|
||||||
if last_chunk_type != chunk_type:
|
if last_chunk_type != chunk_type:
|
||||||
|
|
@ -195,33 +161,27 @@ async def question(
|
||||||
# Output the chunk
|
# Output the chunk
|
||||||
if current_outputter:
|
if current_outputter:
|
||||||
current_outputter.output(content)
|
current_outputter.output(content)
|
||||||
elif chunk_type == "answer":
|
elif chunk_type == "final-answer":
|
||||||
print(content, end="", flush=True)
|
print(content, end="", flush=True)
|
||||||
else:
|
|
||||||
# Handle legacy format (backward compatibility)
|
|
||||||
if "thought" in response:
|
|
||||||
think(response["thought"])
|
|
||||||
|
|
||||||
if "observation" in response:
|
# Close any remaining outputter
|
||||||
observe(response["observation"])
|
if current_outputter:
|
||||||
|
current_outputter.__exit__(None, None, None)
|
||||||
|
current_outputter = None
|
||||||
|
# Add final newline if we were outputting answer
|
||||||
|
elif last_chunk_type == "final-answer":
|
||||||
|
print()
|
||||||
|
|
||||||
if "answer" in response:
|
else:
|
||||||
print(response["answer"])
|
# Non-streaming response
|
||||||
|
if "answer" in response:
|
||||||
|
print(response["answer"])
|
||||||
|
if "error" in response:
|
||||||
|
raise RuntimeError(response["error"])
|
||||||
|
|
||||||
if "error" in response:
|
finally:
|
||||||
raise RuntimeError(response["error"])
|
# Clean up socket connection
|
||||||
|
socket.close()
|
||||||
if obj["complete"]:
|
|
||||||
# Close any remaining outputter
|
|
||||||
if current_outputter:
|
|
||||||
current_outputter.__exit__(None, None, None)
|
|
||||||
current_outputter = None
|
|
||||||
# Add final newline if we were outputting answer
|
|
||||||
elif last_chunk_type == "answer":
|
|
||||||
print()
|
|
||||||
break
|
|
||||||
|
|
||||||
await ws.close()
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|
||||||
|
|
@ -236,6 +196,12 @@ def main():
|
||||||
help=f'API URL (default: {default_url})',
|
help=f'API URL (default: {default_url})',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
'-t', '--token',
|
||||||
|
default=default_token,
|
||||||
|
help='Authentication token (default: $TRUSTGRAPH_TOKEN)',
|
||||||
|
)
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'-f', '--flow-id',
|
'-f', '--flow-id',
|
||||||
default="default",
|
default="default",
|
||||||
|
|
@ -292,19 +258,18 @@ def main():
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
||||||
asyncio.run(
|
question(
|
||||||
question(
|
url = args.url,
|
||||||
url = args.url,
|
flow_id = args.flow_id,
|
||||||
flow_id = args.flow_id,
|
question = args.question,
|
||||||
question = args.question,
|
user = args.user,
|
||||||
user = args.user,
|
collection = args.collection,
|
||||||
collection = args.collection,
|
plan = args.plan,
|
||||||
plan = args.plan,
|
state = args.state,
|
||||||
state = args.state,
|
group = args.group,
|
||||||
group = args.group,
|
verbose = args.verbose,
|
||||||
verbose = args.verbose,
|
streaming = not args.no_streaming,
|
||||||
streaming = not args.no_streaming,
|
token = args.token,
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|
|
||||||
|
|
@ -4,89 +4,50 @@ Uses the DocumentRAG service to answer a question
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import os
|
import os
|
||||||
import asyncio
|
|
||||||
import json
|
|
||||||
import uuid
|
|
||||||
from websockets.asyncio.client import connect
|
|
||||||
from trustgraph.api import Api
|
from trustgraph.api import Api
|
||||||
|
|
||||||
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
|
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
|
||||||
|
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
|
||||||
default_user = 'trustgraph'
|
default_user = 'trustgraph'
|
||||||
default_collection = 'default'
|
default_collection = 'default'
|
||||||
default_doc_limit = 10
|
default_doc_limit = 10
|
||||||
|
|
||||||
async def question_streaming(url, flow_id, question, user, collection, doc_limit):
|
def question(url, flow_id, question, user, collection, doc_limit, streaming=True, token=None):
|
||||||
"""Streaming version using websockets"""
|
|
||||||
|
|
||||||
# Convert http:// to ws://
|
# Create API client
|
||||||
if url.startswith('http://'):
|
api = Api(url=url, token=token)
|
||||||
url = 'ws://' + url[7:]
|
|
||||||
elif url.startswith('https://'):
|
|
||||||
url = 'wss://' + url[8:]
|
|
||||||
|
|
||||||
if not url.endswith("/"):
|
if streaming:
|
||||||
url += "/"
|
# Use socket client for streaming
|
||||||
|
socket = api.socket()
|
||||||
|
flow = socket.flow(flow_id)
|
||||||
|
|
||||||
url = url + "api/v1/socket"
|
try:
|
||||||
|
response = flow.document_rag(
|
||||||
|
question=question,
|
||||||
|
user=user,
|
||||||
|
collection=collection,
|
||||||
|
doc_limit=doc_limit,
|
||||||
|
streaming=True
|
||||||
|
)
|
||||||
|
|
||||||
mid = str(uuid.uuid4())
|
# Stream output
|
||||||
|
for chunk in response:
|
||||||
|
print(chunk.content, end="", flush=True)
|
||||||
|
print() # Final newline
|
||||||
|
|
||||||
async with connect(url) as ws:
|
finally:
|
||||||
req = {
|
socket.close()
|
||||||
"id": mid,
|
else:
|
||||||
"service": "document-rag",
|
# Use REST API for non-streaming
|
||||||
"flow": flow_id,
|
flow = api.flow().id(flow_id)
|
||||||
"request": {
|
resp = flow.document_rag(
|
||||||
"query": question,
|
question=question,
|
||||||
"user": user,
|
user=user,
|
||||||
"collection": collection,
|
collection=collection,
|
||||||
"doc-limit": doc_limit,
|
doc_limit=doc_limit,
|
||||||
"streaming": True
|
)
|
||||||
}
|
print(resp)
|
||||||
}
|
|
||||||
|
|
||||||
req = json.dumps(req)
|
|
||||||
await ws.send(req)
|
|
||||||
|
|
||||||
while True:
|
|
||||||
msg = await ws.recv()
|
|
||||||
obj = json.loads(msg)
|
|
||||||
|
|
||||||
if "error" in obj:
|
|
||||||
raise RuntimeError(obj["error"])
|
|
||||||
|
|
||||||
if obj["id"] != mid:
|
|
||||||
print("Ignore message")
|
|
||||||
continue
|
|
||||||
|
|
||||||
response = obj["response"]
|
|
||||||
|
|
||||||
# Handle streaming format (chunk)
|
|
||||||
if "chunk" in response:
|
|
||||||
chunk = response["chunk"]
|
|
||||||
print(chunk, end="", flush=True)
|
|
||||||
elif "response" in response:
|
|
||||||
# Final response with complete text
|
|
||||||
# Already printed via chunks, just add newline
|
|
||||||
pass
|
|
||||||
|
|
||||||
if obj["complete"]:
|
|
||||||
print() # Final newline
|
|
||||||
break
|
|
||||||
|
|
||||||
await ws.close()
|
|
||||||
|
|
||||||
def question_non_streaming(url, flow_id, question, user, collection, doc_limit):
|
|
||||||
"""Non-streaming version using HTTP API"""
|
|
||||||
|
|
||||||
api = Api(url).flow().id(flow_id)
|
|
||||||
|
|
||||||
resp = api.document_rag(
|
|
||||||
question=question, user=user, collection=collection,
|
|
||||||
doc_limit=doc_limit,
|
|
||||||
)
|
|
||||||
|
|
||||||
print(resp)
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|
||||||
|
|
@ -101,6 +62,12 @@ def main():
|
||||||
help=f'API URL (default: {default_url})',
|
help=f'API URL (default: {default_url})',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
'-t', '--token',
|
||||||
|
default=default_token,
|
||||||
|
help='Authentication token (default: $TRUSTGRAPH_TOKEN)',
|
||||||
|
)
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'-f', '--flow-id',
|
'-f', '--flow-id',
|
||||||
default="default",
|
default="default",
|
||||||
|
|
@ -127,6 +94,7 @@ def main():
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'-d', '--doc-limit',
|
'-d', '--doc-limit',
|
||||||
|
type=int,
|
||||||
default=default_doc_limit,
|
default=default_doc_limit,
|
||||||
help=f'Document limit (default: {default_doc_limit})'
|
help=f'Document limit (default: {default_doc_limit})'
|
||||||
)
|
)
|
||||||
|
|
@ -141,30 +109,20 @@ def main():
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
||||||
if not args.no_streaming:
|
question(
|
||||||
asyncio.run(
|
url=args.url,
|
||||||
question_streaming(
|
flow_id=args.flow_id,
|
||||||
url=args.url,
|
question=args.question,
|
||||||
flow_id=args.flow_id,
|
user=args.user,
|
||||||
question=args.question,
|
collection=args.collection,
|
||||||
user=args.user,
|
doc_limit=args.doc_limit,
|
||||||
collection=args.collection,
|
streaming=not args.no_streaming,
|
||||||
doc_limit=args.doc_limit,
|
token=args.token,
|
||||||
)
|
)
|
||||||
)
|
|
||||||
else:
|
|
||||||
question_non_streaming(
|
|
||||||
url=args.url,
|
|
||||||
flow_id=args.flow_id,
|
|
||||||
question=args.question,
|
|
||||||
user=args.user,
|
|
||||||
collection=args.collection,
|
|
||||||
doc_limit=args.doc_limit,
|
|
||||||
)
|
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|
||||||
print("Exception:", e, flush=True)
|
print("Exception:", e, flush=True)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|
|
||||||
|
|
@ -4,13 +4,10 @@ Uses the GraphRAG service to answer a question
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import os
|
import os
|
||||||
import asyncio
|
|
||||||
import json
|
|
||||||
import uuid
|
|
||||||
from websockets.asyncio.client import connect
|
|
||||||
from trustgraph.api import Api
|
from trustgraph.api import Api
|
||||||
|
|
||||||
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
|
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
|
||||||
|
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
|
||||||
default_user = 'trustgraph'
|
default_user = 'trustgraph'
|
||||||
default_collection = 'default'
|
default_collection = 'default'
|
||||||
default_entity_limit = 50
|
default_entity_limit = 50
|
||||||
|
|
@ -18,89 +15,51 @@ default_triple_limit = 30
|
||||||
default_max_subgraph_size = 150
|
default_max_subgraph_size = 150
|
||||||
default_max_path_length = 2
|
default_max_path_length = 2
|
||||||
|
|
||||||
async def question_streaming(
|
def question(
|
||||||
url, flow_id, question, user, collection, entity_limit, triple_limit,
|
url, flow_id, question, user, collection, entity_limit, triple_limit,
|
||||||
max_subgraph_size, max_path_length
|
max_subgraph_size, max_path_length, streaming=True, token=None
|
||||||
):
|
):
|
||||||
"""Streaming version using websockets"""
|
|
||||||
|
|
||||||
# Convert http:// to ws://
|
# Create API client
|
||||||
if url.startswith('http://'):
|
api = Api(url=url, token=token)
|
||||||
url = 'ws://' + url[7:]
|
|
||||||
elif url.startswith('https://'):
|
|
||||||
url = 'wss://' + url[8:]
|
|
||||||
|
|
||||||
if not url.endswith("/"):
|
if streaming:
|
||||||
url += "/"
|
# Use socket client for streaming
|
||||||
|
socket = api.socket()
|
||||||
|
flow = socket.flow(flow_id)
|
||||||
|
|
||||||
url = url + "api/v1/socket"
|
try:
|
||||||
|
response = flow.graph_rag(
|
||||||
|
question=question,
|
||||||
|
user=user,
|
||||||
|
collection=collection,
|
||||||
|
entity_limit=entity_limit,
|
||||||
|
triple_limit=triple_limit,
|
||||||
|
max_subgraph_size=max_subgraph_size,
|
||||||
|
max_path_length=max_path_length,
|
||||||
|
streaming=True
|
||||||
|
)
|
||||||
|
|
||||||
mid = str(uuid.uuid4())
|
# Stream output
|
||||||
|
for chunk in response:
|
||||||
|
print(chunk.content, end="", flush=True)
|
||||||
|
print() # Final newline
|
||||||
|
|
||||||
async with connect(url) as ws:
|
finally:
|
||||||
req = {
|
socket.close()
|
||||||
"id": mid,
|
else:
|
||||||
"service": "graph-rag",
|
# Use REST API for non-streaming
|
||||||
"flow": flow_id,
|
flow = api.flow().id(flow_id)
|
||||||
"request": {
|
resp = flow.graph_rag(
|
||||||
"query": question,
|
question=question,
|
||||||
"user": user,
|
user=user,
|
||||||
"collection": collection,
|
collection=collection,
|
||||||
"entity-limit": entity_limit,
|
entity_limit=entity_limit,
|
||||||
"triple-limit": triple_limit,
|
triple_limit=triple_limit,
|
||||||
"max-subgraph-size": max_subgraph_size,
|
max_subgraph_size=max_subgraph_size,
|
||||||
"max-path-length": max_path_length,
|
max_path_length=max_path_length
|
||||||
"streaming": True
|
)
|
||||||
}
|
print(resp)
|
||||||
}
|
|
||||||
|
|
||||||
req = json.dumps(req)
|
|
||||||
await ws.send(req)
|
|
||||||
|
|
||||||
while True:
|
|
||||||
msg = await ws.recv()
|
|
||||||
obj = json.loads(msg)
|
|
||||||
|
|
||||||
if "error" in obj:
|
|
||||||
raise RuntimeError(obj["error"])
|
|
||||||
|
|
||||||
if obj["id"] != mid:
|
|
||||||
print("Ignore message")
|
|
||||||
continue
|
|
||||||
|
|
||||||
response = obj["response"]
|
|
||||||
|
|
||||||
# Handle streaming format (chunk)
|
|
||||||
if "chunk" in response:
|
|
||||||
chunk = response["chunk"]
|
|
||||||
print(chunk, end="", flush=True)
|
|
||||||
elif "response" in response:
|
|
||||||
# Final response with complete text
|
|
||||||
# Already printed via chunks, just add newline
|
|
||||||
pass
|
|
||||||
|
|
||||||
if obj["complete"]:
|
|
||||||
print() # Final newline
|
|
||||||
break
|
|
||||||
|
|
||||||
await ws.close()
|
|
||||||
|
|
||||||
def question_non_streaming(
|
|
||||||
url, flow_id, question, user, collection, entity_limit, triple_limit,
|
|
||||||
max_subgraph_size, max_path_length
|
|
||||||
):
|
|
||||||
"""Non-streaming version using HTTP API"""
|
|
||||||
|
|
||||||
api = Api(url).flow().id(flow_id)
|
|
||||||
|
|
||||||
resp = api.graph_rag(
|
|
||||||
question=question, user=user, collection=collection,
|
|
||||||
entity_limit=entity_limit, triple_limit=triple_limit,
|
|
||||||
max_subgraph_size=max_subgraph_size,
|
|
||||||
max_path_length=max_path_length
|
|
||||||
)
|
|
||||||
|
|
||||||
print(resp)
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|
||||||
|
|
@ -115,6 +74,12 @@ def main():
|
||||||
help=f'API URL (default: {default_url})',
|
help=f'API URL (default: {default_url})',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
'-t', '--token',
|
||||||
|
default=default_token,
|
||||||
|
help='Authentication token (default: $TRUSTGRAPH_TOKEN)',
|
||||||
|
)
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'-f', '--flow-id',
|
'-f', '--flow-id',
|
||||||
default="default",
|
default="default",
|
||||||
|
|
@ -141,24 +106,28 @@ def main():
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'-e', '--entity-limit',
|
'-e', '--entity-limit',
|
||||||
|
type=int,
|
||||||
default=default_entity_limit,
|
default=default_entity_limit,
|
||||||
help=f'Entity limit (default: {default_entity_limit})'
|
help=f'Entity limit (default: {default_entity_limit})'
|
||||||
)
|
)
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'-t', '--triple-limit',
|
'--triple-limit',
|
||||||
|
type=int,
|
||||||
default=default_triple_limit,
|
default=default_triple_limit,
|
||||||
help=f'Triple limit (default: {default_triple_limit})'
|
help=f'Triple limit (default: {default_triple_limit})'
|
||||||
)
|
)
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'-s', '--max-subgraph-size',
|
'-s', '--max-subgraph-size',
|
||||||
|
type=int,
|
||||||
default=default_max_subgraph_size,
|
default=default_max_subgraph_size,
|
||||||
help=f'Max subgraph size (default: {default_max_subgraph_size})'
|
help=f'Max subgraph size (default: {default_max_subgraph_size})'
|
||||||
)
|
)
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'-p', '--max-path-length',
|
'-p', '--max-path-length',
|
||||||
|
type=int,
|
||||||
default=default_max_path_length,
|
default=default_max_path_length,
|
||||||
help=f'Max path length (default: {default_max_path_length})'
|
help=f'Max path length (default: {default_max_path_length})'
|
||||||
)
|
)
|
||||||
|
|
@ -173,36 +142,23 @@ def main():
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
||||||
if not args.no_streaming:
|
question(
|
||||||
asyncio.run(
|
url=args.url,
|
||||||
question_streaming(
|
flow_id=args.flow_id,
|
||||||
url=args.url,
|
question=args.question,
|
||||||
flow_id=args.flow_id,
|
user=args.user,
|
||||||
question=args.question,
|
collection=args.collection,
|
||||||
user=args.user,
|
entity_limit=args.entity_limit,
|
||||||
collection=args.collection,
|
triple_limit=args.triple_limit,
|
||||||
entity_limit=args.entity_limit,
|
max_subgraph_size=args.max_subgraph_size,
|
||||||
triple_limit=args.triple_limit,
|
max_path_length=args.max_path_length,
|
||||||
max_subgraph_size=args.max_subgraph_size,
|
streaming=not args.no_streaming,
|
||||||
max_path_length=args.max_path_length,
|
token=args.token,
|
||||||
)
|
)
|
||||||
)
|
|
||||||
else:
|
|
||||||
question_non_streaming(
|
|
||||||
url=args.url,
|
|
||||||
flow_id=args.flow_id,
|
|
||||||
question=args.question,
|
|
||||||
user=args.user,
|
|
||||||
collection=args.collection,
|
|
||||||
entity_limit=args.entity_limit,
|
|
||||||
triple_limit=args.triple_limit,
|
|
||||||
max_subgraph_size=args.max_subgraph_size,
|
|
||||||
max_path_length=args.max_path_length,
|
|
||||||
)
|
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|
||||||
print("Exception:", e, flush=True)
|
print("Exception:", e, flush=True)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|
|
||||||
|
|
@ -5,64 +5,39 @@ and user prompt. Both arguments are required.
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import os
|
import os
|
||||||
import json
|
from trustgraph.api import Api
|
||||||
import uuid
|
|
||||||
import asyncio
|
|
||||||
from websockets.asyncio.client import connect
|
|
||||||
|
|
||||||
default_url = os.getenv("TRUSTGRAPH_URL", 'ws://localhost:8088/')
|
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
|
||||||
|
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
|
||||||
|
|
||||||
async def query(url, flow_id, system, prompt, streaming=True):
|
def query(url, flow_id, system, prompt, streaming=True, token=None):
|
||||||
|
|
||||||
if not url.endswith("/"):
|
# Create API client
|
||||||
url += "/"
|
api = Api(url=url, token=token)
|
||||||
|
socket = api.socket()
|
||||||
|
flow = socket.flow(flow_id)
|
||||||
|
|
||||||
url = url + "api/v1/socket"
|
try:
|
||||||
|
# Call text completion
|
||||||
|
response = flow.text_completion(
|
||||||
|
system=system,
|
||||||
|
prompt=prompt,
|
||||||
|
streaming=streaming
|
||||||
|
)
|
||||||
|
|
||||||
mid = str(uuid.uuid4())
|
if streaming:
|
||||||
|
# Stream output to stdout without newline
|
||||||
|
for chunk in response:
|
||||||
|
print(chunk.content, end="", flush=True)
|
||||||
|
# Add final newline after streaming
|
||||||
|
print()
|
||||||
|
else:
|
||||||
|
# Non-streaming: print complete response
|
||||||
|
print(response)
|
||||||
|
|
||||||
async with connect(url) as ws:
|
finally:
|
||||||
|
# Clean up socket connection
|
||||||
req = {
|
socket.close()
|
||||||
"id": mid,
|
|
||||||
"service": "text-completion",
|
|
||||||
"flow": flow_id,
|
|
||||||
"request": {
|
|
||||||
"system": system,
|
|
||||||
"prompt": prompt,
|
|
||||||
"streaming": streaming
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
await ws.send(json.dumps(req))
|
|
||||||
|
|
||||||
while True:
|
|
||||||
|
|
||||||
msg = await ws.recv()
|
|
||||||
|
|
||||||
obj = json.loads(msg)
|
|
||||||
|
|
||||||
if "error" in obj:
|
|
||||||
raise RuntimeError(obj["error"])
|
|
||||||
|
|
||||||
if obj["id"] != mid:
|
|
||||||
continue
|
|
||||||
|
|
||||||
if "response" in obj["response"]:
|
|
||||||
if streaming:
|
|
||||||
# Stream output to stdout without newline
|
|
||||||
print(obj["response"]["response"], end="", flush=True)
|
|
||||||
else:
|
|
||||||
# Non-streaming: print complete response
|
|
||||||
print(obj["response"]["response"])
|
|
||||||
|
|
||||||
if obj["complete"]:
|
|
||||||
if streaming:
|
|
||||||
# Add final newline after streaming
|
|
||||||
print()
|
|
||||||
break
|
|
||||||
|
|
||||||
await ws.close()
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|
||||||
|
|
@ -77,6 +52,12 @@ def main():
|
||||||
help=f'API URL (default: {default_url})',
|
help=f'API URL (default: {default_url})',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
'-t', '--token',
|
||||||
|
default=default_token,
|
||||||
|
help='Authentication token (default: $TRUSTGRAPH_TOKEN)',
|
||||||
|
)
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'system',
|
'system',
|
||||||
nargs=1,
|
nargs=1,
|
||||||
|
|
@ -105,17 +86,18 @@ def main():
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
||||||
asyncio.run(query(
|
query(
|
||||||
url=args.url,
|
url=args.url,
|
||||||
flow_id=args.flow_id,
|
flow_id=args.flow_id,
|
||||||
system=args.system[0],
|
system=args.system[0],
|
||||||
prompt=args.prompt[0],
|
prompt=args.prompt[0],
|
||||||
streaming=not args.no_streaming
|
streaming=not args.no_streaming,
|
||||||
))
|
token=args.token,
|
||||||
|
)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|
||||||
print("Exception:", e, flush=True)
|
print("Exception:", e, flush=True)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|
|
||||||
|
|
@ -10,76 +10,61 @@ using key=value arguments on the command line, and these replace
|
||||||
import argparse
|
import argparse
|
||||||
import os
|
import os
|
||||||
import json
|
import json
|
||||||
import uuid
|
from trustgraph.api import Api
|
||||||
import asyncio
|
|
||||||
from websockets.asyncio.client import connect
|
|
||||||
|
|
||||||
default_url = os.getenv("TRUSTGRAPH_URL", 'ws://localhost:8088/')
|
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
|
||||||
|
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
|
||||||
|
|
||||||
async def query(url, flow_id, template_id, variables, streaming=True):
|
def query(url, flow_id, template_id, variables, streaming=True, token=None):
|
||||||
|
|
||||||
if not url.endswith("/"):
|
# Create API client
|
||||||
url += "/"
|
api = Api(url=url, token=token)
|
||||||
|
socket = api.socket()
|
||||||
|
flow = socket.flow(flow_id)
|
||||||
|
|
||||||
url = url + "api/v1/socket"
|
try:
|
||||||
|
# Call prompt
|
||||||
|
response = flow.prompt(
|
||||||
|
id=template_id,
|
||||||
|
variables=variables,
|
||||||
|
streaming=streaming
|
||||||
|
)
|
||||||
|
|
||||||
mid = str(uuid.uuid4())
|
if streaming:
|
||||||
|
full_response = {"text": "", "object": ""}
|
||||||
|
|
||||||
async with connect(url) as ws:
|
# Stream output
|
||||||
|
for chunk in response:
|
||||||
|
content = chunk.content
|
||||||
|
if content:
|
||||||
|
print(content, end="", flush=True)
|
||||||
|
full_response["text"] += content
|
||||||
|
|
||||||
req = {
|
# Check if this is an object response (JSON)
|
||||||
"id": mid,
|
if hasattr(chunk, 'object') and chunk.object:
|
||||||
"service": "prompt",
|
full_response["object"] = chunk.object
|
||||||
"flow": flow_id,
|
|
||||||
"request": {
|
|
||||||
"id": template_id,
|
|
||||||
"variables": variables,
|
|
||||||
"streaming": streaming
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
await ws.send(json.dumps(req))
|
# Handle final output
|
||||||
|
if full_response["text"]:
|
||||||
|
# Add final newline after streaming text
|
||||||
|
print()
|
||||||
|
elif full_response["object"]:
|
||||||
|
# Print JSON object (pretty-printed)
|
||||||
|
print(json.dumps(json.loads(full_response["object"]), indent=4))
|
||||||
|
|
||||||
full_response = {"text": "", "object": ""}
|
else:
|
||||||
|
# Non-streaming: handle response
|
||||||
while True:
|
if isinstance(response, str):
|
||||||
|
print(response)
|
||||||
msg = await ws.recv()
|
elif isinstance(response, dict):
|
||||||
|
if "text" in response:
|
||||||
obj = json.loads(msg)
|
|
||||||
|
|
||||||
if "error" in obj:
|
|
||||||
raise RuntimeError(obj["error"])
|
|
||||||
|
|
||||||
if obj["id"] != mid:
|
|
||||||
continue
|
|
||||||
|
|
||||||
response = obj["response"]
|
|
||||||
|
|
||||||
# Handle text responses (streaming)
|
|
||||||
if "text" in response and response["text"]:
|
|
||||||
if streaming:
|
|
||||||
# Stream output to stdout without newline
|
|
||||||
print(response["text"], end="", flush=True)
|
|
||||||
full_response["text"] += response["text"]
|
|
||||||
else:
|
|
||||||
# Non-streaming: print complete response
|
|
||||||
print(response["text"])
|
print(response["text"])
|
||||||
|
elif "object" in response:
|
||||||
|
print(json.dumps(json.loads(response["object"]), indent=4))
|
||||||
|
|
||||||
# Handle object responses (JSON, never streamed)
|
finally:
|
||||||
if "object" in response and response["object"]:
|
# Clean up socket connection
|
||||||
full_response["object"] = response["object"]
|
socket.close()
|
||||||
|
|
||||||
if obj["complete"]:
|
|
||||||
if streaming and full_response["text"]:
|
|
||||||
# Add final newline after streaming text
|
|
||||||
print()
|
|
||||||
elif full_response["object"]:
|
|
||||||
# Print JSON object (pretty-printed)
|
|
||||||
print(json.dumps(json.loads(full_response["object"]), indent=4))
|
|
||||||
break
|
|
||||||
|
|
||||||
await ws.close()
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|
||||||
|
|
@ -94,6 +79,12 @@ def main():
|
||||||
help=f'API URL (default: {default_url})',
|
help=f'API URL (default: {default_url})',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
'-t', '--token',
|
||||||
|
default=default_token,
|
||||||
|
help='Authentication token (default: $TRUSTGRAPH_TOKEN)',
|
||||||
|
)
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'-f', '--flow-id',
|
'-f', '--flow-id',
|
||||||
default="default",
|
default="default",
|
||||||
|
|
@ -135,17 +126,18 @@ specified multiple times''',
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
||||||
asyncio.run(query(
|
query(
|
||||||
url=args.url,
|
url=args.url,
|
||||||
flow_id=args.flow_id,
|
flow_id=args.flow_id,
|
||||||
template_id=args.id[0],
|
template_id=args.id[0],
|
||||||
variables=variables,
|
variables=variables,
|
||||||
streaming=not args.no_streaming
|
streaming=not args.no_streaming,
|
||||||
))
|
token=args.token,
|
||||||
|
)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|
||||||
print("Exception:", e, flush=True)
|
print("Exception:", e, flush=True)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue