-
-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #922 from weni-ai/feature/zeroshot-5.0.0
Feature/zeroshot 5.0.0
- Loading branch information
Showing
7 changed files
with
2,025 additions
and
2,103 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,56 +1,39 @@ | ||
BASE_PROMPT = """<|begin_of_text|><|start_header_id|>system<|end_header_id|> | ||
{context_description} {context} | ||
{reflection} | ||
# {classes_title} | ||
{all_classes}<|eot_id|><|start_header_id|>user<|end_header_id|> | ||
{system_prompt}<|eot_id|><|start_header_id|>user<|end_header_id|> | ||
{input}<|eot_id|><|start_header_id|>assistant<|end_header_id|> | ||
""" | ||
|
||
class FormatPrompt: | ||
const_prompt_data = { | ||
"por": { | ||
"context_description": "Você é muito especialista em classificar a frase do usuário em um chatbot sobre:", | ||
"reflection": "Pare, pense bem e responda com APENAS UM ÚNICO `id` da classe que melhor represente a intenção para a frase do usuário de acordo com a análise de seu contexto, responda APENAS com o `id` da classe só se você tiver muita certeza e não explique o motivo. Na ausência, falta de informações ou caso a frase do usuário não se enquadre em nenhuma classe, classifique como \"-1\".", | ||
"classes_title": "Essas são as Classes com seus Id e Contexto:" | ||
}, | ||
"eng": { | ||
"context_description": "You are very expert in classifying the user sentence in a chatbot about:", | ||
"reflection": "Stop, think carefully, and respond with ONLY ONE SINGLE `id` of the class that best represents the intention for the user's sentence according to the analysis of its context, respond ONLY with the `id` of the class if you are very sure and do not explain the reason. In the absence, lack of information, or if the user's sentence does not fit into any class, classify as \"-1\".", | ||
"classes_title": "These are the Classes and its Context:" | ||
}, | ||
"spa": { | ||
"context_description": "Eres muy experto en clasificar la frase del usuario en un chatbot sobre:", | ||
"reflection": "Deténgase, piense bien y responda con SOLO UN ÚNICO `id` de la clase que mejor represente la intención para la frase del usuario de acuerdo con el análisis de su contexto, responda SOLO con el `id` de la clase si está muy seguro y no explique el motivo. En ausencia, falta de información o en caso de que la frase del usuario no se ajuste a ninguna clase, clasifique como \"-1\".", | ||
"classes_title": "Estas son las Clases con sus Id y Contexto:" | ||
} | ||
"system_prompt": "Task: Classify the 'User' message within a chatbot about: {context}. Carefully consider the context and respond with ONLY ONE tag of the class that best represents the intent of the 'User' message with the below categories.\n\n<BEGIN CONTENT CATEGORIES>\n{classes_formatted}\n<END CONTENT CATEGORIES>", | ||
"question": "{input}", | ||
} | ||
|
||
def generate_prompt(self, language: str, zeroshot_data: dict): | ||
translated_text = self.const_prompt_data[language] | ||
context = zeroshot_data.get("context") | ||
input = zeroshot_data.get("text") | ||
all_classes = self.setup_ids_on_classes(zeroshot_data.get("options")) | ||
classes_formatted = self.format_classes(all_classes) | ||
|
||
prompt = BASE_PROMPT.format(context_description=translated_text.get("context_description"), | ||
reflection=translated_text.get("reflection"), | ||
classes_title=translated_text.get("classes_title"), | ||
context=context, | ||
all_classes=all_classes, | ||
input=input) | ||
print(f"prompt: {prompt}") | ||
system_prompt = self.const_prompt_data["system_prompt"].format(context=context, classes_formatted=classes_formatted) | ||
question = self.const_prompt_data["question"].format(input=input) | ||
|
||
prompt = BASE_PROMPT.format(system_prompt=system_prompt, input=question) | ||
return prompt | ||
|
||
def setup_ids_on_classes(self, all_classes): | ||
for index, class_obj in enumerate(all_classes): | ||
id = index + 1 | ||
class_obj["id"] = id | ||
|
||
return all_classes | ||
|
||
def format_classes(self, all_classes): | ||
classes_formatted = '\n'.join([f"A{mclass['id']}: {mclass['class']} - {mclass['context']}" for index, mclass in enumerate(all_classes)]) | ||
classes_formatted += f"\nA{len(all_classes)+1}: none - if there is insufficient information or if the User message doesn't fit any class" | ||
return classes_formatted | ||
|
||
def get_default_language(self): | ||
return "por" | ||
return "por" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
import json | ||
import requests | ||
import boto3 | ||
|
||
from django.conf import settings | ||
from .format_classification import FormatClassification | ||
from .format_prompt import FormatPrompt | ||
|
||
|
||
class InvokeModel: | ||
|
||
def __init__(self, zeroshot_data): | ||
self.model_backend = settings.ZEROSHOT_MODEL_BACKEND | ||
self.zeroshot_data = zeroshot_data | ||
|
||
def invoke(self): | ||
prompt = self._get_prompt(self.zeroshot_data) | ||
|
||
if self.model_backend == "runpod": | ||
return self._invoke_runpod(prompt) | ||
elif self.model_backend == "bedrock": | ||
return self._invoke_bedrock(prompt) | ||
else: | ||
raise ValueError(f"Unsupported model backend: {self.model_backend}") | ||
|
||
def _get_prompt(self, zeroshot_data): | ||
prompt_formatter = FormatPrompt() | ||
|
||
language = zeroshot_data.get("language", prompt_formatter.get_default_language()) | ||
return prompt_formatter.generate_prompt(language, zeroshot_data) | ||
|
||
def _invoke_runpod(self, prompt): | ||
payload = json.dumps({ | ||
"input": { | ||
"prompt": prompt, | ||
"sampling_params": { | ||
"max_tokens": settings.ZEROSHOT_MAX_TOKENS, | ||
"n": settings.ZEROSHOT_N, | ||
"top_p": settings.ZEROSHOT_TOP_P, | ||
"top_k": settings.ZEROSHOT_TOP_K, | ||
"temperature": settings.ZEROSHOT_TEMPERATURE, | ||
"stop": settings.ZEROSHOT_STOP | ||
} | ||
|
||
} | ||
}) | ||
|
||
headers = { | ||
"Content-Type": "application/json; charset: utf-8", | ||
"Authorization": f"Bearer {settings.ZEROSHOT_TOKEN}", | ||
} | ||
response_nlp = None | ||
response = {"output": {}} | ||
|
||
url = settings.ZEROSHOT_BASE_NLP_URL | ||
if len(settings.ZEROSHOT_SUFFIX) > 0: | ||
url += settings.ZEROSHOT_SUFFIX | ||
response_nlp = requests.post( | ||
headers=headers, | ||
url=url, | ||
data=payload | ||
) | ||
|
||
if response_nlp.status_code == 200: | ||
classification = response_nlp.json() | ||
classification_formatter = FormatClassification(classification) | ||
formatted_classification = classification_formatter.get_classification(self.zeroshot_data) | ||
|
||
response["output"] = formatted_classification | ||
|
||
return response | ||
|
||
def _invoke_bedrock(self, prompt): | ||
response = {"output": {}} | ||
|
||
session = boto3.Session( | ||
aws_access_key_id=settings.ZEROSHOT_BEDROCK_AWS_KEY, | ||
aws_secret_access_key=settings.ZEROSHOT_BEDROCK_AWS_SECRET, | ||
region_name=settings.ZEROSHOT_BEDROCK_AWS_REGION | ||
) | ||
|
||
bedrock_runtime = session.client('bedrock-runtime') | ||
payload = json.dumps({ | ||
"max_tokens": settings.ZEROSHOT_MAX_TOKENS, | ||
"top_p": settings.ZEROSHOT_TOP_P, | ||
"top_k": settings.ZEROSHOT_TOP_K, | ||
"stop": settings.ZEROSHOT_STOP, | ||
"temperature": settings.ZEROSHOT_TEMPERATURE, | ||
"prompt": prompt | ||
}) | ||
|
||
bedrock_response = bedrock_runtime.invoke_model( | ||
body=payload, | ||
contentType='application/json', | ||
accept='application/json', | ||
modelId=settings.ZEROSHOT_BEDROCK_MODEL_ID, | ||
trace='ENABLED' | ||
) | ||
|
||
classification = json.loads(bedrock_response['body'].read().decode('utf-8')) | ||
|
||
classification_formatter = FormatClassification(classification) | ||
formatted_classification = classification_formatter.get_classification(self.zeroshot_data) | ||
|
||
response["output"] = formatted_classification | ||
return response | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.