TrancheVest commited on
Commit
a2df663
·
1 Parent(s): 3463beb

Fix error handling and improve crypto data retrieval

Browse files
Files changed (2) hide show
  1. app.py +51 -165
  2. utils.py +107 -212
app.py CHANGED
@@ -6,179 +6,65 @@ from utils import (
6
  evaluate_expertise,
7
  get_crypto_data,
8
  )
9
- import random
10
 
11
 
12
  def run_chat(crypto, data_span):
13
- # This non-generator wrapper is needed to avoid Gradio issues
14
- def _run_chat_gen(crypto, data_span):
15
- # Validate inputs
16
- valid_cryptos = ["btc", "eth", "virtual", "bnb"]
17
- valid_spans = ["24h", "7d", "14d", "30d", "60d"]
18
- if crypto not in valid_cryptos or data_span not in valid_spans:
19
- yield [("🤖", "❌ Invalid crypto or data span selection")], []
20
- return
21
-
22
- try:
23
- crypto_data = get_crypto_data(crypto, data_span)
24
- chat_history = []
25
- previous_qa = ""
26
- qa_history = []
27
-
28
- # Add an initial bot message to confirm it's working
29
- chat_history.append(("Starting analysis for " + crypto + " over " + data_span + " timeframe...", ""))
30
- yield chat_history, []
31
- time.sleep(1)
32
-
33
- for i in range(5):
34
- # --- QUESTION ---
35
- question = get_question(previous_qa)
36
- # append as a right-only message
37
- chat_history.append(("", question.content))
38
- yield chat_history, [] # show question
39
- time.sleep(1)
40
-
41
- # --- ANSWER ---
42
- answer = get_answer(question.content, previous_qa, crypto_data)
43
- # append as a left-only message
44
- chat_history.append((answer.content, ""))
45
- yield chat_history, [] # show answer
46
-
47
- # track for final evaluation
48
- qa_history.append({"question": question.content, "answer": answer.content})
49
- previous_qa += f"\nQ: {question.content}\nA: {answer.content}\n"
50
- time.sleep(1)
51
-
52
- # --- FINAL EVALUATION ---
53
- evaluation = evaluate_expertise(qa_history)
54
- chat_history.append(("📊 Evaluation:\n" + evaluation.content, ""))
55
- yield chat_history, chat_history
56
-
57
- except Exception as e:
58
- import traceback
59
- error_msg = f"Error: {str(e)}\n{traceback.format_exc()}"
60
- chat_history = [("⚠️ An error occurred during the analysis: " + str(e), "")]
61
- yield chat_history, []
62
-
63
- # Return the generator itself - this is the key fix
64
- return _run_chat_gen(crypto, data_span)
65
-
66
-
67
- # Use a standard theme that's compatible with all Gradio versions
68
- custom_css = """
69
- .gradio-container {
70
- background: linear-gradient(to bottom right, rgba(80, 80, 255, 0.05), rgba(0, 170, 170, 0.05));
71
- font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
72
- }
73
- .gr-button-primary {
74
- background-color: #6366f1 !important;
75
- color: white !important;
76
- }
77
- .gr-box {
78
- border-radius: 10px !important;
79
- box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1) !important;
80
- }
81
- """
82
-
83
- # Create emoji indicators for cryptocurrencies
84
- crypto_emojis = {
85
- "btc": "₿ Bitcoin",
86
- "eth": "Ξ Ethereum",
87
- "virtual": "🔮 Virtual",
88
- "bnb": "🪙 BNB"
89
- }
90
-
91
- # Create time span emojis
92
- time_emojis = {
93
- "24h": "⏰ 24 Hours",
94
- "7d": "📅 7 Days",
95
- "14d": "🗓️ 14 Days",
96
- "30d": "📆 30 Days",
97
- "60d": "📈 60 Days"
98
- }
99
-
100
- with gr.Blocks(css=custom_css) as demo:
101
- with gr.Box(css="padding: 20px; border-radius: 10px; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);"):
102
- gr.Markdown(
103
- """
104
- # 🧠 TranchVest AI - Crypto Risk Assessment
105
- ### Analyze cryptocurrency behavior with AI-powered insights
106
- """
107
  )
