Spaces:
Sleeping
Sleeping
| from config import * | |
| def make_request(user_input:str, | |
| short_history:list, | |
| chat_history:list): | |
| """Makes a request to the Hugging Face API""" | |
| client = InferenceClient( | |
| MODEL_PATH, | |
| token=HUGGING_FACE_API_KEY, | |
| ) | |
| try: | |
| response = client.chat_completion( | |
| messages=short_history, | |
| max_tokens = 5000, | |
| stream = False, | |
| ) | |
| # get the response | |
| message = response.choices[0].message['content'] | |
| # analyse the content to see if there is an action to perform | |
| try: | |
| perform_actions = look_for_actions(user_input, message) | |
| except Exception as e: | |
| st.info(f"An error occurred while looking for actions: {e}") | |
| perform_actions = (False, None) | |
| # if there was an action to perform, resubmit the question to the chatbot: | |
| if perform_actions[0]: | |
| # replace the last message in the short history with the new message | |
| short_history[-1] = {'role':'user', 'content':perform_actions[1]} | |
| # replace the first message with the system prompt without url analysis | |
| short_history[0] = {'role':'system', 'content':SYSTEM_PROMPT_NO_URL} | |
| # wait a little bit to avoid the API limit | |
| time.sleep(1) | |
| # make the request again | |
| response = client.chat_completion( | |
| messages=short_history, | |
| max_tokens = 5000, | |
| stream = False, | |
| ) | |
| # append to the history | |
| chat_history.append({'content':user_input, 'role':'user'}) | |
| chat_history.append(response.choices[0].message) # append the response | |
| return chat_history | |
| except Exception as e: | |
| st.error(f"An error occurred: {e}") | |
| st.stop() | |
| def get_site_content(url:str): | |
| """Receives a URL and returns the content of the site""" | |
| # create an user agent | |
| headers = { | |
| 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3' | |
| } | |
| # get the site content | |
| response = requests.get(url, headers=headers) | |
| soup = BeautifulSoup(response.text, 'html.parser') | |
| # remove styles and scripts | |
| for script in soup(["script", "style"]): | |
| script.extract() | |
| # let the meta descriptions of the header and all the content inside the body | |
| # for the meta tags, get the tag itself and its content | |
| meta_tags = soup.head.find_all('meta') | |
| meta_tags_text = '' | |
| for tag in meta_tags: | |
| meta_tags_text += f'<{tag.name} {tag.attrs}>\n' | |
| # get the body text | |
| body_text = soup.body.get_text() | |
| # join the meta tags and the body text | |
| text = f'{meta_tags_text}\n{body_text}' | |
| # remove empty lines | |
| text = os.linesep.join([s for s in text.splitlines() if s]) | |
| return text | |
| def look_for_actions(user_input:str, message:str): | |
| """Reveives a message and look for the pattern ###ACTION###function###URL###""" | |
| # check if the pattern is in the message. | |
| if '###' in message: | |
| # split the message by the pattern ###ACTION###function###URL### to get the URL and the action | |
| split_string = message.split('###') | |
| if 'getSiteContent' in message: | |
| st.info("I need to visit the site to provide the answer. Please wait...") | |
| url = split_string[3].strip() | |
| # remove everything inside ### and ### (including the ###) from the user_input | |
| user_input = re.sub(r'###.*?###', '', user_input) | |
| # add the content of the website to the message | |
| url_content = f'{user_input}. Content of the site {url}:\n{get_site_content(url)}' | |
| # check if the url_content is too long. If soo, keep trimming the text until it is not too long | |
| while get_token_amount(url_content) > 5000: | |
| url_content = url_content[:-100] | |
| return (True, url_content) | |
| # if there is no action to perform, return None | |
| return (False, None) | |
| def get_token_amount(text, | |
| model_name="gpt-4") -> int: | |
| """Uses the tiktoken library to check if a text is too long for a given model. | |
| Even tough we are using a Llama model, we are using the GPT-4 model ans an approximation. | |
| Args: | |
| text (str): The text to check. | |
| model_name (str): The name of the model to check. Defaults to "gpt-4". | |
| Returns: | |
| int: The number of tokens in the text. | |
| """ | |
| encoding = tiktoken.encoding_for_model(model_name) | |
| tokens = encoding.encode(text) | |
| return len(tokens) | |