Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

mock_openai_server.py 6.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. #!/usr/bin/env python3
  2. import json
  3. import time
  4. import uuid
  5. from typing import Any, Iterator
  6. from flask import Flask, request, jsonify, Response
  7. app = Flask(__name__)
  8. # Mock models list
  9. MODELS = [
  10. {
  11. "id": "gpt-3.5-turbo",
  12. "object": "model",
  13. "created": 1677649963,
  14. "owned_by": "openai",
  15. },
  16. {"id": "gpt-4", "object": "model", "created": 1687882411, "owned_by": "openai"},
  17. {
  18. "id": "text-embedding-ada-002",
  19. "object": "model",
  20. "created": 1671217299,
  21. "owned_by": "openai-internal",
  22. },
  23. ]
  24. @app.route("/v1/models", methods=["GET"])
  25. def list_models() -> Any:
  26. """List available models."""
  27. return jsonify({"object": "list", "data": MODELS})
  28. @app.route("/v1/chat/completions", methods=["POST"])
  29. def chat_completions() -> Any:
  30. """Handle chat completions."""
  31. data = request.json or {}
  32. model = data.get("model", "gpt-3.5-turbo")
  33. messages = data.get("messages", [])
  34. stream = data.get("stream", False)
  35. # Generate mock response
  36. response_content = "This is a mock response from the OpenAI server."
  37. if messages:
  38. last_message = messages[-1].get("content", "")
  39. response_content = f"Mock response to: {last_message[:100]}..."
  40. if stream:
  41. # Streaming response
  42. def generate() -> Iterator[str]:
  43. # Send initial chunk
  44. chunk = {
  45. "id": f"chatcmpl-{uuid.uuid4().hex[:8]}",
  46. "object": "chat.completion.chunk",
  47. "created": int(time.time()),
  48. "model": model,
  49. "choices": [
  50. {
  51. "index": 0,
  52. "delta": {"role": "assistant", "content": ""},
  53. "finish_reason": None,
  54. }
  55. ],
  56. }
  57. yield f"data: {json.dumps(chunk)}\n\n"
  58. # Send content in chunks
  59. words = response_content.split()
  60. for word in words:
  61. chunk = {
  62. "id": f"chatcmpl-{uuid.uuid4().hex[:8]}",
  63. "object": "chat.completion.chunk",
  64. "created": int(time.time()),
  65. "model": model,
  66. "choices": [
  67. {
  68. "index": 0,
  69. "delta": {"content": word + " "},
  70. "finish_reason": None,
  71. }
  72. ],
  73. }
  74. yield f"data: {json.dumps(chunk)}\n\n"
  75. time.sleep(0.05) # Simulate streaming delay
  76. # Send final chunk
  77. chunk = {
  78. "id": f"chatcmpl-{uuid.uuid4().hex[:8]}",
  79. "object": "chat.completion.chunk",
  80. "created": int(time.time()),
  81. "model": model,
  82. "choices": [{"index": 0, "delta": {}, "finish_reason": "stop"}],
  83. }
  84. yield f"data: {json.dumps(chunk)}\n\n"
  85. yield "data: [DONE]\n\n"
  86. return Response(generate(), mimetype="text/event-stream")
  87. else:
  88. # Non-streaming response
  89. return jsonify(
  90. {
  91. "id": f"chatcmpl-{uuid.uuid4().hex[:8]}",
  92. "object": "chat.completion",
  93. "created": int(time.time()),
  94. "model": model,
  95. "choices": [
  96. {
  97. "index": 0,
  98. "message": {"role": "assistant", "content": response_content},
  99. "finish_reason": "stop",
  100. }
  101. ],
  102. "usage": {
  103. "prompt_tokens": len(str(messages)),
  104. "completion_tokens": len(response_content.split()),
  105. "total_tokens": len(str(messages)) + len(response_content.split()),
  106. },
  107. }
  108. )
  109. @app.route("/v1/completions", methods=["POST"])
  110. def completions() -> Any:
  111. """Handle text completions."""
  112. data = request.json or {}
  113. model = data.get("model", "gpt-3.5-turbo-instruct")
  114. prompt = data.get("prompt", "")
  115. response_text = f"Mock completion for prompt: {prompt[:100]}..."
  116. return jsonify(
  117. {
  118. "id": f"cmpl-{uuid.uuid4().hex[:8]}",
  119. "object": "text_completion",
  120. "created": int(time.time()),
  121. "model": model,
  122. "choices": [
  123. {
  124. "text": response_text,
  125. "index": 0,
  126. "logprobs": None,
  127. "finish_reason": "stop",
  128. }
  129. ],
  130. "usage": {
  131. "prompt_tokens": len(prompt.split()),
  132. "completion_tokens": len(response_text.split()),
  133. "total_tokens": len(prompt.split()) + len(response_text.split()),
  134. },
  135. }
  136. )
  137. @app.route("/v1/embeddings", methods=["POST"])
  138. def embeddings() -> Any:
  139. """Handle embeddings requests."""
  140. data = request.json or {}
  141. model = data.get("model", "text-embedding-ada-002")
  142. input_text = data.get("input", "")
  143. # Generate mock embedding (1536 dimensions for ada-002)
  144. mock_embedding = [0.1] * 1536
  145. return jsonify(
  146. {
  147. "object": "list",
  148. "data": [{"object": "embedding", "embedding": mock_embedding, "index": 0}],
  149. "model": model,
  150. "usage": {
  151. "prompt_tokens": len(input_text.split()),
  152. "total_tokens": len(input_text.split()),
  153. },
  154. }
  155. )
  156. @app.route("/v1/models/<model_id>", methods=["GET"])
  157. def get_model(model_id: str) -> tuple[Any, int] | Any:
  158. """Get specific model details."""
  159. for model in MODELS:
  160. if model["id"] == model_id:
  161. return jsonify(model)
  162. return jsonify({"error": "Model not found"}), 404
  163. @app.route("/health", methods=["GET"])
  164. def health() -> Any:
  165. """Health check endpoint."""
  166. return jsonify({"status": "healthy"})
  167. if __name__ == "__main__":
  168. print("🚀 Starting Mock OpenAI Server on http://localhost:5004")
  169. print("Available endpoints:")
  170. print(" - GET /v1/models")
  171. print(" - POST /v1/chat/completions")
  172. print(" - POST /v1/completions")
  173. print(" - POST /v1/embeddings")
  174. print(" - GET /v1/models/<model_id>")
  175. print(" - GET /health")
  176. app.run(host="0.0.0.0", port=5004, debug=True)