use anyhow::Result;
use rag_module::RagModule;
use rag_module::services::search_service::ChatSearchOptions;
#[tokio::main]
async fn main() -> Result<()> {
println!("š Continue Chat Example: Adding to Existing Conversation");
println!("This example continues an existing context with new messages\n");
// Detect which mode we're running in
let qdrant_url = std::env::var("QDRANT_URL").ok();
let mode = match &qdrant_url {
Some(url) if url.contains("amazonaws.com") => "āļø AWS Cloud Mode",
Some(_) => "š Local Server Mode",
None => "š¾ Embedded Mode",
};
println!("Running in: {}", mode);
if let Some(url) = &qdrant_url {
println!("Qdrant URL: {}", url);
}
println!("āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n");
// Initialize RAG module with SAME path as complete_chat_example
let mut rag_module = RagModule::new("./example-enhanced-chat-data").await?;
rag_module.initialize().await?;
println!("ā
RAG Module initialized\n");
// Use SAME user_id and context_id as complete_chat_example
let user_id = "cudewvsbxakj1n";
let context_id = "test5"; // Same context as before - messages should continue from existing index
let chat_title = Some("Complete Chat Demo - REST vs GraphQL"); // Same title
rag_module.set_user_context(user_id).await?;
println!("š Continuing existing conversation...");
println!("ā
Context ID: {} (reusing existing context)", context_id);
println!("š User ID: {}\n", user_id);
// First, retrieve existing conversation to see current state
println!("š Retrieving existing conversation history...");
let existing_history = rag_module.get_query_response_pairs(context_id, None).await?;
println!("ā
Found {} existing conversation pairs\n", existing_history.total_pairs);
// Show existing conversation
if existing_history.total_pairs > 0 {
println!("š EXISTING CONVERSATION:");
println!("āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā");
for (i, pair) in existing_history.pairs.iter().enumerate() {
println!("Turn {}: User: {}", i + 1, pair.query.content);
println!("Turn {}: Assistant: {}...\n", i + 1, &pair.response.content[..100]);
}
println!("āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n");
}
// === NEW TURN 4: Continue with different topic but related ===
println!("š¬ NEW TURN 4: Asking about performance");
let prompt4 = "Which one is faster in terms of performance?";
println!("User: {}", prompt4);
let prompt_id4 = rag_module.add_prompt(context_id, prompt4, user_id, chat_title).await?;
println!("ā
Prompt stored (ID: {})", prompt_id4);
let response4 = "Performance comparison depends on the use case:\n\n**REST is typically faster when**:\n- Simple queries with full resource access\n- Using HTTP caching effectively\n- Accessing single resources\n- Example: GET /users/123 with browser cache = instant!\n\n**GraphQL can be faster when**:\n- Need multiple resources (saves round trips)\n- Mobile with slow networks (smaller payloads)\n- Complex nested data requirements\n\n**Real example**:\n```\nREST: 3 requests for user + posts + comments\n- /users/123 (200ms)\n- /posts?userId=123 (300ms) \n- /comments?userId=123 (250ms)\nTotal: 750ms + overhead\n\nGraphQL: 1 request\n- POST /graphql (400ms)\nTotal: 400ms!\n```\n\n**Bottom line**: GraphQL wins for complex data fetching, REST wins for simple cached resources. It's about optimizing for your specific access patterns, which relates to everything we discussed about over-fetching and caching.";
let response_id4 = rag_module.add_response(context_id, response4, user_id, chat_title).await?;
println!("Assistant: {}...", &response4[..120]);
println!("ā
Response stored (ID: {})\n", response_id4);
// === NEW TURN 5: Ask about implementation ===
println!("š¬ NEW TURN 5: Implementation question");
let prompt5 = "How do I decide which one to use for a new mobile app project?";
println!("User: {}", prompt5);
let prompt_id5 = rag_module.add_prompt(context_id, prompt5, user_id, chat_title).await?;
println!("ā
Prompt stored (ID: {})", prompt_id5);
let response5 = "Great question for a new mobile app! Here's a decision framework based on everything we've covered:\n\n**Choose REST when**:\nā
Simple CRUD operations\nā
Team already knows REST well\nā
Standard resource-based API\nā
Heavy caching requirements\nā
Rapid prototyping needed\n\n**Choose GraphQL when**:\nā
Complex, nested data relationships\nā
Multiple client types (iOS, Android, Web) with different needs\nā
Frequent API changes/iterations\nā
Need to minimize mobile data usage (remember the over-fetching problem!)\nā
Want real-time features (subscriptions)\nā
Backend has microservices you want to unify\n\n**For your mobile app specifically**:\n1. Start with data requirements - how complex are relationships?\n2. Consider team expertise - learning curve matters\n3. Think about data usage - mobile users care about payload size\n4. Plan for growth - will requirements change often?\n\n**My recommendation**: If your app has complex data needs or you're targeting users with limited data plans, GraphQL's flexibility and efficiency (avoiding over-fetching as we discussed) makes it worth the initial complexity. Otherwise, REST's simplicity might get you to market faster.\n\nRemember: You can also start with REST and migrate later, or even use both (REST for simple endpoints, GraphQL for complex ones)!";
let response_id5 = rag_module.add_response(context_id, response5, user_id, chat_title).await?;
println!("Assistant: {}...", &response5[..120]);
println!("ā
Response stored (ID: {})\n", response_id5);
// === SEARCH AND VERIFY CONTINUATION ===
println!("š Testing Chat Search Service with Continued Context:");
let chat_search_options = ChatSearchOptions {
context_id: Some(context_id.to_string()),
role: None,
from_timestamp: None,
to_timestamp: None,
from_message_index: None,
to_message_index: None,
limit: Some(20),
include_metadata: true,
user_id: Some(user_id.to_string()),
};
let chat_search_results = rag_module.search_service
.search_chat_history(chat_search_options)
.await?;
println!("ā
Chat search returned complete conversation history:");
println!("\n{}", serde_json::to_string_pretty(&chat_search_results).unwrap_or_else(|_| "Error formatting".to_string()));
// Verify message count
if let Some(result) = chat_search_results.first() {
if let Some(messages) = result.get("m").and_then(|v| v.as_array()) {
println!("\nā
Total messages in conversation: {}", messages.len());
println!(" Expected: 10 messages (3 original pairs + 2 new pairs = 5 Q&A pairs Ć 2)");
// Show message indices to verify continuation
println!("\nš Message indices verification:");
for (idx, msg) in messages.iter().enumerate() {
if let (Some(role), Some(content)) = (
msg.get("r").and_then(|v| v.as_str()),
msg.get("c").and_then(|v| v.as_str())
) {
let content_preview = if content.len() > 60 {
format!("{}...", &content[..60])
} else {
content.to_string()
};
println!(" Message {}: role={}, content={}", idx, role, content_preview);
}
}
}
}
// === VERIFY CONTEXT RETRIEVAL ===
println!("\nš Verifying Updated Context Retrieval:");
let final_history = rag_module.get_query_response_pairs(context_id, None).await?;
println!(" Total conversation pairs: {}", final_history.total_pairs);
println!(" Context ID: {}", final_history.context_id);
println!(" Chat title: {}", final_history.chat_title);
println!("\nš COMPLETE CONVERSATION HISTORY:");
println!("āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā");
for (i, pair) in final_history.pairs.iter().enumerate() {
println!("Turn {}: User: {}", i + 1, pair.query.content);
println!("Turn {}: Assistant: {}...\n", i + 1, &pair.response.content[..80]);
}
println!("āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā");
// === FINAL SUMMARY ===
println!("\n");
println!("āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā");
println!(" CONVERSATION CONTINUATION SUMMARY ");
println!("āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā");
println!("ā
Successfully continued existing conversation!");
println!(" ⢠Context ID: {}", context_id);
println!(" ⢠User ID: {}", user_id);
println!(" ⢠Previous messages: {} pairs", existing_history.total_pairs);
println!(" ⢠New messages: 2 pairs");
println!(" ⢠Total messages: {} pairs", final_history.total_pairs);
println!();
println!("š Key Features Demonstrated:");
println!(" ā
Message index continuation (didn't restart from 0)");
println!(" ā
Context preservation across sessions");
println!(" ā
Proper deduplication of messages");
println!(" ā
Conversation flow maintained");
println!(" ā
Same user_id and context_id across examples");
println!();
println!("š Storage Path: ./example-enhanced-chat-data (shared with complete_chat_example)");
println!("āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā");
Ok(())
}