Compare commits

...

10 Commits

Author SHA1 Message Date
KoDer 1a05d3a6d9 Start devloping vulkan 2026-04-29 21:08:19 +07:00
KoDer c02a886327 Merge branch 'main' of http://bipfr.servebeer.com:3000/KoDer/BiPy 2026-04-29 19:33:23 +07:00
KoDer 83420a314a update console design 2026-04-29 19:32:36 +07:00
KoDer 96f0d24c58 Обновить Xenith/token/token.h 2026-04-29 10:57:06 +03:00
KoDer d20cf1b17a Обновить Xenith/core.cpp 2026-04-29 10:56:38 +03:00
KoDer 1cad201b23 Обновить Xenith/typedef.h 2026-04-29 10:54:50 +03:00
KoDer de1c37a16f Обновить main.cpp 2026-04-29 10:54:26 +03:00
KoDer 55bc00e5dc Удалить main 2026-04-29 08:08:05 +03:00
KoDer 0a7974260d edit chatbot and core 2026-04-29 02:05:59 +07:00
KoDer 224a6444ef create core and base chatbot
Co-authored-by: Copilot <copilot@github.com>
2026-04-29 02:05:43 +07:00
14 changed files with 475 additions and 133 deletions
-5
View File
@@ -1,5 +0,0 @@
{
"recommendations": [
"codeium.codeium"
]
}
+7
View File
@@ -0,0 +1,7 @@
{
// Используйте IntelliSense, чтобы узнать о возможных атрибутах.
// Наведите указатель мыши, чтобы просмотреть описания существующих атрибутов.
// Для получения дополнительной информации посетите: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": []
}
+7 -2
View File
@@ -7,9 +7,14 @@
"args": [
"-fdiagnostics-color=always",
"-g",
"${file}",
"-fopenmp",
"${fileDirname}/main.cpp",
"${fileDirname}/Xenith/core.cpp",
"${fileDirname}/Xenith/token/token.cpp",
"-o",
"${fileDirname}/${fileBasenameNoExtension}"
"${fileDirname}/main",
"-I", "${fileDirname}/Xenith",
"-I", "${fileDirname}/Xenith/token"
],
"options": {
"cwd": "${fileDirname}"
+59 -56
View File
@@ -1,82 +1,85 @@
#include "core.h"
#include "core.hpp"
#include <cmath>
#include <cstdlib>
#include <omp.h>
NeuralNetwork::NeuralNetwork(LayerStructure_t layers[], int count) {
numLayers = count;
for (int i = 0; i < count; i++) {
layerSizes.push_back(layers[i].size);
}
#define MAX_CORES 16
// Инициализация весов случайными числами
NeuralNetwork::NeuralNetwork(LayerStructure_t layers[], int count) : numLayers(count) {
for (int i = 0; i < count; i++) sizes.push_back(layers[i].size);
for (int i = 0; i < count - 1; i++) {
std::vector<std::vector<double>> layerWeights;
for (int j = 0; j < layerSizes[i+1]; j++) {
std::vector<double> nodeWeights;
for (int k = 0; k < layerSizes[i]; k++) {
nodeWeights.push_back(((double)rand() / RAND_MAX) * 2 - 1);
}
layerWeights.push_back(nodeWeights);
std::vector<std::vector<double>> layerW;
double scale = sqrt(2.0 / sizes[i]);
for (int j = 0; j < sizes[i+1]; j++) {
std::vector<double> nodeW;
for (int k = 0; k < sizes[i]; k++)
nodeW.push_back(((double)rand()/RAND_MAX * 2 - 1) * scale);
layerW.push_back(nodeW);
}
weights.push_back(layerWeights);
std::vector<double> layerBiases;
for (int j = 0; j < layerSizes[i+1]; j++) {
layerBiases.push_back(((double)rand() / RAND_MAX) * 2 - 1);
}
biases.push_back(layerBiases);
weights.push_back(layerW);
biases.push_back(std::vector<double>(sizes[i+1], 0.0));
}
}
std::vector<double> NeuralNetwork::feedForward(std::vector<double> input) {
std::vector<double> NeuralNetwork::feedForward(const std::vector<double>& input) {
outputs.clear();
outputs.push_back(input);
std::vector<double> current = input;
std::vector<double> curr = input;
for (int i = 0; i < numLayers - 1; i++) {
std::vector<double> next;
for (int j = 0; j < layerSizes[i+1]; j++) {
for (int j = 0; j < sizes[i+1]; j++) {
double sum = biases[i][j];
for (int k = 0; k < layerSizes[i]; k++) {
sum += current[k] * weights[i][j][k];
}
next.push_back(sigmoid(sum));
for (int k = 0; k < (int)curr.size(); k++) sum += curr[k] * weights[i][j][k];
next.push_back(1.0 / (1.0 + exp(-sum)));
}
current = next;
outputs.push_back(current);
curr = next;
outputs.push_back(curr);
}
return current;
return curr;
}
void NeuralNetwork::train(std::vector<double> input, std::vector<double> target, double lr) {
// 1. Прямой проход
feedForward(input);
// 2. Вычисление ошибок для выходного слоя
double NeuralNetwork::train(const std::vector<double>& input, const std::vector<double>& target, double lr) {
omp_set_num_threads(MAX_CORES);
std::vector<double> pred = feedForward(input);
std::vector<std::vector<double>> errors(numLayers);
errors[numLayers - 1].resize(layerSizes[numLayers - 1]);
for (int i = 0; i < layerSizes[numLayers - 1]; i++) {
double output = outputs[numLayers - 1][i];
errors[numLayers - 1][i] = (target[i] - output) * sigmoidDerivative(output);
errors[numLayers - 1].resize(sizes[numLayers - 1]);
double totalErr = 0;
for (int i = 0; i < sizes[numLayers - 1]; i++) {
double e = target[i] - pred[i];
errors[numLayers - 1][i] = e * pred[i] * (1.0 - pred[i]);
totalErr += e * e;
}
// 3. Обратное распространение ошибки на скрытые слои
for (int i = numLayers - 2; i > 0; i--) {
errors[i].resize(layerSizes[i]);
for (int j = 0; j < layerSizes[i]; j++) {
double error = 0.0;
for (int k = 0; k < layerSizes[i+1]; k++) {
error += errors[i+1][k] * weights[i][k][j];
errors[i].resize(sizes[i]);
#pragma omp parallel for
for (int j = 0; j < sizes[i]; j++) {
double e = 0;
for (int k = 0; k < sizes[i + 1]; k++) {
e += errors[i + 1][k] * weights[i][k][j];
}
errors[i][j] = error * sigmoidDerivative(outputs[i][j]);
errors[i][j] = e * outputs[i][j] * (1.0 - outputs[i][j]);
}
}
for (int i = 0; i < numLayers - 1; i++) {
#pragma omp parallel for
for (int j = 0; j < sizes[i + 1]; j++) {
double errorTerm = lr * errors[i + 1][j];
// Вложенный цикл обновления весов
for (int k = 0; k < sizes[i]; k++) {
weights[i][j][k] += errorTerm * outputs[i][k];
}
biases[i][j] += errorTerm;
}
}
// 4. Обновление весов и смещений
for (int i = 0; i < numLayers - 1; i++) {
for (int j = 0; j < layerSizes[i+1]; j++) {
for (int k = 0; k < layerSizes[i]; k++) {
weights[i][j][k] += lr * errors[i+1][j] * outputs[i][k];
}
biases[i][j] += lr * errors[i+1][j];
}
}
}
return totalErr;
}
-28
View File
@@ -1,28 +0,0 @@
#ifndef CORE_H
#define CORE_H
#include "typedef.h"
#include <vector>
#include <cmath>
#include <iostream>
#include <cstdlib>
class NeuralNetwork {
private:
int numLayers;
std::vector<int> layerSizes;
std::vector<std::vector<std::vector<double>>> weights; // weights[layer][to_node][from_node]
std::vector<std::vector<double>> biases; // biases[layer][node]
std::vector<std::vector<double>> outputs; // Храним выходы слоев для backprop
double sigmoid(double x) { return 1.0 / (1.0 + exp(-x)); }
double sigmoidDerivative(double x) { return x * (1.0 - x); }
public:
NeuralNetwork(LayerStructure_t layers[], int count);
std::vector<double> feedForward(std::vector<double> input);
void train(std::vector<double> input, std::vector<double> target, double learningRate);
};
#endif
+25
View File
@@ -0,0 +1,25 @@
#ifndef CORE_H
#define CORE_H
#include "typedef.hpp"
#include <vector>
#include <cmath>
class NeuralNetwork {
private:
int numLayers;
std::vector<int> sizes;
std::vector<std::vector<std::vector<double>>> weights;
std::vector<std::vector<double>> biases;
std::vector<std::vector<double>> outputs;
double sigmoid(double x) { return 1.0 / (1.0 + exp(-x)); }
double sigmoidDeriv(double x) { return x * (1.0 - x); }
public:
NeuralNetwork(LayerStructure_t layers[], int count);
std::vector<double> feedForward(const std::vector<double>& input);
double train(const std::vector<double>& input, const std::vector<double>& target, double lr);
};
#endif
+2
View File
@@ -0,0 +1,2 @@
#version 450
+46
View File
@@ -0,0 +1,46 @@
#include "token.hpp"
#include <algorithm>
#include <random>
void Tokenizer::add(std::string word) {
int id = wordToId.size();
wordToId[word] = id;
idToWord[id] = word;
}
std::string Tokenizer::getWord(int id) {
return idToWord.count(id) ? idToWord[id] : "";
}
std::vector<int> Tokenizer::textToTokens(const std::string& text) {
std::vector<int> tokens;
size_t pos = 0;
while (pos < text.length()) {
int longestId = -1; size_t longestLen = 0;
for (auto const& [word, id] : wordToId) {
if (text.compare(pos, word.length(), word) == 0) {
if (word.length() > longestLen) {
longestLen = word.length(); longestId = id;
}
}
}
if (longestId != -1) {
tokens.push_back(longestId);
pos += longestLen;
} else pos++;
}
return tokens;
}
Embedder::Embedder(int vSize, int dim) {
std::mt19937 gen(42);
std::uniform_real_distribution<double> dist(-1.0, 1.0);
matrix.resize(vSize, std::vector<double>(dim));
for(int i=0; i<vSize; i++)
for(int j=0; j<dim; j++) matrix[i][j] = dist(gen);
}
std::vector<double> Embedder::get(int id) {
if (id >= 0 && id < (int)matrix.size()) return matrix[id];
return std::vector<double>(matrix[0].size(), 0.0);
}
+43
View File
@@ -0,0 +1,43 @@
#ifndef TOKEN_H
#define TOKEN_H
#include <string>
#include <vector>
#include <map>
class Tokenizer {
public:
std::map<std::string, int> wordToId;
std::map<int, std::string> idToWord;
Tokenizer() {
add("<EOS>"); add("[SYS]"); add("[USER]"); add("[AI]"); add(" "); add("\n");
add("."); add(","); add("!"); add("?"); add(":"); add(";"); add("-"); add("\""); add("("); add(")");
add("а"); add("б"); add("в"); add("г"); add("д"); add("е"); add("ё"); add("ж");
add("з"); add("и"); add("й"); add("к"); add("л"); add("м"); add("н"); add("о");
add("п"); add("р"); add("с"); add("т"); add("у"); add("ф"); add("х"); add("ц");
add("ч"); add("ш"); add("щ"); add("ъ"); add("ы"); add("ь"); add("э"); add("ю"); add("я");
add("и"); add("в"); add("не"); add("на"); add("я"); add("что"); add("тот"); add("быть");
add("с"); add("а"); add("весь"); add("это"); add("как"); add("она"); add("по"); add("но");
add("они"); add("к"); add("у"); add("ты"); add("из"); add("мы"); add("за"); add("вы");
add("привет"); add("дела"); add("робот"); add("хорошо"); add("спасибо");
add("да"); add("нет"); add("могу"); add("помочь"); add("знаю"); add("кто");
add("где"); add("когда"); add("почему"); add("хочу"); add("очень");
add("тебя"); add("зовут"); add("BiPy");
}
void add(std::string word);
int getID(std::string word);
std::string getWord(int id);
std::vector<int> textToTokens(const std::string& text);
};
class Embedder {
public:
std::vector<std::vector<double>> matrix;
Embedder(int vSize, int dim);
std::vector<double> get(int id);
};
#endif
-15
View File
@@ -1,15 +0,0 @@
#ifndef TYPEDEF_H
#define TYPEDEF_H
#include <vector>
typedef enum {
SIGMOID
} FunctionActivate_t;
typedef struct {
int size;
FunctionActivate_t activate;
} LayerStructure_t;
#endif
+11
View File
@@ -0,0 +1,11 @@
#ifndef TYPEDEF_H
#define TYPEDEF_H
const int MAX_CONTEXT = 32; // Сколько токенов видит сеть
const int EMBED_DIM = 8; // Размер вектора одного токена
const int MAX_VOCAB = 90; // Размер словаря
typedef enum { SIGMOID } FunctionActivate_t;
typedef struct { int size; FunctionActivate_t activate; } LayerStructure_t;
#endif
+24
View File
@@ -0,0 +1,24 @@
[SYS]ты полезный робот помощник[USER]привет[AI]привет как дела?
[SYS]ты полезный робот помощник[USER]помоги составить меню на ужин из курицы и грибов[AI]Конечно! Можно приготовить классическое фрикасе в сливочном соусе или запечь куриное филе с грибами под сырной шапкой. Что звучит аппетитнее?
[SYS]ты полезный робот помощник[USER]как в Python быстро объединить два списка без дубликатов?[AI]Используй преобразование в множество: list(set(list1) | set(list2)). Это самый быстрый и лаконичный способ.
[SYS]ты полезный робот помощник[USER]мне нужно написать короткое поздравление для коллеги с днем рождения[AI]Держи вариант: «С днем рождения! Желаю крутых проектов, неиссякаемого вдохновения и чтобы работа всегда была в радость. Ура!»
[SYS]ты полезный робот помощник[USER]почему небо синее?[AI]Это происходит из-за релеевского рассеяния: солнечный свет взаимодействует с атмосферой, и короткие волны синего цвета рассеиваются сильнее остальных.
[SYS]ты полезный робот помощник[USER]придумай три идеи для стартапа в 2024 году[AI]1. Платформа для аренды домашних инструментов через ИИ-подбор. 2. Сервис автоматизации «цифрового детокса». 3. Агрегатор экологичных локальных фермерских продуктов.
[SYS]ты полезный робот помощник[USER]что делать, если не выспался, а впереди важный день?[AI]Пей больше воды, прими контрастный душ и старайся делать самые сложные задачи в первой половине дня, пока держится остаток концентрации.
[SYS]ты полезный робот помощник[USER]напиши завязку для детективного романа[AI]«Утром на столе известного антиквара лежал предмет, который он сам лично уничтожил двадцать лет назад. Дверь была заперта изнутри, а камеры не зафиксировали ни одного движения».
[SYS]ты полезный робот помощник[USER]как правильно составить договор аренды квартиры?[AI]Обязательно укажи паспортные данные сторон, опиши состояние имущества, зафиксируй сумму залога и условия его возврата, а также приложи опись техники и мебели.
[SYS]ты полезный робот помощник[USER]составь план тренировки на 15 минут дома[AI]Начни с разминки (2 мин), затем сделай 3 круга: приседания (15 раз), отжимания (10 раз) и планка (45 сек). В конце — легкая растяжка.
[SYS]ты полезный робот помощник[USER]найди ошибку в предложении: «Он одел пальто и вышел»[AI]Ошибка в употреблении глагола. Правильно говорить «надел пальто». Запомни: одевают кого-то, а надевают на себя.
[SYS]ты полезный робот помощник[USER]в чем смысл цитаты «Я знаю, что ничего не знаю»?[AI]Это парадокс Сократа. Он означает, что чем больше человек познает мир, тем яснее он осознает масштаб того, что ему еще неизвестно.
[SYS]ты полезный робот помощник[USER]порекомендуй книгу по саморазвитию[AI]Попробуй «Атомные привычки» Джеймса Клира. Она дает конкретные инструменты, как внедрять полезные изменения в жизнь маленькими шагами.
[SYS]ты полезный робот помощник[USER]как перевести «I'm looking forward to it» на русский?[AI]Самый точный вариант: «Я с нетерпением этого жду» или «Я очень жду этого».
[SYS]ты полезный робот помощник[USER]что приготовить на завтрак за 5 минут?[AI]Овсянка в микроволновке с бананом или тост с авокадо и яйцом-пашот. Быстро, полезно и сытно!
[SYS]ты полезный робот помощник[USER]как работает блокчейн простыми словами?[AI]Это как цифровая тетрадь, записи в которой нельзя стереть или изменить. Копия этой тетради есть у каждого участника, поэтому обмануть систему невозможно.
[SYS]ты технический эксперт, отвечай кратко и по делу[USER]как сбросить кэш DNS в Windows?[AI]Запусти командную строку от имени администратора и введи: ipconfig /flushdns.
[SYS]ты технический эксперт, отвечай кратко и по делу[USER]в чем разница между TCP и UDP?[AI]TCP гарантирует доставку данных и порядок пакетов; UDP работает быстрее, но не проверяет доставку.
[SYS]ты технический эксперт, отвечай кратко и по делу[USER]почему ноутбук сильно шумит?[AI]Основные причины: запыление системы охлаждения, высыхание термопасты или высокая фоновая нагрузка на процессор.
[SYS]ты технический эксперт, отвечай кратко и по делу[USER]как проверить статус порта 8080 на Linux?[AI]Используй команду: sudo lsof -i :8080 или netstat -tuln | grep 8080.
[SYS]ты технический эксперт, отвечай кратко и по делу[USER]что такое рекурсия в программировании?[AI]Это процесс, при котором функция вызывает саму себя в своем теле до достижения базового условия.
[SYS]ты технический эксперт, отвечай кратко и по делу[USER]какой SQL-запрос удаляет таблицу?[AI]Команда: DROP TABLE название_таблицы;.
[SYS]ты технический эксперт, отвечай кратко и по делу[USER]зачем нужен Docker?[AI]Для контейнеризации приложений, обеспечивающей идентичную работу программы на любой ОС.
[SYS]ты технический эксперт, отвечай кратко и по делу[USER]как быстро найти процесс по имени и убить его в Linux?[AI]Используй: pkill имя_процесса.
Executable
BIN
View File
Binary file not shown.
+251 -27
View File
@@ -1,38 +1,262 @@
#include <iostream>
#include <iomanip>
#include <vector>
#include <ctime>
#include "Xenith/core.h"
#include "Xenith/typedef.h"
#include <string>
#include <iomanip>
#include <sstream>
#include <fstream>
#include <algorithm>
#include "Xenith/core.hpp"
#include "Xenith/token/token.hpp"
#include <chrono>
int main() {
srand(time(NULL));
std::string currentSystemPrompt = "";
LayerStructure_t layers[] = {
{2, SIGMOID}, // Вход: 2 числа
{3, SIGMOID}, // Скрытый слой
{1, SIGMOID} // Выход: 1 число
};
LayerStructure_t layers[] = {
{MAX_CONTEXT * EMBED_DIM, SIGMOID},
{256, SIGMOID},
{MAX_VOCAB, SIGMOID}
};
NeuralNetwork nn(layers, 3);
std::vector<double> buildNetInput(const std::vector<int>& tokens, Embedder& emb) {
std::vector<double> netInput;
netInput.reserve(MAX_CONTEXT * EMBED_DIM);
int start = (int)tokens.size() - MAX_CONTEXT;
if (start < 0) start = 0;
int count = 0;
for (int i = start; i < (int)tokens.size(); i++) {
std::vector<double> v = emb.get(tokens[i]);
netInput.insert(netInput.end(), v.begin(), v.end());
count++;
}
while (count < MAX_CONTEXT) {
for (int d = 0; d < EMBED_DIM; d++) netInput.push_back(0.0);
count++;
}
return netInput;
}
// Данные для обучения
std::vector<std::vector<double>> inputs = {{1, 1}, {1, 0}, {0, 0}, {0, 1}};
std::vector<std::vector<double>> targets = {{0}, {1}, {1}, {0}};
// Цикл обучения
std::cout << "Training..." << std::endl;
for (int epoch = 0; epoch < 20000; epoch++) {
for (int i = 0; i < inputs.size(); i++) {
nn.train(inputs[i], targets[i], 0.5);
}
void trainOnSequence(NeuralNetwork& nn, Tokenizer& tok, Embedder& emb, const std::string& dataset, int epochs, double lr) {
std::vector<int> allTokens = tok.textToTokens(dataset);
if (allTokens.size() < 2) {
std::cout << "Error: Sequence too short for training." << std::endl;
return;
}
int numLayers = sizeof(layers) / sizeof(layers[0]);
long long totalParams = 0;
for (int i = 0; i < numLayers - 1; i++) {
totalParams += (long long)layers[i].size * layers[i + 1].size + layers[i + 1].size;
}
// Проверка результатов
std::cout << "Results:" << std::endl;
for (int i = 0; i < inputs.size(); i++) {
std::vector<double> res = nn.feedForward(inputs[i]);
std::cout << inputs[i][0] << " " << inputs[i][1] << " -> "
<< (res[0] > 0.5 ? 1 : 0) << " (raw: " << res[0] << ")" << std::endl;
std::string modelSizeStr;
{
std::stringstream ss;
if (totalParams >= 1e12) ss << std::fixed << std::setprecision(1) << totalParams / 1e12 << "t";
else if (totalParams >= 1e9) ss << std::fixed << std::setprecision(1) << totalParams / 1e9 << "b";
else if (totalParams >= 1e6) ss << std::fixed << std::setprecision(1) << totalParams / 1e6 << "m";
else if (totalParams >= 1e3) ss << std::fixed << std::setprecision(1) << totalParams / 1e3 << "k";
else ss << totalParams;
modelSizeStr = ss.str();
}
std::string sequenceStr = "";
for (int tId : allTokens) {
sequenceStr += "{" + tok.getWord(tId) + " (" + std::to_string(tId) + ")} ";
}
auto startTime = std::chrono::high_resolution_clock::now();
int trainSteps = 0;
double stepsPerSec = 0, maxLoss = 0;
std::cout << "Training logic: Next Token Prediction..." << std::endl;
std::cout << "\033[s\n\n";
for (int e = 1; e <= epochs; e++) {
double totalLoss = 0;
for (size_t i = 1; i < allTokens.size(); i++) {
std::vector<int> context(allTokens.begin(), allTokens.begin() + i);
std::vector<double> target(MAX_VOCAB, 0.0);
target[allTokens[i]] = 1.0;
totalLoss += nn.train(buildNetInput(context, emb), target, lr);
trainSteps++;
auto currentTime = std::chrono::high_resolution_clock::now();
if (std::chrono::duration<double>(currentTime - startTime).count() >= 0.1) {
stepsPerSec = trainSteps / std::chrono::duration<double>(currentTime - startTime).count();
trainSteps = 0;
startTime = currentTime;
}
std::cout << "\033[u";
std::cout << "Epoch " << std::setw(4) << e << "/" << epochs
<< " | Token: " << std::setw(4) << i << "/" << allTokens.size()
<< " | Loss: " << std::fixed << std::setprecision(6) << totalLoss
<< " | Max Loss: " << maxLoss << "\033[K\n";
std::cout << "SPEED: " << std::setw(6) << std::fixed << std::setprecision(1) << stepsPerSec
<< " st/s | MODEL: " << std::setw(7) << modelSizeStr
<< " | CURRENT: [" << std::left << std::setw(15) << tok.getWord(allTokens[i]) << "]"
<< "\033[K" << std::flush;
}
maxLoss = totalLoss;
}
std::cout << "\nDone!" << std::endl;
}
int main() {
Tokenizer tok;
Embedder emb(MAX_VOCAB, EMBED_DIM);
int numLayers = sizeof(layers) / sizeof(layers[0]);
NeuralNetwork nn(layers, numLayers);
while (true) {
std::cout << "xentith~$ ";
std::string cmdIn;
std::getline(std::cin, cmdIn);
if (cmdIn == "/exit") break;
if (cmdIn == "/train") {
int epochs;
double lr;
std::cout << "--- Training Setup ---\n";
std::cout << "Enter number of epochs: ";
std::string epStr; std::getline(std::cin, epStr);
epochs = std::stoi(epStr);
std::cout << "Enter learning rate (e.g. 0.1): ";
std::string lrStr; std::getline(std::cin, lrStr);
lr = std::stod(lrStr);
std::cout << "\n--- Example Content ---\n";
std::cout << "User: ";
std::string userPart;
std::getline(std::cin, userPart);
std::cout << "AI: ";
std::string aiPart;
std::getline(std::cin, aiPart);
std::string finalData = "[SYS]" + currentSystemPrompt +
"[USER]" + userPart +
"[AI]" + aiPart + "<EOS>";
std::cout << "\nTraining logic: Pattern Recognition..." << std::endl;
trainOnSequence(nn, tok, emb, finalData, epochs, lr);
}
else if (cmdIn == "/trainFile") {
std::string content;
std::cout << "Enter filename: ";
std::string filename;
std::getline(std::cin, filename);
std::ifstream file(filename);
if (file.is_open()) {
std::stringstream buffer;
buffer << file.rdbuf();
content = buffer.str();
std::cout << "Loaded " << content.length() << " characters from file." << std::endl;
} else {
std::cout << "Could not open file!" << std::endl;
continue;
}
int epochs;
double lr;
std::cout << "Enter number of epochs: ";
std::string epStr; std::getline(std::cin, epStr);
epochs = std::stoi(epStr);
std::cout << "Enter learning rate (e.g. 0.1): ";
std::string lrStr; std::getline(std::cin, lrStr);
lr = std::stod(lrStr);
std::string finalData = "[SYS]" + currentSystemPrompt + content + "<EOS>";
trainOnSequence(nn, tok, emb, finalData, epochs, lr);
} else if (cmdIn == "/sysPrompt") {
std::cout << "Current System Prompt: " << currentSystemPrompt << std::endl;
std::cout << "Enter new System Prompt: ";
std::getline(std::cin, currentSystemPrompt);
std::cout << "System Prompt updated!" << std::endl;
}
else if (cmdIn == "/help") {
std::cout << "\n--- MENU ---" << std::endl;
std::cout << "/train\n/trainFile\n/sysPrompt\n/help\n/exit\n";
} else if (cmdIn == "/clr") {
std::cout << "\033[2J\033[1;1H";
} else {
std::string prompt = "[SYS]" + currentSystemPrompt + "[USER]" + cmdIn + "[AI]";
std::vector<int> currentTokens = tok.textToTokens(prompt);
std::cout << "AI: ";
long long totalParams = 0;
for (int i = 0; i < numLayers - 1; i++) {
long long weights = (long long)layers[i].size * layers[i + 1].size;
long long biases = (long long)layers[i + 1].size;
totalParams += (weights + biases);
}
std::string modelSizeStr;
{
std::stringstream ss;
if (totalParams >= 1000000000000LL) ss << std::fixed << std::setprecision(1) << (double)totalParams / 1000000000000.0 << "t";
else if (totalParams >= 1000000000LL) ss << std::fixed << std::setprecision(1) << (double)totalParams / 1000000000.0 << "b";
else if (totalParams >= 1000000LL) ss << std::fixed << std::setprecision(1) << (double)totalParams / 1000000.0 << "m";
else if (totalParams >= 1000LL) ss << std::fixed << std::setprecision(1) << (double)totalParams / 1000.0 << "k";
else ss << totalParams;
modelSizeStr = ss.str();
}
// Переменные для замера скорости
auto startTime = std::chrono::high_resolution_clock::now();
int tokensInSecond = 0;
double tokensPerSec = 0;
for (int g = 0; g < 1024; g++) {
std::vector<double> out = nn.feedForward(buildNetInput(currentTokens, emb));
int bestId = 0;
for (int i = 0; i < MAX_VOCAB; i++) {
if (out[i] > out[bestId]) bestId = i;
}
if (bestId == 0) break;
tokensInSecond++;
auto currentTime = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> elapsed = currentTime - startTime;
if (elapsed.count() >= 0.1) {
tokensPerSec = tokensInSecond / elapsed.count();
tokensInSecond = 0;
startTime = currentTime;
}
std::string word = tok.getWord(bestId);
std::cout << word << std::flush;
std::cout << "\033[s" << "\033[999;1H" << "\033[2K"
<< "--- [ID: " << bestId << "] | "
<< "Speed: " << std::fixed << std::setprecision(1) << tokensPerSec*10 << " t/s | "
<< "Model: " << modelSizeStr << " params ---"
<< "\033[u" << std::flush;
currentTokens.push_back(bestId);
}
// Чтобы курсор не остался внизу после генерации
std::cout << std::endl;
}
}
return 0;