From bb7ac5d380114a5eed5ca4f480a3774fe4b39618 Mon Sep 17 00:00:00 2001 From: Cyber MacGeddon Date: Sun, 10 Nov 2024 10:06:31 +0000 Subject: [PATCH] Argument parsing (agent manager is broken) --- .../trustgraph/base/base_processor.py | 5 +- .../trustgraph/agent/react/README.md | 16 +++ .../trustgraph/agent/react/service.py | 97 +++++++++++++++++++ 3 files changed, 116 insertions(+), 2 deletions(-) create mode 100644 trustgraph-flow/trustgraph/agent/react/README.md diff --git a/trustgraph-base/trustgraph/base/base_processor.py b/trustgraph-base/trustgraph/base/base_processor.py index 9b2e29ac..f258ff1a 100644 --- a/trustgraph-base/trustgraph/base/base_processor.py +++ b/trustgraph-base/trustgraph/base/base_processor.py @@ -39,8 +39,9 @@ class BaseProcessor: def __del__(self): - if self.client: - self.client.close() + if hasattr(self, "client"): + if self.client: + self.client.close() @staticmethod def add_args(parser): diff --git a/trustgraph-flow/trustgraph/agent/react/README.md b/trustgraph-flow/trustgraph/agent/react/README.md new file mode 100644 index 00000000..b60851d4 --- /dev/null +++ b/trustgraph-flow/trustgraph/agent/react/README.md @@ -0,0 +1,16 @@ + +agent-manager-react \ + -p pulsar://localhost:6650 \ + --tool-type \ + shuttle=knowledge-base:query \ + cats=knowledge-base:query \ + compute=text-completion:computation \ + --tool-description \ + shuttle="Query a knowledge base with information about the space shuttle. The query should be a simple natural language question" \ + cats="Query a knowledge base with information about Mark's cats. The query should be a simple natural language question" \ + compute="A computation engine which can answer questions about maths and computation" \ + --tool-argument \ + cats="query:string:The search query string" \ + shuttle="query:string:The search query string" \ + compute="computation:string:The computation to solve" + diff --git a/trustgraph-flow/trustgraph/agent/react/service.py b/trustgraph-flow/trustgraph/agent/react/service.py index 0477552d..c8880571 100755 --- a/trustgraph-flow/trustgraph/agent/react/service.py +++ b/trustgraph-flow/trustgraph/agent/react/service.py @@ -4,6 +4,7 @@ Simple agent infrastructure broadly implements the ReAct flow. import json import re +import sys from pulsar.schema import JsonSchema @@ -35,6 +36,73 @@ class Processor(ConsumerProducer): def __init__(self, **params): + tool_base = {} + + # Parsing the prompt information to the prompt configuration + # structure + tool_type_arg = params.get("tool_type", []) + if tool_type_arg: + for t in tool_type_arg: + toks = t.split("=", 1) + if len(toks) < 2: + raise RuntimeError( + f"Tool-type string not well-formed: {t}" + ) + ttoks = toks[1].split(":", 1) + if len(ttoks) == 1: + tool_base[toks[0]] = { + "type": ttoks[0], + "input-arg": "query", + "arguments": {}, + } + else: + tool_base[toks[0]] = { + "type": ttoks[0], + "input-arg": ttoks[1], + "arguments": {}, + } + + # Parsing the prompt information to the prompt configuration + # structure + tool_desc_arg = params.get("tool_description", []) + if tool_desc_arg: + for t in tool_desc_arg: + toks = t.split("=", 1) + if len(toks) < 2: + raise RuntimeError( + f"Tool-type string not well-formed: {t}" + ) + if toks[0] not in tool_base: + raise RuntimeError(f"Description, tool {toks[0]} not known") + tool_base[toks[0]]["description"] = toks[1] + + # Parsing the prompt information to the prompt configuration + # structure + tool_arg_arg = params.get("tool_argument", []) + if tool_arg_arg: + for t in tool_arg_arg: + toks = t.split("=", 1) + if len(toks) < 2: + raise RuntimeError( + f"Tool-type string not well-formed: {t}" + ) + ttoks = toks[1].split(":", 2) + if len(ttoks) != 3: + raise RuntimeError( + f"Tool argument string not well-formed: {t}" + ) + if toks[0] not in tool_base: + raise RuntimeError(f"Description, tool {toks[0]} not known") + tool_base[toks[0]]["arguments"][ttoks[0]] = { + "name": ttoks[0], + "type": ttoks[1], + "description": ttoks[2], + } + + print(json.dumps(tool_base, indent=4)) + + sys.exit(0) + input_queue = params.get("input_queue", default_input_queue) output_queue = params.get("output_queue", default_output_queue) subscriber = params.get("subscriber", default_subscriber) @@ -275,6 +343,35 @@ class Processor(ConsumerProducer): help=f'Graph RAG response queue (default: {gr_response_queue})', ) + parser.add_argument( + '--tool-type', nargs='*', + help=f'''Specifies the type of an agent tool. Takes the form +=. is the name of the tool. is one of +knowledge-base, text-completion. Additional parameters are specified +for different tools which are tool-specific. e.g. knowledge-query: +which specifies the name of the arg whose content is fed into the knowledge +query as a question. text-completion: specifies the name of the arg +whose content is fed into the text-completion service as a prompt''' + ) + + parser.add_argument( + '--tool-description', nargs='*', + help=f'''Specifies the textual description of a tool. Takes +the form =. The description is important, it teaches the +LLM how to use the tool. It should describe what it does and how to +use the arguments. This is specified in natural language.''' + ) + + parser.add_argument( + '--tool-argument', nargs='*', + help=f'''Specifies argument usage for a tool. Takes +the form =::. The description is important, +it is read by the LLM and used to determine how to use the argument. + can be specified multiple times to give a tool multiple arguments. + is one of string, number. is a natural language +description.''' + ) + def run(): Processor.start(module, __doc__)