| import logging |
| from typing import Any |
|
|
| from openai import Stream |
|
|
| from rag_utils.rag_utils import calc_n_tokens |
|
|
| from .setup_load import OpenAI |
|
|
| |
|
|
| logger = logging.getLogger() |
|
|
| SYSTEM_PROMPT = """ |
| You are an AI assistant that helps answer questions by searching through video transcripts. |
| I have retrieved the transcripts most likely to answer the user's question. |
| Carefully read through the transcripts to find information that helps answer the question. |
| Be brief - your response should not be more than two paragraphs. |
| Only use information directly stated in the provided transcripts to answer the question. |
| Do not add any information or make any claims that are not explicitly supported by the transcripts. |
| If the transcripts do not contain enough information to answer the question, state that you do not have enough information to provide a complete answer. |
| Format the response clearly. If only one of the transcripts answers the question, don't reference the other and don't explain why its content is irrelevant. |
| Do not speak in the first person. DO NOT write a letter, make an introduction, or salutation. |
| Reference the speaker's name when you say what they said. |
| """ |
|
|
|
|
| def set_messages(system_prompt: str, user_prompt: str) -> tuple[list[dict[str, str]], int]: |
| """ |
| Set the messages for the chat completion. |
| |
| Args: |
| system_prompt (str): The system prompt. |
| user_prompt (str): The user prompt. |
| |
| Returns: |
| tuple[list[dict[str, str]], int]: A tuple containing the messages and the total number of input tokens. |
| """ |
| messages1 = [ |
| {"role": "system", "content": system_prompt}, |
| {"role": "user", "content": user_prompt}, |
| ] |
| n_system_tokens = calc_n_tokens(system_prompt) |
| n_user_tokens = calc_n_tokens(user_prompt) |
| n_input_tokens = n_system_tokens + n_user_tokens |
| logger.info( |
| f"System Prompt is {n_system_tokens} tokens, User Prompt is {n_user_tokens} tokens" |
| ) |
| return messages1, n_input_tokens |
|
|
|
|
| def make_user_prompt(question: str, keep_texts: list[dict[str, Any]]) -> str: |
| """ |
| Create the user prompt based on the question and the retrieved transcripts. |
| |
| Args: |
| question (str): The user's question. |
| keep_texts (dict[str, dict[str, str]]): The retrieved transcripts. |
| |
| Returns: |
| str: The user prompt. |
| """ |
| user_prompt = f""" |
| Question: {question} |
| ============================== |
| """ |
| if len(keep_texts) > 0: |
| list_strs = [] |
| for i, tx_val in enumerate(keep_texts): |
| text0 = tx_val["text"] |
| speaker_name = tx_val["Speaker"] |
| list_strs.append(f"Video Transcript {i+1}\nSpeaker: {speaker_name}\n{text0}") |
| user_prompt += "\n-------\n".join(list_strs) |
| user_prompt += """ |
| ============================== |
| After analyzing the above video transcripts, please provide a helpful answer to my question. Remember to stay within two paragraphs |
| Address the response to me directly. Do not use any information not explicitly supported by the transcripts. Remember to reference the speaker's name.""" |
| else: |
| |
| user_prompt += "No relevant video transcripts were found. Please just return a result that says something like 'I'm sorry, but the answer to {Question} was not found in the transcripts from the R/Gov Conference'" |
| |
| return user_prompt |
|
|
|
|
| |
| |
|
|
|
|
| |
| def do_1_query(messages1: list[dict[str, str]], gen_client: OpenAI, stream: bool = False): |
| """ |
| Generate a response using the specified chat completion model. |
| |
| Args: |
| messages1 (list[dict[str, str]]): The messages for the chat completion. |
| gen_client (OpenAI): The generation client (OpenAI). |
| |
| Returns: |
| Stream: The generated response stream. |
| """ |
|
|
| model1 = "gpt-4o" |
|
|
| |
| response1 = gen_client.chat.completions.create( |
| messages=messages1, model=model1, seed=18, temperature=0, stream=stream |
| ) |
|
|
| return response1 |
|
|
|
|
| def text_from_response_static(response1) -> str: |
| return response1.choices[0].message.content |
|
|
|
|
| def text_from_response_stream(response1: Stream): |
| for chunk in response1: |
| content = chunk.choices[0].delta.content |
| if content is not None: |
| yield content |
|
|
|
|
| def do_generation( |
| query1: str, keep_texts: list[dict[str, Any]], gen_client: OpenAI, stream: bool = False |
| ): |
| """ |
| Generate the chatbot response using the specified generation client. |
| |
| Args: |
| query1 (str): The user's query. |
| keep_texts (dict[str, dict[str, str]]): The retrieved relevant texts. |
| gen_client (OpenAI): The generation client (OpenAI). |
| |
| Returns: |
| tuple[Stream, int]: A tuple containing the generated response stream and the number of prompt tokens. |
| """ |
| user_prompt = make_user_prompt(query1, keep_texts=keep_texts) |
| messages1, prompt_tokens = set_messages(SYSTEM_PROMPT, user_prompt) |
| response = do_1_query(messages1, gen_client, stream=stream) |
|
|
| if stream: |
| response1 = text_from_response_stream(response1=response) |
| else: |
| response1 = text_from_response_static(response1=response) |
|
|
| return response1, prompt_tokens |
|
|