Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 46 additions & 8 deletions Endpoints/AnalysisEndpoints.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using WebEditor.Controllers.Requests;
using System.Text.Json;
using WebEditor.Controllers.Requests;
using WebEditor.Services;

namespace WebEditor.Endpoints
Expand All @@ -7,17 +8,54 @@ public static class AnalysisEndpoints
{
public static void MapAnalysisEndpoints(this WebApplication app)
{
app.MapPost("/analyze", async (TextRequest request, OpenAiService openAi) =>
app.MapPost("/analyze", async (
TextRequest request,
OpenAiService openAi,
TextStatisticsService statsService) =>
{
if (string.IsNullOrWhiteSpace(request.Text))
return Results.BadRequest("Текст не может быть пустым");

var result = await openAi.AnalyzeTextAsync(
request.Text,
request.Language ?? "ru",
request.UserPrompt // ← новое поле
);
return Results.Ok(result);
try
{
var aiResult = await openAi.AnalyzeTextAsync(
request.Text,
request.Language ?? "ru",
request.UserPrompt
);

var stats = statsService.Calculate(request.Text);
var parsed = JsonDocument.Parse(aiResult);

// Собираем финальный объект через Dictionary
var finalResult = new
{
issues = parsed.RootElement
.GetProperty("issues")
.EnumerateArray()
.Select(i => new
{
category = i.TryGetProperty("category", out var c) ? c.GetString() : "",
original = i.TryGetProperty("original", out var o) ? o.GetString() : "",
suggestion = i.TryGetProperty("suggestion", out var s) ? s.GetString() : "",
description = i.TryGetProperty("description", out var d) ? d.GetString() : ""
})
.ToList(),
statistics = new
{
wordCount = stats.WordCount,
sentenceCount = stats.SentenceCount,
readabilityScore = stats.ReadabilityScore,
waterScore = stats.WaterScore
}
};

return Results.Ok(finalResult);
}
catch (Exception ex)
{
return Results.Problem(ex.Message);
}
});
}
}
Expand Down
3 changes: 2 additions & 1 deletion Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@ public static void Main(string[] args)
builder.Configuration.GetConnectionString("Default")));

// SERVICES
builder.Services.AddSingleton<TextStatisticsService>();
builder.Services.AddSingleton<OpenAiService>();

