Spaces:
Sleeping
Sleeping
from sentence_transformers import SentenceTransformer | |
import gradio as gr | |
import os | |
import json | |
from bs4 import BeautifulSoup | |
import requests | |
from huggingface_hub import InferenceClient | |
from langchain.vectorstores import Chroma | |
# Required imports | |
from sentence_transformers import SentenceTransformer | |
from langchain.embeddings import HuggingFaceEmbeddings # Use Hugging Face wrapper for SentenceTransformers | |
from langchain.document_loaders import DirectoryLoader, TextLoader | |
from langchain.text_splitter import CharacterTextSplitter | |
from langchain.schema import Document | |
from langchain.vectorstores import Chroma | |
import numpy as np | |
from sklearn.manifold import TSNE | |
import plotly.graph_objects as go | |
from langchain_community.document_loaders import TextLoader | |
from langchain.text_splitter import CharacterTextSplitter | |
from langchain.schema import Document | |
import chromadb.utils.embedding_functions as embedding_functions | |
from langchain_community.embeddings import HuggingFaceEmbeddings | |
hf_token = os.getenv('HF_TOKEN') | |
huggingface_ef = embedding_functions.HuggingFaceEmbeddingFunction( | |
api_key=hf_token, | |
model_name="sentence-transformers/all-MiniLM-L6-v2" | |
) | |
#get their investor type | |
investor_type_value = "" | |
# Function to set the investor type | |
def set_investor_type(investor_type): | |
global investor_type_value | |
investor_type_value = investor_type | |
return f"Investor type set to: {investor_type}" | |
embedding_model = HuggingFaceEmbeddings(model_name='sentence-transformers/all-MiniLM-L6-v2') | |
# Define global variables | |
BOT_AVATAR = 'https://automatedstockmining.org/wp-content/uploads/2024/08/south-west-value-mining-logo.webp' | |
#for the search vector database | |
# Initialize Chroma vector store directory | |
db_name2 = "search_checkvector_db" | |
# Read in the text for processing | |
health_check_text = '' | |
with open('search_requirements.txt', 'r', encoding='utf-8') as search_text: | |
search_requirements_text = search_text.read() | |
# Split text into chunks | |
search_splitter = CharacterTextSplitter(chunk_size=20, chunk_overlap=2) | |
parts = search_splitter.split_text(search_requirements_text) | |
search_documents = [Document(page_content=chunk) for chunk in parts] | |
# Initialize Chroma with documents and embeddings | |
search_vectorstore = Chroma.from_documents( | |
documents=search_documents, | |
embedding=embedding_model, | |
persist_directory=db_name2 | |
) | |
# Initialize Chroma vector store directory | |
db_name = "health_checkvector_db" | |
# Read in the text for processing | |
health_check_text = '' | |
with open('healthcheck.txt', 'r', encoding='utf-8') as file: | |
health_check_text = file.read() | |
# Split text into chunks | |
text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=200) | |
chunks = text_splitter.split_text(health_check_text) | |
# Convert chunks into Document objects | |
documents = [Document(page_content=chunk) for chunk in chunks] | |
# Initialize Chroma with documents and embeddings | |
vectorstore = Chroma.from_documents( | |
documents=documents, | |
embedding=embedding_model, | |
persist_directory=db_name | |
) | |
client = InferenceClient(token=hf_token) | |
custom_css = ''' | |
.gradio-container { | |
font-family: 'Roboto', sans-serif; | |
} | |
.main-header { | |
text-align: center; | |
color: #4a4a4a; | |
margin-bottom: 2rem; | |
} | |
.tab-header { | |
font-size: 1.2rem; | |
font-weight: bold; | |
margin-bottom: 1rem; | |
} | |
.custom-chatbot { | |
border-radius: 10px; | |
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); | |
} | |
.custom-button { | |
background-color: #3498db; | |
color: white; | |
border: none; | |
padding: 10px 20px; | |
border-radius: 5px; | |
cursor: pointer; | |
transition: background-color 0.3s ease; | |
} | |
.custom-button:hover { | |
background-color: #2980b9; | |
} | |
''' | |
def extract_text_from_webpage(html): | |
soup = BeautifulSoup(html, "html.parser") | |
for script in soup(["script", "style"]): | |
script.decompose() | |
visible_text = soup.get_text(separator=" ", strip=True) | |
return visible_text | |
def search(query): | |
term = query | |
max_chars_per_page = 8000 | |
all_results = [] | |
with requests.Session() as session: | |
try: | |
resp = session.get( | |
url="https://www.google.com/search", | |
headers={"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0"}, | |
params={"q": term, "num": 7}, | |
timeout=5 | |
) | |
resp.raise_for_status() | |
soup = BeautifulSoup(resp.text, "html.parser") | |
result_block = soup.find_all("div", attrs={"class": "g"}) | |
for result in result_block: | |
link = result.find("a", href=True) | |
if link: | |
link = link["href"] | |
try: | |
webpage = session.get(link, headers={"User-Agent": "Mozilla/5.0"}, timeout=5) | |
webpage.raise_for_status() | |
visible_text = extract_text_from_webpage(webpage.text) | |
if len(visible_text) > max_chars_per_page: | |
visible_text = visible_text[:max_chars_per_page] | |
all_results.append({"link": link, "text": visible_text}) | |
except requests.exceptions.RequestException as e: | |
print(f"Failed to retrieve {link}: {e}") | |
all_results.append({"link": link, "text": None}) | |
except requests.exceptions.RequestException as e: | |
print(f"Google search failed: {e}") | |
return all_results | |
def process_query(user_input, history): | |
yield 'locating vectorstore 🛠️' | |
docs = vectorstore.similarity_search(user_input, k=5) | |
# Retrieve and concatenate results | |
retrieved_texts = " ".join([doc.page_content for doc in docs]) | |
#similarity search on searches | |
searches = search_vectorstore.similarity_search(user_input, k=3) | |
# Retrieve and concatenate results | |
search_texts = " ".join([doc.page_content for doc in searches]) | |
yield 'Preparing your request 🛠️' | |
# Step 1: Generate a search term based on the user query | |
messages = [ | |
{ | |
"role": "user", | |
"content": f"""Based on this chat history {history} the user's request '{user_input}', and this vector database {search_texts} - ignore it unless it relates to the user input, provide: | |
- The number of searches needed to answer the query | |
- The specific search terms required for each query, formatted as a Python object. | |
The response should follow this exact format (example shown): | |
{{ "number_of_searches_needed": 4, | |
"searches": ["First search term", "Second search term", "Third search term", "Fourth search term"] | |
}} | |
Return only the data in the specified format without additional text or explanation. | |
IMPORTANT: NEVER ASSUME THE DATE IN ANY OF YOUR SEARCHES UNLESS THE USER GIVES YOU ONE, YOU DONT KNOW WHAT THE DATE IS BECAUSE OF YOUR KNOWLEDGE CUTOFF. ONLY SEARCH FOR RELEVANT THINGS BASED ON THE USER REQUEST FOR EXAMPLE IF THEY ASK ABOUT STOCK PRICE ONL;Y SEARCH FOR STOCK PRICE | |
important: if the user input isnt complex use less searches in the intrest of time | |
""" | |
} | |
] | |
# Create streaming chat completion request | |
stream = client.chat.completions.create( | |
model="Qwen/Qwen2.5-72B-Instruct", | |
messages=messages, | |
max_tokens=500, | |
stream=False | |
) | |
#take the response from the model and convert it into a list of searches | |
returned = stream.choices[0].message.content | |
dictionary_returned = json.loads(returned) | |
searches_needed = dictionary_returned['searches'] | |
yield f'Searching the web for {searches_needed} 🌐' | |
completed_search = [] | |
for value in searches_needed: | |
print(f'searching for {value}') | |
var = search(value) | |
completed_search.append(json.dumps(var)) | |
# Format results as a JSON string for model input | |
yield 'thinking...' | |
# Step 3: Generate a response using the search results | |
response = client.chat_completion( | |
model="Qwen/Qwen2.5-72B-Instruct", | |
messages=[{"role": "user", "content": f"Using the search results: {completed_search} and chat history {history}, this vector database on health checks {retrieved_texts} answer the user's query '{user_input}' in an concise way, using numerical data if available, follow the instructions from the vector database if they apply. tailor it to them - {investor_type_value}"}], | |
max_tokens=3000, | |
stream=True | |
) | |
yield "Analyzing the data and getting ready to respond 📊" | |
# Stream final response | |
final_response = "" | |
for chunk in response: | |
content = chunk.choices[0].delta.content or '' | |
final_response += content | |
yield final_response | |
theme = gr.themes.Citrus( | |
primary_hue="indigo", | |
secondary_hue="indigo", | |
neutral_hue="zinc", | |
) | |
examples = [ | |
["whats the trending social sentiment like for Nvidia"], | |
["What's the latest news on Cisco Systems stock"], | |
["Analyze technical indicators for Adobe, are they presenting buy or sell signals"], | |
["Write me a smart sheet on the trending social sentiment and technical indicators for Nvidia"], | |
["What are the best stocks to buy this month"], | |
["What companies report earnings this week"], | |
["write me a health check on adobe"], | |
] | |
chatbot = gr.Chatbot( | |
label="IM.analyst", | |
avatar_images=[None, BOT_AVATAR], | |
show_copy_button=True, | |
layout="panel", | |
height=700 | |
) | |
with gr.Blocks(theme=theme) as demo: | |
with gr.Column(): | |
gr.Markdown("## quantineuron.com: IM.analyst - Building the Future of Investing") | |
investor_type_input = gr.Textbox(label="tell IM.analyst about how you invest", placeholder="Enter your investment style", interactive=True) | |
set_type_button = gr.Button("Set Investor Type") | |
set_type_button.click(set_investor_type, inputs=investor_type_input, outputs=None) | |
with gr.Column(scale=3, min_width=600): | |
chat_interface = gr.ChatInterface( | |
fn=process_query, | |
chatbot=chatbot, | |
examples=examples | |
) | |
with gr.Column(): | |
gr.Markdown(''' | |
**Disclaimer**: The information provided by IM.analyst is for educational and informational purposes only and does not constitute financial, investment, or professional advice. By using this service, you acknowledge and agree that all decisions you make based on the information provided are made at your own risk. Neither IM.analyst nor quantineuron.com is liable for any financial losses or damages resulting from reliance on information provided by this chatbot. | |
By using IM.analyst, you agree to be bound by quantineuron.com’s [Terms of Service](https://quantineuron.com/disclaimer-statement/), [Terms and Conditions](https://quantineuron.com/terms-and-conditions/), [Data Protection and Privacy Policy](https://quantineuron.com/data-protection-and-privacy-policy/), [our discalimer statement](https://quantineuron.com/disclaimer-statement/) and this Disclaimer Statement. We recommend reviewing these documents carefully. Your continued use of this service confirms your acceptance of these terms and conditions, and it is your responsibility to stay informed of any updates or changes. | |
**Important Note**: Investing in financial markets carries risk, and it is possible to lose some or all of the invested capital. Always consider seeking advice from a qualified financial advisor. | |
''') | |
demo.launch() |