AiChatContentFacadeRepository.php 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. <?php
  2. namespace App\Repositories\Eloquent;
  3. use App\Models\AiChatContent;
  4. use App\Repositories\Contracts\AiChatContentInterface;
  5. use App\Repositories\StreamHandler\AIStreamHandler;
  6. use Carbon\Carbon;
  7. use Illuminate\Database\Eloquent\Builder;
  8. use Monolog\Handler\RotatingFileHandler;
  9. use Monolog\Logger;
  10. class AiChatContentFacadeRepository extends BaseRepository implements AiChatContentInterface
  11. {
  12. private $AIStreamHandler = null;
  13. public function sendData(int $userId, string $conversation_id, string $content)
  14. {
  15. $AIConfig = config("console.AI");
  16. $data = [
  17. 'inputs' => (object) null,
  18. 'query' => $content,
  19. 'response_mode' => "streaming",
  20. "conversation_id"=>$conversation_id,
  21. "user"=>$userId,
  22. "files"=>null
  23. ];
  24. $headers = array(
  25. "Content-Type: application/json",
  26. "Authorization: Bearer ".$AIConfig["secret"]
  27. );
  28. $url = $AIConfig["url"].self::SEND_CHAT_URL;
  29. try {
  30. $addData[] = array(
  31. "user_id"=>$userId,
  32. "conversation_id"=>null,
  33. "target_id"=>AiChatContent::ROBOT_USER_ID,
  34. "content"=>$content,
  35. "operate_type"=>AiChatContent::OPERATE_TYPE_ASK
  36. );
  37. $result = $this->postData($data,$headers,$url);
  38. $addData[]=array(
  39. "user_id"=>AiChatContent::ROBOT_USER_ID,
  40. "conversation_id"=>$result["conversation_id"],
  41. "target_id"=>$userId,
  42. "content"=>$result["answer"],
  43. "path"=>$result["path"],
  44. "operate_type"=>AiChatContent::OPERATE_TYPE_ANSWER
  45. );
  46. foreach ($addData as &$val){
  47. if (empty($val["conversation_id"])){
  48. $val["conversation_id"] = $result["conversation_id"];
  49. $val["path"]=$result["path"];
  50. }
  51. AiChatContent::query()->create($val);
  52. }
  53. if (isset($result["path"])){
  54. unset($result["path"]);
  55. }
  56. return $this->response($result);
  57. }catch (\Exception $exception){
  58. return $this->error()->fail($exception->getMessage());
  59. }
  60. }
  61. /**
  62. * 发送数据
  63. * @param array $data
  64. * @param array $headers
  65. * @param $url
  66. * @return array
  67. * @throws \Exception
  68. */
  69. private function postData(array $data,array $headers,$url)
  70. {
  71. $this->AIStreamHandler = new AIStreamHandler($data);
  72. $ch = curl_init();
  73. curl_setopt($ch, CURLOPT_URL,$url);
  74. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  75. curl_setopt($ch, CURLOPT_HEADER, false);
  76. curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
  77. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
  78. curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
  79. curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
  80. curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
  81. curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
  82. curl_setopt($ch, CURLOPT_WRITEFUNCTION, [$this->AIStreamHandler,"callback"]);
  83. // 设置超时时间
  84. // curl_setopt($ch, CURLOPT_TIMEOUT, 120); // 整个请求的超时时间为 120 秒
  85. // curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30); // 连接建立的超时时间为 30 秒
  86. $response = curl_exec($ch);
  87. if (curl_errno($ch)) {
  88. $this->logError(curl_error($ch).PHP_EOL.PHP_EOL);
  89. }
  90. curl_close($ch);
  91. return $this->AIStreamHandler->getData(null);
  92. }
  93. private function logError($content)
  94. {
  95. $sqlFile = 'logs/curl/curl.error.log';
  96. (new Logger('curl'))->pushHandler(new RotatingFileHandler(storage_path($sqlFile)))->info($content);
  97. }
  98. public function getChatContentList(array $conditions, array $fields, string $sort, int $page, int $limit)
  99. {
  100. $result = AiChatContent::query()
  101. ->select(["id","user_id","conversation_id",
  102. "target_id","content","operate_type",
  103. "created_at"]
  104. )->with([
  105. "user"=>function ($with) {
  106. $with->select([
  107. "id","third_up_nickname","third_up_headimg",
  108. "wx_nickname","wx_headimgurl"
  109. ]
  110. );
  111. },
  112. "target"=>function ($with) {
  113. $with->select([
  114. "id","third_up_nickname","third_up_headimg",
  115. "wx_nickname","wx_headimgurl"
  116. ]
  117. );
  118. },
  119. ])
  120. ->where(
  121. function(Builder $query) use($conditions){
  122. if (isset($conditions['Robot'])){
  123. if (!isset($conditions["user_id"])){
  124. return $this->error()->fail("请联系管理员,必填参数user_id不能为空");
  125. };
  126. $ROBOT_USER_ID = AiChatContent::ROBOT_USER_ID;
  127. $query->whereRaw(
  128. "((user_id={$conditions["user_id"]} and target_id = {$ROBOT_USER_ID}) OR (user_id={$ROBOT_USER_ID} and target_id = {$conditions["user_id"]}))"
  129. );
  130. $startTime = Carbon::parse('-3 days')->toDateTimeString();
  131. $endTime = Carbon::now();
  132. $query->WhereBetween("created_at",array($startTime,$endTime));
  133. if (!empty($conditions["conversation_id"])){
  134. $query->where("conversation_id",$conditions["conversation_id"]);
  135. }
  136. }
  137. }
  138. )->orderByRaw($sort)->paginate($limit, $fields);
  139. return $this->response($result);
  140. }
  141. }