diff --git a/build/.cmake/api/v1/reply/index-2026-05-15T11-45-40-0759.json b/build/.cmake/api/v1/reply/index-2026-05-15T17-21-02-0403.json similarity index 100% rename from build/.cmake/api/v1/reply/index-2026-05-15T11-45-40-0759.json rename to build/.cmake/api/v1/reply/index-2026-05-15T17-21-02-0403.json diff --git a/build/.ninja_deps b/build/.ninja_deps index 09cf3f2..129355d 100644 Binary files a/build/.ninja_deps and b/build/.ninja_deps differ diff --git a/build/.ninja_log b/build/.ninja_log index f1d3535..5f2ee5f 100644 --- a/build/.ninja_log +++ b/build/.ninja_log @@ -1,24 +1,32 @@ # ninja log v5 -4 104 1778781069727168295 CMakeFiles/BIPY_App.dir/glad/glad.c.o fefc672e5ba266d4 -1 10013 1778784423530677763 CMakeFiles/Xenith_Studio.dir/Xenith/core.cpp.o 75fc1accc9ccbfb7 -3 252 1778784413776238204 CMakeFiles/Xenith_Studio.dir/imgui/backends/imgui_impl_opengl3.cpp.o c304bba33816b766 -4 3195 1778356067684895625 CMakeFiles/BIPY_App.dir/imgui/imgui_draw.cpp.o aadac94ced07c385 -3 525 1778784414048712486 CMakeFiles/Xenith_Studio.dir/imgui/backends/imgui_impl_glfw.cpp.o 365209c92a3adff5 -4 3849 1778356068338800863 CMakeFiles/BIPY_App.dir/imgui/imgui_widgets.cpp.o a4289b0d8e815019 -5 2848 1778356067338391370 CMakeFiles/BIPY_App.dir/imgui/imgui_demo.cpp.o 1cce55d13d233628 -4 2983 1778356067474176706 CMakeFiles/BIPY_App.dir/imgui/imgui_tables.cpp.o e443056602aa9f6e -4 10037 1778783521781801022 CMakeFiles/BIPY_App.dir/main.cpp.o c17c6f3b932c08b1 -2 3330 1778784416851815172 CMakeFiles/Xenith_Studio.dir/imgui/imgui_draw.cpp.o 1800e14a851f25f -2 2750 1778784416272029553 CMakeFiles/Xenith_Studio.dir/imgui/imgui_demo.cpp.o 7f9519f75639670 4 4153 1778356068641915985 CMakeFiles/BIPY_App.dir/imgui/imgui.cpp.o e920e8e567c1a611 10347 10665 1778784916629791881 Xenith_Studio 3b63d1325bf76a8b -5 8912 1778780147519966740 CMakeFiles/BIPY_App.dir/Xenith/core.cpp.o 6cb7eb29ca382303 -2 2219 1778784415742112339 CMakeFiles/Xenith_Studio.dir/imgui/imgui_tables.cpp.o 7af2c6b743b00546 -4 333 1778356183513052019 CMakeFiles/BIPY_App.dir/imgui/backends/imgui_impl_glfw.cpp.o 98ffae70adc86661 -2 137 1778845540743304132 build.ninja e62af03e6510d470 -1 2096 1778784415617799929 CMakeFiles/Xenith_Studio.dir/Xenith/token/token.cpp.o a2b96f15ecedfdd7 -5 262 1778356064753829258 CMakeFiles/BIPY_App.dir/imgui/backends/imgui_impl_opengl3.cpp.o 676a63c53e4312bd -2 3544 1778784417065823495 CMakeFiles/Xenith_Studio.dir/imgui/imgui_widgets.cpp.o 3971787f04936e8 -4 1654 1778780308577521598 CMakeFiles/BIPY_App.dir/Xenith/token/token.cpp.o bb661ce05133983a -2 4369 1778784417888358381 CMakeFiles/Xenith_Studio.dir/imgui/imgui.cpp.o 65b5accda161432f +2 2750 1778784416272029553 CMakeFiles/Xenith_Studio.dir/imgui/imgui_demo.cpp.o 7f9519f75639670 +2 3330 1778784416851815172 CMakeFiles/Xenith_Studio.dir/imgui/imgui_draw.cpp.o 1800e14a851f25f +4 2983 1778356067474176706 CMakeFiles/BIPY_App.dir/imgui/imgui_tables.cpp.o e443056602aa9f6e +5 2848 1778356067338391370 CMakeFiles/BIPY_App.dir/imgui/imgui_demo.cpp.o 1cce55d13d233628 +4 3849 1778356068338800863 CMakeFiles/BIPY_App.dir/imgui/imgui_widgets.cpp.o a4289b0d8e815019 +3 525 1778784414048712486 CMakeFiles/Xenith_Studio.dir/imgui/backends/imgui_impl_glfw.cpp.o 365209c92a3adff5 +4 10037 1778783521781801022 CMakeFiles/BIPY_App.dir/main.cpp.o c17c6f3b932c08b1 4 10347 1778784916307341110 CMakeFiles/Xenith_Studio.dir/main.cpp.o 1d76afb3a7c80307 +2 4369 1778784417888358381 CMakeFiles/Xenith_Studio.dir/imgui/imgui.cpp.o 65b5accda161432f +4 1654 1778780308577521598 CMakeFiles/BIPY_App.dir/Xenith/token/token.cpp.o bb661ce05133983a +4 104 1778781069727168295 CMakeFiles/BIPY_App.dir/glad/glad.c.o fefc672e5ba266d4 +2 3544 1778784417065823495 CMakeFiles/Xenith_Studio.dir/imgui/imgui_widgets.cpp.o 3971787f04936e8 +5 262 1778356064753829258 CMakeFiles/BIPY_App.dir/imgui/backends/imgui_impl_opengl3.cpp.o 676a63c53e4312bd +1 2096 1778784415617799929 CMakeFiles/Xenith_Studio.dir/Xenith/token/token.cpp.o a2b96f15ecedfdd7 +2 137 1778865662389891016 build.ninja e62af03e6510d470 +4 333 1778356183513052019 CMakeFiles/BIPY_App.dir/imgui/backends/imgui_impl_glfw.cpp.o 98ffae70adc86661 +2 2219 1778784415742112339 CMakeFiles/Xenith_Studio.dir/imgui/imgui_tables.cpp.o 7af2c6b743b00546 +5 8912 1778780147519966740 CMakeFiles/BIPY_App.dir/Xenith/core.cpp.o 6cb7eb29ca382303 +4 3195 1778356067684895625 CMakeFiles/BIPY_App.dir/imgui/imgui_draw.cpp.o aadac94ced07c385 +1 10013 1778784423530677763 CMakeFiles/Xenith_Studio.dir/Xenith/core.cpp.o 75fc1accc9ccbfb7 +3 252 1778784413776238204 CMakeFiles/Xenith_Studio.dir/imgui/backends/imgui_impl_opengl3.cpp.o c304bba33816b766 +5 10938 1778865724645927242 CMakeFiles/Xenith_Studio.dir/main.cpp.o 1d76afb3a7c80307 +10939 11279 1778865724988598575 Xenith_Studio 3b63d1325bf76a8b +3 10019 1778866395827010833 CMakeFiles/Xenith_Studio.dir/main.cpp.o 1d76afb3a7c80307 +10019 10298 1778866396109399696 Xenith_Studio 3b63d1325bf76a8b +3 10320 1778866459031278247 CMakeFiles/Xenith_Studio.dir/main.cpp.o 1d76afb3a7c80307 +10320 10631 1778866459343783291 Xenith_Studio 3b63d1325bf76a8b +4 10229 1778867165712694964 CMakeFiles/Xenith_Studio.dir/main.cpp.o 1d76afb3a7c80307 +10229 10510 1778867165996696192 Xenith_Studio 3b63d1325bf76a8b diff --git a/build/CMakeFiles/Xenith_Studio.dir/main.cpp.o b/build/CMakeFiles/Xenith_Studio.dir/main.cpp.o index 13fff71..69fc8eb 100644 Binary files a/build/CMakeFiles/Xenith_Studio.dir/main.cpp.o and b/build/CMakeFiles/Xenith_Studio.dir/main.cpp.o differ diff --git a/build/Xenith_Studio b/build/Xenith_Studio index f866404..d38202e 100755 Binary files a/build/Xenith_Studio and b/build/Xenith_Studio differ diff --git a/build/architecture.txt b/build/architecture.txt index 539a657..e4937fa 100644 --- a/build/architecture.txt +++ b/build/architecture.txt @@ -1,26 +1,20 @@ [ARCHITECTURE] -layers=4 +layers=3 [LAYER 0] -size=2048 +size=65536 branch=-1 sources= branches= [LAYER 1] -size=128 +size=2048 branch=-1 -sources= -branches= +sources=0 +branches=-1 [LAYER 2] -size=128 -branch=-1 -sources= -branches= - -[LAYER 3] size=300 branch=-1 -sources= -branches= +sources=1 +branches=-1 diff --git a/build/imgui.ini b/build/imgui.ini index 49835e2..0e5bb49 100644 --- a/build/imgui.ini +++ b/build/imgui.ini @@ -12,7 +12,7 @@ Size=1280,720 [Window][Main] Pos=0,0 -Size=2560,1371 +Size=1600,1000 [Window][Studio] Pos=0,0 @@ -28,5 +28,5 @@ Size=1600,1000 [Window][##Props] Pos=26,120 -Size=240,220 +Size=240,240 diff --git a/main.cpp b/main.cpp index b999fbc..0e87fbd 100644 --- a/main.cpp +++ b/main.cpp @@ -1,5 +1,5 @@ // ============================================================================ -// Xenith Studio - Node Editor v3.1 (Исправлено обучение + Загрузка из файла + Фикс портов) +// Xenith AI Studio v3.2 // ============================================================================ #define IMGUI_DEFINE_MATH_OPERATORS @@ -21,12 +21,23 @@ #include #include #include +#include +#include #include "Xenith/core.hpp" #include "Xenith/token/token.hpp" // ============================================================================ -// NODE EDITOR ENGINE +// ⚠️ ГЛОБАЛЬНЫЕ НАСТРОЙКИ - ДОЛЖНЫ БЫТЬ ПЕРЕД ВСЕМИ ФУНКЦИЯМИ КОТОРЫЕ ИХ ИСПОЛЬЗУЮТ +// ============================================================================ + +int UI_CONTEXT = 512; +int UI_EMBED = 128; +int UI_VOCAB = 300; +int MAX_RESPONSE_TOKENS = 128; + +// ============================================================================ +// NODE EDITOR ENGINE (теперь видит UI_CONTEXT, UI_EMBED, UI_VOCAB) // ============================================================================ namespace NodeEditor { @@ -54,12 +65,14 @@ struct Node { int layerSize; int branchCount; int activeBranch; + bool isSizeFixed; // NEW: для Input/Output std::vector inputs; std::vector outputs; Node(int id_, const std::string& t_, NodeType type_) : id(id_), title(t_), type(type_), pos(0,0), size(180,100), - selected(false), dragging(false), layerSize(128), branchCount(2), activeBranch(-1) { + selected(false), dragging(false), layerSize(128), branchCount(2), + activeBranch(-1), isSizeFixed(false) { UpdatePorts(); } @@ -67,25 +80,32 @@ struct Node { inputs.clear(); outputs.clear(); switch(type) { case NodeType::Input: - // ИСПРАВЛЕНО: 0 входов, 1 выход outputs.push_back(Port("Out", PortType::Output)); + isSizeFixed = true; + // Размер вычисляется из глобальных настроек + layerSize = UI_CONTEXT * UI_EMBED; break; case NodeType::Hidden: - // ИСПРАВЛЕНО: 1 вход, 1 выход inputs.push_back(Port("In", PortType::Input)); outputs.push_back(Port("Out", PortType::Output)); + isSizeFixed = false; break; case NodeType::Output: - // ИСПРАВЛЕНО: 1 вход, 0 выходов inputs.push_back(Port("In", PortType::Input)); + isSizeFixed = true; + layerSize = UI_VOCAB; break; case NodeType::Splitter: inputs.push_back(Port("In", PortType::Input)); - for(int i=0;iAddRect(scr, scr + n.size, GetNodeColor(n.type, n.selected), 6, 0, 2.0f); dl->AddText(scr + ImVec2(10,4), IM_COL32(255,255,255,255), n.title.c_str()); - dl->AddText(scr + ImVec2(10,20), IM_COL32(160,160,160,200), std::to_string(n.layerSize).c_str()); + + // Отображение размера + if(n.isSizeFixed) { + std::string sizeInfo = std::to_string(n.layerSize) + " (auto)"; + dl->AddText(scr + ImVec2(10,20), IM_COL32(160,160,160,200), sizeInfo.c_str()); + if(n.type == NodeType::Input) { + dl->AddText(scr + ImVec2(10,36), IM_COL32(100,100,100,150), "CTX×EMB"); + } else if(n.type == NodeType::Output) { + dl->AddText(scr + ImVec2(10,36), IM_COL32(100,100,100,150), "VOCAB"); + } + } else { + dl->AddText(scr + ImVec2(10,20), IM_COL32(160,160,160,200), std::to_string(n.layerSize).c_str()); + } if(n.type == NodeType::Splitter || n.type == NodeType::Merger) { dl->AddText(scr + ImVec2(10, n.size.y-18), IM_COL32(255,220,100,255), (" x"+std::to_string(n.branchCount)).c_str()); } + // Порты ввода for(size_t i=0; iAddCircle(p, 5, IM_COL32(50,50,50,255), 12, 1.5f); dl->AddText(p + ImVec2(10,-5), IM_COL32(200,200,200,255), n.inputs[i].name.c_str()); } + // Порты вывода for(size_t i=0; iAddLine(canvasPos+ImVec2(x,0), canvasPos+ImVec2(x,canvasSize.y), IM_COL32(40,44,55,120)); - for(float y=off.y; yAddLine(canvasPos+ImVec2(0,y), canvasPos+ImVec2(canvasSize.x,y), IM_COL32(40,44,55,120)); + for(float x=off.x; xAddLine(canvasPos+ImVec2(x,0), canvasPos+ImVec2(x,canvasSize.y), IM_COL32(40,44,55,120)); + for(float y=off.y; yAddLine(canvasPos+ImVec2(0,y), canvasPos+ImVec2(canvasSize.x,y), IM_COL32(40,44,55,120)); DrawConnections(dl, g, canvasPos, g.pan); for(auto& n : g.nodes) DrawNode(dl, n, g, canvasPos, g.pan); @@ -267,13 +313,29 @@ void DrawGraph(GraphState& g, const ImVec2& canvasSize) { if(ImGui::BeginPopupContextItem("##Ctx")) { ImVec2 wPos = ImGui::GetMousePos() - canvasPos - g.pan; - if(ImGui::MenuItem("🟢 Input")) { g.nodes.emplace_back(g.nextId++, "Input", NodeType::Input); g.nodes.back().pos=wPos; } - if(ImGui::MenuItem(" Hidden")) { g.nodes.emplace_back(g.nextId++, "Hidden", NodeType::Hidden); g.nodes.back().pos=wPos; } - if(ImGui::MenuItem(" Output")) { g.nodes.emplace_back(g.nextId++, "Output", NodeType::Output); g.nodes.back().pos=wPos; } + if(ImGui::MenuItem("🟢 Input")) { + auto& n = g.nodes.emplace_back(g.nextId++, "Input", NodeType::Input); + n.pos=wPos; + } + if(ImGui::MenuItem(" Hidden")) { + auto& n = g.nodes.emplace_back(g.nextId++, "Hidden", NodeType::Hidden); + n.pos=wPos; + } + if(ImGui::MenuItem(" Output")) { + auto& n = g.nodes.emplace_back(g.nextId++, "Output", NodeType::Output); + n.pos=wPos; + } ImGui::Separator(); - if(ImGui::MenuItem(" Splitter (x2)")) { auto& n=g.nodes.emplace_back(g.nextId++, "Splitter", NodeType::Splitter); n.pos=wPos; n.branchCount=2; n.UpdatePorts(); } - if(ImGui::MenuItem(" Merger (x2)")) { auto& n=g.nodes.emplace_back(g.nextId++, "Merger", NodeType::Merger); n.pos=wPos; n.branchCount=2; n.UpdatePorts(); } - ImGui::Separator(); ImGui::Text("LMB: Drag/Connect | RMB: Cancel | MMB: Pan"); + if(ImGui::MenuItem(" Splitter")) { + auto& n = g.nodes.emplace_back(g.nextId++, "Splitter", NodeType::Splitter); + n.pos=wPos; n.branchCount=2; n.UpdatePorts(); + } + if(ImGui::MenuItem(" Merger")) { + auto& n = g.nodes.emplace_back(g.nextId++, "Merger", NodeType::Merger); + n.pos=wPos; n.branchCount=2; n.UpdatePorts(); + } + ImGui::Separator(); + ImGui::Text("LMB: Drag/Connect | RMB: Cancel | MMB: Pan"); ImGui::EndPopup(); } @@ -282,16 +344,32 @@ void DrawGraph(GraphState& g, const ImVec2& canvasSize) { if(it != g.nodes.end()) { Node& sel = *it; ImGui::SetNextWindowPos(canvasPos + ImVec2(10,10)); - ImGui::SetNextWindowSize(ImVec2(240,220)); + ImGui::SetNextWindowSize(ImVec2(240,240)); if(ImGui::Begin("##Props", nullptr, ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoMove)) { - ImGui::TextColored(ImVec4(1,1,0.5f,1), "%s # %d", sel.title.c_str(), sel.id); ImGui::Separator(); + ImGui::TextColored(ImVec4(1,1,0.5f,1), "%s # %d", sel.title.c_str(), sel.id); + ImGui::Separator(); - if(sel.type != NodeType::Output) { ImGui::InputInt("Neurons", &sel.layerSize); if(sel.layerSize<1) sel.layerSize=1; } + // Редактирование размера ТОЛЬКО для не-фиксированных слоёв + if(!sel.isSizeFixed) { + ImGui::InputInt("Neurons", &sel.layerSize); + if(sel.layerSize < 1) sel.layerSize = 1; + } else { + ImGui::Text("Size: %d (auto)", sel.layerSize); + if(sel.type == NodeType::Input) { + ImGui::TextColored(ImVec4(0.5,0.5,0.5,1), "= CONTEXT × EMBED"); + ImGui::TextColored(ImVec4(0.5,0.5,0.5,1), "= %d × %d", UI_CONTEXT, UI_EMBED); + } else if(sel.type == NodeType::Output) { + ImGui::TextColored(ImVec4(0.5,0.5,0.5,1), "= VOCAB_SIZE"); + ImGui::TextColored(ImVec4(0.5,0.5,0.5,1), "= %d", UI_VOCAB); + } + } if(sel.type == NodeType::Splitter || sel.type == NodeType::Merger) { + ImGui::Separator(); ImGui::SliderInt("Branches", &sel.branchCount, 2, 8); if(ImGui::IsItemDeactivatedAfterEdit()) sel.UpdatePorts(); } else if(sel.type == NodeType::Input) { + ImGui::Separator(); ImGui::Text("Branch:"); ImGui::RadioButton("Combined", &sel.activeBranch, -1); ImGui::RadioButton("A (0)", &sel.activeBranch, 0); @@ -300,7 +378,8 @@ void DrawGraph(GraphState& g, const ImVec2& canvasSize) { ImGui::Spacing(); if(ImGui::Button("🗑 Delete", ImVec2(-1,28))) { - g.connections.erase(std::remove_if(g.connections.begin(), g.connections.end(), [id=sel.id](const Connection& c){return c.fromNode==id||c.toNode==id;}), g.connections.end()); + g.connections.erase(std::remove_if(g.connections.begin(), g.connections.end(), + [id=sel.id](const Connection& c){return c.fromNode==id||c.toNode==id;}), g.connections.end()); g.nodes.erase(it); g.selectedNode=-1; } ImGui::End(); @@ -316,8 +395,20 @@ void SyncFromConfigs(GraphState& g, const std::vector& cfgs) { NodeType t = c.sources.empty() ? NodeType::Input : (i==cfgs.size()-1 ? NodeType::Output : NodeType::Hidden); Node n(g.nextId++, t==NodeType::Input?"Input":t==NodeType::Output?"Output":"Hidden", t); n.pos = ImVec2(120 + i*260, 150 + (i%3)*120); - n.layerSize = c.size; n.activeBranch = c.branch; - // UpdatePorts вызывается в конструкторе, но для гарантии: + + // Фиксированные размеры для Input/Output + if(t == NodeType::Input) { + n.layerSize = UI_CONTEXT * UI_EMBED; + n.isSizeFixed = true; + } else if(t == NodeType::Output) { + n.layerSize = UI_VOCAB; + n.isSizeFixed = true; + } else { + n.layerSize = c.size; + n.isSizeFixed = false; + } + + n.activeBranch = c.branch; n.UpdatePorts(); g.nodes.push_back(n); } @@ -337,7 +428,9 @@ void SyncToConfigs(GraphState& g, std::vector& cfgs) { for(size_t i=0;iid] = (int)i; for(const Node* n : sorted) { - LayerStructure_t l; l.size=n->layerSize; l.branch=n->activeBranch; + LayerStructure_t l; + l.size = n->layerSize; + l.branch = n->activeBranch; for(const auto& c : g.connections) { if(c.toNode==n->id && idToIdx.count(c.fromNode)) { l.sources.push_back(idToIdx[c.fromNode]); @@ -362,13 +455,21 @@ std::string GenerateArchitectureText(const GraphState& g, const std::vector& configs, const std::string& filename) { std::ofstream file(filename); if(!file.is_open()) return false; @@ -538,9 +639,6 @@ bool LoadDatasetFromFile(std::string& buffer, const std::string& filename) { // GLOBAL STATE // ============================================================================ -int UI_CONTEXT = 256, UI_EMBED = 8, UI_VOCAB = 300; -int MAX_RESPONSE_TOKENS = 50; - struct UIState { std::vector chats; int activeChat = 0; @@ -553,11 +651,11 @@ struct UIState { int epochs = 10; int doneEpochs = 0; + // Performance metrics double tokensPerSecond = 0.0; double generationTokensPerSecond = 0.0; int totalTokensTrained = 0; std::chrono::steady_clock::time_point trainingStartTime; - std::chrono::steady_clock::time_point lastTokenTime; char dsBuf[524288] = ""; std::vector parsedSamples; @@ -568,7 +666,6 @@ struct UIState { NodeEditor::GraphState graph; std::string architectureText; - bool showArchitecture = true; char archFilePath[256] = "architecture.txt"; char datasetFilePath[256] = "dataset.txt"; @@ -609,7 +706,6 @@ void TrainTask(NeuralNetwork* nn, Tokenizer* tk, Embedder* eb) { int os = ui.layers.back().size; double totalLoss = 0; int sampleCount = 0; - int totalTokens = 0; ui.trainingStartTime = std::chrono::steady_clock::now(); ui.totalTokensTrained = 0; @@ -633,7 +729,6 @@ void TrainTask(NeuralNetwork* nn, Tokenizer* tk, Embedder* eb) { double loss = nn->train(PrepInput(context, *eb), target, ui.lr); totalLoss += loss; sampleCount++; - totalTokens++; ui.totalTokensTrained++; context.push_back(aiToks[i]); @@ -663,19 +758,16 @@ void TrainTask(NeuralNetwork* nn, Tokenizer* tk, Embedder* eb) { ui.doneEpochs++; - // Логируем каждую эпоху std::cout << "Epoch " << (e+1) << "/" << ui.epochs - << " | Loss: " << (totalLoss/sampleCount) + << " | Loss: " << (totalLoss/(sampleCount>0?sampleCount:1)) << " | Time: " << epochTime << "s" - << " | Tokens/sec: " << ui.tokensPerSecond - << "\n"; + << " | Tokens/sec: " << ui.tokensPerSecond << "\n"; } if(sampleCount > 0) { std::lock_guard lk(ui.mtx); ui.lastStatus.totalLoss = totalLoss / sampleCount; - // Общая статистика auto totalTime = std::chrono::duration( std::chrono::steady_clock::now() - ui.trainingStartTime).count(); if(totalTime > 0) { @@ -686,6 +778,7 @@ void TrainTask(NeuralNetwork* nn, Tokenizer* tk, Embedder* eb) { ui.training=false; ui.stop=false; } + // ============================================================================ // MAIN // ============================================================================ @@ -700,6 +793,7 @@ int main() { io.Fonts->AddFontFromFileTTF("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", 16.0f, nullptr, io.Fonts->GetGlyphRangesCyrillic()); ImGui_ImplGlfw_InitForOpenGL(win, true); ImGui_ImplOpenGL3_Init("#version 130"); + // Init default architecture ui.layers = { LayerStructure_t(UI_CONTEXT*UI_EMBED,{}), LayerStructure_t(512,{0}), @@ -721,6 +815,9 @@ int main() { std::cout << "Loaded architecture from " << ui.archFilePath << "\n"; } + // Track last values for auto-update + int lastContext = UI_CONTEXT, lastEmbed = UI_EMBED, lastVocab = UI_VOCAB; + while(!glfwWindowShouldClose(win)) { glfwPollEvents(); ImGui_ImplOpenGL3_NewFrame(); ImGui_ImplGlfw_NewFrame(); ImGui::NewFrame(); @@ -750,6 +847,7 @@ int main() { ImGui::EndMenuBar(); } + // Status bar { std::lock_guard lk(ui.mtx); ImGui::Text("Epoch: %d/%d | Loss: %.5f | %.1f%%", @@ -761,6 +859,7 @@ int main() { } ImGui::Separator(); + // Three columns ImGui::Columns(3, "MainCols", true); ImGui::SetColumnWidth(0, io.DisplaySize.x*0.35f); ImGui::SetColumnWidth(1, io.DisplaySize.x*0.35f); @@ -792,18 +891,18 @@ int main() { } if(ImGui::BeginTabItem("Training")) { + // Performance metrics ImGui::TextColored(ImVec4(0,1,1,1), "Performance Metrics:"); ImGui::Separator(); - { std::lock_guard lk(ui.mtx); ImGui::Text("Training Speed: %.2f tokens/sec", ui.tokensPerSecond); ImGui::Text("Generation Speed: %.2f tokens/sec", ui.generationTokensPerSecond); ImGui::Text("Total Tokens Trained: %d", ui.totalTokensTrained); } - ImGui::Separator(); + // Settings ImGui::SliderFloat("Learning Rate", &ui.lr, 0.0001f, 0.1f, "%.5f"); ImGui::InputInt("Epochs", &ui.epochs); if(ui.epochs<1) ui.epochs=1; ImGui::InputInt("Max Response Tokens", &MAX_RESPONSE_TOKENS); if(MAX_RESPONSE_TOKENS<1) MAX_RESPONSE_TOKENS=1; @@ -811,6 +910,21 @@ int main() { ImGui::InputInt("Embedding Dim", &UI_EMBED); if(UI_EMBED<1) UI_EMBED=1; ImGui::InputInt("Vocab Size", &UI_VOCAB); if(UI_VOCAB<1) UI_VOCAB=1; + // Auto-update fixed layer sizes when globals change + if(UI_CONTEXT != lastContext || UI_EMBED != lastEmbed || UI_VOCAB != lastVocab) { + lastContext = UI_CONTEXT; lastEmbed = UI_EMBED; lastVocab = UI_VOCAB; + for(auto& node : ui.graph.nodes) { + if(node.type == NodeEditor::NodeType::Input) { + node.layerSize = UI_CONTEXT * UI_EMBED; + node.UpdatePorts(); + } else if(node.type == NodeEditor::NodeType::Output) { + node.layerSize = UI_VOCAB; + node.UpdatePorts(); + } + } + ui.architectureText = NodeEditor::GenerateArchitectureText(ui.graph, ui.layers); + } + ImGui::Separator(); ImGui::TextColored(ImVec4(1,0.5f,0,1), "⚠️ Recommendations:"); if(ui.parsedSamples.size() < 10) { @@ -822,15 +936,17 @@ int main() { if(ui.lr > 0.01f) { ImGui::TextColored(ImVec4(1,0.8f,0,1), "• High learning rate! Try 0.001-0.01"); } + + // Dataset loading + ImGui::Separator(); + ImGui::Text("Dataset File:"); + ImGui::InputText("##DSFile", ui.datasetFilePath, 256); + if(ImGui::Button("Load Dataset from File")) { - std::string tempBuffer; // 1. Создаем переменную для загрузки + std::string tempBuffer; if(LoadDatasetFromFile(tempBuffer, ui.datasetFilePath)) { - // 2. Копируем данные из переменной в буфер ImGui - // Используем strncpy, чтобы не переполнить массив ui.dsBuf strncpy(ui.dsBuf, tempBuffer.c_str(), sizeof(ui.dsBuf) - 1); - ui.dsBuf[sizeof(ui.dsBuf) - 1] = '\0'; // Гарантируем завершение строки нулем - - // 3. Парсим обновленный буфер + ui.dsBuf[sizeof(ui.dsBuf) - 1] = '\0'; ui.parsedSamples = ParseDataset(ui.dsBuf, tok); ui.datasetLoaded = true; std::cout << "Loaded " << ui.parsedSamples.size() << " samples\n"; @@ -954,16 +1070,13 @@ int main() { auto genEndTime = std::chrono::steady_clock::now(); double genTime = std::chrono::duration(genEndTime - genStartTime).count(); - // Добавляем информацию о скорости в лог (опционально) std::cout << "Generated " << generatedTokens << " tokens in " - << genTime << "s (" - << (generatedTokens/genTime) << " tok/s)\n"; + << genTime << "s (" << (generatedTokens/genTime) << " tok/s)\n"; chat.messages.push_back({"AI", ans}); ui.inputBuf[0]=0; ui.scrollChat=true; } - } ImGui::EndChild();