diff --git a/assistant_dists/universal_selectors_assistant/dev.yml b/assistant_dists/universal_selectors_assistant/dev.yml index f8eb90a13..48c447c5f 100644 --- a/assistant_dists/universal_selectors_assistant/dev.yml +++ b/assistant_dists/universal_selectors_assistant/dev.yml @@ -10,6 +10,13 @@ services: - "./annotators/SentSeg:/src" ports: - 8011:8011 + universal-llm-based-skill-selector: + volumes: + - "./skill_selectors/universal_llm_based_skill_selector:/src" + - "./common:/src/common" + - "./components:/src/components" + ports: + - 8187:8187 universal-llm-based-response-selector: volumes: - "./response_selectors/universal_llm_based_response_selector:/src" diff --git a/assistant_dists/universal_selectors_assistant/docker-compose.override.yml b/assistant_dists/universal_selectors_assistant/docker-compose.override.yml index cc5b57c89..18f5db054 100644 --- a/assistant_dists/universal_selectors_assistant/docker-compose.override.yml +++ b/assistant_dists/universal_selectors_assistant/docker-compose.override.yml @@ -3,7 +3,7 @@ services: command: sh -c 'bin/wait && python -m deeppavlov_agent.run agent.pipeline_config=assistant_dists/universal_selectors_assistant/pipeline_conf.json' environment: WAIT_HOSTS: "sentseg:8011, universal-llm-based-response-selector:8181, combined-classification:8087, - sentence-ranker:8128, openai-api-chatgpt:8145, openai-api-davinci3:8131, + sentence-ranker:8128, openai-api-chatgpt:8145, openai-api-davinci3:8131, universal-llm-based-skill-selector:8187, openai-api-gpt4:8159, openai-api-gpt4-32k:8160, openai-api-chatgpt-16k:8167, dff-universal-prompted-skill:8147" WAIT_HOSTS_TIMEOUT: ${WAIT_TIMEOUT:-1000} @@ -28,8 +28,9 @@ services: env_file: [ .env ] build: args: - CONFIG: combined_classifier.json SERVICE_PORT: 8087 + SERVICE_NAME: combined_classification + CONFIG: combined_classifier.json context: . dockerfile: ./annotators/combined_classification/Dockerfile command: gunicorn --workers=1 server:app -b 0.0.0.0:8087 --timeout 600 @@ -42,6 +43,29 @@ services: reservations: memory: 2G + universal-llm-based-skill-selector: + env_file: [ .env ] + build: + args: + SERVICE_PORT: 8187 + SERVICE_NAME: skill_selector + DEFAULT_LM_SERVICE_URL: http://openai-api-chatgpt:8145/respond + DEFAULT_LM_SERVICE_CONFIG: openai-chatgpt.json + GENERATIVE_TIMEOUT: 20 + N_UTTERANCES_CONTEXT: 3 + MAX_N_SKILLS: 3 + context: . + dockerfile: ./skill_selectors/universal_llm_based_skill_selector/Dockerfile + command: flask run -h 0.0.0.0 -p 8187 + environment: + - FLASK_APP=server + deploy: + resources: + limits: + memory: 100M + reservations: + memory: 100M + universal-llm-based-response-selector: env_file: [ .env ] build: diff --git a/assistant_dists/universal_selectors_assistant/pipeline_conf.json b/assistant_dists/universal_selectors_assistant/pipeline_conf.json index 6e87e5ff0..55a0ad90f 100644 --- a/assistant_dists/universal_selectors_assistant/pipeline_conf.json +++ b/assistant_dists/universal_selectors_assistant/pipeline_conf.json @@ -112,12 +112,13 @@ } }, "skill_selectors": { - "rule_based_selector": { + "skill_selector": { "connector": { - "protocol": "python", - "class_name": "skill_selectors.rule_based_selector.connector:RuleBasedSkillSelectorConnector" + "protocol": "http", + "timeout": 10.0, + "url": "http://universal-llm-based-skill-selector:8187/respond" }, - "dialog_formatter": "state_formatters.dp_formatters:base_skill_selector_formatter_dialog", + "dialog_formatter": "state_formatters.dp_formatters:cropped_dialog", "response_formatter": "state_formatters.dp_formatters:simple_formatter_service", "previous_services": [ "annotators" @@ -127,8 +128,8 @@ ], "is_enabled": true, "source": { - "component": "components/xSwFvtAUdvtQosvzpb7oMg.yml", - "service": "skill_selectors/rule_based_selector/service_configs/agent" + "component": "components/jkdfh12oien9dfuih1.yml", + "service": "skill_selectors/universal_llm_based_skill_selector/service_configs/universal-llm-based-skill-selector" } } }, diff --git a/components.tsv b/components.tsv index 87a5fe564..c63e101da 100644 --- a/components.tsv +++ b/components.tsv @@ -186,4 +186,10 @@ 8182 llm-based-skill-selector 8183 external-integration-skill 8184 external-fake-server -8185 dff-roles-prompted-skill +8185 dff-roles-prompted-skill +8186 +8187 universal-llm-based-skill-selector +8188 +8189 +8190 +8191 \ No newline at end of file diff --git a/components/jkdfh12oien9dfuih1.yml b/components/jkdfh12oien9dfuih1.yml new file mode 100644 index 000000000..8f00c4f01 --- /dev/null +++ b/components/jkdfh12oien9dfuih1.yml @@ -0,0 +1,25 @@ +name: skill_selector +display_name: Universal LLM-based Skill Selector +component_type: null +model_type: Dictionary/Pattern-based +is_customizable: false +author: publisher@deeppavlov.ai +description: Algorithm that selects skills to generate hypotheses among the given list of all available + skills in pipeline and provided LLM service +ram_usage: 100M +gpu_usage: null +group: skill_selectors +connector: + protocol: http + timeout: 10.0 + url: http://universal-llm-based-skill-selector:8187/respond +dialog_formatter: state_formatters.dp_formatters:cropped_dialog +response_formatter: state_formatters.dp_formatters:simple_formatter_service +previous_services: +- annotators +required_previous_services: null +state_manager_method: null +tags: null +endpoint: respond +service: skill_selectors/universal_llm_based_skill_selector/service_configs/universal-llm-based-skill-selector +date_created: '2023-03-16T09:45:32' diff --git a/response_selectors/llm_based_response_selector/server.py b/response_selectors/llm_based_response_selector/server.py index c7316a8c8..1f5fe1979 100644 --- a/response_selectors/llm_based_response_selector/server.py +++ b/response_selectors/llm_based_response_selector/server.py @@ -58,6 +58,9 @@ def select_response_by_scores(hypotheses, scores): def select_response(dialog_context, hypotheses, human_uttr_attributes): + if human_uttr_attributes.get("return_all_hypotheses", None): + return "\n".join(['"' + hyp["skill_name"] + '": "' + hyp["text"] + '"' for hyp in hypotheses]) + try: ie_types = [ "external service" if hyp["skill_name"] in EXTERNAL_SKILLS else "internal service" for hyp in hypotheses @@ -85,6 +88,7 @@ def select_response(dialog_context, hypotheses, human_uttr_attributes): sending_variables, ) result = response[0] + result = result.replace("[internal service]", "").replace("[external service]", "").strip() except Exception as e: sentry_sdk.capture_exception(e) logger.exception(e) diff --git a/response_selectors/universal_llm_based_response_selector/README.md b/response_selectors/universal_llm_based_response_selector/README.md index 989ae5698..9435e9ae3 100644 --- a/response_selectors/universal_llm_based_response_selector/README.md +++ b/response_selectors/universal_llm_based_response_selector/README.md @@ -45,7 +45,7 @@ for lm_service in ["ChatGPT"]: {"openai_api_key": "FILL IN"} ], # ---------------------------- response selector parameters - "response_selector_prompt": "Select the most funny answer.", + "response_selector_prompt": "Select the most funny answer.\nLIST_OF_HYPOTHESES\n", "response_selector_lm_service_url": LM_SERVICES_MAPPING[lm_service], "response_selector_lm_service_config": { diff --git a/response_selectors/universal_llm_based_response_selector/server.py b/response_selectors/universal_llm_based_response_selector/server.py index 2187beeeb..51fd0241b 100644 --- a/response_selectors/universal_llm_based_response_selector/server.py +++ b/response_selectors/universal_llm_based_response_selector/server.py @@ -71,6 +71,9 @@ def select_response_by_scores(hypotheses, scores): def select_response(dialog, hypotheses, human_uttr_attributes): dialog_context = [uttr["text"] for uttr in dialog["utterances"][-N_UTTERANCES_CONTEXT:]] + if human_uttr_attributes.get("return_all_hypotheses", None): + return "\n".join(['"' + hyp["skill_name"] + '": "' + hyp["text"] + '"' for hyp in hypotheses]) + # get prompt from the current utterance attributes given_prompt = human_uttr_attributes.get("response_selector_prompt", DEFAULT_PROMPT) for i in range(1, len(dialog["utterances"]) + 1, 2): @@ -113,6 +116,7 @@ def select_response(dialog, hypotheses, human_uttr_attributes): sending_variables, ) result = response[0] + result = result.replace("[internal service]", "").replace("[external service]", "").strip() except Exception as e: sentry_sdk.capture_exception(e) logger.exception(e) diff --git a/response_selectors/universal_llm_based_response_selector/service_configs/universal-llm-based-response-selector/service.yml b/response_selectors/universal_llm_based_response_selector/service_configs/universal-llm-based-response-selector/service.yml index 2557d3bd7..00756f68c 100644 --- a/response_selectors/universal_llm_based_response_selector/service_configs/universal-llm-based-response-selector/service.yml +++ b/response_selectors/universal_llm_based_response_selector/service_configs/universal-llm-based-response-selector/service.yml @@ -2,7 +2,8 @@ name: universal-llm-based-response-selector endpoints: - respond compose: - env_file: [ .env,.env_secret ] + env_file: + - .env build: args: SERVICE_PORT: 8181 diff --git a/skill_selectors/llm_based_skill_selector/server.py b/skill_selectors/llm_based_skill_selector/server.py index c97520190..63599b716 100644 --- a/skill_selectors/llm_based_skill_selector/server.py +++ b/skill_selectors/llm_based_skill_selector/server.py @@ -58,6 +58,9 @@ def select_skills(dialog): # pipeline is smth like this: ['annotators.sentseg', 'skills.dummy_skill', # 'candidate_annotators.sentence_ranker', 'response_selectors.response_selector', ...] all_skill_names = [el.split(".")[1] for el in pipeline if "skills" in el] + if human_uttr_attributes.get("selected_skills", None) in ["all", []]: + logger.info(f"llm_based_skill_selector selected ALL skills:\n`{all_skill_names}`") + return all_skill_names try: if "LIST_OF_AVAILABLE_AGENTS_WITH_DESCRIPTIONS" in PROMPT: diff --git a/skill_selectors/universal_llm_based_skill_selector/Dockerfile b/skill_selectors/universal_llm_based_skill_selector/Dockerfile new file mode 100644 index 000000000..29ff86068 --- /dev/null +++ b/skill_selectors/universal_llm_based_skill_selector/Dockerfile @@ -0,0 +1,29 @@ +FROM python:3.10 + +RUN mkdir /src + +COPY ./skill_selectors/universal_llm_based_skill_selector/requirements.txt /src/requirements.txt +RUN pip install -r /src/requirements.txt + +ARG SERVICE_PORT +ENV SERVICE_PORT ${SERVICE_PORT} +ARG GENERATIVE_TIMEOUT +ENV GENERATIVE_TIMEOUT ${GENERATIVE_TIMEOUT} +ARG ENVVARS_TO_SEND +ENV ENVVARS_TO_SEND ${ENVVARS_TO_SEND} +ARG N_UTTERANCES_CONTEXT=5 +ENV N_UTTERANCES_CONTEXT ${N_UTTERANCES_CONTEXT} +ARG DEFAULT_LM_SERVICE_URL +ENV DEFAULT_LM_SERVICE_URL ${DEFAULT_LM_SERVICE_URL} +ARG DEFAULT_LM_SERVICE_CONFIG +ENV DEFAULT_LM_SERVICE_CONFIG ${DEFAULT_LM_SERVICE_CONFIG} +ARG MAX_N_SKILLS +ENV MAX_N_SKILLS ${MAX_N_SKILLS} + +COPY skill_selectors/universal_llm_based_skill_selector /src +WORKDIR /src +COPY ./common/ ./common/ +COPY ./components/ ./components/ + + +CMD gunicorn --workers=1 server:app -b 0.0.0.0:${SERVICE_PORT} --timeout=1200 diff --git a/skill_selectors/universal_llm_based_skill_selector/README.md b/skill_selectors/universal_llm_based_skill_selector/README.md new file mode 100644 index 000000000..d24e9b570 --- /dev/null +++ b/skill_selectors/universal_llm_based_skill_selector/README.md @@ -0,0 +1,92 @@ +# Universal LLM-based Skill Selector + +## Description + +Debugging Skill Selector is a component selecting a list of skills to generate hypotheses. +The LLM-based Skill Selector utilizes LLM service to select the skills in a generative manner. +The considered LLM-service, generative parameters and prompt are provided IN attributes of +the last human utterance. The list of all available skills is picked up from human utterance attributes. + + +**Important** Provide `"return_all_hypotheses": True` (to return joined list of all returned hypotheses) +and `"selected_skills": "all"` (to turn on dff_universal_prompted_skill because all other prompted skills +are not deployed during debugging process). + +How to use: + +```python +import requests +import random +from time import sleep + + +LM_SERVICES_MAPPING = { + "ChatGPT": "http://openai-api-chatgpt:8145/respond", +} +for lm_service in ["ChatGPT"]: + print(f"Checking `Universal Assistant` with `{lm_service}`") + + result = requests.post( + "http://0.0.0.0:4242", + json={ + "user_id": f"test-user-{random.randint(100, 1000)}", + "payload": "How much is two plus two?", + # ---------------------------- batch of universal skills to generate hypotheses + "skill_name": ["Mathematician Skill", "blondy_skill"], + "prompt": ["Answer as a mathematician.", "Answer like you are a stupid Blondy Girl."], + "lm_service_url": [LM_SERVICES_MAPPING[lm_service], LM_SERVICES_MAPPING[lm_service]], + "lm_service_config": [ + { + "max_new_tokens": 64, + "temperature": 0.9, + "top_p": 1.0, + "frequency_penalty": 0, + "presence_penalty": 0 + }, + None + ], + "lm_service_kwargs": [ + {"openai_api_key": "FILL IN"}, + {"openai_api_key": "FILL IN"} + ], + # ---------------------------- response selector MUST RETURN ALL HYPOTHESES JOINED + "return_all_hypotheses": True, + # ---------------------------- skill selector + "selected_skills": "all", # must use it to turn on universal skill (others are not deployed!) + "skill_selector_prompt": """ +Select up to 2 the most relevant to the dialog context skills based on the given short descriptions of abilities of different skills of the assistant. + +Skills: +"Mathematician Skill": "A skill pretending to be a mathematician." +"blondy_skill": "A Skill pretending to be a blondy girl." + +Return only names of the selected skills divided by comma. Do not respond to the dialog context.""", + "skill_selector_lm_service_url": LM_SERVICES_MAPPING[lm_service], + "skill_selector_lm_service_config": + { + "max_new_tokens": 64, + "temperature": 0.4, + "top_p": 1.0, + "frequency_penalty": 0, + "presence_penalty": 0 + }, + "skill_selector_lm_service_kwargs": {"openai_api_key": "FILL IN"}, + }).json() + print(f"Response:\n{result['response']}") + if result["active_skill"] not in ["Dummy Skill", "dummy_skill"]: + print("Success!") + elif lm_service in ["ChatGPT", "GPT-3.5"]: + print(f"\nATTENTION! OpenAI services do not work!\n") + else: + print(f"\nERROR: `Universal Assistant` returned `{result}`\n") + sleep(5) +``` + +### Parameters + +The algorithm utilizes `N_UTTERANCES_CONTEXT` last utterances as a context for LLM. +Number of returned skills can ve varied by the prompt itself. + +## Dependencies + +- generative service `DEFAULT_LM_SERVICE_URL` or the given in attributes in the last human utterance \ No newline at end of file diff --git a/skill_selectors/universal_llm_based_skill_selector/requirements.txt b/skill_selectors/universal_llm_based_skill_selector/requirements.txt new file mode 100644 index 000000000..a6192076b --- /dev/null +++ b/skill_selectors/universal_llm_based_skill_selector/requirements.txt @@ -0,0 +1,9 @@ +flask==1.1.1 +itsdangerous==2.0.1 +gunicorn==19.9.0 +requests==2.22.0 +numpy==1.25.0 +sentry-sdk==0.12.3 +jinja2<=3.0.3 +Werkzeug<=2.0.3 +pyyaml==6.0.1 diff --git a/skill_selectors/universal_llm_based_skill_selector/server.py b/skill_selectors/universal_llm_based_skill_selector/server.py new file mode 100644 index 000000000..6273ee480 --- /dev/null +++ b/skill_selectors/universal_llm_based_skill_selector/server.py @@ -0,0 +1,135 @@ +import json +import logging +import yaml +import time +from os import getenv, listdir + +import sentry_sdk +from flask import Flask, request, jsonify +from common.prompts import send_request_to_prompted_generative_service, compose_sending_variables + + +sentry_sdk.init(getenv("SENTRY_DSN")) +logging.basicConfig(format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", level=logging.INFO) +logger = logging.getLogger(__name__) + +app = Flask(__name__) + +GENERATIVE_TIMEOUT = int(getenv("GENERATIVE_TIMEOUT", 5)) +N_UTTERANCES_CONTEXT = int(getenv("N_UTTERANCES_CONTEXT", 3)) + +DEFAULT_PROMPT = json.load(open("common/prompts/skill_selector.json", "r"))["prompt"] +DEFAULT_LM_SERVICE_URL = getenv("DEFAULT_LM_SERVICE_URL", "http://transformers-lm-gptjt:8161/respond") +DEFAULT_LM_SERVICE_CONFIG = getenv("DEFAULT_LM_SERVICE_CONFIG", "default_generative_config.json") +DEFAULT_LM_SERVICE_CONFIG = json.load(open(f"common/generative_configs/{DEFAULT_LM_SERVICE_CONFIG}", "r")) +ENVVARS_TO_SEND = { + "http://transformers-lm-gptj:8130/respond": [], + "http://transformers-lm-bloomz7b:8146/respond": [], + "http://transformers-lm-oasst12b:8158/respond": [], + "http://openai-api-chatgpt:8145/respond": ["OPENAI_API_KEY", "OPENAI_ORGANIZATION"], + "http://openai-api-chatgpt-16k:8167/respond": ["OPENAI_API_KEY", "OPENAI_ORGANIZATION"], + "http://openai-api-davinci3:8131/respond": ["OPENAI_API_KEY", "OPENAI_ORGANIZATION"], + "http://openai-api-gpt4:8159/respond": ["OPENAI_API_KEY", "OPENAI_ORGANIZATION"], + "http://openai-api-gpt4-32k:8160/respond": ["OPENAI_API_KEY", "OPENAI_ORGANIZATION"], + "http://transformers-lm-gptjt:8161/respond": [], + "http://anthropic-api-claude-v1:8164/respond": ["ANTHROPIC_API_KEY"], + "http://anthropic-api-claude-instant-v1:8163/respond": ["ANTHROPIC_API_KEY"], + "http://transformers-lm-vicuna13b:8168/respond": [], + "http://transformers-lm-ruxglm:8171/respond": [], + "http://transformers-lm-rugpt35:8178/respond": [], +} + +DEFAULT_SKILLS = ["dummy_skill"] +MAX_N_SKILLS = int(getenv("MAX_N_SKILLS")) +DEFAULT_PROMPT = DEFAULT_PROMPT.replace("up to MAX_N_SKILLS", f"up to {MAX_N_SKILLS}") + + +def collect_descriptions_from_components(skill_names): + result = {} + for fname in listdir("components/"): + if "yml" in fname: + component = yaml.load(open(f"components/{fname}", "r"), Loader=yaml.FullLoader) + if component["name"] in skill_names: + result[component["name"]] = component["description"] + + return result + + +def select_skills(dialog): + global DEFAULT_PROMPT, N_UTTERANCES_CONTEXT + selected_skills = [] + selected_skills += DEFAULT_SKILLS + + dialog_context = [uttr["text"] for uttr in dialog["utterances"][-N_UTTERANCES_CONTEXT:]] + human_uttr_attributes = dialog["human_utterances"][-1].get("attributes", {}) + # collect skill names from human utterance attributes in DEBUG mode + all_skill_names = human_uttr_attributes.get("skill_name", []) + if human_uttr_attributes.get("selected_skills", None) in ["all", []]: + # also add all skills from pipeline + pipeline = dialog.get("attributes", {}).get("pipeline", []) + all_skill_names += [el.split(".")[1] for el in pipeline if "skills" in el] + logger.info(f"universal_llm_based_skill_selector selected ALL skills:\n`{all_skill_names}`") + return all_skill_names + + try: + logger.info(f"universal_llm_based_skill_selector sends dialog context to llm:\n`{dialog_context}`") + prompt = human_uttr_attributes.pop("skill_selector_prompt", DEFAULT_PROMPT) + + if "LIST_OF_AVAILABLE_AGENTS_WITH_DESCRIPTIONS" in prompt: + # need to add skill descriptions in prompt in replacement of `LIST_OF_AVAILABLE_AGENTS_WITH_DESCRIPTIONS` + skill_descr_dict = collect_descriptions_from_components(all_skill_names) + skill_descriptions = "Skills:\n" + skill_descriptions += "\n".join([f'"{name}": "{descr}"' for name, descr in skill_descr_dict.items()]) + prompt = prompt.replace("LIST_OF_AVAILABLE_AGENTS_WITH_DESCRIPTIONS", skill_descriptions) + logger.info(f"prompt: {prompt}") + + lm_service_url = human_uttr_attributes.pop("skill_selector_lm_service_url", DEFAULT_LM_SERVICE_URL) + logger.info(f"lm_service_url: {lm_service_url}") + # this is a dictionary! not a file! + lm_service_config = human_uttr_attributes.pop("skill_selector_lm_service_config", None) + lm_service_kwargs = human_uttr_attributes.pop("skill_selector_lm_service_kwargs", None) + lm_service_kwargs = {} if lm_service_kwargs is None else lm_service_kwargs + envvars_to_send = ENVVARS_TO_SEND.get(lm_service_url, []) + sending_variables = compose_sending_variables( + lm_service_kwargs, + envvars_to_send, + ) + + response = send_request_to_prompted_generative_service( + dialog_context, + prompt, + lm_service_url, + lm_service_config, + GENERATIVE_TIMEOUT, + sending_variables, + ) + for skill_name in all_skill_names: + if skill_name in response[0]: + selected_skills += [skill_name] + except Exception as e: + sentry_sdk.capture_exception(e) + logger.exception(e) + logger.info("Exception in LLM's invocation. Turn on all skills from pipeline.") + + logger.info(f"universal_llm_based_skill_selector selected:\n`{selected_skills}`") + + selected_skills = list(set(selected_skills)) + if selected_skills == ["dummy_skill"]: + logger.info("Selected only Dummy Skill. Turn on all skills from pipeline.") + selected_skills.extend(all_skill_names) + return selected_skills + + +@app.route("/respond", methods=["POST"]) +def respond(): + st_time = time.time() + dialogs = request.json.get("dialogs", []) + responses = [] + + for dialog in dialogs: + responses.append(select_skills(dialog)) + + total_time = time.time() - st_time + logger.info(f"universal_llm_based_skill_selector exec time = {total_time:.3f}s") + + return jsonify(responses) diff --git a/skill_selectors/universal_llm_based_skill_selector/service_configs/universal-llm-based-skill-selector/environment.yml b/skill_selectors/universal_llm_based_skill_selector/service_configs/universal-llm-based-skill-selector/environment.yml new file mode 100644 index 000000000..cb9f52aee --- /dev/null +++ b/skill_selectors/universal_llm_based_skill_selector/service_configs/universal-llm-based-skill-selector/environment.yml @@ -0,0 +1,8 @@ +SERVICE_PORT: 8187 +SERVICE_NAME: skill_selector +DEFAULT_LM_SERVICE_URL: http://openai-api-chatgpt:8145/respond +DEFAULT_LM_SERVICE_CONFIG: openai-chatgpt.json +GENERATIVE_TIMEOUT: 20 +N_UTTERANCES_CONTEXT: 3 +MAX_N_SKILLS: 3 +FLASK_APP: server \ No newline at end of file diff --git a/skill_selectors/universal_llm_based_skill_selector/service_configs/universal-llm-based-skill-selector/service.yml b/skill_selectors/universal_llm_based_skill_selector/service_configs/universal-llm-based-skill-selector/service.yml new file mode 100644 index 000000000..b73272534 --- /dev/null +++ b/skill_selectors/universal_llm_based_skill_selector/service_configs/universal-llm-based-skill-selector/service.yml @@ -0,0 +1,31 @@ +name: universal-llm-based-skill-selector +endpoints: +- respond +compose: + env_file: + - .env + build: + args: + SERVICE_PORT: 8187 + SERVICE_NAME: skill_selector + DEFAULT_LM_SERVICE_URL: http://openai-api-chatgpt:8145/respond + DEFAULT_LM_SERVICE_CONFIG: openai-chatgpt.json + GENERATIVE_TIMEOUT: 20 + N_UTTERANCES_CONTEXT: 3 + MAX_N_SKILLS: 3 + FLASK_APP: server + context: . + dockerfile: ./skill_selectors/universal_llm_based_skill_selector/Dockerfile + command: flask run -h 0.0.0.0 -p 8187 + environment: + - FLASK_APP=server + deploy: + resources: + limits: + memory: 100M + reservations: + memory: 100M + ports: + - 8187:8187 +proxy: null + diff --git a/skill_selectors/universal_llm_based_skill_selector/test.py b/skill_selectors/universal_llm_based_skill_selector/test.py new file mode 100644 index 000000000..c15d79996 --- /dev/null +++ b/skill_selectors/universal_llm_based_skill_selector/test.py @@ -0,0 +1,42 @@ +import requests +from os import getenv + + +SERVICE_PORT = int(getenv("SERVICE_PORT")) + + +def test_respond(): + result = requests.post( + f"http://0.0.0.0:{SERVICE_PORT}/respond", + json={ + "dialogs": [ + { + "attributes": { + "pipeline": [ + "skills.dummy_skill", + "skills.dff_official_email_prompted_skill", + "skills.dff_plan_for_article_prompted_skill", + ], + }, + "human_utterances": [ + { + "text": "help me with my article about penguins", + } + ], + "utterances": [ + { + "text": "help me with my article about penguins", + } + ], + } + ], + }, + ).json()[0] + print(result) + + assert "dff_plan_for_article_prompted_skill" in result, f"Got\n{result}\n, something is wrong" + print("Success!") + + +if __name__ == "__main__": + test_respond() diff --git a/skill_selectors/universal_llm_based_skill_selector/test.sh b/skill_selectors/universal_llm_based_skill_selector/test.sh new file mode 100755 index 000000000..468a5a38f --- /dev/null +++ b/skill_selectors/universal_llm_based_skill_selector/test.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +python test.py \ No newline at end of file