package com.sonic.cow.client.input.voicechat.domain;

import com.alibaba.fastjson.annotation.JSONField;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.google.common.collect.Lists;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.StringUtils;

import java.util.List;

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class LLMConfig {
    @ApiModelProperty("必填：大模型平台标识。使用火山方舟平台时，该参数固定取值：ArkV3。")
    @JSONField(name="Provider")
    private String Provider;
    @ApiModelProperty("可选 自定义推理接入点 EndPointId。当需要使用模型推理功能（如直接调用部署的基础模型）时，此参数为必填。\n" +
            "可前往控制台创建或查询自定义推理接入点。\n" +
            "注意\n" +
            "EndPointId 与 BotId 不可同时填写，若同时填写，则 EndPointId 生效。\n" +
            "当前仅支持自定义推理接入点，不支持预置推理接入点。")
    @JSONField(name="EndPointId")
    private String EndPointId;
    @ApiModelProperty("必填：API 密钥。使用火山方舟平台时，该参数为必填。")
    @JSONField(name="APIKey")
    private String APIKey;
//    @ApiModelProperty("可选 输出文本的最大 token 限制。默认值为 1024。")
//    private int MaxTokens;
//    @ApiModelProperty("可选 采样温度，用于控制生成文本的随机性和创造性，值越大随机性越高。\n" +
//            "取值范围为 (0, 1]，默认值为 0.1。")
//    private double Temperature;
//    @ApiModelProperty("可选 采样的选择范围，控制输出 token 的多样性。模型将从概率分布中累计概率超过该取值的标记中进行采样，以确保采样的选择范围不会过宽，值越大输出的 token 类型越丰富。\n" +
//            "取值范围为 [0, 1]，默认值为 0.3。")
//    private double TopP;
    @ApiModelProperty("可选 示例值：[\"你是小宁，性格幽默又善解人意。你在表达时需简明扼要，有自己的观点。\"]\n" +
            "系统提示词。用于输入控制大模型行为方式的指令，定义了模型的角色、行为准则，特定的输出格式等。")
    @JSONField(name="SystemMessages")
    private String[] SystemMessages;
    @ApiModelProperty("可选 示例值：[ { \"Role\": \"user\", \"Content\": \"你好\" }, { \"Role\": \"assistant\", \"Content\": \"有什么可以帮到你的？\" }, { \"Role\": \"user\", \"Content\": \"你是谁？\" }, { \"Role\": \"assistant\", \"Content\": \"我是你的智能问答助手。\" }\n" +
            "用户提示词，可用于增强模型的回复质量，模型回复时会优先参考此处内容，引导模型生成特定的输出或执行特定的任务。\n" +
            "UserPrompts 存储的对话轮数受 HistoryLength 控制。例如 UserPrompts 中预先存储了两轮对话，HistoryLength 设置为 3，用户已进行了三轮对话，第四轮会话开始时，UserPrompts 中存储的内容会被全部删除。\n" +
            "注意\n" +
            "UserPrompts 中 Role 的取值只包含 user 和 assistant，且必须成对出现，否则大模型可能会出现未定义行为。")
    @JSONField(name="UserPrompts")
    private UserPrompt[] UserPrompts;
//    @ApiModelProperty("可选 示例值：3\n" +
//            "历史问题轮数。默认值为 3。\n" +
//            "在调用该接口时需要确保所有 UserPrompts 和 SystemMessage 消息文本总长度不超过大模型上下文长度。\n" +
//            "例如：历史问题轮数为 3，使用 Skylark2-lite-8k 大模型，长度限制为 8k，UserPrompts 预先存储了两轮对话，用户输入了第一轮会话的问题，此时 SystemMessages+UserPrompts+第一轮会话问题总长度不超过8k。")
//    @JSONField(name="HistoryLength")
//    private int HistoryLength;

    @ApiModelProperty("关闭或开启大模型的深度思考能力。若你使用的是具备深度思考能力的模型，强烈建议通过该字段关闭模型的深度思考能力（disabled），以避免智能体回复耗时过长，影响对话的流畅性。")
    @JSONField(name="ThinkingType")
    private String ThinkingType;


    /**
     * 获取LLM配置
     *
     * @param llmEndPointId
     * @return
     */
    public static LLMConfig getLLMConfig(String llmEndPointId, String llmApiKey, String systemPrompt, List<UserPrompt> userPrompts) {
        List<String> systemPromptList = Lists.newArrayList();
        if (StringUtils.isNotEmpty(systemPrompt)) {
            systemPromptList.add(systemPrompt);
        }
        List<UserPrompt> userPromptList = Lists.newArrayList();
        if (CollectionUtils.isNotEmpty(userPrompts)) {
            userPromptList.addAll(userPrompts);
        }
        return LLMConfig.builder()
                .Provider("BytePlus")
                .EndPointId(llmEndPointId)
                .APIKey(llmApiKey)
//                .Temperature(0.1f)
//                .MaxTokens(1024)
//                .TopP(0.3f)
                .SystemMessages(systemPromptList.toArray(new String[0]))
                .UserPrompts(userPromptList.toArray(new UserPrompt[0]))
                //历史问题轮数。默认值为 3。
//                .HistoryLength(100)
                .ThinkingType("disabled")
                .build();
    }

}