using System.IO; namespace BotSharp.Core.Files.Services; public partial class BotSharpFileService { public async Task InstructPdf(string? provider, string? model, string? modelId, string prompt, List files) { var content = string.Empty; if (string.IsNullOrWhiteSpace(prompt) || files.IsNullOrEmpty()) { return content; } var guid = Guid.NewGuid().ToString(); var sessionDir = GetSessionDirectory(guid); if (!ExistDirectory(sessionDir)) { Directory.CreateDirectory(sessionDir); } try { var pdfFiles = await SaveFiles(sessionDir, files); var images = await ConvertPdfToImages(pdfFiles); if (images.IsNullOrEmpty()) return content; var completion = CompletionProvider.GetChatCompletion(_services, provider: provider ?? "openai", model: model, modelId: modelId ?? "gpt-4", multiModal: true); var message = await completion.GetChatCompletions(new Agent() { Id = Guid.Empty.ToString(), }, new List { new RoleDialogModel(AgentRole.User, prompt) { Files = images.Select(x => new BotSharpFile { FileStorageUrl = x }).ToList() } }); content = message.Content; return content; } catch (Exception ex) { _logger.LogError($"Error when analyzing pdf in file service: {ex.Message}\r\n{ex.InnerException}"); return content; } finally { Directory.Delete(sessionDir, true); } } #region Private methods private string GetSessionDirectory(string id) { var dir = Path.Combine(_baseDir, SESSION_FOLDER, id); return dir; } private async Task> SaveFiles(string dir, List files, string extension = "pdf") { if (string.IsNullOrWhiteSpace(dir) || files.IsNullOrEmpty()) { return Enumerable.Empty(); } var locs = new List(); foreach (var file in files) { try { var bytes = new byte[0]; if (!string.IsNullOrEmpty(file.FileUrl)) { var http = _services.GetRequiredService(); using var client = http.CreateClient(); bytes = await client.GetByteArrayAsync(file.FileUrl); } else if (!string.IsNullOrEmpty(file.FileData)) { (_, bytes) = GetFileInfoFromData(file.FileData); } if (!bytes.IsNullOrEmpty()) { var guid = Guid.NewGuid().ToString(); var fileDir = Path.Combine(dir, guid); if (!ExistDirectory(fileDir)) { Directory.CreateDirectory(fileDir); } var pdfDir = Path.Combine(fileDir, $"{guid}.{extension}"); using (var fs = new FileStream(pdfDir, FileMode.Create)) { fs.Write(bytes, 0, bytes.Length); fs.Close(); locs.Add(pdfDir); Thread.Sleep(100); } } } catch (Exception ex) { _logger.LogWarning($"Error when saving pdf file: {ex.Message}\r\n{ex.InnerException}"); continue; } } return locs; } private async Task> ConvertPdfToImages(IEnumerable files) { var images = new List(); var converter = GetPdf2ImageConverter(); if (converter == null || files.IsNullOrEmpty()) { return images; } foreach (var file in files) { try { var segs = file.Split(Path.DirectorySeparatorChar); var dir = string.Join(Path.DirectorySeparatorChar, segs.SkipLast(1)); var folder = Path.Combine(dir, "screenshots"); var urls = await converter.ConvertPdfToImages(file, folder); images.AddRange(urls); } catch (Exception ex) { _logger.LogWarning($"Error when converting pdf file to images ({file}): {ex.Message}\r\n{ex.InnerException}"); continue; } } return images; } #endregion }