diff --git a/profiler/src/profiler/TracyConfig.cpp b/profiler/src/profiler/TracyConfig.cpp index c3084e73..70fc0832 100644 --- a/profiler/src/profiler/TracyConfig.cpp +++ b/profiler/src/profiler/TracyConfig.cpp @@ -47,6 +47,7 @@ void LoadConfig() if( v2 = ini_get( ini, "llm", "useragent" ); v2 ) s_config.llmUserAgent = v2; if( v2 = ini_get( ini, "llm", "searchIdentifier" ); v2 ) s_config.llmSearchIdentifier = v2; if( v2 = ini_get( ini, "llm", "searchApiKey" ); v2 ) s_config.llmSearchApiKey = v2; + if( v2 = ini_get( ini, "llm", "searchBraveApiKey" ); v2 ) s_config.llmSearchBraveApiKey = v2; if( ini_sget( ini, "llm", "annotateCallstacks", "%d", &v ) ) s_config.llmAnnotateCallstacks = v; if( ini_sget( ini, "llm", "limitToolReplySize", "%d", &v ) ) s_config.llmLimitToolReplySize = v; if( ini_sget( ini, "llm", "maxToolReplySizeValue", "%d", &v ) ) s_config.llmMaxToolReplySizeValue = v; @@ -98,6 +99,7 @@ bool SaveConfig() fprintf( f, "useragent = %s\n", s_config.llmUserAgent.c_str() ); fprintf( f, "searchIdentifier = %s\n", s_config.llmSearchIdentifier.c_str() ); fprintf( f, "searchApiKey = %s\n", s_config.llmSearchApiKey.c_str() ); + fprintf( f, "searchBraveApiKey = %s\n", s_config.llmSearchBraveApiKey.c_str() ); fprintf( f, "annotateCallstacks = %i\n", (int)s_config.llmAnnotateCallstacks ); fprintf( f, "limitToolReplySize = %i\n", (int)s_config.llmLimitToolReplySize ); fprintf( f, "maxToolReplySizeValue = %i\n", s_config.llmMaxToolReplySizeValue ); diff --git a/profiler/src/profiler/TracyConfig.hpp b/profiler/src/profiler/TracyConfig.hpp index 3c8331ab..c49e8dc9 100644 --- a/profiler/src/profiler/TracyConfig.hpp +++ b/profiler/src/profiler/TracyConfig.hpp @@ -43,6 +43,7 @@ struct Config std::string llmUserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36"; std::string llmSearchIdentifier; std::string llmSearchApiKey; + std::string llmSearchBraveApiKey; bool llmAnnotateCallstacks = false; bool llmLimitToolReplySize = false; int llmMaxToolReplySizeValue = 48*1024; diff --git a/profiler/src/profiler/TracyLlm.cpp b/profiler/src/profiler/TracyLlm.cpp index aa7abb8c..07105d49 100644 --- a/profiler/src/profiler/TracyLlm.cpp +++ b/profiler/src/profiler/TracyLlm.cpp @@ -392,6 +392,19 @@ void TracyLlm::Draw() ImGui::SameLine(); if( ImGui::Button( ICON_FA_HOUSE "##csekey" ) ) OpenWebpage( "https://developers.google.com/custom-search/v1/overview" ); + ImGui::AlignTextToFramePadding(); + ImGui::TextUnformatted( "Brave Search API Key:" ); + ImGui::SameLine(); + snprintf( buf, sizeof( buf ), "%s", s_config.llmSearchBraveApiKey.c_str() ); + ImGui::SetNextItemWidth( ImGui::GetContentRegionAvail().x - ImGui::CalcTextSize( ICON_FA_HOUSE ).x - ImGui::GetStyle().FramePadding.x * 2 - ImGui::GetStyle().ItemSpacing.x ); + if( ImGui::InputTextWithHint( "##bravekey", "Brave API key", buf, sizeof( buf ) ) ) + { + s_config.llmSearchBraveApiKey = buf; + SaveConfig(); + } + ImGui::SameLine(); + if( ImGui::Button( ICON_FA_HOUSE "##bravekey" ) ) OpenWebpage( "https://brave.com/search/api/" ); + ImGui::TreePop(); } diff --git a/profiler/src/profiler/TracyLlmTools.cpp b/profiler/src/profiler/TracyLlmTools.cpp index 2c5038c3..98bd6075 100644 --- a/profiler/src/profiler/TracyLlmTools.cpp +++ b/profiler/src/profiler/TracyLlmTools.cpp @@ -522,6 +522,12 @@ std::string TracyLlmTools::SearchWeb( std::string query ) NetworkCheck; query = UrlEncode( query ); + if( !s_config.llmSearchBraveApiKey.empty() ) + { + const auto result = SearchWebBrave( query ); + if( !result.starts_with( "Error:" ) && !result.starts_with( "No results" ) ) return result; + } + if( !s_config.llmSearchApiKey.empty() && !s_config.llmSearchIdentifier.empty() ) { const auto result = SearchWebGoogle( query ); @@ -557,6 +563,50 @@ std::string TracyLlmTools::SearchWebGoogle( std::string query ) return "Error: Google search failed"; } +std::string TracyLlmTools::SearchWebBrave( std::string query ) +{ + const std::string header = "X-Subscription-Token: " + s_config.llmSearchBraveApiKey; + const std::vector headers = { header.c_str() }; + const auto response = FetchHttp( "https://api.search.brave.com/res/v1/web/search?q=" + query, headers ); + try + { + auto json = nlohmann::json::parse( response ); + nlohmann::json results; + + if( json.contains( "web" ) && json["web"].contains( "results" ) && json["web"]["results"].size() != 0 ) + { + auto& webResults = json["web"]["results"]; + for( auto& item : webResults ) + { + nlohmann::json result; + if( item.contains( "age" ) ) result["age"] = RemoveNewline( item["age"].get_ref() ); + result["title"] = RemoveNewline( item["title"].get_ref() ); + result["preview"] = RemoveNewline( item["description"].get_ref() ); + result["url"] = RemoveNewline( item["url"].get_ref() ); + results.emplace_back( result ); + } + } + if( json.contains( "discussions" ) && json["discussions"].contains( "results" ) && json["discussions"]["results"].size() != 0 ) + { + auto& webResults = json["discussions"]["results"]; + for( auto& item : webResults ) + { + nlohmann::json result; + if( item.contains( "age" ) ) result["age"] = RemoveNewline( item["age"].get_ref() ); + result["title"] = RemoveNewline( item["title"].get_ref() ); + result["preview"] = RemoveNewline( item["description"].get_ref() ); + result["url"] = RemoveNewline( item["url"].get_ref() ); + results.emplace_back( result ); + } + } + + if( !results.empty() ) return results.dump( -1, ' ', false, nlohmann::json::error_handler_t::replace ); + } + catch( const nlohmann::json::exception& e ) {} + + return "Error: Brave search failed"; +} + std::string TracyLlmTools::SearchWebDuckDuckGo( std::string query ) { auto response = FetchHttp( "https://lite.duckduckgo.com/lite?q=" + query ); diff --git a/profiler/src/profiler/TracyLlmTools.hpp b/profiler/src/profiler/TracyLlmTools.hpp index 7f0368a7..6d1666e0 100644 --- a/profiler/src/profiler/TracyLlmTools.hpp +++ b/profiler/src/profiler/TracyLlmTools.hpp @@ -56,6 +56,7 @@ private: std::string GetDictionary( std::string word, const std::string& lang ); std::string SearchWeb( std::string query ); std::string SearchWebGoogle( std::string query ); + std::string SearchWebBrave( std::string query ); std::string SearchWebDuckDuckGo( std::string query ); std::string GetWebpage( const std::string& url ); std::string SearchManual( const std::string& query, TracyLlmApi& api, bool hasEmbeddingsModel );