MockOpenAIController.php 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. <?php
  2. namespace App\Http\Controllers;
  3. use Illuminate\Http\JsonResponse;
  4. use Illuminate\Http\Request;
  5. use Illuminate\Support\Str;
  6. class MockOpenAIController extends Controller
  7. {
  8. /**
  9. * 模拟 Chat Completions API
  10. */
  11. public function chatCompletions(Request $request): JsonResponse
  12. {
  13. // 随机延迟
  14. $this->randomDelay($request->query('delay', 'h'));
  15. // 随机返回错误
  16. if ($errorResponse = $this->randomError($request->query('error', 'h'))) {
  17. return $errorResponse;
  18. }
  19. $model = $request->input('model', 'gpt-3.5-turbo');
  20. $messages = $request->input('messages', []);
  21. return response()->json([
  22. 'id' => 'chatcmpl-'.Str::random(29),
  23. 'object' => 'chat.completion',
  24. 'created' => time(),
  25. 'model' => $model,
  26. 'choices' => [
  27. [
  28. 'index' => 0,
  29. 'message' => [
  30. 'role' => 'assistant',
  31. 'content' => $this->generateMockResponse($messages),
  32. ],
  33. 'finish_reason' => 'stop',
  34. ],
  35. ],
  36. 'usage' => [
  37. 'prompt_tokens' => rand(10, 100),
  38. 'completion_tokens' => rand(20, 200),
  39. 'total_tokens' => rand(30, 300),
  40. ],
  41. ]);
  42. }
  43. /**
  44. * 模拟 Completions API
  45. */
  46. public function completions(Request $request): JsonResponse
  47. {
  48. // 随机延迟
  49. $this->randomDelay($request->query('delay', 'h'));
  50. // 随机返回错误
  51. if ($errorResponse = $this->randomError($request->query('error', 'h'))) {
  52. return $errorResponse;
  53. }
  54. $model = $request->input('model', 'text-davinci-003');
  55. $prompt = $request->input('prompt', '');
  56. return response()->json([
  57. 'id' => 'cmpl-'.Str::random(29),
  58. 'object' => 'text_completion',
  59. 'created' => time(),
  60. 'model' => $model,
  61. 'choices' => [
  62. [
  63. 'text' => $this->generateMockTextResponse($prompt),
  64. 'index' => 0,
  65. 'logprobs' => null,
  66. 'finish_reason' => 'stop',
  67. ],
  68. ],
  69. 'usage' => [
  70. 'prompt_tokens' => rand(10, 100),
  71. 'completion_tokens' => rand(20, 200),
  72. 'total_tokens' => rand(30, 300),
  73. ],
  74. ]);
  75. }
  76. /**
  77. * 模拟 Models API
  78. */
  79. public function models(Request $request): JsonResponse
  80. {
  81. return response()->json([
  82. 'object' => 'list',
  83. 'data' => [
  84. [
  85. 'id' => 'gpt-4',
  86. 'object' => 'model',
  87. 'created' => 1687882411,
  88. 'owned_by' => 'openai',
  89. ],
  90. [
  91. 'id' => 'gpt-3.5-turbo',
  92. 'object' => 'model',
  93. 'created' => 1677610602,
  94. 'owned_by' => 'openai',
  95. ],
  96. [
  97. 'id' => 'text-davinci-003',
  98. 'object' => 'model',
  99. 'created' => 1669599635,
  100. 'owned_by' => 'openai-internal',
  101. ],
  102. ],
  103. ]);
  104. }
  105. /**
  106. * 随机延迟
  107. */
  108. private function randomDelay(string $level): void
  109. {
  110. switch ($level) {
  111. case 'l':
  112. sleep(1);
  113. break;
  114. case 'm':
  115. sleep(rand(1, 3));
  116. break;
  117. case 'h':
  118. // 90% 概率 1-3秒延迟
  119. // 10% 概率 60-100秒延迟
  120. if (rand(1, 100) <= 10) {
  121. sleep(rand(60, 100));
  122. } else {
  123. sleep(rand(1, 3));
  124. }
  125. break;
  126. default:
  127. break;
  128. }
  129. }
  130. /**
  131. * 随机返回错误响应
  132. */
  133. private function randomError(string $level): ?JsonResponse
  134. {
  135. switch ($level) {
  136. case 'l':
  137. if (rand(1, 100) <= 10) {
  138. return $this->rateLimitError();
  139. }
  140. break;
  141. case 'm':
  142. if (rand(1, 100) <= 20) {
  143. return $this->rateLimitError();
  144. }
  145. break;
  146. case 'h':
  147. // 20% 概率返回三种错误
  148. if (rand(1, 100) <= 20) {
  149. $errorType = rand(1, 3);
  150. switch ($errorType) {
  151. case 1:
  152. return $this->badRequestError();
  153. case 2:
  154. return $this->internalServerError();
  155. case 3:
  156. return $this->rateLimitError();
  157. }
  158. }
  159. break;
  160. default:
  161. return null;
  162. break;
  163. }
  164. return null;
  165. }
  166. /**
  167. * 400 错误响应
  168. */
  169. private function badRequestError(): JsonResponse
  170. {
  171. return response()->json([
  172. 'error' => [
  173. 'message' => 'Invalid request: missing required parameter',
  174. 'type' => 'invalid_request_error',
  175. 'param' => null,
  176. 'code' => null,
  177. ],
  178. ], 400);
  179. }
  180. /**
  181. * 500 错误响应
  182. */
  183. private function internalServerError(): JsonResponse
  184. {
  185. return response()->json([
  186. 'error' => [
  187. 'message' => 'The server had an error while processing your request. Sorry about that!',
  188. 'type' => 'server_error',
  189. 'param' => null,
  190. 'code' => null,
  191. ],
  192. ], 500);
  193. }
  194. /**
  195. * 429 限流错误响应
  196. */
  197. private function rateLimitError(): JsonResponse
  198. {
  199. return response()->json([
  200. 'error' => [
  201. 'message' => 'Rate limit reached for requests',
  202. 'type' => 'requests',
  203. 'param' => null,
  204. 'code' => 'rate_limit_exceeded',
  205. ],
  206. ], 429);
  207. }
  208. /**
  209. * 生成模拟聊天响应
  210. */
  211. private function generateMockResponse(array $messages): string
  212. {
  213. $responses = [
  214. '这是一个模拟的AI响应。我正在模拟OpenAI的API服务器。',
  215. '感谢您的问题!这是一个测试响应,用于模拟真实的AI助手。',
  216. '我是一个模拟的AI助手。您的请求已被处理,这是模拟生成的回复。',
  217. '模拟Hello! This is a mock response from the simulated OpenAI API server.',
  218. '模拟Thank you for your message. This is a simulated response for testing purposes.',
  219. '模拟I understand your question. This is a mock reply generated by the test API server.',
  220. ];
  221. return $responses[array_rand($responses)].' (响应时间: '.date('Y-m-d H:i:s').')';
  222. }
  223. /**
  224. * 生成模拟文本补全响应
  225. */
  226. private function generateMockTextResponse(string $prompt): string
  227. {
  228. $responses = [
  229. ' 这是对您提示的模拟补全回复。',
  230. ' Mock completion response for your prompt.',
  231. ' 模拟的文本补全结果,用于测试目的。',
  232. ' This is a simulated text completion.',
  233. ' 基于您的输入生成的模拟响应。',
  234. ];
  235. return $responses[array_rand($responses)];
  236. }
  237. }