108
-
109
- with gr.Row(equal_height=True):
110
- with gr.Column(scale=1):
111
- gr.Markdown("### 🚀 Configuration")
112
- with gr.Box(css="padding: 15px; border-radius: 8px; background: rgba(0, 0, 0, 0.03);"):
113
- crypto_dropdown = gr.Dropdown(
114
- list(crypto_emojis.values()),
115
- label="Select Cryptocurrency",
116
- value="₿ Bitcoin",
117
- container=True,
118
- interactive=True
119
- )
120
- span_dropdown = gr.Dropdown(
121
- list(time_emojis.values()),
122
- label="Select Time Frame",
123
- value="📅 7 Days",
124
- container=True,
125
- interactive=True
126
- )
127
- start_btn = gr.Button(
128
- "🔍 Start Analysis",
129
- variant="primary",
130
- size="lg"
131
- )
132
-
133
- with gr.Column(scale=2):
134
- chatbot = gr.Chatbot(
135
- height=600,
136
- bubble_full_width=False,
137
- show_copy_button=True,
138
- avatar_images=("https://em-content.zobj.net/source/microsoft-teams/363/robot_1f916.png", None),
139
- css="border-radius: 12px; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);"
140
- )
141
-
142
- # Tips and information section
143
- with gr.Accordion("ℹ️ About This Tool", open=False):
144
- gr.Markdown(
145
- """
146
- ### How to use this tool:
147
- 1. **Select a cryptocurrency** from the dropdown menu
148
- 2. **Choose a time frame** for analysis
149
- 3. **Click 'Start Analysis'** to begin the AI-driven assessment
150
- 4. The AI will ask a series of questions about risk factors
151
- 5. At the end, you'll receive a comprehensive risk evaluation
152
-
153
- This tool helps evaluate investment risk factors for different cryptocurrencies based on market behavior and trends.
154
- """
155
  )
156
-
157
- # Add hidden state
 
158
  state = gr.State([])
159
 
160
- # Process the input values from the dropdowns to match the expected format in run_chat
161
- def preprocess_input(crypto, span):
162
- # Extract the crypto code from the dropdown display value
163
- crypto_code = next((code for code, display in crypto_emojis.items() if display == crypto), "btc")
164
- # Extract the span code from the dropdown display value
165
- span_code = next((code for code, display in time_emojis.items() if display == span), "7d")
166
- return crypto_code, span_code
167
-
168
- # Connect the button click - with proper function pipeline
169
- def process_and_run(crypto_display, span_display):
170
- # First preprocess the display values to get the codes
171
- crypto_code, span_code = preprocess_input(crypto_display, span_display)
172
- # Then run the chat with those codes and return the generator directly
173
- # This is the key fix - we're directly returning the generator
174
- return run_chat(crypto_code, span_code)
175
-
176
  start_btn.click(
177
- fn=process_and_run, # Use named parameter for clarity
178
- inputs=[crypto_dropdown, span_dropdown],
179
- outputs=[chatbot, state],
180
- api_name="start_analysis", # Add API name for better traceability
181
- show_progress="minimal" # Add a progress indicator while processing
182
  )
183
 
184
  demo.launch()
 
6
  evaluate_expertise,
7
  get_crypto_data,
8
  )
 
9
 
10
 
11
  def run_chat(crypto, data_span):
12
+ # Validate inputs
13
+ valid_cryptos = ["btc", "eth", "virtual", "bnb"]
14
+ valid_spans = ["24h", "7d", "14d", "30d", "60d"]
15
+ if crypto not in valid_cryptos or data_span not in valid_spans:
16
+ yield [("🤖", "❌ Invalid crypto or data span selection")], []
17
+ return
18
+
19
+ crypto_data = get_crypto_data(crypto, data_span)
20
+ chat_history = []
21
+ previous_qa = ""
22
+ qa_history = []
23
+
24
+ for _ in range(5):
25
+ # --- QUESTION ---
26
+ question = get_question(previous_qa)
27
+ # append as a right-only message
28
+ chat_history.append(("", question.content))
29
+ yield chat_history, [] # show question
30
+ time.sleep(1)
31
+
32
+ # --- ANSWER ---
33
+ answer = get_answer(question.content, previous_qa, crypto_data)
34
+ # append as a left-only message
35
+ chat_history.append((answer.content, ""))
36
+ yield chat_history, [] # show answer
37
+
38
+ # track for final evaluation
39
+ qa_history.append({"question": question.content, "answer": answer.content})
40
+ previous_qa += f"\nQ: {question.content}\nA: {answer.content}\n"
41
+ time.sleep(1)
42
+
43
+ # --- FINAL EVALUATION ---
44
+ evaluation = evaluate_expertise(qa_history)
45
+ chat_history.append(("📊 Evaluation:", evaluation.content))
46
+ yield chat_history, chat_history
47
+
48
+
49
+ with gr.Blocks() as demo:
50
+ gr.Markdown("## 🧠 TranchVest AI - Crypto Behavior Analysis")
51
+
52
+ with gr.Row():
53
+ crypto_dropdown = gr.Dropdown(
54
+ ["btc", "eth", "virtual", "bnb"], label="Select Crypto"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55
  )
