Skip to content

Commit 69228d7

Browse files
committed
add debug option to recommend
1 parent be67606 commit 69228d7

3 files changed

Lines changed: 138 additions & 39 deletions

File tree

examples/financial_advisor/src/advisor/interactive.rs

Lines changed: 92 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ impl<'a> InteractiveSession<'a> {
102102
println!("{}", "Available commands:".yellow());
103103
println!(
104104
" {} - Get recommendation for a stock symbol",
105-
"recommend <SYMBOL> [notes]".cyan()
105+
"recommend <SYMBOL> [--debug] [notes]".cyan()
106106
);
107107
println!(" {} - Show client profile", "profile".cyan());
108108
println!(
@@ -149,17 +149,32 @@ impl<'a> InteractiveSession<'a> {
149149

150150
"recommend" | "r" => {
151151
if parts.len() < 2 {
152-
println!("{} Usage: recommend <SYMBOL> [notes]", "❓".yellow());
152+
println!(
153+
"{} Usage: recommend <SYMBOL> [--debug] [notes]",
154+
"❓".yellow()
155+
);
153156
return Ok(true);
154157
}
155158

156159
let symbol = parts[1].to_uppercase();
157-
let notes = if parts.len() > 2 {
158-
Some(parts[2..].join(" "))
160+
161+
// Check for debug flag and extract notes
162+
let mut debug_mode = false;
163+
let mut remaining_parts = &parts[2..];
164+
165+
if !remaining_parts.is_empty() && remaining_parts[0] == "--debug" {
166+
debug_mode = true;
167+
remaining_parts = &remaining_parts[1..];
168+
}
169+
170+
let notes = if !remaining_parts.is_empty() {
171+
Some(remaining_parts.join(" "))
159172
} else {
160173
None
161174
};
162-
self.handle_recommendation(&symbol, client, notes).await?;
175+
176+
self.handle_recommendation_with_debug(&symbol, client, notes, debug_mode)
177+
.await?;
163178
}
164179

165180
"profile" | "p" => {
@@ -282,7 +297,6 @@ impl<'a> InteractiveSession<'a> {
282297
println!("Result: '{actual}'");
283298
}
284299

285-
286300
"exit" | "quit" | "q" => {
287301
return Ok(false);
288302
}
@@ -307,7 +321,7 @@ impl<'a> InteractiveSession<'a> {
307321
println!("{}", "Available commands:".yellow());
308322
println!(
309323
" {} - Get recommendation for a stock symbol",
310-
"recommend <SYMBOL> [notes]".cyan()
324+
"recommend <SYMBOL> [--debug] [notes]".cyan()
311325
);
312326
println!(" {} - Show client profile", "profile".cyan());
313327
println!(
@@ -370,14 +384,30 @@ impl<'a> InteractiveSession<'a> {
370384
symbol: &str,
371385
client: &ClientProfile,
372386
notes: Option<String>,
387+
) -> Result<()> {
388+
self.handle_recommendation_with_debug(symbol, client, notes, false)
389+
.await
390+
}
391+
392+
async fn handle_recommendation_with_debug(
393+
&mut self,
394+
symbol: &str,
395+
client: &ClientProfile,
396+
notes: Option<String>,
397+
debug_mode: bool,
373398
) -> Result<()> {
374399
println!(
375-
"{} Generating recommendation for {}...",
400+
"{} Generating recommendation for {}{}...",
376401
"🔍".yellow(),
377-
symbol
402+
symbol,
403+
if debug_mode { " (debug mode)" } else { "" }
378404
);
379405

380-
match self.advisor.get_recommendation(symbol, client, notes).await {
406+
match self
407+
.advisor
408+
.get_recommendation_with_debug(symbol, client, notes, debug_mode)
409+
.await
410+
{
381411
Ok(recommendation) => {
382412
println!();
383413
println!("{}", "📊 Recommendation Generated".green().bold());
@@ -393,21 +423,29 @@ impl<'a> InteractiveSession<'a> {
393423
"Confidence".cyan(),
394424
recommendation.confidence * 100.0
395425
);
396-
426+
397427
// Show analysis mode prominently
398428
let mode_display = match recommendation.analysis_mode {
399-
crate::advisor::AnalysisMode::AIPowered => "🤖 AI-Powered Analysis".bright_green(),
400-
crate::advisor::AnalysisMode::RuleBased => "📊 Rule-Based Analysis".bright_yellow(),
429+
crate::advisor::AnalysisMode::AIPowered => {
430+
"🤖 AI-Powered Analysis".bright_green()
431+
}
432+
crate::advisor::AnalysisMode::RuleBased => {
433+
"📊 Rule-Based Analysis".bright_yellow()
434+
}
401435
};
402436
println!("{}: {}", "Mode".cyan(), mode_display);
403-
437+
404438
// Show data source information
405439
let data_source_display = match recommendation.data_source {
406-
crate::advisor::DataSource::RealStockData => "📈 Real Market Data".bright_blue(),
407-
crate::advisor::DataSource::SimulatedData => "🎲 Simulated Data".bright_magenta(),
440+
crate::advisor::DataSource::RealStockData => {
441+
"📈 Real Market Data".bright_blue()
442+
}
443+
crate::advisor::DataSource::SimulatedData => {
444+
"🎲 Simulated Data".bright_magenta()
445+
}
408446
};
409447
println!("{}: {}", "Data Source".cyan(), data_source_display);
410-
448+
411449
println!("{}: {}", "Client".cyan(), recommendation.client_id);
412450
println!();
413451
println!("{}", "Reasoning:".yellow());
@@ -585,21 +623,21 @@ impl<'a> InteractiveSession<'a> {
585623
rec.recommendation_type.as_str().bold()
586624
);
587625
println!(" {}: {:.1}%", "Confidence".cyan(), rec.confidence * 100.0);
588-
626+
589627
// Show analysis mode with clear indicator
590628
let mode_display = match rec.analysis_mode {
591629
crate::advisor::AnalysisMode::AIPowered => "🤖 AI-Powered".bright_green(),
592630
crate::advisor::AnalysisMode::RuleBased => "📊 Rule-Based".bright_yellow(),
593631
};
594632
println!(" {}: {}", "Analysis Mode".cyan(), mode_display);
595-
633+
596634
// Show data source
597635
let data_source_display = match rec.data_source {
598636
crate::advisor::DataSource::RealStockData => "📈 Real Data".bright_blue(),
599637
crate::advisor::DataSource::SimulatedData => "🎲 Simulated".bright_magenta(),
600638
};
601639
println!(" {}: {}", "Data Source".cyan(), data_source_display);
602-
640+
603641
println!(" {}: {}", "Client ID".cyan(), rec.client_id);
604642
println!(
605643
" {}: {}",
@@ -872,7 +910,7 @@ impl<'a> InteractiveSession<'a> {
872910
// Display branches in a tree structure
873911
println!("{}", "Repository Branches:".yellow());
874912
println!();
875-
913+
876914
// Sort branches to ensure main/master comes first
877915
let mut sorted_branches = branches.clone();
878916
sorted_branches.sort_by(|a, b| {
@@ -890,32 +928,42 @@ impl<'a> InteractiveSession<'a> {
890928
let is_last = i == sorted_branches.len() - 1;
891929
let connector = if is_last { "└──" } else { "├──" };
892930
let vertical_line = if is_last { " " } else { "│ " };
893-
931+
894932
// Determine branch color and symbol
895-
let (branch_display, symbol) = if branch == &current_branch {
933+
let (branch_display, symbol) = if branch == current_branch {
896934
(branch.green().bold(), "●") // Current branch
897935
} else if branch == "main" || branch == "master" {
898936
(branch.blue().bold(), "◆") // Main branch
899937
} else {
900938
(branch.normal(), "○") // Other branches
901939
};
902-
940+
903941
// Display branch with appropriate formatting
904-
println!("{} {} {} {}",
905-
connector.dimmed(),
942+
println!(
943+
"{} {} {} {}",
944+
connector.dimmed(),
906945
symbol,
907946
branch_display,
908-
if branch == &current_branch { "(current)".dimmed() } else { "".normal() }
947+
if branch == current_branch {
948+
"(current)".dimmed()
949+
} else {
950+
"".normal()
951+
}
909952
);
910-
953+
911954
// Show some recent commits for the current branch
912-
if branch == &current_branch {
955+
if branch == current_branch {
913956
if let Ok(history) = self.advisor.get_memory_history(Some(3)).await {
914957
for (j, commit) in history.iter().enumerate() {
915958
let is_last_commit = j == history.len() - 1 || j == 2;
916-
let commit_connector = if is_last_commit { "└──" } else { "├──" };
917-
918-
println!("{} {} {} {}",
959+
let commit_connector = if is_last_commit {
960+
"└──"
961+
} else {
962+
"├──"
963+
};
964+
965+
println!(
966+
"{} {} {} {}",
919967
vertical_line.dimmed(),
920968
commit_connector.dimmed(),
921969
commit.hash[..8].yellow(),
@@ -932,9 +980,18 @@ impl<'a> InteractiveSession<'a> {
932980
println!(" {} Main branch", "◆".blue());
933981
println!(" {} Other branches", "○".normal());
934982
println!();
935-
println!("{} All branches share the same versioned memory system", "💾".cyan());
936-
println!("{} Switch branches with: switch <branch-name>", "🔀".yellow());
937-
println!("{} Create new branch with: branch <branch-name>", "🌿".green());
983+
println!(
984+
"{} All branches share the same versioned memory system",
985+
"💾".cyan()
986+
);
987+
println!(
988+
"{} Switch branches with: switch <branch-name>",
989+
"🔀".yellow()
990+
);
991+
println!(
992+
"{} Create new branch with: branch <branch-name>",
993+
"🌿".green()
994+
);
938995

939996
Ok(())
940997
}
@@ -1036,5 +1093,4 @@ impl<'a> InteractiveSession<'a> {
10361093
);
10371094
}
10381095
}
1039-
10401096
}

examples/financial_advisor/src/advisor/mod.rs

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
use anyhow::Result;
44
use chrono::{DateTime, Utc};
5+
use colored::Colorize;
56
// OpenAI integration for AI-powered recommendations
67
use serde::{Deserialize, Serialize};
78
use uuid::Uuid;
@@ -125,6 +126,17 @@ impl FinancialAdvisor {
125126
symbol: &str,
126127
client_profile: &ClientProfile,
127128
notes: Option<String>,
129+
) -> Result<Recommendation> {
130+
self.get_recommendation_with_debug(symbol, client_profile, notes, false)
131+
.await
132+
}
133+
134+
pub async fn get_recommendation_with_debug(
135+
&mut self,
136+
symbol: &str,
137+
client_profile: &ClientProfile,
138+
notes: Option<String>,
139+
debug_mode: bool,
128140
) -> Result<Recommendation> {
129141
if self.verbose {
130142
println!("🔍 Fetching market data for {symbol}...");
@@ -145,7 +157,7 @@ impl FinancialAdvisor {
145157
.recommendation_engine
146158
.generate(symbol, client_profile, &market_data, &self.memory_store)
147159
.await?;
148-
160+
149161
// Set the data source
150162
recommendation.data_source = stock_data.data_source;
151163

@@ -155,12 +167,13 @@ impl FinancialAdvisor {
155167
}
156168

157169
let (ai_reasoning, analysis_mode) = self
158-
.generate_ai_reasoning(
170+
.generate_ai_reasoning_with_debug(
159171
symbol,
160172
&recommendation.recommendation_type,
161173
&serde_json::from_str::<serde_json::Value>(&market_data.content)
162174
.unwrap_or(serde_json::json!({})),
163175
client_profile,
176+
debug_mode,
164177
)
165178
.await?;
166179

@@ -458,6 +471,24 @@ impl FinancialAdvisor {
458471
recommendation_type: &RecommendationType,
459472
market_data: &serde_json::Value,
460473
client: &ClientProfile,
474+
) -> Result<(String, AnalysisMode)> {
475+
self.generate_ai_reasoning_with_debug(
476+
symbol,
477+
recommendation_type,
478+
market_data,
479+
client,
480+
false,
481+
)
482+
.await
483+
}
484+
485+
async fn generate_ai_reasoning_with_debug(
486+
&self,
487+
symbol: &str,
488+
recommendation_type: &RecommendationType,
489+
market_data: &serde_json::Value,
490+
client: &ClientProfile,
491+
debug_mode: bool,
461492
) -> Result<(String, AnalysisMode)> {
462493
// Build context from market data
463494
let price = market_data["price"].as_f64().unwrap_or(0.0);
@@ -501,6 +532,16 @@ impl FinancialAdvisor {
501532
recommendation_type = recommendation_type
502533
);
503534

535+
// Print prompt if debug mode is enabled
536+
if debug_mode {
537+
println!();
538+
println!("{}", "🔍 OpenAI Prompt Debug".bright_cyan().bold());
539+
println!("{}", "━".repeat(60).dimmed());
540+
println!("{prompt}");
541+
println!("{}", "━".repeat(60).dimmed());
542+
println!();
543+
}
544+
504545
// Make OpenAI API call
505546
let openai_request = serde_json::json!({
506547
"model": "gpt-3.5-turbo",

examples/financial_advisor/src/advisor/recommendations.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ use anyhow::Result;
44
use chrono::Utc;
55
use uuid::Uuid;
66

7-
use super::{AnalysisMode, ClientProfile, DataSource, Recommendation, RecommendationType, RiskTolerance};
7+
use super::{
8+
AnalysisMode, ClientProfile, DataSource, Recommendation, RecommendationType, RiskTolerance,
9+
};
810
use crate::memory::{MemoryStore, ValidatedMemory};
911
use crate::validation::ValidationResult;
1012

0 commit comments

Comments
 (0)