123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568 |
- <?php
- namespace App\Http\Controllers\V1\Ai;
- use App\Auth;
- use App\Http\Controllers\V1\Controller;
- use App\libs\helpers\Helper;
- use App\libs\helpers\LogHelper;
- use App\libs\helpers\Response;
- use App\Models\Config;
- use App\Models\Keyword;
- use App\Models\TaskList;
- use App\Models\User;
- use App\Models\UserRole;
- use Illuminate\Http\Request;
- use Illuminate\Support\Facades\Log;
- use App\Exceptions\ApiException;
- use Overtrue\Pinyin\Pinyin;
- class AiController extends Controller
- {
- public $code = '_Ai';
- /**
- * 用户提交任务
- */
- public function submitTask(Request $request): \Illuminate\Http\JsonResponse
- {
- try {
- (int) $plot = Config::query()->where('key', 'plot')->value('value');
- if (!$plot) {
- return Response::fail('系统错误,请联系管理员#');
- }
- if (Auth::$user->diamond < $plot) {
- return Response::fail('钻石不够了,请先充值');
- }
- $roleId = $request->post('roleId', 0);
- if ($roleId) {
- $role = UserRole::query()->find($roleId);
- if (!$role) {
- return Response::fail('没有该角色');
- }
- } else {
- $role = UserRole::query()->create([
- 'user_id' => Auth::$userId,
- 'name' => $request->post('name', ''),
- 'sex' => $request->post('sex', ''),
- 'age' => $request->post('age', ''),
- 'star' => $request->post('star', ''),
- 'level' => $request->post('level', ''),
- 'is_piny' => $request->post('is_piny', 1),
- ]);
- if (!$role) {
- return Response::fail('提交失败,请稍后再试!');
- }
- }
- User::query()->where('id', Auth::$userId)->decrement('diamond', $plot);
- $task = TaskList::query()->create([
- 'user_id' => Auth::$userId,
- 'role_id' => $role->id,
- 'image' => $request->post('image', ''),
- 'surplus_diamond' => Auth::$user->diamond - $plot,
- 'nickname' => 'AI绘本生成',
- 'plot' => $plot,
- ]);
- if (!$task) {
- return Response::fail('任务提交失败');
- }
- return Response::success(['id' => $task->id], '提交成功,请稍等');
- } catch (\Exception $exception) {
- LogHelper::exceptionLog($exception, $this->code);
- return Response::fail($exception->getMessage());
- }
- }
- /**
- * 获取任务详情.
- *
- * @return \Illuminate\Http\JsonResponse
- */
- public function getTaskDetail(Request $request)
- {
- try {
- $id = $request->get('id', 0);
- return Response::success(TaskList::query()->where('user_id', Auth::$userId)->find($id));
- } catch (\Exception $exception) {
- LogHelper::exceptionLog($exception, $this->code);
- return Response::fail($exception->getMessage());
- }
- }
- /**
- * 获取字数.
- *
- * @return int|mixed
- */
- private function getBuildCountString($level = 1)
- {
- $string = Config::query()->where('key', 'class_count')->first()->toArray();
- foreach ($string['value'] ?? [] as $value) {
- if ($level == $value['lv']) {
- return $value['count'];
- }
- }
- return 200;
- }
- /**
- * 生成故事.
- */
- public function buildStory(Request $request): \Illuminate\Http\JsonResponse
- {
- try {
- $task = TaskList::query()->with('role')->where('state', 0)->inRandomOrder()->first();
- if (!$task) {
- return Response::fail('暂无任务');
- }
- $key = [];
- // $keyword = Keyword::query()->pluck('keyword');
- // foreach ($keyword as $value) {
- // $key[] = $value;
- // }
- // $keyword = implode(',', $key);
- $keyword = Config::query()->where('key', 'prompt_gushi')->value('value');
- $task->state = 1;
- $task->save();
- Log::warning('这个是当前的次数:' . $this->getBuildCountString($task->level));
- $prompt = "一个{$task->role->sex},叫{$task->role->name},{$task->role->age}岁。{$keyword},要求不低于{$this->getBuildCountString($task->role->level)}字。备注:不要加什么特殊符号只需要正常的逗号句号叹号这些。";
- $messages[] = ['role' => 'user', 'content' => $prompt];
- $data = [
- 'messages' => $messages,
- ];
- $postData = json_encode($data);
- $complete = $this->host($postData);
- $task->init_content = $complete['result'];
- $task->save();
- return Response::success($complete);
- } catch (\Exception $exception) {
- LogHelper::exceptionLog($exception, $this->code);
- return Response::fail($exception->getMessage());
- }
- }
- /**
- * 生成标题.
- *
- * @return \Illuminate\Http\JsonResponse
- */
- public function buildTitle(Request $request)
- {
- try {
- $task = TaskList::query()->with('role')->where('state', 1)->inRandomOrder()->first();
- if (!$task) {
- return Response::fail('暂无任务');
- }
- $task->state = 2;
- $task->save();
- $prompt = $task->init_content . '。将这段童话故事生成一个标题,标题不能有特殊符号,只需要纯文字标题即可,不需要其他任何文字,标题文字控制在10个字以内。不能超过10个字';
- $messages[] = ['role' => 'user', 'content' => $prompt];
- $data = [
- 'messages' => $messages,
- ];
- $postData = json_encode($data);
- $complete = $this->host($postData);
- // $task->state = 2;
- $task->title = $complete['result'];
- $task->save();
- return Response::success($complete);
- } catch (\Exception $exception) {
- LogHelper::exceptionLog($exception, $this->code);
- return Response::fail($exception->getMessage());
- }
- }
- /**
- * 生成关键词.
- *
- * @return \Illuminate\Http\JsonResponse
- */
- public function buildKeyword(Request $request)
- {
- try {
- $task = TaskList::query()->with('role')->where('state', 2)->inRandomOrder()->first();
- if (!$task) {
- return Response::fail('暂无任务');
- }
- $keyword = Config::query()->where('key', 'prompt_keyword')->value('value');
- $prompt = $task->init_content . $keyword;
- $messages[] = ['role' => 'user', 'content' => $prompt];
- $data = [
- 'messages' => $messages,
- ];
- $task->state = 3;
- $task->save();
- $postData = json_encode($data);
- $complete = $this->host($postData);
- // $task->state = 3;
- $task->keyword = $complete['result'];
- $task->save();
- return Response::success($complete);
- } catch (\Exception $exception) {
- LogHelper::exceptionLog($exception, $this->code);
- return Response::fail($exception->getMessage());
- }
- }
- /**
- * 翻译英文.
- */
- private function toEnglish($prompt)
- {
- $keyword = Config::query()->where('key', 'prompt_style')->value('value');
- $prompt = $prompt . $keyword;
- $promptTo = '我希望你能担任英语翻译、拼写校对和修辞改进的角色。我会将翻译的结果用于如stable diffusion、midjourney等绘画场景生成图片,语言要求尽量优美。我会用任何语言和你交流,你会识别语言,将其翻译为英语并仅回答翻译的最终结果,不要写解释。我的第一句话是:' . $prompt . '。请立刻翻译,不要回复其它内容。';
- $messages[] = ['role' => 'user', 'content' => $promptTo];
- $data = [
- 'messages' => $messages,
- ];
- $postData = json_encode($data);
- $complete = $this->host($postData);
- return $complete['result'];
- }
- /**
- * 提交sd生成插图.
- *
- * @return \Illuminate\Http\JsonResponse
- */
- public function buildSd(Request $request)
- {
- try {
- $task = TaskList::query()->with('role')->where('state', 3)->inRandomOrder()->first();
- if (!$task) {
- return Response::fail('暂无任务');
- }
- $task->state = 4;
- $task->save();
- $keyword = $this->toEnglish($task->keyword);
- $param = ['name' => '甜瓜(动漫风格)',
- 'init_image' => '',
- 'prompt' => $keyword,
- 'width' => '512',
- 'height' => '512',
- 'guidance_scale' => '7',
- 'samples' => '1',
- 'model_id' => '3',
- 'scheduler' => 'DDPMScheduler',
- 'type' => 'text2img',
- 'num_inference_steps' => '30',
- 'keywords' => $keyword,
- ];
- $result = (new Helper())->opensd($param);
- $result = json_decode($result, true);
- Log::warning('这个是SD回调信息:' . json_encode($result, 256));
- if (isset($result['data']['id'])) {
- $task->sd_id = $result['data']['id'];
- } else {
- $task->state = 3;
- }
- $task->save();
- return Response::success($result['data']);
- } catch (\Exception $exception) {
- LogHelper::exceptionLog($exception, $this->code);
- return Response::fail($exception->getMessage());
- }
- }
- /**
- * 查询生成进度.
- *
- * @return \Illuminate\Http\JsonResponse
- */
- public function getOpensdDetail(Request $request)
- {
- $task = TaskList::query()->where('state', 4)->inRandomOrder()->first();
- if (!$task) {
- return $this->error('暂无任务');
- }
- $res = (new Helper())->opensdDetail($task->sd_id);
- $res = @json_decode($res, true);
- if (200 != $res['code']) {
- return Response::fail($res['msg']);
- }
- if ('fail' == $res['data']['state']) {
- $task->state = 3;
- $task->desc = $res['data']['fail_reason'];
- }
- $task->save();
- if ('success' == $res['data']['state']) {
- $path = $this->saveImage($res['data']['gen_img']);
- $task->sd_image = $path;
- $task->state = 5;
- $task->save();
- }
- return $this->success('操作成功', $res['data']);
- }
- /**
- * 获取品牌排版.
- *
- * @return \Illuminate\Http\JsonResponse
- */
- public function buildPinyin(Request $request)
- {
- try {
- $task = TaskList::query()->where('state', 5)->inRandomOrder()->first();
- if (!$task) {
- return $this->error('暂无任务');
- }
- if (empty($file_name)) {
- $file_name = md5(time()) . '.png';
- }
- $path = public_path() . '/images/' . $file_name;
- $shell = 'wkhtmltoimage https://t18.9026.com/api/ai/Pinyin?id=' . $task->id . ' ' . $path;
- exec($shell, $result, $status);
- if ($status) {
- $this->exit_out('生成图片失败', ['生成图片失败' => [$shell, $result, $status]]);
- }
- $domain = request()->getScheme() . '://' . request()->getHost();
- $pdfPath = $domain . '/images/' . $file_name;
- $task->image_path = $pdfPath;
- $result = $this->extracted($task);
- $task->pinyin_content = $result;
- $task->state = 6;
- $task->save();
- return Response::success($result);
- } catch (\Exception $exception) {
- LogHelper::exceptionLog($exception, $this->code);
- return Response::fail($exception->getMessage());
- }
- }
- /**
- * 下载PDF.
- *
- * @return \Illuminate\Http\JsonResponse
- */
- public function downloadPdf(Request $request)
- {
- try {
- $id = $request->input('id', 0);
- $task = TaskList::query()->find($id);
- if (!$task) {
- return Response::fail('没有该任务');
- }
- if (!empty($task->pdf_path)) {
- return Response::success(['url' => $task->pdf_path]);
- }
- if (empty($file_name)) {
- $file_name = md5(time()) . '.pdf';
- }
- $path = public_path() . '/pdf/' . $file_name;
- $shell = 'wkhtmltopdf https://t18.9026.com/api/ai/Pinyin?id=' . $task->id . ' ' . $path;
- exec($shell, $result, $status);
- if ($status) {
- $this->exit_out('生成PDF失败', ['生成PDF失败' => [$shell, $result, $status]]);
- }
- $domain = request()->getScheme() . '://' . request()->getHost();
- $pdfPath = $domain . '/pdf/' . $file_name;
- $task->pdf_path = $pdfPath;
- $task->save();
- return Response::success(['url' => $pdfPath]);
- } catch (\Exception $exception) {
- LogHelper::exceptionLog($exception, $this->code);
- return Response::fail($exception->getMessage());
- }
- }
- private function splitChineseCharacters($inputString, $type = 0)
- {
- if (0 == $type) {
- $inputString = str_replace("\n", '', $inputString);
- }
- $inputString = str_replace('“', '', $inputString);
- $inputString = str_replace('”', '', $inputString);
- // $inputString = preg_replace('/[^\w\s-]+/u', '', $inputString);
- $length = mb_strlen($inputString, 'utf-8');
- $result = [];
- for ($i = 0; $i < $length; $i++) {
- $result[] = mb_substr($inputString, $i, 1, 'utf-8');
- }
- return $result;
- // return $inputString;
- }
- public function Pinyin(Request $request)
- {
- try {
- $id = $request->input('id');
- $task = TaskList::query()->find($id);
- $result = $this->extracted($task);
- return view('pdf', ['data' => $result, 'img' => $task->image, 'title' => $task->title]);
- } catch (\Exception $exception) {
- LogHelper::exceptionLog($exception, $this->code);
- return Response::fail($exception->getMessage());
- }
- }
- public function containsPunctuation($str)
- {
- // 定义要检测的符号
- $punctuation = '/[,。!、]/u'; // 中文逗号、中文句号、中文感叹号
- // 使用 preg_match 函数进行匹配
- return 1 === preg_match($punctuation, $str);
- }
- public function generate_pdf($html_path = '', $file_name = '')
- {
- if (empty($file_name)) {
- $file_name = md5(time()) . '.pdf';
- }
- $path = public_path() . '/pdf/' . $file_name;
- var_dump($path);
- exit;
- $shell = 'wkhtmltopdf --outline --minimum-font-size 9 ' . $html_path . ' ' . $path;
- exec($shell, $result, $status);
- if ($status) {
- $this->exit_out('生成PDF失败', ['生成PDF失败' => [$shell, $result, $status]]);
- }
- $domain = request()->getScheme() . '://' . request()->getHost();
- return $domain . '/pdf/' . $file_name;
- }
- public function exit_out($msg, $exceptionData = false, $code = 1, $data = [])
- {
- $out = ['code' => $code, 'msg' => $msg, 'data' => $data];
- if (false !== $exceptionData) {
- $this->trace([$msg => $exceptionData], 'error');
- }
- $json = json_encode($out, JSON_UNESCAPED_UNICODE);
- throw new ApiException($json);
- }
- public function trace($log = '', $level = 'info')
- {
- Log::log($level, $log);
- }
- /**
- * 保存图片.
- *
- * @return \Illuminate\Http\JsonResponse|string
- */
- private function saveImage($image_url)
- {
- $imageContent = file_get_contents($image_url);
- $imageDir = $_SERVER['DOCUMENT_ROOT'] . '/static/images/' . date('Ymd') . '/';
- $imageName = uniqid() . time() . '_image.png';
- $imagePath = $imageDir . $imageName;
- if (!is_dir($imageDir)) {
- mkdir($imageDir, 0777, true);
- }
- if (false !== $imageContent) {
- $savedImages = file_put_contents($imagePath, $imageContent);
- if (false !== $savedImages) {
- return $_SERVER['HTTP_HOST'] . '/static/images/' . date('Ymd') . '/' . $imageName;
- }
- return false;
- }
- return false;
- }
- /**
- * 执行请求
- */
- private function host($postData)
- {
- $ch = curl_init();
- curl_setopt_array($ch, [
- CURLOPT_URL => getenv('BAIDU_ERNIE_BOT40_URL') . '?access_token=' . Helper::getAccessToken(),
- CURLOPT_RETURNTRANSFER => true,
- CURLOPT_POST => true,
- CURLOPT_POSTFIELDS => $postData,
- ]);
- $res = curl_exec($ch);
- curl_close($ch);
- Log::warning('请求头:' .$postData);
- Log::warning('请求返回值:' .$res);
- return json_decode(trim($res), true);
- }
- public function extracted($result, $type = 0, $sdImage = ''): string
- {
- if (0 == $type) {
- $inputString = $result->init_content;
- $sdImage = $result->sd_image;
- } else {
- $inputString = $result;
- }
- $inputString = str_replace('“', '', $inputString);
- $inputString = str_replace('”', '', $inputString);
- $inputString = str_replace('——', '', $inputString);
- $inputString = str_replace('—', '', $inputString);
- $inputStringFor = $this->splitChineseCharacters($inputString, 1);
- $arr = [];
- $i = 0;
- foreach ($inputStringFor as $key => $value) {
- if ("\n" == $value) {
- $arr[] = $key - $i;
- $i++;
- }
- }
- $splitCharacters = $this->splitChineseCharacters($inputString);
- $pinyin = Pinyin::Sentence($inputString)->toArray();
- $string = '';
- $count = 0;
- foreach ($pinyin as $value) {
- $count += mb_strlen($value);
- }
- $img = '<img style="width: 100%;height:auto;float: right;margin-right: 10px;margin-top: 10px; margin-bottom: 5px" src="https://' . $sdImage . '"/>';
- $stringCount = 0;
- foreach ($pinyin as $key => $value) {
- if ($this->containsPunctuation($value)) {
- $value = ' ';
- }
- $stringCount += mb_strlen($value);
- if (in_array($count - $stringCount, [158, 159, 160, 161, 162, 163]) && !strstr($string, '<img')) {
- $string = $string . $img;
- }
- if (in_array($key + 1, $arr)) {
- // $string = $string . "<span><sup>{$value}</sup>{$splitCharacters[$key]}</span><br style='clear: both'><br style='clear: both'>";
- $string = $string . "<span>{$splitCharacters[$key]}</span><br style='clear: both'><br style='clear: both'>";
- } else {
- $style = '';
- // if (in_array($key, $arr) || 0 == $key) {
- // $style = 'style="margin-left: 5rem"';
- // }
- // $string = $string . '<span ' . $style . "><sup>{$value}</sup>{$splitCharacters[$key]}</span>";
- $string = $string . '<span ' . $style . ">{$splitCharacters[$key]}</span>";
- }
- }
- return $string;
- }
- }
|