56
+ span_dropdown = gr.Dropdown(
57
+ ["24h", "7d", "14d", "30d", "60d"], label="Select Data Span"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
58
  )
59
+ start_btn = gr.Button("Start Chat")
60
+
61
+ chatbot = gr.Chatbot(height=600)
62
  state = gr.State([])
63
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
  start_btn.click(
65
+ run_chat,
66
+ [crypto_dropdown, span_dropdown],
67
+ [chatbot, state],
 
 
68
  )
69
 
70
  demo.launch()
utils.py CHANGED
@@ -1,63 +1,35 @@
1
  import os
2
  from dotenv import load_dotenv
 
3
  import time
4
  import requests
5
- import logging
6
- import traceback
7
 
8
- # Configure logging
9
- logging.basicConfig(level=logging.INFO)
10
- logger = logging.getLogger(__name__)
11
-
12
- # Create a simple class to mimic LLM response format
13
- class MockResponse:
14
- def __init__(self, content):
15
- self.content = content
16
-
17
- # Load environment variables
18
  load_dotenv()
19
 
20
- # Get AWS credentials from environment
21
  AWS_REGION = os.getenv("AWS_REGION")
22
  AWS_ACCESS_KEY_ID = os.getenv("AWS_ACCESS_KEY_ID")
23
  AWS_SECRET_ACCESS_KEY = os.getenv("AWS_SECRET_ACCESS_KEY")
24
  AWS_CHAT_MODEL_ID = os.getenv("AWS_CHAT_MODEL_ID")
25
 
26
- # Set up LLM with proper error handling
27
- try:
28
- # Only import and configure if credentials are available
29
- if all([AWS_REGION, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_CHAT_MODEL_ID]):
30
- # Configure AWS credentials
31
- os.environ["AWS_ACCESS_KEY_ID"] = AWS_ACCESS_KEY_ID
32
- os.environ["AWS_SECRET_ACCESS_KEY"] = AWS_SECRET_ACCESS_KEY
33
- os.environ["AWS_DEFAULT_REGION"] = AWS_REGION
34
-
35
- from langchain_aws import ChatBedrock
36
-
37
- llm_questioner = ChatBedrock(
38
- model_id=AWS_CHAT_MODEL_ID,
39
- temperature=0.5,
40
- )
41
-
42
- llm_answerer = ChatBedrock(
43
- model_id=AWS_CHAT_MODEL_ID,
44
- temperature=0.5,
45
- )
46
-
47
- llm_evaluator = ChatBedrock(
48
- model_id=AWS_CHAT_MODEL_ID,
49
- temperature=0.5,
50
- )
51
-
52
- logger.info("Successfully initialized AWS Bedrock LLMs")
53
- USE_MOCK_RESPONSES = False
54
- else:
55
- logger.warning("Missing AWS credentials, using mock responses")
56
- USE_MOCK_RESPONSES = True
57
- except Exception as e:
58
- logger.error(f"Error initializing AWS Bedrock: {str(e)}")
59
- logger.error(traceback.format_exc())
60
- USE_MOCK_RESPONSES = True
61
 
