MockOpenAIController.php 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. <?php
  2. namespace App\Http\Controllers;
  3. use Illuminate\Http\Request;
  4. use Illuminate\Http\JsonResponse;
  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. }