using Microsoft.AspNetCore.Mvc; using System.IO; using OASystem.API.OAMethodLib.DoubaoAPI; using OASystem.API.OAMethodLib.HunYuanAPI; using OASystem.API.OAMethodLib.QiYeWeChatAPI; using OASystem.Domain.ViewModels.QiYeWeChat; using TencentCloud.Hunyuan.V20230901.Models; namespace OASystem.API.Controllers { /// /// AI测试控制器 /// [Route("api/[controller]")] public class AITestController : ControllerBase { private readonly IHunyuanService _hunyuanService; private readonly IDoubaoService _doubaoService; private readonly ILogger _logger; private readonly IQiYeWeChatApiService _qiYeWeChatApiService; public AITestController(IHunyuanService hunyuanService, IDoubaoService doubaoService, ILogger logger, IQiYeWeChatApiService qiYeWeChatApiService) { _hunyuanService = hunyuanService; _doubaoService = doubaoService; _logger = logger; _qiYeWeChatApiService = qiYeWeChatApiService; } #region 企业微信发送邮件测试 /// /// 企业微信发送邮件测试 /// [HttpPost("sendEmail")] public async Task> SendEmail([FromForm] IFormFile[] feils) { try { var req = new EmailRequestDto() { ToEmails = new List { "johnny.yang@pan-american-intl.com" }, CcEmails = new List { "Roy.lei@pan-american-intl.com" }, BccEmails = new List { "Roy.lei@pan-american-intl.com" }, Subject = "测试邮件 - 来自企业微信API", Body = "这是一封通过企业微信API发送的测试邮件,包含附件。", Files = feils }; var response = await _qiYeWeChatApiService.EmailSendAsync(req); return Ok(response); } catch (Exception ex) { _logger.LogError(ex, "调用企业微信邮件API失败。"); return StatusCode(500, new { Message = "调用企业微信邮件API失败,请检查配置或网络。", Detail = ex.Message }); } } #endregion #region 豆包 AI /// /// 豆包基础对话 /// [HttpPost("doubao-chat")] public async Task> DoubaoChat(string question, bool isThinking = false) { try { var messages = new List { new DouBaoChatMessage { Role = DouBaoRole.user, Content = question } }; var options = new CompleteChatOptions { ThinkingOptions = new thinkingOptions { IsThinking = isThinking } }; var response = await _doubaoService.CompleteChatAsync(messages, options); return Ok(response); } catch (Exception ex) { _logger.LogError(ex, "调用豆包API失败。"); return StatusCode(500, new { Message = "调用豆包API失败", Detail = ex.Message }); } } /// /// 豆包上传文件 /// [HttpPost("doubao-upload")] public async Task> DoubaoUpload(IFormFile file, string purpose = "user_data") { if (file == null || file.Length == 0) return BadRequest("请选择要上传的文件"); try { var stream = file.OpenReadStream(); var existsFileExpand = new List { "pdf", "docx" }; if (!existsFileExpand.Contains(file.FileName.Split('.').Last().ToLower())) { return BadRequest("请上传pdf、docx文件!不支持其他文件"); } if (file.FileName.Split('.').Last().ToLower() == "docx") { using var docxStream = file.OpenReadStream(); var pdfStream = DoubaoService.ConvertDocxStreamToPdfStream(docxStream); stream = pdfStream; } var response = await _doubaoService.UploadFileAsync(stream, file.FileName, purpose); stream.Dispose(); return Ok(response); } catch (Exception ex) { _logger.LogError(ex, "豆包上传文件失败"); return StatusCode(500, new { Message = "上传失败", Detail = ex.Message }); } } /// /// 豆包获取文件列表 /// [HttpGet("doubao-files")] public async Task> DoubaoListFiles() { try { var response = await _doubaoService.ListFilesAsync(); return Ok(response); } catch (Exception ex) { _logger.LogError(ex, "获取豆包文件列表失败"); return StatusCode(500, new { Message = "获取失败", Detail = ex.Message }); } } /// /// 豆包删除文件 /// [HttpDelete("doubao-file/{fileId}")] public async Task> DoubaoDeleteFile(string fileId) { try { var response = await _doubaoService.DeleteFileAsync(fileId); return Ok(response); } catch (Exception ex) { _logger.LogError(ex, "删除豆包文件失败"); return StatusCode(500, new { Message = "删除失败", Detail = ex.Message }); } } /// /// 豆包多模态对话(支持文本+图片) /// /// 表单请求参数 [HttpPost("doubao-multimodal-chat")] public async Task> DoubaoMultimodalChat([FromForm] DoubaoMultimodalChatRequest request) { if (string.IsNullOrWhiteSpace(request.Question)) return BadRequest("问题不能为空"); try { var contentItems = new List { new DoubaoMultimodalContentItem { Type = "text", Text = request.Question.Trim() } }; if (!string.IsNullOrWhiteSpace(request.FileId)) { contentItems.Add(new DoubaoMultimodalContentItem { Type = "file", FileId = request.FileId.Trim(), }); } if (request.Image != null && request.Image.Length > 0) { using var ms = new MemoryStream(); await request.Image.CopyToAsync(ms); var base64 = Convert.ToBase64String(ms.ToArray()); var mimeType = request.Image.ContentType ?? "image/jpeg"; var dataUrl = $"data:{mimeType};base64,{base64}"; contentItems.Add(new DoubaoMultimodalContentItem { Type = "image_url", ImageUrl = new DoubaoMultimodalImageUrl { Url = dataUrl } }); } var messages = new List { new DoubaoMultimodalChatMessage { Role = "user", Content = contentItems } }; var options = new CompleteMultimodalChatOptions { ThinkingOptions = new DoubaoMultimodalThinkingOptions { IsThinking = request.IsThinking, ReasoningEffort = "medium" } }; var response = await _doubaoService.CompleteMultimodalChatAsync(messages, options); return Ok(response ?? string.Empty); } catch (Exception ex) { _logger.LogError(ex, "调用豆包多模态API失败。"); return StatusCode(500, new { Message = "调用豆包多模态API失败", Detail = ex.Message }); } } #endregion #region 混元 AI /// /// 基础对话示例 /// [HttpPost("chat")] public async Task> BasicChat(string question) { try { var response = await _hunyuanService.ChatCompletionsHunyuan_t1_latestAsync(question); return Ok(response); } catch (Exception ex) { _logger.LogError(ex, "调用腾讯云混元API失败。"); return StatusCode(500, new { Message = "调用腾讯云API失败,请检查配置或网络。", Detail = ex.Message }); } } /// /// 模拟“根据文件提问”的API端点 /// 注意:此示例中,文件内容通过请求体传入。 /// 实际场景中,文件内容可能来自用户上传并解析(如PDF、TXT解析为文本)后的结果。 /// [HttpPost("ask-with-file")] public async Task> AskBasedOnFile([FromBody] AskWithFileRequest request) { if (string.IsNullOrEmpty(request.FileContent) || string.IsNullOrEmpty(request.Question)) { return BadRequest(new { Message = "FileContent和Question字段不能为空。" }); } try { var answer = await _hunyuanService.AskWithFileContextAsync(request.FileContent, request.Question, request.Model); return Ok(answer); } catch (Exception ex) { _logger.LogError(ex, "处理基于文件的提问失败。"); return StatusCode(500, new { Message = "处理请求失败。", Detail = ex.Message }); } } /// /// 用于测试的GET端点,快速验证服务可用性(使用示例数据) /// [HttpGet("test-file-query")] public async Task> TestFileQuery() { // 示例文件内容和问题 var sampleFileContent = "在软件开发中,依赖注入(Dependency Injection)是一种设计模式,用于实现控制反转(Inversion of Control, IoC)。它允许在类外部创建依赖对象,并通过构造函数、属性或方法将其‘注入’到类中,从而降低类之间的耦合度。"; var sampleQuestion = "依赖注入的主要目的是什么?"; var model = "hunyuan-lite"; // 可使用 "hunyuan-pro" 等 try { var answer = await _hunyuanService.AskWithFileContextAsync(sampleFileContent, sampleQuestion, model); return Ok($"测试成功。问题:'{sampleQuestion}'\n回答:{answer}"); } catch (Exception ex) { _logger.LogError(ex, "测试文件提问失败。"); return StatusCode(500, new { Message = "测试失败。", Detail = ex.Message }); } } /// /// 用于“根据文件提问”的请求体 /// public class AskWithFileRequest { public string FileContent { get; set; } = string.Empty; public string Question { get; set; } = string.Empty; public string Model { get; set; } = "hunyuan-lite"; } /// /// 豆包多模态对话请求体(form-data) /// public class DoubaoMultimodalChatRequest { public string Question { get; set; } = string.Empty; public IFormFile? Image { get; set; } public bool IsThinking { get; set; } = false; public string FileId { get; set; } = string.Empty; } #endregion } }