diff --git a/manual/tracy.md b/manual/tracy.md index ea4c83b8..cde0663e 100644 --- a/manual/tracy.md +++ b/manual/tracy.md @@ -12,7 +12,7 @@ The user manual **Bartosz Taudul** [\](mailto:wolf@nereid.pl) -2025-11-11 +2025-11-29 ::: # Quick overview {#quick-overview .unnumbered} diff --git a/profiler/CMakeLists.txt b/profiler/CMakeLists.txt index d01731d3..7825af70 100644 --- a/profiler/CMakeLists.txt +++ b/profiler/CMakeLists.txt @@ -66,6 +66,7 @@ set(SERVER_FILES TracyFileselector.cpp TracyFilesystem.cpp TracyImGui.cpp + TracyManualData.cpp TracyMarkdown.cpp TracyMicroArchitecture.cpp TracyMouse.cpp diff --git a/profiler/src/profiler/TracyLlm.cpp b/profiler/src/profiler/TracyLlm.cpp index 3ab05ebc..e5eafb33 100644 --- a/profiler/src/profiler/TracyLlm.cpp +++ b/profiler/src/profiler/TracyLlm.cpp @@ -24,7 +24,7 @@ extern double s_time; constexpr size_t InputBufferSize = 1024; -TracyLlm::TracyLlm( Worker& worker ) +TracyLlm::TracyLlm( Worker& worker, const TracyManualData& manual ) : m_exit( false ) , m_input( nullptr ) { @@ -47,7 +47,7 @@ TracyLlm::TracyLlm( Worker& worker ) m_api = std::make_unique(); m_chatUi = std::make_unique(); - m_tools = std::make_unique( worker ); + m_tools = std::make_unique( worker, manual ); m_busy = true; QueueConnect(); diff --git a/profiler/src/profiler/TracyLlm.hpp b/profiler/src/profiler/TracyLlm.hpp index 00be91b0..6c34a19e 100644 --- a/profiler/src/profiler/TracyLlm.hpp +++ b/profiler/src/profiler/TracyLlm.hpp @@ -19,6 +19,7 @@ namespace tracy class TracyLlmApi; class TracyLlmChat; class TracyLlmTools; +class TracyManualData; class Worker; class TracyLlm @@ -40,7 +41,7 @@ class TracyLlm }; public: - TracyLlm( Worker& worker ); + TracyLlm( Worker& worker, const TracyManualData& manual ); ~TracyLlm(); [[nodiscard]] bool IsBusy() const { std::lock_guard lock( m_lock ); return m_busy; } diff --git a/profiler/src/profiler/TracyLlmTools.cpp b/profiler/src/profiler/TracyLlmTools.cpp index 52baf2fb..870848dd 100644 --- a/profiler/src/profiler/TracyLlmTools.cpp +++ b/profiler/src/profiler/TracyLlmTools.cpp @@ -9,15 +9,12 @@ #include #include "TracyConfig.hpp" -#include "TracyEmbed.hpp" #include "TracyLlmApi.hpp" #include "TracyLlmTools.hpp" +#include "TracyManualData.hpp" #include "TracyStorage.hpp" #include "TracyUtility.hpp" #include "TracyWorker.hpp" -#include "tracy_xxhash.h" - -#include "data/Manual.hpp" constexpr const char* NoNetworkAccess = "Internet access is disabled by the user. You may inform the user that he can enable it in the settings, so that you can use the tools to gather information."; @@ -81,122 +78,29 @@ static std::unique_ptr ParseHtml( const std::string& html ) return doc; } -TracyLlmTools::TracyLlmTools( Worker& worker ) - : m_manual( Unembed( Manual ) ) - , m_worker( worker ) +TracyLlmTools::TracyLlmTools( Worker& worker, const TracyManualData& manual ) + : m_worker( worker ) + , m_manual( manual ) { - std::string_view manual( m_manual->data(), m_manual->size() ); - const auto sz = (int)m_manual->size(); - - std::vector levels = { 0 }; - std::vector chapterNames = { "Title Page" }; - - int manualChunkPos = 0; - int pos = 0; - while( pos < sz ) + int idx = 0; + for( auto& chunk : m_manual.GetChunks() ) { - std::string::size_type next = pos; - for(;;) + std::string hdr; + if( !chunk.section.empty() ) hdr += "Section " + chunk.section; + if( !chunk.title.empty() ) { - next = manual.find( '\n', next ); - if( next == std::string_view::npos ) - { - next = sz; - break; - } - if( next+1 >= sz || manual[next+1] == '\n' ) break; - next++; + if( !chunk.section.empty() ) hdr += ": "; + hdr += chunk.title; } - if( next != pos ) + hdr += '\n'; + + for( auto& line : SplitLines( chunk.text.c_str(), chunk.text.size() ) ) { - std::string_view line( manual.data() + pos, next - pos ); - if( line != "---" && line != ":::" && line != "::: bclogo" ) - { - if( line[0] == '#' ) - { - if( manualChunkPos != pos ) - { - auto start = manualChunkPos; - auto end = pos; - manualChunkPos = pos; - - while( manual[start] != '\n' ) start++; - while( manual[start] == '\n' ) start++; - while( manual[end-1] == '\n' ) end--; - - if( end > start ) - { - std::string text, section, title, parents; - text = std::string( manual.data() + start, end - start ); - if( levels[0] != 0 ) - { - section = std::to_string( levels[0] ); - for( size_t i=1; idata(), m_manual->size() ); auto cache = GetCachePath( model.c_str() ); try { - m_manualEmbeddings = std::make_unique( cache, hash ); + m_manualEmbeddings = std::make_unique( cache, m_manual.GetHash() ); m_manualEmbeddingState = { .model = model, .done = true }; } catch( std::exception& ) {} @@ -315,7 +218,6 @@ void TracyLlmTools::BuildManualEmbeddings( const std::string& model, TracyLlmApi void TracyLlmTools::ManualEmbeddingsWorker( TracyLlmApi& api ) { - const uint64_t hash = XXH3_64bits( m_manual->data(), m_manual->size() ); auto cache = GetCachePath( m_manualEmbeddingState.model.c_str() ); std::unique_lock lock( m_lock ); @@ -395,7 +297,7 @@ void TracyLlmTools::ManualEmbeddingsWorker( TracyLlmApi& api ) i += bsz; } - m_manualEmbeddings->Save( cache, hash ); + m_manualEmbeddings->Save( cache, m_manual.GetHash() ); lock.lock(); m_manualEmbeddingState.inProgress = false; @@ -825,12 +727,13 @@ std::string TracyLlmTools::SearchManual( const std::string& query, TracyLlmApi& } if( chunks.size() > MaxOutputChunks ) chunks.resize( MaxOutputChunks ); + auto& manualChunks = m_manual.GetChunks(); const auto maxSize = CalcMaxSize(); int totalSize = 0; int idx; for( idx = 0; idx < chunks.size(); idx++ ) { - totalSize += m_manualChunks[chunks[idx].first].text.size(); + totalSize += manualChunks[chunks[idx].first].text.size(); if( totalSize >= maxSize ) break; } if( idx < chunks.size() ) chunks.resize( idx ); @@ -838,7 +741,7 @@ std::string TracyLlmTools::SearchManual( const std::string& query, TracyLlmApi& nlohmann::json json; for( auto& chunk : chunks ) { - auto& m = m_manualChunks[chunk.first]; + auto& m = manualChunks[chunk.first]; nlohmann::json r; r["distance"] = chunk.second; r["content"] = m.text; diff --git a/profiler/src/profiler/TracyLlmTools.hpp b/profiler/src/profiler/TracyLlmTools.hpp index e26caaf4..ba2e82c7 100644 --- a/profiler/src/profiler/TracyLlmTools.hpp +++ b/profiler/src/profiler/TracyLlmTools.hpp @@ -17,6 +17,7 @@ namespace tracy { class TracyLlmApi; +class TracyManualData; class Worker; class TracyLlmTools @@ -36,15 +37,7 @@ public: float progress = 0; }; - struct ManualChunk - { - std::string text; - std::string section; - std::string title; - std::string parents; - }; - - TracyLlmTools( Worker& worker ); + TracyLlmTools( Worker& worker, const TracyManualData& manual ); ~TracyLlmTools(); ToolReply HandleToolCalls( const nlohmann::json& json, TracyLlmApi& api, int contextSize, bool hasEmbeddingsModel ); @@ -82,11 +75,10 @@ private: EmbeddingState m_manualEmbeddingState; std::unique_ptr m_manualEmbeddings; - std::shared_ptr m_manual; - std::vector m_manualChunks; std::vector> m_chunkData; Worker& m_worker; + const TracyManualData& m_manual; }; } diff --git a/profiler/src/profiler/TracyManualData.cpp b/profiler/src/profiler/TracyManualData.cpp new file mode 100644 index 00000000..f9fcb23c --- /dev/null +++ b/profiler/src/profiler/TracyManualData.cpp @@ -0,0 +1,107 @@ +#include "TracyEmbed.hpp" +#include "TracyManualData.hpp" + +#define XXH_INLINE_ALL +#include "tracy_xxhash.h" + +#include "data/Manual.hpp" + +namespace tracy +{ + +TracyManualData::TracyManualData() +{ + auto data = Unembed( Manual ); + m_hash = XXH3_64bits( data->data(), data->size() ); + + std::string_view manual( data->data(), data->size() ); + const auto sz = (int)data->size(); + + std::vector levels = { 0 }; + std::vector chapterNames = { "Title Page" }; + + int manualChunkPos = 0; + int pos = 0; + while( pos < sz ) + { + std::string::size_type next = pos; + for(;;) + { + next = manual.find( '\n', next ); + if( next == std::string_view::npos ) + { + next = sz; + break; + } + if( next+1 >= sz || manual[next+1] == '\n' ) break; + next++; + } + if( next != pos ) + { + std::string_view line( manual.data() + pos, next - pos ); + if( line[0] == '#' ) + { + if( manualChunkPos != pos ) + { + AddManualChunk( manual, manualChunkPos, pos, levels, chapterNames ); + manualChunkPos = pos; + } + + int level = 1; + if( line.find( ".unnumbered}" ) == std::string_view::npos ) + { + while( level < line.size() && line[level] == '#' ) level++; + if( level != levels.size() ) + { + levels.resize( level, 0 ); + chapterNames.resize( level ); + } + levels[level - 1]++; + chapterNames[level - 1] = line.substr( level + 1 ); + } + } + } + pos = next + 1; + while( pos < sz && manual[pos] == '\n' ) pos++; + } + if( manualChunkPos != pos ) + { + AddManualChunk( manual, manualChunkPos, pos, levels, chapterNames ); + } +} + +void TracyManualData::AddManualChunk( const std::string_view& manual, int start, int end, const std::vector& levels, const std::vector& chapterNames ) +{ + while( manual[start] != '\n' ) start++; + while( manual[start] == '\n' ) start++; + while( manual[end-1] == '\n' ) end--; + + if( end > start ) + { + std::string text, section, title, parents; + text = std::string( manual.data() + start, end - start ); + if( levels[0] != 0 ) + { + section = std::to_string( levels[0] ); + for( size_t i=1; i +#include +#include +#include + +namespace tracy +{ + +class TracyManualData +{ +public: + struct ManualChunk + { + std::string text; + std::string section; + std::string title; + std::string parents; + }; + + TracyManualData(); + + [[nodiscard]] const std::vector& GetChunks() const { return m_manualChunks; } + [[nodiscard]] uint64_t GetHash() const { return m_hash; } + +private: + void AddManualChunk( const std::string_view& manual, int manualChunkPos, int pos, const std::vector& levels, const std::vector& chapterNames ); + + std::vector m_manualChunks; + uint64_t m_hash; +}; + +} + +#endif diff --git a/profiler/src/profiler/TracyView.cpp b/profiler/src/profiler/TracyView.cpp index 87c658a6..ceb4fd84 100644 --- a/profiler/src/profiler/TracyView.cpp +++ b/profiler/src/profiler/TracyView.cpp @@ -17,6 +17,7 @@ #include "TracyFileRead.hpp" #include "TracyFilesystem.hpp" #include "TracyImGui.hpp" +#include "TracyManualData.hpp" #include "TracyPrint.hpp" #include "TracySourceView.hpp" #include "TracyTexture.hpp" @@ -57,11 +58,12 @@ View::View( void(*cbMainThread)(const std::function&, bool), const char* , m_achievements( s_config.achievements ) , m_horizontalScrollMultiplier( s_config.horizontalScrollMultiplier ) , m_verticalScrollMultiplier( s_config.verticalScrollMultiplier ) + , m_manualData( std::make_shared() ) #ifdef __EMSCRIPTEN__ , m_td( 2, "ViewMt" ) #else , m_td( std::thread::hardware_concurrency(), "ViewMt" ) - , m_llm( m_worker ) + , m_llm( m_worker, *m_manualData ) #endif { InitTextEditor(); @@ -86,11 +88,12 @@ View::View( void(*cbMainThread)(const std::function&, bool), FileRead& f , m_achievements( s_config.achievements ) , m_horizontalScrollMultiplier( s_config.horizontalScrollMultiplier ) , m_verticalScrollMultiplier( s_config.verticalScrollMultiplier ) + , m_manualData( std::make_shared() ) #ifdef __EMSCRIPTEN__ , m_td( 2, "ViewMt" ) #else , m_td( std::thread::hardware_concurrency(), "ViewMt" ) - , m_llm( m_worker ) + , m_llm( m_worker, *m_manualData ) #endif { m_notificationTime = 4; diff --git a/profiler/src/profiler/TracyView.hpp b/profiler/src/profiler/TracyView.hpp index 23f308ed..452d0dea 100644 --- a/profiler/src/profiler/TracyView.hpp +++ b/profiler/src/profiler/TracyView.hpp @@ -63,6 +63,7 @@ struct CpuCtxDraw; struct LockDraw; struct PlotDraw; struct FlameGraphContext; +class TracyManualData; class View @@ -929,6 +930,8 @@ private: double m_horizontalScrollMultiplier = 1.0; double m_verticalScrollMultiplier = 1.0; + std::shared_ptr m_manualData; + TaskDispatch m_td; std::vector m_flameGraphData; struct