Ai.php 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692
  1. <?php
  2. //decode by http://www.yunlu99.com/
  3. namespace app\controller\api;
  4. use laytp\controller\Api;
  5. use laytp\library\Random;
  6. use think\facade\Db;
  7. use ins\Words;
  8. use app\service\api\UserServiceFacade;
  9. use app\service\ChatgptServiceFacade;
  10. use app\service\api\MiniappServiceFacade;
  11. use app\service\BillServiceFacade;
  12. use app\service\ConfServiceFacade;
  13. use app\service\MemberServiceFacade;
  14. use app\service\api\YijianServiceFacade;
  15. use app\service\api\SdapiServiceFacade;
  16. use app\service\api\InsServiceFacade;
  17. use app\service\api\ImageCensorServiceFacade;
  18. use app\service\api\SpeechServiceFacade;
  19. use openai\OpenAi;
  20. use laytp\library\UploadDomain;
  21. use think\facade\Filesystem;
  22. class Ai extends Api
  23. {
  24. protected function _initialize()
  25. {
  26. }
  27. public $noNeedLogin = array("chat", "chat4event", "chat4", "test", "test2", "recognizer", "chatgpt");
  28. public function chat()
  29. {
  30. global $_GPC;
  31. $modelVipinfo = new \app\model\Vipinfo();
  32. $loginUserInfo = UserServiceFacade::getUserInfo();
  33. $modelQuestion = new \app\model\Question();
  34. $prompt = $this->request->post("prompt", '');
  35. $guide = $this->request->post("guide", '');
  36. $answer = $this->request->post("answer", '');
  37. $platform = $this->request->header("platform", "H5");
  38. $conf = ConfServiceFacade::groupGet("system.config", 0);
  39. $type = $this->request->post("type", "gpt35");
  40. $numberAlias = !empty($conf["number_alias"]) ? $conf["number_alias"] : "点数";
  41. if (!$prompt) {
  42. return $this->error("请填写问题");
  43. }
  44. $clearPrompt = $this->wordFilter($prompt);
  45. $proxy = $this->getUrl($type, $conf);
  46. if ($type == "gpt35") {
  47. $coin = ConfServiceFacade::get("system.plan.unlock_gpt3", 1);
  48. } else {
  49. $coin = ConfServiceFacade::get("system.plan.lock_gpt4", 0);
  50. }
  51. $checkMember = MemberServiceFacade::check($loginUserInfo, $type, $coin, $conf);
  52. if (isset($checkMember["status"]) && !$checkMember["status"]) {
  53. return $this->error($checkMember["msg"], 2);
  54. }
  55. $res = ChatgptServiceFacade::chat($prompt, $guide, $answer, $platform);
  56. if (!$res) {
  57. return $this->error("服务器出现未知错误,请稍后重试或联系客服.", 3);
  58. }
  59. if ($platform == "wxMiniProgram") {
  60. $check = MiniappServiceFacade::msgSecCheck($res, $loginUserInfo["openid_miniapp"]);
  61. if (!$check) {
  62. return $this->error("失败,文字内容安全检测不通过!");
  63. }
  64. } else {
  65. if ($platform == "wxOfficialAccount" || $platform == "H5") {
  66. if (!empty($conf) && !empty($conf["is_h5_filter"]) && $conf["is_h5_filter"] == 1) {
  67. $check = ImageCensorServiceFacade::textCensorUserDefined($res);
  68. if (!empty($check["conclusion"]) && $check["conclusion"] == "不合规") {
  69. return $this->error("失败,文字内容安全检测不通过!");
  70. }
  71. }
  72. }
  73. }
  74. if ($coin > 0) {
  75. $checkMember = MemberServiceFacade::cash($loginUserInfo, $type, $coin, $conf);
  76. if (isset($checkMember["status"]) && !$checkMember["status"]) {
  77. return $this->error($checkMember["msg"], 2);
  78. }
  79. }
  80. $question = $modelQuestion->save(["type" => $type,"uid" => $loginUserInfo["id"], "question" => $prompt, "answer" => $res, "uniacid" => $_GPC["uniacid"]]);
  81. return $this->success("操作成功", $res);
  82. }
  83. public function chatgpt()
  84. {
  85. header("Content-Type: text/event-stream");
  86. header("Cache-Control: no-cache");
  87. header("Connection: keep-alive");
  88. header("X-Accel-Buffering: no");
  89. global $_GPC;
  90. $loginUserInfo = UserServiceFacade::getUserInfo();
  91. $modelVipinfo = new \app\model\Vipinfo();
  92. $modelQuestion = new \app\model\Question();
  93. $type = $this->request->post("type", "gpt35");
  94. $prompt = $this->request->post("prompt", '');
  95. $guide = $this->request->post("guide", '');
  96. $guideId = $this->request->post("guide_id", 0);
  97. $guideType = $this->request->post("guide_type", 0);
  98. $answer = $this->request->post("answer", '');
  99. $messages = $this->request->post("messages", []);
  100. $platform = $this->request->header("platform", "H5");
  101. $conf = ConfServiceFacade::groupGet("system.config", 0);
  102. $numberAlias = !empty($conf["number_alias"]) ? $conf["number_alias"] : "点数";
  103. if ($type == "gpt35") {
  104. $coin = ConfServiceFacade::get("system.plan.unlock_gpt3", 1);
  105. } else {
  106. $coin = ConfServiceFacade::get("system.plan.lock_gpt4", 0);
  107. }
  108. $proxy = $this->getUrl($type, $conf);
  109. $checkMember = MemberServiceFacade::check($loginUserInfo, $type, $coin, $conf);
  110. if (isset($checkMember["status"]) && !$checkMember["status"]) {
  111. return $checkMember["msg"];
  112. }
  113. $temperature = 0.8;
  114. $presencePenalty = 0;
  115. $frequencyPenalty = 0;
  116. if (isset($conf["temperature"])) {
  117. $temperature = floatval($conf["temperature"]) ?? 0.8;
  118. }
  119. if (isset($conf["presence_penalty"])) {
  120. $presencePenalty = floatval($conf["presence_penalty"]) ?? 0;
  121. }
  122. if (isset($conf["frequency_penalty"])) {
  123. $frequencyPenalty = floatval($conf["frequency_penalty"]) ?? 0;
  124. }
  125. $OPENAI_API_KEY = '';
  126. $clearPrompt = $this->wordFilter($prompt);
  127. $headers = ["Accept: application/json", "Content-Type: application/json", "Authorization: Bearer " . $proxy["sk"]];
  128. $messages = [];
  129. if (mb_strlen($answer) + mb_strlen($guide) + mb_strlen($prompt) < 4000) {
  130. if ($answer) {
  131. $messages[] = ["role" => "assistant", "content" => $answer];
  132. }
  133. if ($guide) {
  134. $messages[] = ["role" => "system", "content" => $guide];
  135. }
  136. }
  137. $messages[] = ["role" => "user", "content" => $prompt];
  138. $opts = ["model" => $proxy["model"], "messages" => $messages, "temperature" => $temperature, "presence_penalty" => $presencePenalty, "frequency_penalty" => $frequencyPenalty, "stream" => true];
  139. if ($type == "gpt4") {
  140. $ins = ConfServiceFacade::groupGet("system.ai");
  141. $opts["key"] = $ins["ins_api_key"];
  142. if (!$opts["key"]) {
  143. return error("后台未正确配置参数");
  144. }
  145. $get_post_data = http_build_query($opts);
  146. $API_URL = "https://api.wike.cc/api/gpt4/set" . "?" . $get_post_data;
  147. } else {
  148. $API_URL = $proxy["url"];
  149. }
  150. $response = '';
  151. $section = '';
  152. $callback = function ($ch, $data) use($messages, $loginUserInfo, $modelQuestion, $modelVipinfo, $_GPC, $platform, $conf, $numberAlias, $coin, $clearPrompt, $type, $proxy, $section) {
  153. global $response, $section;
  154. $dataLength = strlen($data);
  155. $complete = @json_decode($data, true);
  156. if ($type == "gpt4" && isset($complete["code"]) && $complete["code"] != 200) {
  157. echo $data;
  158. exit;
  159. }
  160. if (isset($complete->error)) {
  161. file_put_contents(__DIR__ . "/ds.json", json_encode($complete->error));
  162. file_put_contents(__DIR__ . "/ds2.json", json_encode($proxy));
  163. echo "服务器出现未知错误,请稍后重试或联系客服。";
  164. exit;
  165. } else {
  166. if (!empty($section)) {
  167. $data = $section . $data;
  168. $section = '';
  169. } else {
  170. if (substr($data, -1) !== "\n") {
  171. $section = $data;
  172. return $dataLength;
  173. }
  174. }
  175. $wordArr = $this->parseData($data);
  176. foreach ($wordArr as $word) {
  177. if ($word == "data: [DONE]" || $word == "data: [CONTINUE]") {
  178. if (empty($response)) {
  179. goto Vqj1C;
  180. }
  181. if ($platform == "wxOfficialAccount" || $platform == "H5") {
  182. if (!empty($conf) && !empty($conf["is_h5_filter"]) && $conf["is_h5_filter"] == 1) {
  183. $check = ImageCensorServiceFacade::textCensorUserDefined($response);
  184. if (!empty($check["conclusion"]) && $check["conclusion"] == "不合规") {
  185. echo "内容包含敏感信息,不予展示。";
  186. exit;
  187. }
  188. }
  189. }
  190. $end = end($messages);
  191. $clearResponse = $this->wordFilter($response);
  192. $question = $modelQuestion->save(["type" => $type,"uid" => $loginUserInfo["id"], "question" => $clearPrompt, "answer" => $clearResponse, "uniacid" => $_GPC["uniacid"]]);
  193. if ($type == "gpt4") {
  194. $post["answer"] = $clearResponse;
  195. }
  196. $checkMember = MemberServiceFacade::cash($loginUserInfo, $type, $coin, $conf);
  197. if (isset($checkMember["status"]) && !$checkMember["status"]) {
  198. return $this->error($checkMember["msg"], 2);
  199. }
  200. $response = '';
  201. break;
  202. }
  203. $response .= $word;
  204. echo $word;
  205. Vqj1C:
  206. ob_flush();
  207. flush();
  208. }
  209. return $dataLength;
  210. }
  211. };
  212. $ch = curl_init();
  213. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
  214. curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
  215. curl_setopt($ch, CURLOPT_URL, $API_URL);
  216. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  217. curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
  218. curl_setopt($ch, CURLOPT_POST, true);
  219. curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($opts, 320));
  220. curl_setopt($ch, CURLOPT_WRITEFUNCTION, $callback);
  221. curl_exec($ch);
  222. }
  223. private function getUrl($type, $conf)
  224. {
  225. global $_GPC;
  226. if ($type == "gpt35") {
  227. $data = [];
  228. if (empty($conf["connect_lines"]) || $conf["connect_lines"] == 1) {
  229. $res = InsServiceFacade::getproxy($type);
  230. $res2 = json_decode($res, true);
  231. if (empty($res2) || !empty($res2["code"]) && $res2["code"] == 403 || !empty($res2["code"]) && $res2["code"] == 400) {
  232. $data["model"] = "gpt-3.5-turbo-0301";
  233. $data["sk"] = '';
  234. $data["url"] = "https://proxy3.wike.cc/v1/chat/completions";
  235. return $data;
  236. }
  237. return $res2["data"];
  238. } else {
  239. if ($conf["connect_lines"] == 2) {
  240. $info = \app\model\Sk::order("id desc")->where(["uniacid" => $_GPC["uniacid"], "status" => 1])->limit(1)->select();
  241. if (!$info) {
  242. return $this->error("未配置key,或无可用的key");
  243. }
  244. $data["model"] = "gpt-3.5-turbo-0301";
  245. $data["sk"] = $info[0]["sk"];
  246. $data["url"] = $conf["private_proxy"];
  247. }
  248. }
  249. return $data;
  250. } elseif ($type == "gpt4") {
  251. $res = InsServiceFacade::getproxy($type);
  252. $res2 = json_decode($res, true);
  253. if (empty($res2) || !empty($res2["code"]) && $res2["code"] == 403 || !empty($res2["code"]) && $res2["code"] == 400) {
  254. return $this->error("4.0数据获取失败,请稍后再试");
  255. }
  256. $res2["data"]["sk"] = InsServiceFacade::decrypt($res2["data"]["sk"], WIKE);
  257. return $res2["data"];
  258. }
  259. }
  260. public function chat4()
  261. {
  262. global $_GPC;
  263. $post = $this->request->post();
  264. $prompt = $this->request->post("prompt", '');
  265. $guide = $this->request->post("guide", '');
  266. $answer = $this->request->post("answer", '');
  267. $platform = $this->request->header("platform", "H5");
  268. $conf = ConfServiceFacade::groupGet("system.config", 0);
  269. $coin = ConfServiceFacade::get("system.plan.lock_gpt4", 0);
  270. if (!$prompt) {
  271. return $this->error("请填写文本");
  272. }
  273. $loginUserInfo = UserServiceFacade::getUserInfo();
  274. $numberAlias = !empty($conf["number_alias"]) ? $conf["number_alias"] : "点数";
  275. $modelQuestion = new \app\model\Question();
  276. if (empty($conf["is_gpt4"]) || $conf["is_gpt4"] == 2) {
  277. return $this->error("后台未启用gpt4.0", 2);
  278. }
  279. if ($loginUserInfo["coin"] < $coin) {
  280. return $this->error($numberAlias . "不足", 2);
  281. } else {
  282. \app\model\User::where(["id" => $loginUserInfo["id"]])->dec("coin", $coin)->update();
  283. BillServiceFacade::record(0, $coin, "chatgpt", "问答消耗" . $numberAlias, $loginUserInfo["id"], $_GPC["uniacid"]);
  284. }
  285. $res = InsServiceFacade::gpt4($post);
  286. $res2 = json_decode($res, true);
  287. if (empty($res2)) {
  288. return $this->error("请求错误");
  289. }
  290. if (!empty($res2["code"]) && $res2["code"] == 403) {
  291. return $this->error($res2["msg"]);
  292. }
  293. if (!empty($res2["code"]) && $res2["code"] == 400) {
  294. return $this->error($res2["msg"]);
  295. }
  296. if ($platform == "wxMiniProgram") {
  297. $check = MiniappServiceFacade::msgSecCheck($res2["data"], $loginUserInfo["openid_miniapp"]);
  298. if (!$check) {
  299. return $this->error("失败,文字内容安全检测不通过!");
  300. }
  301. } else {
  302. if ($platform == "wxOfficialAccount" || $platform == "H5") {
  303. if (!empty($conf) && !empty($conf["is_h5_filter"]) && $conf["is_h5_filter"] == 1) {
  304. $check = ImageCensorServiceFacade::textCensorUserDefined($res2["data"]);
  305. if (!empty($check["conclusion"]) && $check["conclusion"] == "不合规") {
  306. return $this->error("失败,文字内容安全检测不通过!");
  307. }
  308. }
  309. }
  310. }
  311. $question = $modelQuestion->save(["uid" => $loginUserInfo["id"], "question" => $prompt, "answer" => $res2["data"], "uniacid" => $_GPC["uniacid"]]);
  312. return $this->success("操作成功", $res2["data"]);
  313. }
  314. public function tts()
  315. {
  316. global $_GPC;
  317. $text = $this->request->post("text", '');
  318. if (!$text) {
  319. return $this->error("请填写文本");
  320. }
  321. $res = SpeechServiceFacade::synthesis2($text);
  322. if (isset($res->{"error_code"})) {
  323. return $this->error($res["error_msg"]);
  324. }
  325. return $this->success("操作成功", $res);
  326. }
  327. public function ttsJob()
  328. {
  329. global $_GPC;
  330. $taskIds = $this->request->param("task_ids", '');
  331. if (!$taskIds) {
  332. return $this->error("请上传任务id");
  333. }
  334. $res = SpeechServiceFacade::query($taskIds);
  335. if (isset($res->{"error_code"})) {
  336. return $this->error($res["error_msg"]);
  337. }
  338. return $this->success("操作成功", $res->{"tasks_info"}[0]);
  339. }
  340. public function recognizer()
  341. {
  342. global $_GPC;
  343. $platform = $this->request->header("platform", "H5");
  344. $speech = $this->request->file("speech");
  345. if ($platform == "wxMiniProgram") {
  346. $format = "m4a";
  347. } else {
  348. $format = "wav";
  349. }
  350. $audio = file_get_contents($speech);
  351. $res = SpeechServiceFacade::asr($audio, $format, "16000");
  352. if (isset($res["err_no"]) && $res["err_no"] != 0) {
  353. return $this->error($res["err_msg"]);
  354. }
  355. return $this->success("操作成功", $res);
  356. }
  357. public function getAddress()
  358. {
  359. global $_GPC;
  360. $data = [];
  361. $conf = ConfServiceFacade::groupGet("system.config");
  362. if (empty($conf["connect_lines"]) || $conf["connect_lines"] == 1) {
  363. $data["sk"] = "sk-wfjrfffffffffffffffhufrhuwdyqgygbwdyft";
  364. $data["url"] = "https://ok.justduit.com";
  365. } else {
  366. if ($conf["connect_lines"] == 2) {
  367. $info = \app\model\Sk::order("id desc")->where(["uniacid" => $_GPC["uniacid"], "status" => 1])->limit(1)->select();
  368. if (!$info) {
  369. return $this->error("未配置key,或无可用的key");
  370. }
  371. $data["sk"] = "sk-wfjrfffffffffffffffhufrhuwdyqgygbwdyft";
  372. $data["url"] = "https://ok.justduit.com";
  373. }
  374. }
  375. return $this->success("操作成功", $data);
  376. }
  377. public function painting()
  378. {
  379. global $_GPC;
  380. $modelGallery = new \app\model\Gallery();
  381. $platform = $this->request->header("platform", "H5");
  382. $prompt = $this->request->post("prompt", '');
  383. $negativePrompt = $this->request->post("negative_prompt", '');
  384. $conf = ConfServiceFacade::groupGet("system.config");
  385. $coin = ConfServiceFacade::get("system.plan.unlock_aipainting", 0);
  386. if (!$prompt) {
  387. return $this->error("请填写文本");
  388. }
  389. $res = SdapiServiceFacade::getMj($prompt, $negativePrompt);
  390. print_r($res);
  391. return;
  392. $loginUserInfo = UserServiceFacade::getUserInfo();
  393. if ($platform == "wxMiniProgram") {
  394. $check = MiniappServiceFacade::msgSecCheck($prompt, $loginUserInfo["openid_miniapp"]);
  395. if (!$check) {
  396. return $this->error("失败,文字内容安全检测不通过!");
  397. }
  398. } else {
  399. if ($platform == "wxOfficialAccount" || $platform == "H5") {
  400. if (!empty($conf) && !empty($conf["is_h5_filter"]) && $conf["is_h5_filter"] == 1) {
  401. $check = ImageCensorServiceFacade::textCensorUserDefined($prompt);
  402. if (!empty($check["conclusion"]) && $check["conclusion"] == "不合规") {
  403. return $this->error("失败,文字内容安全检测不通过!");
  404. }
  405. }
  406. }
  407. }
  408. $numberAlias = !empty($conf["number_alias"]) ? $conf["number_alias"] : "点数";
  409. if ($coin > 0) {
  410. if ($loginUserInfo["coin"] < $coin) {
  411. return $this->error("您的点数不足");
  412. }
  413. }
  414. $res = YijianServiceFacade::put_task($prompt);
  415. if (!empty($res["status"]) && $res["status"] != 0) {
  416. return $this->error($res["reason"]);
  417. }
  418. if ($coin > 0) {
  419. \app\model\User::where(["id" => $loginUserInfo["id"]])->dec("coin", $coin)->update();
  420. }
  421. if (!empty($res["data"]["Uuid"])) {
  422. $data["job_id"] = $res["data"]["Uuid"];
  423. $data["prompt"] = $prompt;
  424. $data["paid_coin"] = $coin;
  425. $data["uid"] = $loginUserInfo["id"];
  426. $data["uniacid"] = $_GPC["uniacid"];
  427. $modelGallery->save($data);
  428. BillServiceFacade::record(0, $coin, "chatgpt", "绘画消耗" . $numberAlias, $loginUserInfo["id"], $_GPC["uniacid"]);
  429. }
  430. return $this->success("操作成功", $res["data"]);
  431. }
  432. public function showTask()
  433. {
  434. global $_GPC;
  435. $uuid = $this->request->param("uuid", '');
  436. $loginUserInfo = UserServiceFacade::getUserInfo();
  437. if (!$uuid) {
  438. return $this->error("请上传uuid");
  439. }
  440. $res = YijianServiceFacade::show_task($uuid);
  441. if (!empty($res["status"]) && $res["status"] != 0) {
  442. $coin = ConfServiceFacade::get("system.plan.unlock_aipainting", 0);
  443. if ($coin > 0) {
  444. \app\model\User::where(["id" => $data["uid"]])->inc("coin", $coin)->update();
  445. }
  446. return $this->error($res["reason"]);
  447. }
  448. if (empty($res["data"]["ImagePath"])) {
  449. return $this->success("继续等待", "wait");
  450. }
  451. $filePath = $this->_put_file_from_url_content($res["data"]["ImagePath"]);
  452. $galleryInfo = \app\model\Gallery::where(["job_id" => $uuid])->findOrEmpty();
  453. if ($galleryInfo && empty($galleryInfo["img"])) {
  454. $filesModel = new \app\model\Files();
  455. $fileId = $filesModel->insertGetId(["category_id" => 0, "name" => $uuid . time(), "file_type" => "image", "path" => $filePath["saveName"], "upload_type" => "local", "size" => 1, "create_admin_user_id" => 0, "update_admin_user_id" => 0, "create_time" => date("Y-m-d H:i:s"), "update_time" => date("Y-m-d H:i:s"), "uniacid" => $_GPC["uniacid"], "ext" => "png"]);
  456. $galleryInfo->save(["img" => $fileId]);
  457. }
  458. return $this->success("操作成功", $res["data"]["ImagePath"]);
  459. }
  460. public function checkText()
  461. {
  462. global $_GPC;
  463. $loginUserInfo = UserServiceFacade::getUserInfo();
  464. $prompt = $this->request->param("prompt", '');
  465. $platform = $this->request->header("platform", "H5");
  466. $conf = ConfServiceFacade::groupGet("system.config", 0);
  467. if (!$prompt) {
  468. return $this->error("请填写问题");
  469. }
  470. $str = strstr($prompt, "收割台湾");
  471. if ($str != false) {
  472. return $this->error("您的提问涉及敏感信息");
  473. }
  474. if ($platform == "wxMiniProgram") {
  475. $check = MiniappServiceFacade::msgSecCheck($prompt, $loginUserInfo["openid_miniapp"]);
  476. if (!$check) {
  477. return $this->error("失败,文字内容安全检测不通过!");
  478. }
  479. } else {
  480. if ($platform == "wxOfficialAccount" || $platform == "H5") {
  481. if (!empty($conf) && !empty($conf["is_h5_filter"]) && $conf["is_h5_filter"] == 1) {
  482. $check = ImageCensorServiceFacade::textCensorUserDefined($prompt);
  483. if (!empty($check["conclusion"]) && $check["conclusion"] == "不合规") {
  484. if (!empty($check["data"]) && ($check["data"][0]["subType"] == 1 || $check["data"][0]["subType"] == 2 || $check["data"][0]["subType"] == 3 || $check["data"][0]["subType"] == 5)) {
  485. return $this->error("失败,文字内容安全检测不通过!");
  486. }
  487. }
  488. }
  489. }
  490. }
  491. return $this->success("操作成功");
  492. }
  493. public function chat4event()
  494. {
  495. header("Content-Type: text/event-stream");
  496. header("Cache-Control: no-cache");
  497. header("Connection: keep-alive");
  498. header("X-Accel-Buffering: no");
  499. $OPENAI_API_KEY = "sk-";
  500. $headers = ["Accept: application/json", "Content-Type: application/json", "Authorization: Bearer " . $OPENAI_API_KEY];
  501. $prompt = $this->request->post("prompt", "写一篇文章");
  502. $messages = [["role" => "user", "content" => $prompt]];
  503. $opts = ["model" => "gpt-4", "messages" => $messages, "temperature" => 1.0, "max_tokens" => 2000, "frequency_penalty" => 0, "presence_penalty" => 0.6, "stream" => true];
  504. $callback = function ($ch, $data) {
  505. $complete = json_decode($data);
  506. if (isset($complete->error)) {
  507. print_r($complete->error);
  508. } else {
  509. $word = $this->parseData($data);
  510. if ($word == "data: [DONE]" || $word == "data: [CONTINUE]") {
  511. ob_flush();
  512. flush();
  513. } else {
  514. echo $word;
  515. ob_flush();
  516. flush();
  517. }
  518. }
  519. return strlen($data);
  520. };
  521. $ch = curl_init();
  522. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
  523. curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
  524. curl_setopt($ch, CURLOPT_URL, "https://proxy4.iduomi.cc/v1/chat/completions");
  525. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  526. curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
  527. curl_setopt($ch, CURLOPT_POST, 1);
  528. curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($opts));
  529. curl_setopt($ch, CURLOPT_WRITEFUNCTION, $callback);
  530. curl_exec($ch);
  531. }
  532. public function wordFilter($message)
  533. {
  534. $Filter = new \ins\Words("*");
  535. $clearMessage = $Filter->filter($message);
  536. return $clearMessage;
  537. }
  538. private function parseData($content)
  539. {
  540. $content = trim($content);
  541. $rows = explode("\n", $content);
  542. $result = [];
  543. foreach ($rows as $data) {
  544. if (strpos($data, "data: [DONE]") !== false) {
  545. $char = "data: [DONE]";
  546. } else {
  547. $data = str_replace("data: {", "{", $data);
  548. $data = rtrim($data, "\n\n");
  549. if (strpos($data, "}\n\n{") !== false) {
  550. $arr = explode("}\n\n{", $data);
  551. $data = "{" . $arr[1];
  552. }
  553. $data = @json_decode($data, true);
  554. if (!is_array($data)) {
  555. continue;
  556. }
  557. if ($data["choices"]["0"]["finish_reason"] == "stop") {
  558. $char = "data: [DONE]";
  559. } elseif ($data["choices"]["0"]["finish_reason"] == "length") {
  560. $char = "data: [CONTINUE]";
  561. } else {
  562. $char = $data["choices"]["0"]["delta"]["content"] ?? '';
  563. }
  564. }
  565. $result[] = $char;
  566. }
  567. return $result;
  568. }
  569. public function test()
  570. {
  571. header("Content-Type: text/event-stream");
  572. header("Cache-Control: no-cache");
  573. header("Connection: keep-alive");
  574. header("X-Accel-Buffering: no");
  575. global $_GPC;
  576. $ins = ConfServiceFacade::groupGet("system.ai");
  577. $API_URL = "https://api.wike.cc/api/senseai/chatgpt4";
  578. $data["key"] = $ins["ins_api_key"];
  579. $get_post_data = http_build_query($data);
  580. $callbacks = function ($ch, $data) use($_GPC) {
  581. $complete = @json_decode($data, true);
  582. echo $data;
  583. ob_flush();
  584. flush();
  585. return strlen($data);
  586. };
  587. $ch = curl_init();
  588. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
  589. curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
  590. curl_setopt($ch, CURLOPT_URL, $API_URL . "?" . $get_post_data);
  591. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  592. curl_setopt($ch, CURLOPT_POST, true);
  593. curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
  594. curl_setopt($ch, CURLOPT_WRITEFUNCTION, $callbacks);
  595. curl_exec($ch);
  596. }
  597. public static function send($API_URL, $get_post_data, $type, $ifsign, $sk)
  598. {
  599. $get_post_data = http_build_query($get_post_data);
  600. if ($ifsign) {
  601. $sign = md5($get_post_data . $sk);
  602. $res = self::send_curl($API_URL, $type, $get_post_data, $sign);
  603. } else {
  604. $res = self::send_curl($API_URL, $type, $get_post_data, null);
  605. }
  606. return $res;
  607. }
  608. public static function send_curl($API_URL, $type, $get_post_data, $sign)
  609. {
  610. $ch = curl_init();
  611. if ($type == "POST") {
  612. curl_setopt($ch, CURLOPT_URL, $API_URL);
  613. curl_setopt($ch, CURLOPT_POST, true);
  614. curl_setopt($ch, CURLOPT_POSTFIELDS, $get_post_data);
  615. } elseif ($type == "GET") {
  616. curl_setopt($ch, CURLOPT_URL, $API_URL . "?" . $get_post_data);
  617. }
  618. if ($sign) {
  619. curl_setopt($ch, CURLOPT_HTTPHEADER, ["sign:" . $sign]);
  620. }
  621. curl_setopt($ch, CURLOPT_REFERER, $API_URL);
  622. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  623. curl_setopt($ch, CURLOPT_TIMEOUT, 300);
  624. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
  625. curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
  626. $resdata = curl_exec($ch);
  627. curl_close($ch);
  628. return $resdata;
  629. }
  630. protected function uploadImage($file, $post = array())
  631. {
  632. if (empty($post["upload_type"])) {
  633. $uploadType = "local";
  634. } else {
  635. $uploadType = $post["upload_type"];
  636. }
  637. if (!in_array($uploadType, ["local", "ali-oss", "qiniu-kodo"])) {
  638. return $this->error($uploadType . "上传方式未定义");
  639. }
  640. $fileExt = strtolower($file->getOriginalExtension());
  641. $uploadDomain = new UploadDomain();
  642. if (!$uploadDomain->check($file->getOriginalName(), $file->getSize(), $fileExt, $file->getMime())) {
  643. }
  644. $saveName = date("Ymd") . "/" . md5(uniqid(mt_rand())) . ".{$fileExt}";
  645. $uploadDir = $this->request->post("dir");
  646. $object = $uploadDir ? $uploadDir . "/" . $saveName : $saveName;
  647. $data = [];
  648. $filePath = $object;
  649. $uploadDir = ltrim("/", $uploadDir);
  650. $saveName = Filesystem::putFileAs("/" . $uploadDir, $file, "/" . $object);
  651. $filePath = $saveName;
  652. $data["image"] = request()->domain() . STATIC_PATH . "/storage/" . $saveName;
  653. $data["name"] = $saveName;
  654. return $data;
  655. }
  656. private function _put_file_from_url_content($url)
  657. {
  658. $name = md5(uniqid(mt_rand())) . ".png";
  659. $saveName = date("Ymd") . "/" . $name;
  660. $path = IA_ROOT_WK . "/public/static/storage/";
  661. set_time_limit(0);
  662. $url = trim($url);
  663. $curl = curl_init();
  664. curl_setopt($curl, CURLOPT_URL, $url);
  665. curl_setopt($curl, CURLOPT_HEADER, 0);
  666. curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
  667. $file = curl_exec($curl);
  668. curl_close($curl);
  669. $filename = $path . $saveName;
  670. if (!file_exists($path . date("Ymd"))) {
  671. mkdir($path . date("Ymd"), 0755, true);
  672. }
  673. $write = @fopen($filename, "w");
  674. if ($write == false) {
  675. return false;
  676. }
  677. if (fwrite($write, $file) == false) {
  678. return false;
  679. }
  680. if (fclose($write) == false) {
  681. return false;
  682. }
  683. $data["filename"] = $filename;
  684. $data["url"] = request()->domain() . STATIC_PATH . "/storage/" . $saveName;
  685. $data["saveName"] = $saveName;
  686. $data["name"] = $name;
  687. return $data;
  688. }
  689. }