代码拉取完成,页面将自动刷新
/*
* Copyright 2024 KylinSoft Co., Ltd.
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "xunfeivisionengine_p.h"
#include <unistd.h>
#include <map>
#include "imageloader.h"
#include "servererror.h"
#include "token.h"
#include "util.h"
namespace {
std::map<int, std::string> imageStyleMap = {
{0, "探索无限"}, {1, "古风"}, {2, "二次元"}, {3, "写实风格"},
{4, "浮世绘"}, {5, "low poly"}, {6, "未来主义"}, {7, "像素风格"},
{8, "概念艺术"}, {9, "赛博朋克"}, {10, "洛丽塔风格"}, {11, "巴洛克风格"},
{12, "超现实主义"}, {13, "水彩画"}, {14, "蒸汽波艺术"}, {15, "油画"},
{16, "卡通画"},
};
}
XunfeiVisionEnginePrivate::XunfeiVisionEnginePrivate() {}
XunfeiVisionEnginePrivate::~XunfeiVisionEnginePrivate() {}
std::string XunfeiVisionEnginePrivate::engineName() const {
return std::string("xunfei");
}
void XunfeiVisionEnginePrivate::setConfig(const std::string &config) {
Json::Value configJson = xunfei_vision_util::formatJsonFromString(config);
if (configJson.isNull() || !configJson.isMember("apiKey") ||
!configJson.isMember("secretKey") || !configJson.isMember("appId") ||
!configJson["apiKey"].isString() ||
!configJson["secretKey"].isString() ||
!configJson["appId"].isString()) {
std::fprintf(stderr, "Invalid config for xunfei vision engine: %s\n",
config.c_str());
return;
}
appId_ = configJson["appId"].asString();
apiKey_ = configJson["apiKey"].asString();
secretKey_ = configJson["secretKey"].asString();
}
std::string XunfeiVisionEnginePrivate::modelInfo() const {
const char *info = R"(
{
"vendor": "讯飞",
"name": "视觉大模型",
"subConfig": [
{
"name": "图片生成",
"config": [
{
"displayName": "APPID",
"configName": "appId"
},
{
"displayName": "APIKey",
"configName": "apiKey"
},
{
"displayName": "APISecret",
"configName": "secretKey"
}
]
}
]
}
)";
return info;
}
int XunfeiVisionEnginePrivate::maxConcurrentPrompt2ImageTasks() const {
return 2;
}
void XunfeiVisionEnginePrivate::setPrompt2ImageCallback(
ai_engine::lm::vision::ImageResultCallback callback) {
imageResultCallback_ = callback;
}
void XunfeiVisionEnginePrivate::setPrompt2ImageSize(int width, int height) {
imageWidth_ = width;
imageHeight_ = height;
}
void XunfeiVisionEnginePrivate::setPrompt2ImageNumber(int number) {
imageNumber_ = number;
}
void XunfeiVisionEnginePrivate::setPrompt2ImageStyle(int style) {
imageStyle_ = imageStyleMap[style];
}
std::string XunfeiVisionEnginePrivate::supportedPrompt2ImageParams() const {
const char *params = R"(
{
"resolution-ratio": ["512x512", "640x360", "640x480", "640x640", "680x512", "512x680", "768x768", "720x1280", "1280x720", "1024x1024"],
"image-number": 1
})";
return params;
}
bool writePrompt2ImageResult(std::string data, intptr_t userData) {
XunfeiVisionEnginePrivate *self = (XunfeiVisionEnginePrivate *)userData;
std::string resultString = self->incompleteResult_.data() + data;
Json::Value resultJson =
xunfei_vision_util::formatJsonFromString(resultString);
if (resultJson.isNull() || !resultJson.isObject()) {
self->incompleteResult_ += data;
return true;
}
if (int errorCode = xunfei_vision_server_error::parseErrorCode(data)) {
fprintf(stderr, "xunfei text2image failed: %s\n", data.c_str());
auto errorTuple =
xunfei_vision_server_error::errorCode2visionResult(errorCode);
self->currentError_ = ai_engine::lm::EngineError(
ai_engine::lm::AiCapability::Speech, std::get<0>(errorTuple),
(int)std::get<1>(errorTuple), data);
self->runCallbackWithError(self->currentError_, self->imageNumber_,
self->imageNumber_);
return false;
}
if (resultJson.isMember("message")) {
self->currentError_ = ai_engine::lm::EngineError(
ai_engine::lm::AiCapability::Vision,
ai_engine::lm::EngineErrorCategory::Initialization,
(int)ai_engine::lm::VisionEngineErrorCode::Unauthorized,
resultJson["message"].asString());
fprintf(stderr, "xunfei authentication failed: %s\n",
resultJson["message"].asString().c_str());
return false;
}
if (resultString.substr(resultString.length() - 3) != "}}}") {
self->incompleteResult_ += data;
self->currentError_ = ai_engine::lm::EngineError(
ai_engine::lm::AiCapability::Vision,
ai_engine::lm::EngineErrorCategory::OutputError,
(int)ai_engine::lm::VisionEngineErrorCode::ImageGenerationFailed,
"图片数据不完整");
return true;
}
self->incompleteResult_.clear();
ai_engine::lm::vision::ImageData imageData;
for (int i = 0; i < resultJson["payload"]["choices"]["text"].size(); i++) {
auto imageDataString = xunfei_vision_util::base64Decode(
resultJson["payload"]["choices"]["text"][i]["content"].asString());
auto imageInfo = vision::image_loader::getImageInfoFromData(
(unsigned char *)imageDataString.data(), imageDataString.size());
ai_engine::lm::EngineError error;
imageData.error = error;
imageData.format = imageInfo.format;
imageData.width = imageInfo.width;
imageData.height = imageInfo.height;
imageData.imageData =
std::vector<char>(imageDataString.begin(), imageDataString.end());
imageData.index = i;
imageData.total = resultJson["payload"]["choices"]["text"].size();
}
self->imageResultCallback_(imageData);
self->currentError_ = ai_engine::lm::EngineError();
return true;
}
bool XunfeiVisionEnginePrivate::prompt2Image(
const std::string &prompt, ai_engine::lm::EngineError &error) {
incompleteResult_.clear();
if (!imageResultCallback_) {
return false;
}
if (prompt.empty()) {
error = ai_engine::lm::EngineError(
ai_engine::lm::AiCapability::Vision,
ai_engine::lm::EngineErrorCategory::Initialization,
(int)ai_engine::lm::VisionEngineErrorCode::TooLittleData,
"文本为空");
runCallbackWithError(error, imageNumber_, imageNumber_);
return false;
}
Json::Value bodyJson;
bodyJson["header"]["app_id"] = appId_;
bodyJson["parameter"]["chat"]["domain"] = "general";
bodyJson["parameter"]["chat"]["width"] = imageWidth_;
bodyJson["parameter"]["chat"]["height"] = imageHeight_;
bodyJson["payload"]["message"]["text"][0]["role"] = "user";
if (imageStyle_.empty()) {
bodyJson["payload"]["message"]["text"][0]["content"] =
std::string(prompt);
} else if (imageStyle_ == "low poly") {
bodyJson["payload"]["message"]["text"][0]["content"] =
std::string(prompt) + "," + "低多边形";
} else {
bodyJson["payload"]["message"]["text"][0]["content"] =
std::string(prompt) + "," + imageStyle_;
}
std::string bodyString = bodyJson.toStyledString();
cpr::Url url{xunfei_vision_token::getAuthenticationUrl(apiKey_, secretKey_,
hostUrl_)};
cpr::Header header{cpr::Header{{"Content-Type", "application/json"},
{"charset", "UTF-8"}}};
cpr::Body body{cpr::Body{{bodyString}}};
cpr::LowSpeed lowSpeed{1, 10};
cpr::Response response =
cpr::Post(url, header, body, lowSpeed,
cpr::WriteCallback{writePrompt2ImageResult, (intptr_t)this});
return processPrompt2ImageResult(response, error);
}
bool XunfeiVisionEnginePrivate::processPrompt2ImageResult(
cpr::Response &response, ai_engine::lm::EngineError &error) {
if (response.error.code == cpr::ErrorCode::REQUEST_CANCELLED ||
!currentStatus()) {
error = currentError_;
runCallbackWithError(error, imageNumber_, imageNumber_);
return false;
}
if (response.error) {
error = ai_engine::lm::EngineError(
ai_engine::lm::AiCapability::Vision,
ai_engine::lm::EngineErrorCategory::OutputError,
(int)ai_engine::lm::VisionEngineErrorCode::NetworkDisconnected,
response.error.message);
runCallbackWithError(error, imageNumber_, imageNumber_);
fprintf(stderr, "net error: %s\n", response.error.message.c_str());
return false;
}
return true;
}
void XunfeiVisionEnginePrivate::runCallbackWithError(
const ai_engine::lm::EngineError &error, const int &index,
const int &total) {
int errorValue = 0;
if (index == total) {
for (int i = 0; i < total; i++) {
ai_engine::lm::vision::ImageData data{
errorValue, errorValue, errorValue, total,
i, std::vector<char>(), error};
imageResultCallback_(data);
}
} else {
ai_engine::lm::vision::ImageData data{
errorValue, errorValue, errorValue, total,
index, std::vector<char>(), error};
imageResultCallback_(data);
}
}
bool XunfeiVisionEnginePrivate::currentStatus() {
return (currentError_.getCode() == -1);
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。