using System.Collections.Concurrent; using System.Text; using System.Text.RegularExpressions; using Newtonsoft.Json; namespace ConsoleApp1; public class EpisodeInfo { public string path; public string name; public string session; public string episode; public string group; public string type; // others, episode, subtitle public string language; } public class EpisodeParseResult { public bool success; public string originalQuestion; public EpisodeInfo parseResult; } public class EpisodeParser { // todo: 添加解析年份 private bool _running = false; private const string PromptPath = "Prompt.txt"; private readonly string _prompt; private readonly OllamaHelper _ollama; private ConcurrentQueue _questions; private ConcurrentQueue _results; public bool Running => _running; public int TotalQuestions => _questions.Count + _results.Count; public int CompletedQuestions => _results.Count; public int RestQuestions => _questions.Count; public bool TryGetResult(out EpisodeParseResult result) { return _results.TryDequeue(out result); } public EpisodeParser() { _prompt = File.ReadAllText(PromptPath); _ollama = new OllamaHelper(); _questions = new ConcurrentQueue(); _results = new ConcurrentQueue(); } public void Append(string question) { _questions.Enqueue(question); } public void Start() { if (_running) return ; _running = true; DoParse(); } private string Preprocess(string respoonds) { return respoonds.Replace("```json\n", "").Replace("```", ""); } private static string RemoveNonDigits(string s) { return Regex.Replace(s, @"[^\d\.]*", ""); } private static string RemoveFrontZeros(string s) { var result = new StringBuilder(); bool front = true; foreach (var c in s) { if (front && c == '0') continue; front = false; result.Append(c); } return result.ToString(); } private static string ProcessSession(string session) { session = RemoveFrontZeros(RemoveNonDigits(session)); if (session.Length > 2) session = ""; return session == "" ? "1" : session; } private static string ProcessEpisode(string episode) { episode = RemoveFrontZeros(RemoveNonDigits(episode)); return episode == "" ? "1" : episode; } private void FinalProcess(EpisodeInfo info) { if (info.type == "others") { info.episode = ""; info.session = ProcessSession(info.session); } else { info.episode = ProcessEpisode(info.episode); info.session = ProcessSession(info.session); } } private async void DoParse() { while (_questions.TryDequeue(out string question)) { var result = new EpisodeParseResult(); result.originalQuestion = question; var responds = await _ollama.Ask(_prompt + $"\"{question}\""); try { responds = Preprocess(responds); result.parseResult = JsonConvert.DeserializeObject(responds); result.parseResult.path = question; result.success = result.parseResult != null; if (result.success) { FinalProcess(result.parseResult); } } catch (Exception _) { result.success = false; } _results.Enqueue(result); } _running = false; } }