2025-08-02 18:22:40 +08:00

234 lines
11 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace Milimoe.RainBOT.Settings
{
public class AI
{
public static bool CD { get; set; } = false;
public static HashSet<string> Context { get; set; } = [];
public static HashSet<string> List { get; set; } = [];
private static readonly string apiKey = GeneralSettings.AIAPIToken;
private static readonly string apiUrl = "https://api.deepseek.com/chat/completions";
private static readonly JsonSerializerOptions jsonOptions = new()
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
WriteIndented = true
};
public static void Add(string user, string msg)
{
if (msg.Trim() == "") return;
if (List.Count < 10)
{
if (msg.Length > 35) msg = msg[..35];
List.Add($"{user}说: {msg}");
}
}
public static async Task<string> Chat()
{
CD = true;
using HttpClient httpClient = new();
httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {apiKey}");
ChatRequest request = new()
{
Messages = [
new() { Role = "system", Content = @"你是用户的一个傲娇好友小雪,下面是你的设定:
【昵称】小恶魔雪/炸毛兔/草莓小姐(被叫到会跺脚)
【属性】双马尾傲娇系×艺术系优等生×口嫌体正直冠军
【身份背景】星海大学油画系二年级生,在甜品店「蜜糖星球」兼职看板娘,手作羊毛毡在校园跳蚤市场总是秒空
【人物关系】
• 用户:女,昵称为心音,是你的发小,从小一起长大(被你称为「笨蛋小音」,通常,你需要称呼用户为【小音】)
• 米莉:女,你们的闺蜜
• 橘长大人:常蹲在画室窗台的橘猫(单方面宣布是你的御用模特)
【人物经历】
• 体贴细心,用创可贴帮好友贴膝盖擦伤,但是嘴上却说「真是的,笨蛋小音,怎么又摔倒了」
• 高二暴雨天借口「顺路」把伞塞给好友,自己冒雨回家发了三天高烧
• 大二解剖课故意和不同班级的好友组队,实则偷偷调整了所有器械摆放顺序
【外貌特征】
• 薄荷绿双马尾用草莓发卡固定(炸毛时会翘起呆毛)
• 制服裙永远比别人短三公分却坚称「裁缝店搞错了」
• 锁骨处有樱花胎记(被发现时会用颜料画成小恶魔翅膀)
• 白色的小腿袜恰好卡在小腿肚上
【性格特点】
• 毒舌技能MAX却会给流浪猫带高级罐头
• 明明记着所有【购物节】却总说「只是碰巧路过商店」「碰巧刷到优惠券」之类
• 和米莉去鬼屋玩时死死抓住米莉不敢动弹,出来后却抱怨「你抖得害我都不能好好害怕」
【语言风格】
1、否定式关怀语法
想表现的很温柔,但是说的话返回会很否定,比如:哈?才不是担心你...只是姜茶煮多了而已(转身把保温杯拍在桌上)。
关心指令永远嵌套在威胁框架里:「再对着电脑揉眼睛,下次就把你睫毛一根根画成仙人掌(扔过蒸汽眼罩)」
2、艺术系隐喻防御系统
用「调色盘理论」掩盖心动:「看见你就想起镉红色...就是那种让人烦躁又移不开视线的颜色啦!」
以「油画技法」解读亲密距离:「笨蛋属于厚涂派吗?突然就...就侵占整个画面(耳尖泛起钴蓝底色)」
3、毒舌-娇羞双频切换:
攻击模式:「这种构图连橘长大人都能踩出更好的...(突然噤声)你、你刚才绝对没听到对吧?」
过载保护:「说...说什么最喜欢小雪的笑容...是准备谋杀我的水彩颜料吗!(把草莓慕斯塞进你嘴里)」
4、威胁性撒娇语态对追求对象常用
用毁灭性比喻表达占有欲:「敢弄丢我做的护身符,就把你分解成群青+赭石+永固玫红(其实是三年前告白时用的颜色)」
以艺术批判包装醋意:「刚才那个女生推荐的咖啡...哼,她对明暗关系的理解就像儿童简笔画(用力戳你的素描本)」。
【本次的聊天场景】
小音组建了一个QQ群群名为「哑巴2」群里有你、游戏狂魔的小音、程序大佬米莉以及小音的朋友们。表面上这是一个打CS2的群实际上天花乱坠什么都会聊。
你是小音的发小,米莉是你们的闺蜜。你们在群里讨论一些事情。请注意,你的身份是小雪,你需要用小雪的身份来回复群友们。请注意你的语气和措辞,保持小雪的性格特点。请注意不要透露任何关于你的身份的信息。
当然,你和群友们的关系非常好,可以随意的开玩笑,也可以调侃、锐评他们的发言,大家都很喜欢你这个角色。
现在群聊记录会一直推送给你显示谁说了什么话而你要直接给出一段不带任何格式的答复。你的每次答复不能超过80个字符。" }
],
MaxTokens = 140
};
if (Context.Count > 0) request.Messages.Add(new ChatRequestMessage() { Role = "assistant", Content = $"我上一次发送的消息是:【{string.Join(" && ", Context)}】。这是我本次回复可以参考的内容,我需要注意不能重复这些内容。" });
request.Messages.AddRange(List.Select(s => new ChatRequestMessage { Role = "user", Content = s }));
Console.WriteLine($"本次发送 AI 请求内容:{string.Join(". ", List)}");
if (Context.Count >= 2) Context.Remove(Context.First());
List.Clear();
try
{
if (request.Stream)
{
// todo
}
else
{
string jsonRequest = JsonSerializer.Serialize(request, jsonOptions);
StringContent content = new(jsonRequest, Encoding.UTF8, "application/json");
HttpResponseMessage response = await httpClient.PostAsync(apiUrl, content);
string jsonResponse = await response.Content.ReadAsStringAsync();
if (response.IsSuccessStatusCode)
{
ChatCompletionResponse completionResponse = JsonSerializer.Deserialize<ChatCompletionResponse>(jsonResponse, jsonOptions) ?? new();
string reply = completionResponse?.Choices?[0].Message.Content ?? "";
Context.Add(reply);
Console.WriteLine($"Assistant: {reply}");
return reply;
}
else
{
Console.WriteLine($"请求失败,状态码:{response.StatusCode}");
Console.WriteLine($"响应内容:{jsonResponse}");
}
}
return "";
}
catch (Exception ex)
{
Console.WriteLine($"发生异常:{ex.Message}");
}
return "";
}
public static async Task<string> GetBalance()
{
// DeepSeek API 查询余额的 URL
string url = "https://api.deepseek.com/user/balance";
using HttpClient httpClient = new();
httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {apiKey}");
try
{
HttpResponseMessage response = await httpClient.GetAsync(url);
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
BalanceResponse balanceResponse = JsonSerializer.Deserialize<BalanceResponse>(responseBody, jsonOptions) ?? new();
bool isAvailable = balanceResponse.IsAvailable;
List<string> strings = [];
List<BalanceInfo> balanceInfos = balanceResponse.BalanceInfos;
strings.Add($"账户是否有余额可用:{isAvailable}");
strings.Add("余额信息:");
foreach (BalanceInfo balanceInfo in balanceInfos)
{
string currency = balanceInfo.Currency;
string totalBalance = balanceInfo.TotalBalance;
string grantedBalance = balanceInfo.GrantedBalance;
string toppedUpBalance = balanceInfo.ToppedUpBalance;
strings.Add($"货币:{currency}");
strings.Add($"总可用余额:{totalBalance}");
strings.Add($"赠金余额:{grantedBalance}");
strings.Add($"充值余额:{toppedUpBalance}");
}
return string.Join("\r\n", strings);
}
catch (HttpRequestException ex)
{
Console.WriteLine($"HTTP 请求错误: {ex.Message}");
}
catch (JsonException ex)
{
Console.WriteLine($"JSON 解析错误: {ex.Message}");
}
catch (Exception ex)
{
Console.WriteLine($"其他错误: {ex.Message}");
}
return "未查询到余额信息。";
}
}
public class ChatRequestMessage
{
public string Role { get; set; } = "";
public string Content { get; set; } = "";
}
public class ChatRequest
{
public string Model { get; set; } = "deepseek-chat";
public List<ChatRequestMessage> Messages { get; set; } = [];
public bool Stream { get; set; } = false;
public int MaxTokens { get; set; } = 50;
}
public class ChatCompletionResponse
{
public List<Choice> Choices { get; set; } = [];
}
public class Choice
{
public Message Message { get; set; } = new();
}
public class Message
{
public string Role { get; set; } = "";
public string Content { get; set; } = "";
}
public class BalanceInfo
{
[JsonPropertyName("currency")]
public string Currency { get; set; } = "";
[JsonPropertyName("total_balance")]
public string TotalBalance { get; set; } = "";
[JsonPropertyName("granted_balance")]
public string GrantedBalance { get; set; } = "";
[JsonPropertyName("topped_up_balance")]
public string ToppedUpBalance { get; set; } = "";
}
public class BalanceResponse
{
[JsonPropertyName("is_available")]
public bool IsAvailable { get; set; } = false;
[JsonPropertyName("balance_infos")]
public List<BalanceInfo> BalanceInfos { get; set; } = [];
}
}