// CORS
builder.Services.AddCors(options =>
options.AddDefaultPolicy(policy =>
Expand Down
224 changes: 223 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,223 @@
# WebEditor
# WebEditor — Система анализа и редактирования текста

Дипломный проект. Информационная система для анализа и редактирования текста с использованием технологий NLP и генеративного ИИ.

---

## Стек технологий

| Слой | Технология |
|---|---|
| Backend | ASP.NET Core Minimal API (C#) |
| Frontend | React.js + Tiptap |
| База данных | MS SQL Server + Entity Framework Core |
| ИИ | Groq API (llama / gpt-oss) |
| Экспорт | DocumentFormat.OpenXml + QuestPDF |

---

## Быстрый старт после клонирования

### 1. Клонируй репозиторий

```bash
git clone https://github.com/твой_юзер/WebEditor.git
cd WebEditor
```

---

### 2. Создай файлы которых нет в репозитории

Эти файлы в `.gitignore` — их нужно создать вручную.

#### `appsettings.Development.json`

Создай в корне проекта рядом с `appsettings.json`:

```json
{
"ConnectionStrings": {
"Default": "Server=ИМЯ_ТВОЕГО_СЕРВЕРА;Database=ServerWebDataBase;Trusted_Connection=True;TrustServerCertificate=True;"
},
"OpenAI": {
"ApiKey": "gsk_xxxxxxxxxxxxxxxx",
"Model": "llama-3.3-70b-versatile"
}
}
```

> Замени `ИМЯ_ТВОЕГО_СЕРВЕРА` на имя своего SQL Server (видно в SSMS вверху Object Explorer, например `Roman` или `DESKTOP-XXXXX\SQLEXPRESS`).
> Замени `gsk_xxxxxxxxxxxxxxxx` на свой API ключ от [console.groq.com](https://console.groq.com).

#### `client/.env`

Создай в папке `client/`:

```
REACT_APP_API_URL=https://localhost:7076
```

> Порт `7076` должен совпадать с тем что указан в `Properties/launchSettings.json` в профиле `https`.

---

### 3. Настрой базу данных

Открой **SSMS** и выполни SQL скрипт для создания базы:

```
/docs/database.sql ← если есть в репозитории
```

Или создай базу вручную — структура таблиц описана в `docs/database_documentation.md`.

После создания базы выполни Scaffold в **Package Manager Console**:

```
Scaffold-DbContext "Server=ИМЯ_СЕРВЕРА;Database=ServerWebDataBase;Trusted_Connection=True;TrustServerCertificate=True;" Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models -Force
```

---

### 4. Установи зависимости фронтенда

```bash
cd client
npm install
```

---

### 5. Запусти проект

Открой **два терминала**:

**Терминал 1 — бэкенд:**
```bash
# В корне проекта (папка с .csproj файлом)
dotnet run
```

**Терминал 2 — фронтенд:**
```bash
cd client
npm start
```

Приложение откроется на `http://localhost:3000`

---

## Структура проекта

```
WebEditor/
├── Endpoints/
│ ├── AnalysisEndpoints.cs # POST /analyze
│ ├── DocumentEndpoints.cs # CRUD документов
│ ├── ExportEndpoints.cs # POST /export/docx, /export/pdf
│ └── ImportEndpoints.cs # POST /import/docx
├── Models/
│ ├── Requests/
│ │ └── TextRequest.cs
│ └── (EF модели генерируются через Scaffold)
├── Prompts/
│ └── SystemPrompt.txt # Системный промпт для ИИ
├── Properties/
│ └── launchSettings.json
├── Services/
│ ├── OpenAiService.cs # Интеграция с Groq API
│ └── TextStatisticsService.cs # Подсчёт статистики текста
├── client/ # React приложение
│ └── src/
│ ├── components/
│ │ ├── EditorToolbar/
│ │ ├── Editor.jsx
│ │ ├── HelpModal.jsx
│ │ ├── IssuePopup.jsx
│ │ ├── ReportModal.jsx
│ │ ├── Results.jsx
│ │ ├── SidePanel.jsx
│ │ └── Toolbar.jsx
│ ├── constants/
│ │ └── categories.js
│ ├── contexts/
│ │ └── ThemeContext.js
│ ├── hooks/
│ │ └── useAnalysis.js
│ └── utils/
│ └── highlight.js
├── appsettings.json # Публичные настройки (заглушки)
├── appsettings.Development.json # СОЗДАТЬ ВРУЧНУЮ — секреты
├── Program.cs
└── WebEditor.csproj
```

---

## Файлы которые нужно создать вручную

| Файл | Где | Зачем |
|---|---|---|
| `appsettings.Development.json` | Корень проекта | API ключ Groq + строка подключения к БД |
| `client/.env` | Папка `client/` | URL бэкенда для React |

---

## Получить API ключ Groq

1. Зайди на [console.groq.com](https://console.groq.com)
2. Зарегистрируйся (бесплатно)
3. API Keys → Create API Key
4. Скопируй ключ в `appsettings.Development.json`

**Доступные модели:**

| Модель | Описание |
|---|---|
| `llama-3.3-70b-versatile` | Стабильная, бесплатная — рекомендуется |
| `openai/gpt-oss-120b` | Мощнее, но больше токенов |
| `qwen/qwen-3-32b` | Хорошо для русского языка |

---

## Настройка промпта

Системный промпт находится в `Prompts/SystemPrompt.txt` — можно редактировать без перекомпиляции. При запуске сервис читает его автоматически.

---

## Возможные проблемы

**`react-scripts не является командой`**
```bash
cd client
npm install
```
Node modules не хранятся в репозитории — нужно установить после клонирования.

**`API вернул ошибку: Unauthorized`**
Проверь что `appsettings.Development.json` создан и API ключ правильный. Убедись что переменная `ASPNETCORE_ENVIRONMENT = Development` прописана в `launchSettings.json`.

**`Не удалось подключиться к БД`**
Проверь строку подключения в `appsettings.Development.json`. Имя сервера видно в SSMS в Object Explorer вверху.

**`TooManyRequests от Groq`**
Бесплатный план имеет лимиты. Подожди минуту или переключись на модель `llama-3.3-70b-versatile`.

---

## Функционал

- Текстовый редактор с форматированием (шрифты, размеры, заголовки, списки, выравнивание)
- Импорт DOCX файлов
- ИИ анализ текста — орфография, пунктуация, грамматика, тавтология, стиль, канцеляризмы
- Автоопределение языка (ru / en / mixed)
- Подсветка ошибок прямо в тексте по категориям
- Контекстный popup с описанием ошибки при клике
- Пользовательские инструкции для ИИ
- Статистика текста (слова, предложения, читаемость, водность)
- Экспорт отчёта в DOCX и PDF
- Светлая и тёмная тема
- Руководство пользователя (кнопка ? в тулбаре)
Loading
Loading