137 lines
No EOL
4.5 KiB
C#
137 lines
No EOL
4.5 KiB
C#
using System.Text;
|
|
using AuthorBuddy.Web.Models;
|
|
|
|
namespace AuthorBuddy.Web.Services;
|
|
|
|
public class LlmWikiService : ILlmWikiService
|
|
{
|
|
private readonly IOllamaService _ollama;
|
|
private readonly OllamaSettings _settings;
|
|
private readonly IProjectService _projectService;
|
|
|
|
public LlmWikiService(IOllamaService ollama, OllamaSettings settings, IProjectService projectService)
|
|
{
|
|
_ollama = ollama;
|
|
_settings = settings;
|
|
_projectService = projectService;
|
|
}
|
|
|
|
public bool WikiExists(int projectId, string rootPath)
|
|
{
|
|
var wikiDir = GetWikiDir(rootPath);
|
|
return Directory.Exists(wikiDir) && Directory.GetFiles(wikiDir, "*.md").Length > 0;
|
|
}
|
|
|
|
public async Task CompileWikiAsync(int projectId, string rootPath, IProgress<string> progress)
|
|
{
|
|
var wikiDir = GetWikiDir(rootPath);
|
|
Directory.CreateDirectory(wikiDir);
|
|
|
|
var files = Directory.GetFiles(rootPath, "*.md", SearchOption.AllDirectories)
|
|
.Where(f => !f.Contains("\\wiki\\") && !f.Contains("/wiki/"))
|
|
.ToList();
|
|
|
|
if (files.Count == 0)
|
|
{
|
|
progress?.Report("Keine Markdown-Dateien gefunden.");
|
|
return;
|
|
}
|
|
|
|
var indexEntries = new List<string>();
|
|
|
|
foreach (var file in files)
|
|
{
|
|
var fileName = Path.GetFileNameWithoutExtension(file);
|
|
var safeName = SanitizeName(fileName);
|
|
progress?.Report($"Komprimiere: {fileName}...");
|
|
|
|
var content = await File.ReadAllTextAsync(file);
|
|
if (string.IsNullOrWhiteSpace(content))
|
|
{
|
|
progress?.Report(" ↳ leer, übersprungen");
|
|
continue;
|
|
}
|
|
|
|
var wikiContent = await CompilePage(content, fileName);
|
|
var wikiPath = Path.Combine(wikiDir, $"{safeName}.md");
|
|
await File.WriteAllTextAsync(wikiPath, wikiContent);
|
|
|
|
indexEntries.Add($"- [{fileName}]({safeName}.md)");
|
|
progress?.Report(" ↳ ✓ Wiki-Seite erstellt");
|
|
}
|
|
|
|
var indexContent = "# Wiki-Index\n\n" +
|
|
$"Erstellt am {DateTime.Now:dd.MM.yyyy HH:mm} aus {files.Count} Quellen.\n\n" +
|
|
string.Join("\n", indexEntries) + "\n";
|
|
await File.WriteAllTextAsync(Path.Combine(wikiDir, "index.md"), indexContent);
|
|
|
|
progress?.Report($"Wiki kompiliert: {indexEntries.Count} Seiten.");
|
|
}
|
|
|
|
public async Task<string> QueryWikiAsync(int projectId, string question)
|
|
{
|
|
var project = await _projectService.GetProjectAsync(projectId);
|
|
if (project == null)
|
|
return "Projekt nicht gefunden.";
|
|
|
|
var wikiDir = GetWikiDir(project.RootPath);
|
|
if (!Directory.Exists(wikiDir))
|
|
return "Wiki noch nicht kompiliert. Bitte zuerst das Wiki erstellen.";
|
|
|
|
var wikiFiles = Directory.GetFiles(wikiDir, "*.md");
|
|
var wikiContent = new StringBuilder();
|
|
|
|
foreach (var file in wikiFiles.OrderBy(f => f))
|
|
{
|
|
var content = await File.ReadAllTextAsync(file);
|
|
wikiContent.AppendLine($"--- {Path.GetFileName(file)} ---");
|
|
wikiContent.AppendLine(content);
|
|
wikiContent.AppendLine();
|
|
}
|
|
|
|
var prompt = $@"Du bist ein Wiki-Assistent. Beantworte die folgende Frage ausschließlich basierend auf dem untenstehenden Wiki. Wenn die Antwort nicht im Wiki zu finden ist, sage das deutlich.
|
|
|
|
WIKI:
|
|
{wikiContent}
|
|
|
|
FRAGE: {question}";
|
|
|
|
return await _ollama.Chat(_settings.StyleModel, prompt, temperature: 0.3, backendName: _settings.StyleBackend);
|
|
}
|
|
|
|
private async Task<string> CompilePage(string content, string title)
|
|
{
|
|
var prompt = $@"Du bist ein Wiki-Redakteur. Erstelle eine strukturierte Wiki-Seite aus dem folgenden Dokument.
|
|
|
|
FORMAT:
|
|
# {title}
|
|
|
|
## Zusammenfassung
|
|
Kurze Zusammenfassung (2-3 Sätze)
|
|
|
|
## Kernkonzepte
|
|
- Konzept 1: Beschreibung
|
|
- Konzept 2: Beschreibung
|
|
|
|
## Details
|
|
Wichtige Fakten und Details aus dem Dokument
|
|
|
|
## Verknüpfungen
|
|
Verweise auf verwandte Themen (falls erkennbar)
|
|
|
|
DOKUMENT:
|
|
{content}";
|
|
|
|
return await _ollama.Chat(_settings.StyleModel, prompt, temperature: 0.3, backendName: _settings.StyleBackend);
|
|
}
|
|
|
|
private static string GetWikiDir(string rootPath) =>
|
|
Path.Combine(rootPath, "wiki");
|
|
|
|
private static string SanitizeName(string name)
|
|
{
|
|
var invalid = Path.GetInvalidFileNameChars();
|
|
var sanitized = new string(name.Where(c => !invalid.Contains(c)).ToArray());
|
|
return string.IsNullOrWhiteSpace(sanitized) ? "unnamed" : sanitized;
|
|
}
|
|
} |