File size: 11,507 Bytes
05c3fbf
c2d85b0
05c3fbf
 
 
 
c2d85b0
 
05c3fbf
 
 
 
 
 
 
 
 
 
 
 
fca837c
05c3fbf
 
 
fca837c
05c3fbf
 
 
 
 
 
4aa0489
 
 
 
 
 
 
 
 
 
 
 
05c3fbf
 
 
 
 
 
f63a79e
05c3fbf
f63a79e
 
 
 
 
 
 
 
 
 
 
 
 
fca837c
f63a79e
 
 
 
 
fa01583
f63a79e
05c3fbf
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c2d85b0
 
 
05c3fbf
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5ede06d
1adeb8a
05c3fbf
 
 
 
 
f63a79e
 
 
 
 
 
 
05c3fbf
 
 
a0d1332
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
05c3fbf
a0d1332
 
 
05c3fbf
 
 
a0d1332
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
05c3fbf
 
a0d1332
05c3fbf
 
a0d1332
1adeb8a
05c3fbf
 
 
a0d1332
05c3fbf
 
 
 
1adeb8a
05c3fbf
 
 
 
 
 
 
 
 
4aa0489
 
 
05c3fbf
 
 
732509d
 
 
 
 
 
 
 
05c3fbf
 
 
4aa0489
05c3fbf
 
 
a0d1332
05c3fbf
4aa0489
cffb259
05c3fbf
8035377
4aa0489
 
 
 
5ede06d
05c3fbf
5ede06d
 
 
 
05c3fbf
 
 
671279d
05c3fbf
5e14f74
05c3fbf
 
 
c692e62
05c3fbf
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
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
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()