62
  crypto_token = {
63
  "btc": "bitcoin",
@@ -72,182 +44,105 @@ crypto_token = {
72
 
73
 
74
  def get_crypto_data(crypto_name, data_span):
75
- try:
76
- # Default mock data in case of errors
77
- mock_data = f"""
78
- Crypto Name: {crypto_name}
79
- Data TimeSpan: {data_span}
80
- Twitter up votes: 65.8
81
- Twitter down votes: 34.2
82
- Value change: 3.25
83
- Value change in currency: 3.25
84
- """
85
-
86
- if crypto_name not in crypto_token:
87
- logger.warning(f"Invalid crypto name: {crypto_name}, using mock data")
88
- return mock_data
89
-
90
- try:
91
- crypto_token_name = crypto_token[crypto_name]
92
- r = requests.get(
93
- f"https://api.coingecko.com/api/v3/coins/{crypto_token_name}?localization=false",
94
- timeout=10 # Add timeout to prevent hanging requests
95
- )
96
-
97
- if r.status_code != 200:
98
- logger.warning(f"API request failed with status code {r.status_code}, using mock data")
99
- return mock_data
100
-
101
- data = r.json()
102
-
103
- # Safely extract data with fallbacks
104
- tw_up_votes = data.get("sentiment_votes_up_percentage", 65.8)
105
- tw_down_votes = data.get("sentiment_votes_down_percentage", 34.2)
106
-
107
- market_data = data.get("market_data", {})
108
-
109
- # Handle different data span formats safely
110
- price_change_key = f"price_change_percentage_{data_span}"
111
- value_change = market_data.get(price_change_key, 3.25)
112
-
113
- price_change_currency_key = f"price_change_percentage_{data_span}_in_currency"
114
- currency_data = market_data.get(price_change_currency_key, {})
115
- value_change_in_currency = currency_data.get("usd", 3.25)
116
-
117
- return f"""
118
- Crypto Name: {crypto_token_name}
119
- Data TimeSpan: {data_span}
120
- Twitter up votes: {tw_up_votes}
121
- Twitter down votes: {tw_down_votes}
122
- Value change: {value_change}
123
- Value change in currency: {value_change_in_currency}
124
- """
125
-
126
- except requests.exceptions.RequestException as e:
127
- logger.error(f"Request error: {str(e)}")
128
- return mock_data
129
-
130
- except Exception as e:
131
- logger.error(f"Error in get_crypto_data: {str(e)}")
132
- logger.error(traceback.format_exc())
133
- return f"""
134
- Crypto Name: {crypto_name}
135
- Data TimeSpan: {data_span}
136
- Twitter up votes: 65.8
137
- Twitter down votes: 34.2
138
- Value change: 3.25
139
- Value change in currency: 3.25
140
- """
141
 
142
 
143
  def get_question(previous_qa=""):
144
  """Generate a crypto question using the questioner LLM"""
145
- try:
146
- if USE_MOCK_RESPONSES:
147
- # Return a mock response for testing
148
- return MockResponse(content="What percentage of your investment portfolio would you allocate to cryptocurrencies?\n\nA) Less than 5%\nB) 5-15%\nC) 16-30%\nD) More than 30%")
149
-
150
- prompt = f"""
151
- You are a questioner and expert in the field of Cryptocurrency and Investments.
152
-
153
- # Instructions
154
- - Your task is to ask question to the user based on Cryptocurrency and Investments.
155
- - You need to ask multiple choice questions so that the user can select the correct answer.
156
- - Make sure the question is clear and the options are distinct.
157
- - Just generate the question and options, do not include any other text.
158
- - Your question will directly be given to the user, so make sure no starting or ending texts are added.
159
- - The reason of asking the question is to evaluate the user's risk profiling.
160
- - We need to build a risk profiling model based on the answers.
161
- - You need to generate a new multiple choice question for risk profiling.
162
-
163
- # Types of Questions
164
- - Risk Tolerance
165
- - Investment Goals
166
- - Time Horizon
167
- - Risk Appetite
168
- - Investment Sentiment
169
- - Details about previous investments
170
- - Percentage of investment in Cryptocurrency
171
-
172
- # previous questions with answers
173
- {previous_qa}
174
-
175
-
176
- """
177
- return llm_questioner.invoke(prompt)
178
-
179
- except Exception as e:
180
- logger.error(f"Error in get_question: {str(e)}")
181
- logger.error(traceback.format_exc())
182
- return MockResponse(content="What is your investment time horizon for cryptocurrency investments?\n\nA) Less than 1 year (short-term)\nB) 1-3 years (medium-term)\nC) 3-5 years (long-term)\nD) More than 5 years (very long-term)")
183
 
184
 
185
  def get_answer(question, previous_qa, crypto_data):
186
  """Generate an answer explanation using the answerer LLM"""
187
- try:
188
- if USE_MOCK_RESPONSES:
189
- # Return a mock response for testing
190
- return MockResponse(content="Based on the data provided for this cryptocurrency and market trends, I would select option B as the most appropriate answer.")
191
-
192
- prompt = f"""
193
- You are an expert in the field of Cryptocurrency and Investments.
194
-
195
- # Instructions
196
- - Your task is to answer the question based on Cryptocurrency and Investments.
197
- - The question will be the multiple choice question.
198
- - Just select the correct answer from the options.
199
- - Do not include any other text.
200
- - Your answer should be consistent with previous answers and build upon them.
201
- - Consider the user's previous responses to maintain a coherent risk profile.
202
-
203
- # Notes
204
- - You need to give answers by looking at the following crypto data
205
-
206
- # Crypto Data
207
- {crypto_data}
208
-
209
- # Previous Q&A History
210
- {previous_qa}
211
-
212
- # Current Question with options
213
- {question}
214
- """
215
- return llm_answerer.invoke(prompt)
216
-
217
- except Exception as e:
218
- logger.error(f"Error in get_answer: {str(e)}")
219
- logger.error(traceback.format_exc())
220
- return MockResponse(content="Based on the current market trends and volatility, option C appears to be the most balanced choice for this cryptocurrency.")
221
 
222
 
223
  def evaluate_expertise(qa_history):
224
  """Evaluate the user's crypto expertise level based on Q&A history"""
225
- try:
226
- if USE_MOCK_RESPONSES:
227
- # Return a mock response for testing
228
- return MockResponse(content="Risk Assessment Summary:\n\n1. Based on the responses, the investor demonstrates a moderate risk tolerance with a preference for balanced investment approaches.\n\n2. The time horizon indicated is medium-term, suggesting some patience for market cycles but not extremely long-term holding.\n\n3. The answers show familiarity with cryptocurrency market dynamics but not deep technical knowledge.\n\nTranche Recommendation: MEZZANINE\n\nThis middle-tier tranche is appropriate for investors who want some exposure to cryptocurrency growth potential while maintaining a reasonable risk profile.")
229
-
230
- prompt = f"""
231
- You are an expert evaluator in the field of Cryptocurrency and Investments.
232
-
233
- # Instructions
234
- - Analyze the following Q&A history to determine the user's risk profiling.
235
- - Consider the complexity of questions asked and the quality of answers provided
236
- - Include 2-3 specific observations about their risk profiling
237
- - Just generate the evaluation, do not include any other text.
238
- - You have to decide the tranche based on user's answer.
239
- - Tranche can be Senior, Mezzanine and Junior.
240
- - You need to give a final verdict based on the user's answer.
241
-
242
- # Q&A History
243
- {qa_history}
244
- """
245
- return llm_evaluator.invoke(prompt)
246
-
247
- except Exception as e:
248
- logger.error(f"Error in evaluate_expertise: {str(e)}")
249
- logger.error(traceback.format_exc())
250
- return MockResponse(content="Risk Assessment Summary:\n\n1. The investor shows a balanced approach to cryptocurrency investment, neither extremely conservative nor highly aggressive.\n\n2. There's an understanding of market volatility and a willingness to accept moderate risk for potential returns.\n\n3. Investment horizon appears to be medium to long-term, indicating patience with market fluctuations.\n\nTranche Recommendation: MEZZANINE\n\nThis investor fits well in the middle tranche, balancing potential growth with reasonable risk management.")
251
 
252
 
253
  def main():
 
1
  import os
2
  from dotenv import load_dotenv
3
+ from langchain_aws import ChatBedrock
4
  import time
5
  import requests
 
 
6
 
 
 
 
 
 
 
 
 
 
 
7
  load_dotenv()
8
 
 
9
  AWS_REGION = os.getenv("AWS_REGION")
10
  AWS_ACCESS_KEY_ID = os.getenv("AWS_ACCESS_KEY_ID")
11
  AWS_SECRET_ACCESS_KEY = os.getenv("AWS_SECRET_ACCESS_KEY")
12
  AWS_CHAT_MODEL_ID = os.getenv("AWS_CHAT_MODEL_ID")
13
 
14
+ # Configure AWS credentials
15
+ os.environ["AWS_ACCESS_KEY_ID"] = AWS_ACCESS_KEY_ID
16
+ os.environ["AWS_SECRET_ACCESS_KEY"] = AWS_SECRET_ACCESS_KEY
17
+ os.environ["AWS_DEFAULT_REGION"] = AWS_REGION
18
+
19
+ llm_questioner = ChatBedrock(
20
+ model_id=AWS_CHAT_MODEL_ID,
21
+ temperature=0.5,
22
+ )
23
+
24
+ llm_answerer = ChatBedrock(
25
+ model_id=AWS_CHAT_MODEL_ID,
26
+ temperature=0.5,
27
+ )
28
+
29
+ llm_evaluator = ChatBedrock(
30
+ model_id=AWS_CHAT_MODEL_ID,
31
+ temperature=0.5,
32
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
 
34
  crypto_token = {
35
  "btc": "bitcoin",
 
44
 
45
 
46
  def get_crypto_data(crypto_name, data_span):
47
+ crypto_name = crypto_token[crypto_name]
48
+ r = requests.get(
49
+ f"https://api.coingecko.com/api/v3/coins/{crypto_name}?localization=false"
50
+ )
51
+ data = r.json()
52
+ tw_up_votes = data["sentiment_votes_up_percentage"]
53
+ tw_down_votes = data["sentiment_votes_down_percentage"]
54
+ value_change = data["market_data"][f"price_change_percentage_{data_span}"]
55
+ value_change_in_currency = data["market_data"][
56
+ f"price_change_percentage_{data_span}_in_currency"
57
+ ]["usd"]
58
+ return f"""
59
+ Crypto Name: {crypto_name}
60
+ Data TimeSpan: {data_span}
61
+ Twitter up votes: {tw_up_votes}
62
+ Twitter down votes: {tw_down_votes}
63
+ Value change: {value_change}
64
+ Value change in currency: {value_change_in_currency}
65
+ """
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
 
67
 
68
  def get_question(previous_qa=""):
69
  """Generate a crypto question using the questioner LLM"""
70
+ prompt = f"""
71
+ You are a questioner and expert in the field of Cryptocurrency and Investments.
72
+
73
+ # Instructions
74
+ - Your task is to ask question to the user based on Cryptocurrency and Investments.
75
+ - You need to ask multiple choice questions so that the user can select the correct answer.
76
+ - Make sure the question is clear and the options are distinct.
77
+ - Just generate the question and options, do not include any other text.
78
+ - Your question will directly be given to the user, so make sure no starting or ending texts are added.
79
+ - The reason of asking the question is to evaluate the user's risk profiling.
80
+ - We need to build a risk profiling model based on the answers.
81
+ - You need to generate a new multiple choice question for risk profiling.
82
+
83
+ # Types of Questions
84
+ - Risk Tolerance
85
+ - Investment Goals
86
+ - Time Horizon
87
+ - Risk Appetite
88
+ - Investment Sentiment
89
+ - Details about previous investments
90
+ - Percentage of investment in Cryptocurrency
91
+
92
+ # previous questions with answers
93
+ {previous_qa}
94
+
95
+
96
+ """
97
+ return llm_questioner.invoke(prompt)
 
 
 
 
 
 
 
 
 
 
98
 
99
 
100
  def get_answer(question, previous_qa, crypto_data):
101
  """Generate an answer explanation using the answerer LLM"""
102
+ prompt = f"""
103
+ You are an expert in the field of Cryptocurrency and Investments.
104
+
105
+ # Instructions
106
+ - Your task is to answer the question based on Cryptocurrency and Investments.
107
+ - The question will be the multiple choice question.
108
+ - Just select the correct answer from the options.
109
+ - Do not include any other text.
110
+ - Your answer should be consistent with previous answers and build upon them.
111
+ - Consider the user's previous responses to maintain a coherent risk profile.
112
+
113
+ # Notes
114
+ - You need to give answers by looking at the following crypto data
115
+
116
+ # Crypto Data
117
+ {crypto_data}
118
+
119
+ # Previous Q&A History
120
+ {previous_qa}
121
+
122
+ # Current Question with options
123
+ {question}
124
+ """
125
+ return llm_answerer.invoke(prompt)
 
 
 
 
 
 
 
 
 
 
126
 
127
 
128
  def evaluate_expertise(qa_history):
129
  """Evaluate the user's crypto expertise level based on Q&A history"""
130
+ prompt = f"""
131
+ You are an expert evaluator in the field of Cryptocurrency and Investments.
132
+
133
+ # Instructions
134
+ - Analyze the following Q&A history to determine the user's risk profiling.
135
+ - Consider the complexity of questions asked and the quality of answers provided
136
+ - Include 2-3 specific observations about their risk profiling
137
+ - Just generate the evaluation, do not include any other text.
138
+ - You have to decide the tranche based on user's answer.
139
+ - Tranche can be Senior, Mezzanine and Junior.
140
+ - You need to give a final verdict based on the user's answer.
141
+
142
+ # Q&A History
143
+ {qa_history}
144
+ """
145
+ return llm_evaluator.invoke(prompt)
 
 
 
 
 
 
 
 
 
 
146
 
147
 
148
  def main():