2026-10-04 00:04:20 +08:00
|
|
|
|
#pragma once
|
2026-09-28 15:28:50 +08:00
|
|
|
|
|
|
|
|
|
|
#include <string>
|
|
|
|
|
|
#include <vector>
|
|
|
|
|
|
#include <map>
|
|
|
|
|
|
|
|
|
|
|
|
#define CURL_STATICLIB
|
|
|
|
|
|
|
|
|
|
|
|
#include "mg_curl_export.h"
|
|
|
|
|
|
|
|
|
|
|
|
#define RAPIDJSON_HAS_STDSTRING 1
|
|
|
|
|
|
#include "rapidjson/document.h"
|
|
|
|
|
|
#include "rapidjson/encodings.h"
|
|
|
|
|
|
#include "rapidjson/stringbuffer.h"
|
|
|
|
|
|
#include "rapidjson/filereadstream.h"
|
|
|
|
|
|
#include "rapidjson/filewritestream.h"
|
|
|
|
|
|
#include "rapidjson/encodedstream.h"
|
|
|
|
|
|
#include "rapidjson/prettywriter.h"
|
|
|
|
|
|
|
|
|
|
|
|
#pragma comment (lib,"wldap32.lib")
|
|
|
|
|
|
#pragma comment (lib,"ws2_32.lib")
|
|
|
|
|
|
#pragma comment (lib,"Crypt32.lib")
|
|
|
|
|
|
#pragma comment (lib,"Normaliz.lib")
|
|
|
|
|
|
|
|
|
|
|
|
namespace AIJSON
|
|
|
|
|
|
{
|
|
|
|
|
|
std::string w2utf(LPCTSTR s, DWORD cp = CP_UTF8);
|
|
|
|
|
|
|
|
|
|
|
|
std::string w2utf(const std::wstring &s, DWORD cp = CP_UTF8);
|
|
|
|
|
|
|
|
|
|
|
|
std::wstring utf2w(LPCSTR s, DWORD cp = CP_UTF8);
|
|
|
|
|
|
|
|
|
|
|
|
std::wstring utf2w(const std::string &s, DWORD cp = CP_UTF8);
|
|
|
|
|
|
|
|
|
|
|
|
using namespace rapidjson;
|
|
|
|
|
|
|
|
|
|
|
|
typedef GenericDocument<UTF8<> > Document8;
|
|
|
|
|
|
typedef GenericValue<UTF8<> > Value8;
|
|
|
|
|
|
typedef const GenericValue<UTF8<> > CValue8;
|
|
|
|
|
|
typedef GenericArray<false, Value8> Arr8;
|
|
|
|
|
|
typedef GenericArray<true, Value8> CArr8;
|
|
|
|
|
|
typedef Value8::ConstMemberIterator CMIt8;
|
|
|
|
|
|
typedef Value8::MemberIterator MIt8;
|
|
|
|
|
|
typedef Value8::ConstValueIterator CVIt8;
|
|
|
|
|
|
typedef Value8::ValueIterator VIt8;
|
|
|
|
|
|
typedef GenericStringBuffer<UTF8<> > StringBuffer8;
|
|
|
|
|
|
typedef PrettyWriter<StringBuffer8, UTF8<>, UTF8<>> PrettyWriter8;
|
|
|
|
|
|
typedef Writer<StringBuffer8, UTF8<>, UTF8<>> Writer8;
|
|
|
|
|
|
|
|
|
|
|
|
Document8::AllocatorType &getJsonAllocator();
|
|
|
|
|
|
Value8& addMember(Value8 &v, LPCSTR name, Value8 &value);
|
|
|
|
|
|
Value8& addMember(Value8 &v, LPCSTR name, LPCSTR value);
|
|
|
|
|
|
Value8& addMember(Value8 &v, LPCSTR name, const int &value);
|
|
|
|
|
|
Value8& addMember(Value8 &v, LPCSTR name, const bool &value);
|
|
|
|
|
|
Value8& addMember(Value8 &v, LPCSTR name, const float &value);
|
|
|
|
|
|
|
|
|
|
|
|
Value8& pushBack(Value8 &arr, Value8 &value);
|
|
|
|
|
|
Value8& pushBack(Value8 &arr, LPCSTR value);
|
|
|
|
|
|
Value8& pushBack(Value8 &arr, const int &value);
|
|
|
|
|
|
Value8& pushBack(Value8 &arr, const bool &value);
|
|
|
|
|
|
Value8& pushBack(Value8 &arr, const float &value);
|
|
|
|
|
|
std::string write2Json(const Value8 &v, bool pretty);
|
|
|
|
|
|
bool json2File(LPCTSTR path, const Value8 &v, bool pretty = false);
|
|
|
|
|
|
bool file2Json(LPCTSTR pszJson, Document8 &doc);
|
|
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
|
|
bool parseValue(CValue8 &v, LPCSTR key, T &t)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!key) return false;
|
|
|
|
|
|
CMIt8 it = v.FindMember(key);
|
|
|
|
|
|
if (it != v.MemberEnd() && it->value.Is<T>())
|
|
|
|
|
|
{
|
|
|
|
|
|
if (it->value.IsNull()) return false;
|
|
|
|
|
|
t = it->value.Get<T>();
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
namespace SHAI
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
class initCurl
|
|
|
|
|
|
{
|
|
|
|
|
|
public:
|
|
|
|
|
|
initCurl() { mg_curl_httpGlobalInit(); }
|
|
|
|
|
|
~initCurl() { mg_curl_httpGlobalCleanup(); }
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class Response;
|
|
|
|
|
|
class Request
|
|
|
|
|
|
{
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
|
|
|
|
enum roleType
|
|
|
|
|
|
{
|
|
|
|
|
|
RT_SYSTEM,
|
|
|
|
|
|
RT_USER,
|
|
|
|
|
|
RT_ASSISTANT,
|
|
|
|
|
|
RT_TOOL
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
struct message
|
|
|
|
|
|
{
|
|
|
|
|
|
roleType role;
|
|
|
|
|
|
std::string content;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
|
|
|
|
Request(LPCSTR apikey
|
|
|
|
|
|
, LPCSTR model
|
|
|
|
|
|
, LPCSTR url
|
|
|
|
|
|
, const bool &stream
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
Request();
|
|
|
|
|
|
|
|
|
|
|
|
void setapikey(LPCSTR apikey) { _apiKey = apikey; }
|
|
|
|
|
|
|
|
|
|
|
|
void setmodel(LPCSTR model) { _model = model; }
|
|
|
|
|
|
|
|
|
|
|
|
void seturl(LPCSTR url) { _apiEndpoint = url; }
|
|
|
|
|
|
|
|
|
|
|
|
void setstream(const bool &stream) { _stream = stream; if (_stream) _stream_options_include_usage = true; }
|
|
|
|
|
|
|
|
|
|
|
|
int send(Response &response) const;
|
|
|
|
|
|
|
|
|
|
|
|
std::string requestBody() const;
|
|
|
|
|
|
|
|
|
|
|
|
void addUserMessage(LPCSTR content);
|
|
|
|
|
|
|
|
|
|
|
|
void addSystemMessage(LPCSTR content);
|
|
|
|
|
|
|
|
|
|
|
|
void addAssistantMessage(LPCSTR content);
|
|
|
|
|
|
|
|
|
|
|
|
void clearMessages();
|
|
|
|
|
|
|
|
|
|
|
|
void addHeaders(LPCSTR key, LPCSTR value);
|
|
|
|
|
|
|
|
|
|
|
|
std::string apiEndPoint() const;
|
|
|
|
|
|
|
|
|
|
|
|
void set_frequency_penalty(const float &f){ _frequency_penalty = f;}
|
|
|
|
|
|
|
|
|
|
|
|
void set_top_p(const float &f) { _top_p = f;}
|
|
|
|
|
|
|
|
|
|
|
|
void set_temperature(const float &f) { _temperature = f;}
|
|
|
|
|
|
|
|
|
|
|
|
void set_max_tokens(const int &d) { _max_tokens = d;}
|
|
|
|
|
|
|
|
|
|
|
|
void set_presence_penalty(const float &f) { _presence_penalty = f;}
|
|
|
|
|
|
|
|
|
|
|
|
void set_top_k(const int &n){ _top_k = n;}
|
|
|
|
|
|
|
2026-10-04 00:04:20 +08:00
|
|
|
|
// 清除最后一个消息
|
2026-09-28 15:28:50 +08:00
|
|
|
|
void popbackMessage();
|
|
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
|
|
|
|
void addMessage(const roleType &rt, LPCSTR content);
|
|
|
|
|
|
|
|
|
|
|
|
std::string getRole(const roleType &rt) const;
|
|
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
std::string _apiKey;
|
|
|
|
|
|
|
|
|
|
|
|
std::string _apiEndpoint;
|
|
|
|
|
|
|
|
|
|
|
|
std::map<std::string, std::string> _headers;
|
|
|
|
|
|
|
|
|
|
|
|
std::string _model;
|
|
|
|
|
|
|
2026-10-04 00:04:20 +08:00
|
|
|
|
/*对话的消息列表。*/
|
2026-09-28 15:28:50 +08:00
|
|
|
|
std::vector<message> _messages;
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
2026-10-04 00:04:20 +08:00
|
|
|
|
如果设置为 True,将会以 SSE(server-sent events)的形式以流式发送消息增量。
|
|
|
|
|
|
消息流以 data: [DONE] 结尾。
|
2026-09-28 15:28:50 +08:00
|
|
|
|
*/
|
|
|
|
|
|
bool _stream;
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
2026-10-04 00:04:20 +08:00
|
|
|
|
流式输出相关选项。只有在 stream 参数为 true 时,才可设置此参数。
|
|
|
|
|
|
如果设置为 true,在流式消息最后的 data: [DONE] 之前将会传输一个额外的块。
|
|
|
|
|
|
此块上的 usage 字段显示整个请求的 token 使用统计信息,而 choices 字段将始终是一个空数组。
|
|
|
|
|
|
所有其他块也将包含一个 usage 字段,但其值为 null。
|
2026-09-28 15:28:50 +08:00
|
|
|
|
*/
|
|
|
|
|
|
bool _stream_options_include_usage;
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
2026-10-04 00:04:20 +08:00
|
|
|
|
介于 -2.0 和 2.0 之间的数字。
|
|
|
|
|
|
如果该值为正,那么新 token 会根据其在已有文本中的出现频率受到相应的惩罚,降低模型重复相同内容的可能性。
|
2026-09-28 15:28:50 +08:00
|
|
|
|
default : 0
|
|
|
|
|
|
*/
|
|
|
|
|
|
float _frequency_penalty;
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
2026-10-04 00:04:20 +08:00
|
|
|
|
介于 1 到 8192 间的整数,限制一次请求中模型生成 completion 的最大 token 数。
|
|
|
|
|
|
输入 token 和输出 token 的总长度受模型的上下文长度的限制。
|
|
|
|
|
|
如未指定 max_tokens参数,默认使用 4096。
|
2026-09-28 15:28:50 +08:00
|
|
|
|
*/
|
|
|
|
|
|
int _max_tokens;
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
2026-10-04 00:04:20 +08:00
|
|
|
|
介于 -2.0 和 2.0 之间的数字。
|
|
|
|
|
|
如果该值为正,那么新 token 会根据其是否已在已有文本中出现受到相应的惩罚,从而增加模型谈论新主题的可能性。
|
2026-09-28 15:28:50 +08:00
|
|
|
|
default : 0
|
|
|
|
|
|
*/
|
|
|
|
|
|
float _presence_penalty;
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
2026-10-04 00:04:20 +08:00
|
|
|
|
一个 object,指定模型必须输出的格式。
|
|
|
|
|
|
可以设置为 { "type": "plain_text" } 以启用纯文本模式,该模式保证模型生成的消息是有效的纯文本。
|
|
|
|
|
|
设置为 { "type": "json_object" } 以启用 JSON 模式,该模式保证模型生成的消息是有效的 JSON。
|
|
|
|
|
|
注意: 使用 JSON 模式时,你还必须通过系统或用户消息指示模型生成 JSON。
|
|
|
|
|
|
否则,模型可能会生成不断的空白字符,直到生成达到令牌限制,从而导致请求长时间运行并显得“卡住”。
|
|
|
|
|
|
此外,如果 finish_reason="length",这表示生成超过了 max_tokens 或对话超过了最大上下文长度,消息内容可能会被部分截断。
|
2026-09-28 15:28:50 +08:00
|
|
|
|
|
2026-10-04 00:04:20 +08:00
|
|
|
|
可能的值: "text" , "json_object"
|
2026-09-28 15:28:50 +08:00
|
|
|
|
default: "text"
|
|
|
|
|
|
*/
|
|
|
|
|
|
std::string _response_format_type;
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
2026-10-04 00:04:20 +08:00
|
|
|
|
一个 string 或最多包含 16 个 string 的 list,在遇到这些词时,API 将停止生成更多的 token。
|
2026-09-28 15:28:50 +08:00
|
|
|
|
*/
|
|
|
|
|
|
std::vector<std::string> _stop;
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
2026-10-04 00:04:20 +08:00
|
|
|
|
采样温度,介于 0 和 2 之间。
|
|
|
|
|
|
更高的值,如 0.8,会使输出更随机,而更低的值,如 0.2,会使其更加集中和确定。
|
|
|
|
|
|
我们通常建议可以更改这个值或者更改 top_p,但不建议同时对两者进行修改。
|
2026-09-28 15:28:50 +08:00
|
|
|
|
default:1
|
|
|
|
|
|
*/
|
|
|
|
|
|
float _temperature;
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
2026-10-04 00:04:20 +08:00
|
|
|
|
作为调节采样温度的替代方案,模型会考虑前 top_p 概率的 token 的结果。
|
|
|
|
|
|
所以 0.1 就意味着只有包括在最高 10% 概率中的 token 会被考虑。
|
|
|
|
|
|
我们通常建议修改这个值或者更改 temperature,但不建议同时对两者进行修改。
|
2026-09-28 15:28:50 +08:00
|
|
|
|
*/
|
|
|
|
|
|
float _top_p;
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
2026-10-04 00:04:20 +08:00
|
|
|
|
是否返回所输出 token 的对数概率。如果为 true,则在 message 的 content 中返回每个输出 token 的对数概率。
|
2026-09-28 15:28:50 +08:00
|
|
|
|
*/
|
|
|
|
|
|
bool _logprobs;
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
2026-10-04 00:04:20 +08:00
|
|
|
|
一个介于 0 到 20 之间的整数 N,指定每个输出位置返回输出概率 top N 的 token,且返回这些 token 的对数概率。
|
|
|
|
|
|
指定此参数时,logprobs 必须为 true。
|
2026-09-28 15:28:50 +08:00
|
|
|
|
*/
|
|
|
|
|
|
int _top_logprobs;
|
|
|
|
|
|
|
|
|
|
|
|
/**/
|
|
|
|
|
|
int _top_k;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class Response
|
|
|
|
|
|
{
|
|
|
|
|
|
public:
|
|
|
|
|
|
Response();
|
|
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
void readResponse(const std::string &s);
|
|
|
|
|
|
|
|
|
|
|
|
bool isUsageTokens() const { return _bUsageTokens; }
|
|
|
|
|
|
|
|
|
|
|
|
const std::string& content() const { return _content; }
|
|
|
|
|
|
|
|
|
|
|
|
const std::string& reasoningContent() const { return _reasoning_content; }
|
|
|
|
|
|
|
|
|
|
|
|
const std::string& allreasoningContent() const { return _all_reasoning_content; }
|
|
|
|
|
|
|
|
|
|
|
|
const std::string& allContent() const { return _all_content; }
|
|
|
|
|
|
|
|
|
|
|
|
int promptTokens() const { return _prompt_tokens; }
|
|
|
|
|
|
|
|
|
|
|
|
int completionTokens() const { return _completion_tokens; }
|
|
|
|
|
|
|
|
|
|
|
|
int totalTokens() const { return _total_tokens; }
|
|
|
|
|
|
|
|
|
|
|
|
void clear();
|
|
|
|
|
|
|
|
|
|
|
|
bool showThinkingContent() { return _bShowThinkingContent; }
|
|
|
|
|
|
|
|
|
|
|
|
void setShowThinkingContent(const bool &bShow) { _bShowThinkingContent = bShow; }
|
|
|
|
|
|
|
|
|
|
|
|
void appendOriginalResponse(const std::string &s) { _allOriginalResponse.push_back(s); }
|
|
|
|
|
|
|
|
|
|
|
|
const std::vector<std::string> &originalResponses() { return _allOriginalResponse; }
|
|
|
|
|
|
|
|
|
|
|
|
void setRecordContext(const bool &b) { _bRecordContext = b; }
|
|
|
|
|
|
|
|
|
|
|
|
bool needRecordContext() { return _bRecordContext; }
|
|
|
|
|
|
|
|
|
|
|
|
void set_finish_reason(LPCSTR s) { _finish_reason = s;}
|
|
|
|
|
|
|
|
|
|
|
|
const std::string& finish_reason() { return _finish_reason; }
|
|
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
void parseChoices(AIJSON::CValue8 &v);
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
|
|
|
|
// tokens
|
|
|
|
|
|
bool _bUsageTokens;
|
|
|
|
|
|
|
2026-10-04 00:04:20 +08:00
|
|
|
|
// finish_reason 类型
|
2026-09-28 15:28:50 +08:00
|
|
|
|
std::string _finish_reason;
|
|
|
|
|
|
|
2026-10-04 00:04:20 +08:00
|
|
|
|
// 单次思考内容
|
2026-09-28 15:28:50 +08:00
|
|
|
|
std::string _reasoning_content;
|
|
|
|
|
|
|
2026-10-04 00:04:20 +08:00
|
|
|
|
// 单次回答内容
|
2026-09-28 15:28:50 +08:00
|
|
|
|
std::string _content;
|
|
|
|
|
|
|
2026-10-04 00:04:20 +08:00
|
|
|
|
// 全部思考内容
|
2026-09-28 15:28:50 +08:00
|
|
|
|
std::string _all_reasoning_content;
|
|
|
|
|
|
|
2026-10-04 00:04:20 +08:00
|
|
|
|
// 全部回答内容
|
2026-09-28 15:28:50 +08:00
|
|
|
|
std::string _all_content;
|
|
|
|
|
|
|
2026-10-04 00:04:20 +08:00
|
|
|
|
// 提问的 token 数
|
2026-09-28 15:28:50 +08:00
|
|
|
|
int _prompt_tokens;
|
|
|
|
|
|
|
2026-10-04 00:04:20 +08:00
|
|
|
|
// 完成的 token 数
|
2026-09-28 15:28:50 +08:00
|
|
|
|
int _completion_tokens;
|
|
|
|
|
|
|
2026-10-04 00:04:20 +08:00
|
|
|
|
// 总 token 数
|
2026-09-28 15:28:50 +08:00
|
|
|
|
int _total_tokens;
|
|
|
|
|
|
|
2026-10-04 00:04:20 +08:00
|
|
|
|
// 是否显示思考内容
|
2026-09-28 15:28:50 +08:00
|
|
|
|
bool _bShowThinkingContent;
|
|
|
|
|
|
|
2026-10-04 00:04:20 +08:00
|
|
|
|
// 是否记录上下文
|
2026-09-28 15:28:50 +08:00
|
|
|
|
bool _bRecordContext;
|
|
|
|
|
|
|
2026-10-04 00:04:20 +08:00
|
|
|
|
// 全部返回
|
2026-09-28 15:28:50 +08:00
|
|
|
|
std::vector<std::string> _allOriginalResponse;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
#pragma region AICloud
|
2026-10-04 00:04:20 +08:00
|
|
|
|
// 智能云提供商
|
2026-09-28 15:28:50 +08:00
|
|
|
|
class AICloud
|
|
|
|
|
|
{
|
|
|
|
|
|
protected:
|
2026-10-04 00:04:20 +08:00
|
|
|
|
// 智能云提供商名称
|
2026-09-28 15:28:50 +08:00
|
|
|
|
std::string _cloudName;
|
|
|
|
|
|
|
|
|
|
|
|
// apiKey
|
|
|
|
|
|
std::string _apiKey;
|
|
|
|
|
|
|
|
|
|
|
|
// api endpoint
|
|
|
|
|
|
std::string _endpoint;
|
|
|
|
|
|
|
2026-10-04 00:04:20 +08:00
|
|
|
|
// 模型列表
|
2026-09-28 15:28:50 +08:00
|
|
|
|
std::vector<std::string> _models;
|
|
|
|
|
|
|
2026-10-04 00:04:20 +08:00
|
|
|
|
// 当前模型
|
2026-09-28 15:28:50 +08:00
|
|
|
|
std::string _current_model;
|
|
|
|
|
|
|
2026-10-04 00:04:20 +08:00
|
|
|
|
// 当前使用云
|
2026-09-28 15:28:50 +08:00
|
|
|
|
bool _current_select;
|
|
|
|
|
|
|
|
|
|
|
|
public:
|
2026-10-04 00:04:20 +08:00
|
|
|
|
// 构造函数
|
2026-09-28 15:28:50 +08:00
|
|
|
|
AICloud() { }
|
|
|
|
|
|
~AICloud() { }
|
|
|
|
|
|
|
|
|
|
|
|
AICloud(LPCSTR name, LPCSTR key, LPCSTR endpoint)
|
|
|
|
|
|
: _apiKey(key)
|
|
|
|
|
|
, _endpoint(endpoint)
|
|
|
|
|
|
, _cloudName(name)
|
|
|
|
|
|
, _current_select(false)
|
|
|
|
|
|
{ }
|
|
|
|
|
|
|
|
|
|
|
|
std::string cloudName()const {return _cloudName;}
|
|
|
|
|
|
void setCloudName(LPCSTR name) { _cloudName = name; }
|
|
|
|
|
|
|
2026-10-04 00:04:20 +08:00
|
|
|
|
// 设置和获取 apiKey
|
2026-09-28 15:28:50 +08:00
|
|
|
|
void setApiKey(LPCSTR key) { _apiKey = key; }
|
|
|
|
|
|
std::string apiKey() const { return _apiKey; }
|
|
|
|
|
|
|
2026-10-04 00:04:20 +08:00
|
|
|
|
// 设置和获取 endpoint
|
2026-09-28 15:28:50 +08:00
|
|
|
|
void setEndpoint(LPCSTR endpoint) { this->_endpoint = endpoint; }
|
|
|
|
|
|
std::string endpoint() const { return _endpoint; }
|
|
|
|
|
|
|
2026-10-04 00:04:20 +08:00
|
|
|
|
// 设置获取 当前模型
|
2026-09-28 15:28:50 +08:00
|
|
|
|
void setCurrentModel(const int &idx);
|
|
|
|
|
|
void setCurrentModel(LPCSTR model){ _current_model = model;}
|
|
|
|
|
|
std::string currentModel() const { return _current_model; }
|
|
|
|
|
|
|
|
|
|
|
|
void setModels(const std::vector<std::string>& models) { _models = models;}
|
|
|
|
|
|
void insertModel(LPCSTR model) { _models.push_back(model); }
|
|
|
|
|
|
const std::vector<std::string>& models() const { return _models; }
|
|
|
|
|
|
|
|
|
|
|
|
void setCurrentSelect(const bool &b) {_current_select = b;}
|
|
|
|
|
|
bool currentSelect() const { return _current_select; }
|
|
|
|
|
|
|
2026-10-04 00:04:20 +08:00
|
|
|
|
// 解析服务器返回的模型列表json
|
|
|
|
|
|
// 支持硅基和deepseek模型
|
2026-09-28 15:28:50 +08:00
|
|
|
|
static void parseModelsJson(LPCSTR js, std::vector<std::string> &models);
|
|
|
|
|
|
|
|
|
|
|
|
virtual void getModels() {}
|
|
|
|
|
|
|
|
|
|
|
|
struct IS_EQUAL
|
|
|
|
|
|
{
|
|
|
|
|
|
IS_EQUAL(AICloud *p): _p(p) {}
|
|
|
|
|
|
AICloud *_p;
|
|
|
|
|
|
bool operator () (AICloud *p) const
|
|
|
|
|
|
{
|
|
|
|
|
|
return p->_cloudName == _p->_cloudName;
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static AICloud* createCloud(LPCSTR name);
|
|
|
|
|
|
static bool IsCustomCloud(AICloud *p);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class AliyunBailian : public AICloud
|
|
|
|
|
|
{
|
|
|
|
|
|
public:
|
|
|
|
|
|
AliyunBailian() { }
|
|
|
|
|
|
~AliyunBailian() { }
|
|
|
|
|
|
|
|
|
|
|
|
AliyunBailian(LPCSTR key)
|
2026-10-04 00:04:20 +08:00
|
|
|
|
: AICloud(AIJSON::w2utf(_T("阿里云百炼")).c_str()
|
2026-09-28 15:28:50 +08:00
|
|
|
|
, key
|
|
|
|
|
|
, "https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions")
|
|
|
|
|
|
{ }
|
|
|
|
|
|
|
|
|
|
|
|
virtual void getModels();
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class SiliconFlow : public AICloud
|
|
|
|
|
|
{
|
|
|
|
|
|
public:
|
|
|
|
|
|
SiliconFlow() { }
|
|
|
|
|
|
~SiliconFlow() { }
|
|
|
|
|
|
|
|
|
|
|
|
SiliconFlow(LPCSTR key)
|
2026-10-04 00:04:20 +08:00
|
|
|
|
: AICloud(AIJSON::w2utf(_T("硅基流动")).c_str()
|
2026-09-28 15:28:50 +08:00
|
|
|
|
, key
|
|
|
|
|
|
, "https://api.siliconflow.cn/v1/chat/completions")
|
|
|
|
|
|
{ }
|
|
|
|
|
|
|
|
|
|
|
|
virtual void getModels();
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class DeepSeek : public AICloud
|
|
|
|
|
|
{
|
|
|
|
|
|
public:
|
|
|
|
|
|
DeepSeek() { }
|
|
|
|
|
|
~DeepSeek() { }
|
|
|
|
|
|
|
|
|
|
|
|
DeepSeek(LPCSTR key)
|
|
|
|
|
|
: AICloud("DeepSeek", key, "https://api.deepseek.com/chat/completions")
|
|
|
|
|
|
{ }
|
|
|
|
|
|
|
|
|
|
|
|
virtual void getModels();
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class Hyperbolic : public AICloud
|
|
|
|
|
|
{
|
|
|
|
|
|
public:
|
|
|
|
|
|
Hyperbolic() { }
|
|
|
|
|
|
~Hyperbolic() { }
|
|
|
|
|
|
|
|
|
|
|
|
Hyperbolic(LPCSTR key)
|
|
|
|
|
|
: AICloud("Hyperbolic", key, "https://api.hyperbolic.xyz/v1/chat/completions")
|
|
|
|
|
|
{ }
|
|
|
|
|
|
|
|
|
|
|
|
virtual void getModels();
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class CustomCloud : public AICloud
|
|
|
|
|
|
{
|
|
|
|
|
|
public:
|
|
|
|
|
|
CustomCloud() { }
|
|
|
|
|
|
~CustomCloud() { }
|
|
|
|
|
|
|
|
|
|
|
|
CustomCloud(LPCSTR name, LPCSTR key, LPCSTR endpoint)
|
|
|
|
|
|
: AICloud(name, key, endpoint)
|
|
|
|
|
|
{ }
|
|
|
|
|
|
|
|
|
|
|
|
virtual void getModels() {};
|
|
|
|
|
|
};
|
|
|
|
|
|
#pragma endregion
|
|
|
|
|
|
|
|
|
|
|
|
class ChatConfig
|
|
|
|
|
|
{
|
|
|
|
|
|
private:
|
|
|
|
|
|
std::string _system_prompt;
|
|
|
|
|
|
int _max_tokens;
|
|
|
|
|
|
float _top_p;
|
|
|
|
|
|
float _temperature;
|
|
|
|
|
|
int _top_k;
|
|
|
|
|
|
float _frequency_penalty;
|
|
|
|
|
|
public:
|
|
|
|
|
|
ChatConfig()
|
|
|
|
|
|
: _system_prompt("")
|
|
|
|
|
|
, _max_tokens(4096)
|
|
|
|
|
|
, _top_p(.7f)
|
|
|
|
|
|
, _temperature(.6f)
|
|
|
|
|
|
, _top_k(50)
|
|
|
|
|
|
, _frequency_penalty(0.0f) { }
|
|
|
|
|
|
|
|
|
|
|
|
void set_system_prompt(LPCTSTR psz) { _system_prompt = AIJSON::w2utf(psz); }
|
|
|
|
|
|
void set_system_prompt(LPCSTR psz) { _system_prompt = psz; }
|
|
|
|
|
|
std::wstring system_prompt_w()const { return AIJSON::utf2w(_system_prompt); };
|
|
|
|
|
|
std::string system_prompt()const { return _system_prompt; }
|
|
|
|
|
|
|
|
|
|
|
|
void set_max_tokens(const int &i) { _max_tokens = i; }
|
|
|
|
|
|
int max_tokens()const { return _max_tokens;}
|
|
|
|
|
|
|
|
|
|
|
|
void set_top_k(const int &i){ _top_k = i;}
|
|
|
|
|
|
int top_k()const { return _top_k;}
|
|
|
|
|
|
|
|
|
|
|
|
void set_top_p(const float &f){ _top_p = f;}
|
|
|
|
|
|
float top_p()const { return _top_p;}
|
|
|
|
|
|
|
|
|
|
|
|
void set_temperature(const float &f){ _temperature = f;}
|
|
|
|
|
|
float temperature()const { return _temperature;}
|
|
|
|
|
|
|
|
|
|
|
|
void set_frequency_penalty(const float &f){ _frequency_penalty = f;}
|
|
|
|
|
|
float frequency_penalty()const { return _frequency_penalty;}
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|