Fix: prompt template overrides (#136)

* Added single-target command-line config generator.  Mainly using for
testing ATM.

* Slightly tweak the config decode so that components can over-ride the
'with' method which injects parameters.

* Deliberately break the prompt-generic template.  Could do better, this
is temporary.

* Add 'prompt-overrides' component, injects new prompts.

* Removed prompt generic reference, not used

* prompt-generic is no longer supported
This commit is contained in:
cybermaggedon 2024-11-05 21:17:34 +00:00 committed by GitHub
parent 8a2126bba5
commit 53c958aaff
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 188 additions and 91 deletions

View file

@ -16,13 +16,10 @@
"ollama": import "components/ollama.jsonnet",
"openai": import "components/openai.jsonnet",
"override-recursive-chunker": import "components/chunker-recursive.jsonnet",
"prompt-template-definitions": import "components/null.jsonnet",
"prompt-template-document-query": import "components/null.jsonnet",
"prompt-template-kq-query": import "components/null.jsonnet",
"prompt-template-relationships": import "components/null.jsonnet",
"prompt-template-rows-template": import "components/null.jsonnet",
"prompt-generic": import "components/prompt-generic.jsonnet",
"prompt-template": import "components/prompt-template.jsonnet",
"prompt-overrides": import "components/prompt-overrides.jsonnet",
"pulsar": import "components/pulsar.jsonnet",
"pulsar-manager": import "components/pulsar-manager.jsonnet",
"trustgraph-base": import "components/trustgraph.jsonnet",

View file

@ -1,81 +0,0 @@
local base = import "base/base.jsonnet";
local images = import "values/images.jsonnet";
local url = import "values/url.jsonnet";
local prompts = import "prompts/mixtral.jsonnet";
{
"prompt" +: {
create:: function(engine)
local container =
engine.container("prompt")
.with_image(images.trustgraph)
.with_command([
"prompt-generic",
"-p",
url.pulsar,
"--text-completion-request-queue",
"non-persistent://tg/request/text-completion",
"--text-completion-response-queue",
"non-persistent://tg/response/text-completion-response",
])
.with_limits("0.5", "128M")
.with_reservations("0.1", "128M");
local containerSet = engine.containers(
"prompt", [ container ]
);
local service =
engine.internalService(containerSet)
.with_port(8080, 8080, "metrics");
engine.resources([
containerSet,
service,
])
},
"prompt-rag" +: {
create:: function(engine)
local container =
engine.container("prompt-rag")
.with_image(images.trustgraph)
.with_command([
"prompt-generic",
"-p",
url.pulsar,
"-i",
"non-persistent://tg/request/prompt-rag",
"-o",
"non-persistent://tg/response/prompt-rag-response",
"--text-completion-request-queue",
"non-persistent://tg/request/text-completion-rag",
"--text-completion-response-queue",
"non-persistent://tg/response/text-completion-rag-response",
])
.with_limits("0.5", "128M")
.with_reservations("0.1", "128M");
local containerSet = engine.containers(
"prompt-rag", [ container ]
);
local service =
engine.internalService(containerSet)
.with_port(8080, 8080, "metrics");
engine.resources([
containerSet,
service,
])
},
}

View file

@ -0,0 +1,28 @@
local base = import "base/base.jsonnet";
local images = import "values/images.jsonnet";
local url = import "values/url.jsonnet";
local prompts = import "prompts/mixtral.jsonnet";
local default_prompts = import "prompts/default-prompts.jsonnet";
{
with:: function(key, value)
if (key == "system-template") then
self + {
prompts +:: {
"system-template": value,
}
}
else
self + {
prompts +:: {
templates +:: {
[key]: {
prompt +:: value
}
}
}
},
} + default_prompts

140
templates/generate Executable file
View file

@ -0,0 +1,140 @@
#!/usr/bin/env python3
import _jsonnet as j
import json
import yaml
import logging
import os
import sys
import zipfile
logger = logging.getLogger("generate")
logging.basicConfig(level=logging.INFO, format='%(message)s')
private_json = "Put your GCP private.json here"
class Generator:
def __init__(self, config, base="./templates/", version="0.0.0"):
self.jsonnet_base = base
self.config = config
self.version = f"\"{version}\"".encode("utf-8")
def process(self, config):
res = j.evaluate_snippet("config", config, import_callback=self.load)
return json.loads(res)
def load(self, dir, filename):
logger.debug("Request jsonnet: %s %s", dir, filename)
if filename == "config.json" and dir == "":
path = os.path.join(".", dir, filename)
return str(path), self.config
if filename == "version.jsonnet" and dir == "./templates/values/":
path = os.path.join(".", dir, filename)
return str(path), self.version
if dir:
candidates = [
os.path.join(".", dir, filename),
os.path.join(".", filename)
]
else:
candidates = [
os.path.join(".", filename)
]
try:
if filename == "vertexai/private.json":
return candidates[0], private_json.encode("utf-8")
for c in candidates:
logger.debug("Try: %s", c)
if os.path.isfile(c):
with open(c, "rb") as f:
logger.debug("Loading: %s", c)
return str(c), f.read()
raise RuntimeError(
f"Could not load file={filename} dir={dir}"
)
except:
path = os.path.join(self.jsonnet_base, filename)
logger.debug("Try: %s", path)
with open(path, "rb") as f:
logger.debug("Loaded: %s", path)
return str(path), f.read()
def main():
if len(sys.argv) != 3:
print()
print("Usage:")
print(" generate <outfile> <version> < input.json")
print()
raise RuntimeError("Arg error")
outfile = sys.argv[1]
version = sys.argv[2]
cfg = sys.stdin.read()
cfg = json.loads(cfg)
logger.info(f"Outputting to {outfile}...")
with zipfile.ZipFile(outfile, mode='w') as out:
def output(name, content):
logger.info(f"Adding {name}...")
out.writestr(name, content)
fname = "tg-launch.yaml"
platform = "docker-compose"
with open(f"./templates/config-to-{platform}.jsonnet", "r") as f:
wrapper = f.read()
gen = Generator(json.dumps(cfg).encode("utf-8"), version=version)
processed = gen.process(wrapper)
y = yaml.dump(processed)
output(fname, y)
# Placeholder for the private.json file. Won't put actual credentials
# here.
output("docker-compose/vertexai/private.json", private_json)
# Grafana config
with open("grafana/dashboards/dashboard.json") as f:
output(
"docker-compose/grafana/dashboards/dashboard.json", f.read()
)
with open("grafana/provisioning/dashboard.yml") as f:
output(
"docker-compose/grafana/provisioning/dashboard.yml", f.read()
)
with open("grafana/provisioning/datasource.yml") as f:
output(
"docker-compose/grafana/provisioning/datasource.yml", f.read()
)
# Prometheus config
with open("prometheus/prometheus.yml") as f:
output("docker-compose/prometheus/prometheus.yml", f.read())
main()

View file

@ -3,9 +3,7 @@ local components = import "components.jsonnet";
local apply = function(p, components)
local component = components[p.name];
(component + {
local base = {
with:: function(k, v) self + {
[k]:: v
@ -18,7 +16,11 @@ local apply = function(p, components)
self
),
}).with_params(p.parameters);
};
local component = base + components[p.name];
component.with_params(p.parameters);
local decode = function(config)
local add = function(state, c) state + apply(c, components);

View file

@ -2,6 +2,15 @@
Language service abstracts prompt engineering from LLM.
"""
#
# FIXME: This module is broken, it doesn't conform to the prompt API change
# made in 0.14, nor the prompt template support.
#
# It could be made to conform by using prompt-template as a starting
# point, and hard-coding all the information.
#
import json
import re
@ -469,5 +478,7 @@ class Processor(ConsumerProducer):
def run():
raise RuntimeError("NOT IMPLEMENTED")
Processor.start(module, __doc__)