[add] better error handling
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
3168bfffd1
commit
ca8c306534
@ -19,36 +19,17 @@ def get_response():
|
|||||||
|
|
||||||
resp = minyma.oai.query(message)
|
resp = minyma.oai.query(message)
|
||||||
|
|
||||||
# Derive LLM Data
|
|
||||||
# llm_resp = resp.get("llm", {})
|
|
||||||
# llm_choices = llm_resp.get("choices", [])
|
|
||||||
|
|
||||||
# Derive VDB Data
|
|
||||||
# vdb_resp = resp.get("vdb", {})
|
|
||||||
# combined_context = [{
|
|
||||||
# "id": vdb_resp.get("ids")[i],
|
|
||||||
# "distance": vdb_resp.get("distances")[i],
|
|
||||||
# "doc": vdb_resp.get("docs")[i],
|
|
||||||
# "metadata": vdb_resp.get("metadatas")[i],
|
|
||||||
# } for i, _ in enumerate(vdb_resp.get("docs", []))]
|
|
||||||
|
|
||||||
# Return Data
|
# Return Data
|
||||||
return resp
|
return resp
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Return the raw vector db related response
|
TODO - Embeds and loads data into the local ChromaDB.
|
||||||
|
|
||||||
|
{
|
||||||
|
"input": "string",
|
||||||
|
"normalizer": "string",
|
||||||
|
}
|
||||||
"""
|
"""
|
||||||
@bp.route("/related", methods=["POST"])
|
bp.route("/embed", methods=["POST"])
|
||||||
def get_related():
|
def post_embeddings():
|
||||||
data = request.get_json()
|
pass
|
||||||
if not data:
|
|
||||||
return {"error": "Missing Message"}
|
|
||||||
|
|
||||||
message = str(data.get("message"))
|
|
||||||
if message == "":
|
|
||||||
return {"error": "Empty Message"}
|
|
||||||
|
|
||||||
related_documents = minyma.vdb.get_related(message)
|
|
||||||
return related_documents
|
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
import os
|
import os
|
||||||
|
|
||||||
|
|
||||||
def get_env(key, default=None, required=False) -> str:
|
def get_env(key, default=None, required=False) -> str | None:
|
||||||
"""Wrapper for gathering env vars."""
|
"""Wrapper for gathering env vars."""
|
||||||
if required:
|
if required:
|
||||||
assert key in os.environ, "Missing Environment Variable: %s" % key
|
assert key in os.environ, "Missing Environment Variable: %s" % key
|
||||||
return str(os.environ.get(key, default))
|
env = os.environ.get(key, default)
|
||||||
|
return str(env) if env is not None else None
|
||||||
|
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
@ -19,7 +20,7 @@ class Config:
|
|||||||
OpenAI API Key - Required
|
OpenAI API Key - Required
|
||||||
"""
|
"""
|
||||||
|
|
||||||
CHROMA_DATA_PATH: str = get_env("CHROMA_DATA_PATH", required=False)
|
CHROMA_DATA_PATH: str | None = get_env("CHROMA_DATA_PATH", required=False)
|
||||||
HOME_ASSISTANT_API_KEY: str = get_env("HOME_ASSISTANT_API_KEY", required=False)
|
HOME_ASSISTANT_API_KEY: str | None = get_env("HOME_ASSISTANT_API_KEY", required=False)
|
||||||
HOME_ASSISTANT_URL: str = get_env("HOME_ASSISTANT_URL", required=False)
|
HOME_ASSISTANT_URL: str | None = get_env("HOME_ASSISTANT_URL", required=False)
|
||||||
OPENAI_API_KEY: str = get_env("OPENAI_API_KEY", required=True)
|
OPENAI_API_KEY: str | None = get_env("OPENAI_API_KEY", required=True)
|
||||||
|
@ -79,20 +79,33 @@ class OpenAIConnector:
|
|||||||
|
|
||||||
print("[OpenAIConnector] Completed Initial OAI Query:\n", indent(json.dumps({ "usage": response.usage, "function_calls": all_funcs }, indent=2), ' ' * 2))
|
print("[OpenAIConnector] Completed Initial OAI Query:\n", indent(json.dumps({ "usage": response.usage, "function_calls": all_funcs }, indent=2), ' ' * 2))
|
||||||
|
|
||||||
# Execute Requested Functions
|
# Build Response Text & Metadata
|
||||||
func_responses = {}
|
func_metadata = {}
|
||||||
for func in all_funcs:
|
func_response = []
|
||||||
func_responses[func] = minyma.plugins.execute(func)
|
|
||||||
|
|
||||||
# Build Response Text
|
for func in all_funcs:
|
||||||
response_content_arr = []
|
# Execute Requested Function
|
||||||
for key, val in func_responses.items():
|
resp = minyma.plugins.execute(func)
|
||||||
indented_val = indent(val, ' ' * 2)
|
|
||||||
response_content_arr.append("- %s\n%s" % (key, indented_val))
|
# Unknown Response
|
||||||
response_content = "\n".join(response_content_arr)
|
if resp is None:
|
||||||
|
print("[OpenAIConnector] Invalid Function Response: %s" % func)
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Get Response
|
||||||
|
content = resp.get("content")
|
||||||
|
metadata = resp.get("metadata")
|
||||||
|
error = resp.get("error")
|
||||||
|
|
||||||
|
# Append Responses & Metadata
|
||||||
|
indented_val = indent(content or error or "Unknown Error", ' ' * 2)
|
||||||
|
func_response.append("- %s\n%s" % (func, indented_val))
|
||||||
|
func_metadata[func] = { "metadata": metadata, "error": error }
|
||||||
|
|
||||||
|
func_response = "\n".join(func_response)
|
||||||
|
|
||||||
# Create Follow Up Prompt
|
# Create Follow Up Prompt
|
||||||
prompt = FOLLOW_UP_PROMPT_TEMPLATE.format(question = question, response = response_content)
|
prompt = FOLLOW_UP_PROMPT_TEMPLATE.format(question = question, response = func_response)
|
||||||
messages = [{"role": "user", "content": prompt}]
|
messages = [{"role": "user", "content": prompt}]
|
||||||
|
|
||||||
print("[OpenAIConnector] Running Follup Up OAI Query")
|
print("[OpenAIConnector] Running Follup Up OAI Query")
|
||||||
@ -116,7 +129,7 @@ class OpenAIConnector:
|
|||||||
# Return Response
|
# Return Response
|
||||||
return {
|
return {
|
||||||
"response": content,
|
"response": content,
|
||||||
"functions": func_responses,
|
"functions": func_metadata,
|
||||||
"usage": {
|
"usage": {
|
||||||
"prompt_tokens": prompt_tokens,
|
"prompt_tokens": prompt_tokens,
|
||||||
"completion_tokens": completion_tokens,
|
"completion_tokens": completion_tokens,
|
||||||
|
@ -13,8 +13,9 @@ class ChromaDBPlugin(MinymaPlugin):
|
|||||||
def __init__(self, config):
|
def __init__(self, config):
|
||||||
self.name = "chroma_db"
|
self.name = "chroma_db"
|
||||||
self.config = config
|
self.config = config
|
||||||
|
self.word_cap = 1000
|
||||||
|
|
||||||
if not config.CHROMA_DATA_PATH:
|
if config.CHROMA_DATA_PATH is None:
|
||||||
self.functions = []
|
self.functions = []
|
||||||
else:
|
else:
|
||||||
self.vdb = ChromaDB(config.CHROMA_DATA_PATH)
|
self.vdb = ChromaDB(config.CHROMA_DATA_PATH)
|
||||||
@ -25,17 +26,28 @@ class ChromaDBPlugin(MinymaPlugin):
|
|||||||
# Get Related
|
# Get Related
|
||||||
related = self.vdb.get_related(collection_name, query)
|
related = self.vdb.get_related(collection_name, query)
|
||||||
|
|
||||||
|
# Get Metadata
|
||||||
|
metadata = [{
|
||||||
|
"id": related.get("ids")[i],
|
||||||
|
"distance": related.get("distances")[i],
|
||||||
|
"metadata": related.get("metadatas")[i],
|
||||||
|
} for i, _ in enumerate(related.get("docs", []))]
|
||||||
|
|
||||||
# Normalize Data
|
# Normalize Data
|
||||||
return list(
|
return list(
|
||||||
map(
|
map(
|
||||||
lambda x: " ".join(x.split()[:self.vdb.word_cap]),
|
lambda x: " ".join(x.split()[:self.word_cap]),
|
||||||
related.get("docs", [])
|
related.get("docs", [])
|
||||||
)
|
)
|
||||||
)
|
), metadata
|
||||||
|
|
||||||
|
|
||||||
def lookup_pubmed_data(self, query: str):
|
def lookup_pubmed_data(self, query: str):
|
||||||
COLLECTION_NAME = "pubmed"
|
COLLECTION_NAME = "pubmed"
|
||||||
documents = self.__lookup_data(COLLECTION_NAME, query)
|
documents, metadata = self.__lookup_data(COLLECTION_NAME, query)
|
||||||
context = '\n'.join(documents)
|
context = '\n'.join(documents)
|
||||||
return context
|
return {
|
||||||
|
"content": context,
|
||||||
|
"metadata": metadata,
|
||||||
|
"error": None
|
||||||
|
}
|
||||||
|
@ -21,6 +21,7 @@ class DuckDuckGoPlugin(MinymaPlugin):
|
|||||||
resp = requests.get("https://html.duckduckgo.com/html/?q=%s" % query, headers=HEADERS)
|
resp = requests.get("https://html.duckduckgo.com/html/?q=%s" % query, headers=HEADERS)
|
||||||
soup = BeautifulSoup(resp.text, features="html.parser")
|
soup = BeautifulSoup(resp.text, features="html.parser")
|
||||||
|
|
||||||
|
# Get Results
|
||||||
results = []
|
results = []
|
||||||
for item in soup.select(".result > div"):
|
for item in soup.select(".result > div"):
|
||||||
title_el = item.select_one(".result__title > a")
|
title_el = item.select_one(".result__title > a")
|
||||||
@ -31,4 +32,18 @@ class DuckDuckGoPlugin(MinymaPlugin):
|
|||||||
|
|
||||||
results.append({"title": title, "description": description})
|
results.append({"title": title, "description": description})
|
||||||
|
|
||||||
return json.dumps(results[:5])
|
# Derive Metadata (Title)
|
||||||
|
metadata = {
|
||||||
|
"titles": list(
|
||||||
|
map(
|
||||||
|
lambda x: x.get("title"),
|
||||||
|
results[:5]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
"content": json.dumps(results[:5]),
|
||||||
|
"metadata": metadata,
|
||||||
|
"error": None
|
||||||
|
}
|
||||||
|
@ -10,18 +10,15 @@ class HomeAssistantPlugin(MinymaPlugin):
|
|||||||
def __init__(self, config):
|
def __init__(self, config):
|
||||||
self.config = config
|
self.config = config
|
||||||
self.name = "home_assistant"
|
self.name = "home_assistant"
|
||||||
|
self.functions = []
|
||||||
|
|
||||||
|
if config.HOME_ASSISTANT_API_KEY and config.HOME_ASSISTANT_URL:
|
||||||
if not config.HOME_ASSISTANT_API_KEY or not config.HOME_ASSISTANT_URL:
|
self.functions = [self.home_automation_command]
|
||||||
if not config.HOME_ASSISTANT_API_KEY:
|
if not config.HOME_ASSISTANT_API_KEY:
|
||||||
print("[HomeAssistantPlugin] Missing HOME_ASSISTANT_API_KEY")
|
print("[HomeAssistantPlugin] Missing HOME_ASSISTANT_API_KEY")
|
||||||
if not config.HOME_ASSISTANT_URL:
|
if not config.HOME_ASSISTANT_URL:
|
||||||
print("[HomeAssistantPlugin] Missing HOME_ASSISTANT_URL")
|
print("[HomeAssistantPlugin] Missing HOME_ASSISTANT_URL")
|
||||||
|
|
||||||
self.functions = []
|
|
||||||
else:
|
|
||||||
self.functions = [self.home_automation_command]
|
|
||||||
|
|
||||||
def home_automation_command(self, natural_language_command: str):
|
def home_automation_command(self, natural_language_command: str):
|
||||||
url = urllib.parse.urljoin(self.config.HOME_ASSISTANT_URL, "/api/conversation/process")
|
url = urllib.parse.urljoin(self.config.HOME_ASSISTANT_URL, "/api/conversation/process")
|
||||||
headers = {
|
headers = {
|
||||||
@ -34,6 +31,17 @@ class HomeAssistantPlugin(MinymaPlugin):
|
|||||||
|
|
||||||
# Parse JSON
|
# Parse JSON
|
||||||
try:
|
try:
|
||||||
return json.dumps(resp.json())
|
r = resp.json()
|
||||||
|
text = r["response"]["speech"]["plain"]["speech"]
|
||||||
|
|
||||||
|
return {
|
||||||
|
"content": text,
|
||||||
|
"metadata": r,
|
||||||
|
"error": None
|
||||||
|
}
|
||||||
except requests.JSONDecodeError:
|
except requests.JSONDecodeError:
|
||||||
return json.dumps({ "error": "Command Failed" })
|
return {
|
||||||
|
"content": None,
|
||||||
|
"metadata": None,
|
||||||
|
"error": "Command Failed"
|
||||||
|
}
|
||||||
|
@ -50,10 +50,11 @@ class VehicleLookupPlugin(MinymaPlugin):
|
|||||||
|
|
||||||
# Invalid JSON
|
# Invalid JSON
|
||||||
if json_resp is None:
|
if json_resp is None:
|
||||||
return json.dumps({
|
return{
|
||||||
|
"content": None,
|
||||||
|
"metadata": text_resp,
|
||||||
"error": error,
|
"error": error,
|
||||||
"response": text_resp,
|
}
|
||||||
})
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Check Result
|
# Check Result
|
||||||
@ -63,7 +64,11 @@ class VehicleLookupPlugin(MinymaPlugin):
|
|||||||
error = "No Results"
|
error = "No Results"
|
||||||
else:
|
else:
|
||||||
error = "API Error: %s" % status_resp
|
error = "API Error: %s" % status_resp
|
||||||
return {"error": error, "response": text_resp}
|
return {
|
||||||
|
"content": None,
|
||||||
|
"metadata": json_resp,
|
||||||
|
"error": error,
|
||||||
|
}
|
||||||
|
|
||||||
# Parse Result
|
# Parse Result
|
||||||
vehicle_info = json_resp.get("content")
|
vehicle_info = json_resp.get("content")
|
||||||
@ -74,17 +79,20 @@ class VehicleLookupPlugin(MinymaPlugin):
|
|||||||
trim = vehicle_info.get("vehicles")[0].get("trim")
|
trim = vehicle_info.get("vehicles")[0].get("trim")
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return json.dumps({
|
return {
|
||||||
|
"content": None,
|
||||||
|
"metadata": text_resp,
|
||||||
"error": "Unknown Error: %s" % e,
|
"error": "Unknown Error: %s" % e,
|
||||||
"response": text_resp,
|
}
|
||||||
})
|
|
||||||
|
|
||||||
return json.dumps({
|
return {
|
||||||
"result": {
|
"content": json.dumps({
|
||||||
"vin": vin,
|
"vin": vin,
|
||||||
"year": year,
|
"year": year,
|
||||||
"make": make,
|
"make": make,
|
||||||
"model": model,
|
"model": model,
|
||||||
"trim": trim,
|
"trim": trim,
|
||||||
},
|
}),
|
||||||
})
|
"metadata": json_resp,
|
||||||
|
"error": None
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user