using Dpz.Core.Service.Network;
using Dpz.Core.Service.Network.Models;
using Medallion.Threading;

namespace Dpz.Core.Web.Library.Api.Service;

public class GenerateSessionTitleService(
    IAiChatService aiChatService,
    ChatCompletionService chatCompletionService,
    IDistributedLockProvider distributedLockProvider,
    ILogger<GenerateSessionTitleService> logger
)
{
    public async Task<string?> GenerateAsync(
        string userId,
        string sessionId,
        string questionContent,
        string answerContent,
        string modelType
    )
    {
        string? sessionName = null;
        var lockKey = $"AI_Analyze.Chat.Lock:{userId}_{sessionId}";
        try
        {
            logger.LogInformation(
                "start generate session title. UserId: {UserId}, SessionId: {SessionId}",
                userId,
                sessionId
            );
            await using (await distributedLockProvider.AcquireLockAsync(lockKey))
            {
                var prompt = new StringBuilder("问:")
                    .AppendLine()
                    .AppendLine(questionContent)
                    .AppendLine()
                    .AppendLine("------")
                    .AppendLine()
                    .AppendLine("答:")
                    .AppendLine()
                    .AppendLine(answerContent)
                    .AppendLine()
                    .AppendLine("------")
                    .AppendLine()
                    .AppendLine("请给以上对话简单总结出一个标题")
                    .ToString();
                var message = new ChatMessage { Role = "user", Message = prompt };

                var result = await chatCompletionService.SendChatAsync(
                    [message],
                    x => x.Stream = false
                );

                if (result is { Success: true, Data: not null, Data.Choices.Count: > 0 })
                {
                    sessionName = result.Data.Choices[0].Message.Content;
                    await aiChatService.CreateSessionAsync(
                        userId,
                        sessionId,
                        sessionName,
                        modelType
                    );
                }
            }
            logger.LogInformation(
                "generate session title completed. UserId: {UserId}, SessionId: {SessionId},SessionName:{SessionName}",
                userId,
                sessionId,
                sessionName
            );
        }
        catch (Exception e)
        {
            logger.LogError(
                e,
                "generate session title failed. UserId: {UserId}, SessionId: {SessionId}",
                userId,
                sessionId
            );
        }

        return sessionName;
    }
}
⚠⚠    以下内容为AI分析的结果,请根据实际情况进行判断。

代码功能解释

这段代码是一个名为 GenerateSessionTitleService 的服务类,主要用于根据用户对话内容自动生成对话会话的标题。以下是详细的功能解释:

主要功能

  1. 自动生成对话标题:根据用户的问题和AI的回答内容,使用AI模型自动生成一个简洁的标题来概括整个对话。

  2. 会话管理:生成标题后,会创建一个新的会话记录,将标题与用户ID、会话ID等信息关联存储。

关键组件

  • 依赖注入的服务
    • IAiChatService:用于创建和管理AI聊天会话
    • ChatCompletionService:用于与AI模型交互,生成对话标题
    • IDistributedLockProvider:提供分布式锁,防止并发操作
    • ILogger:用于记录日志

方法流程

  1. 输入参数

    • userId:用户唯一标识
    • sessionId:会话唯一标识
    • questionContent:用户提问内容
    • answerContent:AI回答内容
    • modelType:使用的AI模型类型
  2. 执行步骤

    • 获取分布式锁(防止同一会话并发操作)
    • 构建提示词(prompt),将用户问题和AI回答组合在一起
    • 调用AI模型生成标题
    • 如果成功获取标题,创建新的会话记录
    • 释放锁并返回生成的标题
  3. 异常处理

    • 捕获并记录任何异常,确保服务不会因异常而崩溃

使用场景

这段代码可能用在聊天应用中,当用户开始一个新的对话时,系统会自动为这个对话生成一个有意义的标题,方便用户后续查找和管理历史对话。

技术细节

  1. 分布式锁:使用 lockKey 确保同一用户同一会话的标题生成操作是串行的
  2. 日志记录:详细记录操作开始、完成和失败的情况
  3. AI提示工程:精心设计的提示词让AI能够更好地生成合适的标题

这种自动生成标题的功能可以显著提升用户体验,特别是在用户有大量历史对话需要管理时。

评论加载中...