File size: 9,368 Bytes
63d903a e977112 0b607fb e977112 3890ae0 e977112 2594602 e977112 81c84f4 64581a6 e977112 a7533b2 b4dffd4 4591c38 b4dffd4 84ed5b1 491e7e1 3890ae0 9b9a599 8b5e7fa e977112 3a4edb7 e977112 8b5e7fa 3a4edb7 e977112 0af92be 8df9cbb 8b5e7fa e977112 3a4edb7 8df9cbb ef10a65 8df9cbb 3a4edb7 e977112 491e7e1 0af92be e977112 aeb79bf 0af92be aeb79bf 19fbf72 aeb79bf 19fbf72 e977112 aeb79bf 19fbf72 8b5e7fa 3890ae0 e977112 8b5e7fa e977112 3890ae0 3436f48 993261b 8b5e7fa e977112 491e7e1 8df9cbb 491e7e1 8df9cbb 491e7e1 8df9cbb 491e7e1 e977112 bd71ef9 e977112 e1a8672 593de4e e977112 84ed5b1 593de4e 15f3dd6 491e7e1 0af92be 491e7e1 66a60a3 15f3dd6 5ac8c2c 15f3dd6 8b5e7fa e977112 b4dffd4 149b538 b4dffd4 d9bca78 2fd4939 aeb79bf 2fd4939 3a4edb7 c1f06dd 2fd4939 c6f42da 2fd4939 c6f42da 2fd4939 993261b e977112 197303a 204d06f 2fd4939 b4dffd4 2594602 480bd35 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 |
import os
import json
import re
import gradio as gr
import requests
from duckduckgo_search import DDGS
from typing import List
from pydantic import BaseModel, Field
from langchain_community.vectorstores import FAISS
from langchain_community.embeddings import HuggingFaceEmbeddings
from langchain_core.documents import Document
from huggingface_hub import InferenceClient
import logging
# Set up basic configuration for logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
# Environment variables and configurations
huggingface_token = os.environ.get("HUGGINGFACE_TOKEN")
MODELS = [
"mistralai/Mistral-7B-Instruct-v0.3",
"mistralai/Mixtral-8x7B-Instruct-v0.1",
"mistralai/Mistral-Nemo-Instruct-2407",
"meta-llama/Meta-Llama-3.1-8B-Instruct",
"meta-llama/Meta-Llama-3.1-70B-Instruct"
]
MODEL_TOKEN_LIMITS = {
"mistralai/Mistral-7B-Instruct-v0.3": 32768,
"mistralai/Mixtral-8x7B-Instruct-v0.1": 32768,
"mistralai/Mistral-Nemo-Instruct-2407": 32768,
"meta-llama/Meta-Llama-3.1-8B-Instruct": 8192,
"meta-llama/Meta-Llama-3.1-70B-Instruct": 8192,
}
DEFAULT_SYSTEM_PROMPT = """You are a world-class financial AI assistant, capable of complex reasoning and reflection.
Reason through the query inside <thinking> tags, and then provide your final response inside <output> tags.
Providing comprehensive and accurate information based on web search results is essential.
Your goal is to synthesize the given context into a coherent and detailed response that directly addresses the user's query.
Please ensure that your response is well-structured, factual."""
def get_embeddings():
return HuggingFaceEmbeddings(model_name="sentence-transformers/stsb-roberta-large")
def duckduckgo_search(query):
with DDGS() as ddgs:
results = ddgs.text(query, max_results=5)
return results
class CitingSources(BaseModel):
sources: List[str] = Field(
...,
description="List of sources to cite. Should be an URL of the source."
)
def chatbot_interface(message, system_prompt, history, model, temperature, num_calls, use_embeddings):
if not message.strip():
return "", history
history = history + [(message, "")]
try:
for response in respond(message, system_prompt, history, model, temperature, num_calls, use_embeddings):
history[-1] = (message, response)
yield history
except gr.CancelledError:
yield history
except Exception as e:
logging.error(f"Unexpected error in chatbot_interface: {str(e)}")
history[-1] = (message, f"An unexpected error occurred: {str(e)}")
yield history
def retry_last_response(system_prompt, history, model, temperature, num_calls, use_embeddings):
if not history:
return history
last_user_msg = history[-1][0]
history = history[:-1] # Remove the last response
return chatbot_interface(last_user_msg, system_prompt, history, model, temperature, num_calls, use_embeddings)
def respond(message, system_prompt, history, model, temperature, num_calls, use_embeddings):
logging.info(f"User Query: {message}")
logging.info(f"Model Used: {model}")
logging.info(f"Use Embeddings: {use_embeddings}")
logging.info(f"System Prompt: {system_prompt}")
try:
full_response = ""
for main_content, sources in get_response_with_search(message, model, num_calls=num_calls, temperature=temperature, use_embeddings=use_embeddings, system_prompt=system_prompt):
full_response += main_content
new_history = history + [(message, full_response)]
yield new_history
if sources:
full_response += f"\n\nSources:\n{sources}"
new_history = history + [(message, full_response)]
yield new_history
except Exception as e:
logging.error(f"Error with {model}: {str(e)}")
error_message = f"An error occurred with the {model} model: {str(e)}. Please try again or select a different model."
new_history = history + [(message, error_message)]
yield new_history
def create_web_search_vectors(search_results):
embed = get_embeddings()
documents = []
for result in search_results:
if 'body' in result:
content = f"{result['title']}\n{result['body']}\nSource: {result['href']}"
documents.append(Document(page_content=content, metadata={"source": result['href']}))
return FAISS.from_documents(documents, embed)
def get_response_with_search(query, model, system_prompt=DEFAULT_SYSTEM_PROMPT, num_calls=3, temperature=0.2, use_embeddings=True):
logging.info(f"get_response_with_search - Query: {query}")
logging.info(f"get_response_with_search - System Prompt: {system_prompt}")
search_results = duckduckgo_search(query)
if use_embeddings:
web_search_database = create_web_search_vectors(search_results)
if not web_search_database:
yield "No web search results available. Please try again.", ""
return
retriever = web_search_database.as_retriever(search_kwargs={"k": 5})
relevant_docs = retriever.get_relevant_documents(query)
context = "\n".join([doc.page_content for doc in relevant_docs])
else:
context = "\n".join([f"{result['title']}\n{result['body']}\nSource: {result['href']}" for result in search_results])
prompt = f"""Using the following context from web search results:
{context}
Write a detailed and complete research document that fulfills the following user request: '{query}'
After writing the document, please provide a list of sources used in your response."""
# Use Hugging Face API
client = InferenceClient(model, token=huggingface_token)
# Calculate input tokens (this is an approximation, you might need a more accurate method)
input_tokens = len(prompt.split())
# Get the token limit for the current model
model_token_limit = MODEL_TOKEN_LIMITS.get(model, 8192) # Default to 8192 if model not found
# Calculate max_new_tokens
max_new_tokens = min(model_token_limit - input_tokens, 4096) # Cap at 4096 to be safe
main_content = ""
for i in range(num_calls):
try:
response = client.chat_completion(
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": prompt}
],
max_tokens=max_new_tokens,
temperature=temperature,
stream=False,
top_p=0.8,
)
# Log the raw response for debugging
logging.info(f"Raw API response: {response}")
# Check if the response is a string (which might be an error message)
if isinstance(response, str):
logging.error(f"API returned an unexpected string response: {response}")
yield f"An error occurred: {response}", ""
return
# If it's not a string, assume it's the expected object structure
if hasattr(response, 'choices') and response.choices:
for choice in response.choices:
if hasattr(choice, 'message') and hasattr(choice.message, 'content'):
chunk = choice.message.content
main_content += chunk
yield main_content, "" # Yield partial main content without sources
else:
logging.error(f"Unexpected response structure: {response}")
yield "An unexpected error occurred. Please try again.", ""
except Exception as e:
logging.error(f"Error in API call: {str(e)}")
yield f"An error occurred: {str(e)}", ""
return
def vote(data: gr.LikeData):
if data.liked:
print(f"You upvoted this response: {data.value}")
else:
print(f"You downvoted this response: {data.value}")
css = """
/* Fine-tune chatbox size */
"""
demo = gr.ChatInterface(
fn=respond,
additional_inputs=[
gr.Textbox(label="System Prompt", lines=5, value=DEFAULT_SYSTEM_PROMPT),
gr.Dropdown(choices=MODELS, label="Select Model", value=MODELS[3]),
gr.Slider(minimum=0.1, maximum=1.0, value=0.2, step=0.1, label="Temperature"),
gr.Slider(minimum=1, maximum=5, value=1, step=1, label="Number of API Calls"),
gr.Checkbox(label="Use Embeddings", value=False),
],
title="AI-powered Web Search Assistant",
description="Ask questions and get answers from web search results.",
theme=gr.Theme.from_hub("allenai/gradio-theme"),
css=css,
examples=[
["What are the latest developments in artificial intelligence?"],
["Can you explain the basics of quantum computing?"],
["What are the current global economic trends?"]
],
cache_examples=False,
analytics_enabled=False,
textbox=gr.Textbox(placeholder="Ask a question", container=False, scale=7),
chatbot=gr.Chatbot(
show_copy_button=True,
likeable=True,
layout="bubble",
height=400
)
)
if __name__ == "__main__":
demo.launch(share=True) |