openai_completion.py 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. import re
  2. from collections.abc import Generator
  3. from time import sleep, time
  4. # import monkeypatch
  5. from typing import Any, Literal, Optional, Union
  6. from openai import AzureOpenAI, BadRequestError, OpenAI
  7. from openai._types import NOT_GIVEN, NotGiven
  8. from openai.resources.completions import Completions
  9. from openai.types import Completion as CompletionMessage
  10. from openai.types.completion import CompletionChoice
  11. from openai.types.completion_usage import CompletionUsage
  12. from core.model_runtime.errors.invoke import InvokeAuthorizationError
  13. class MockCompletionsClass:
  14. @staticmethod
  15. def mocked_openai_completion_create_sync(
  16. model: str
  17. ) -> CompletionMessage:
  18. sleep(1)
  19. return CompletionMessage(
  20. id="cmpl-3QJQa5jXJ5Z5X",
  21. object="text_completion",
  22. created=int(time()),
  23. model=model,
  24. system_fingerprint="",
  25. choices=[
  26. CompletionChoice(
  27. text="mock",
  28. index=0,
  29. logprobs=None,
  30. finish_reason="stop",
  31. )
  32. ],
  33. usage=CompletionUsage(
  34. prompt_tokens=2,
  35. completion_tokens=1,
  36. total_tokens=3,
  37. )
  38. )
  39. @staticmethod
  40. def mocked_openai_completion_create_stream(
  41. model: str
  42. ) -> Generator[CompletionMessage, None, None]:
  43. full_text = "Hello, world!\n\n```python\nprint('Hello, world!')\n```"
  44. for i in range(0, len(full_text) + 1):
  45. sleep(0.1)
  46. if i == len(full_text):
  47. yield CompletionMessage(
  48. id="cmpl-3QJQa5jXJ5Z5X",
  49. object="text_completion",
  50. created=int(time()),
  51. model=model,
  52. system_fingerprint="",
  53. choices=[
  54. CompletionChoice(
  55. text="",
  56. index=0,
  57. logprobs=None,
  58. finish_reason="stop",
  59. )
  60. ],
  61. usage=CompletionUsage(
  62. prompt_tokens=2,
  63. completion_tokens=17,
  64. total_tokens=19,
  65. ),
  66. )
  67. else:
  68. yield CompletionMessage(
  69. id="cmpl-3QJQa5jXJ5Z5X",
  70. object="text_completion",
  71. created=int(time()),
  72. model=model,
  73. system_fingerprint="",
  74. choices=[
  75. CompletionChoice(
  76. text=full_text[i],
  77. index=0,
  78. logprobs=None,
  79. finish_reason="content_filter"
  80. )
  81. ],
  82. )
  83. def completion_create(self: Completions, *, model: Union[
  84. str, Literal["babbage-002", "davinci-002", "gpt-3.5-turbo-instruct",
  85. "text-davinci-003", "text-davinci-002", "text-davinci-001",
  86. "code-davinci-002", "text-curie-001", "text-babbage-001",
  87. "text-ada-001"],
  88. ],
  89. prompt: Union[str, list[str], list[int], list[list[int]], None],
  90. stream: Optional[Literal[False]] | NotGiven = NOT_GIVEN,
  91. **kwargs: Any
  92. ):
  93. openai_models = [
  94. "babbage-002", "davinci-002", "gpt-3.5-turbo-instruct", "text-davinci-003", "text-davinci-002", "text-davinci-001",
  95. "code-davinci-002", "text-curie-001", "text-babbage-001", "text-ada-001",
  96. ]
  97. azure_openai_models = [
  98. "gpt-35-turbo-instruct"
  99. ]
  100. if not re.match(r'^(https?):\/\/[^\s\/$.?#].[^\s]*$', self._client.base_url.__str__()):
  101. raise InvokeAuthorizationError('Invalid base url')
  102. if model in openai_models + azure_openai_models:
  103. if not re.match(r'sk-[a-zA-Z0-9]{24,}$', self._client.api_key) and type(self._client) == OpenAI:
  104. # sometime, provider use OpenAI compatible API will not have api key or have different api key format
  105. # so we only check if model is in openai_models
  106. raise InvokeAuthorizationError('Invalid api key')
  107. if len(self._client.api_key) < 18 and type(self._client) == AzureOpenAI:
  108. raise InvokeAuthorizationError('Invalid api key')
  109. if not prompt:
  110. raise BadRequestError('Invalid prompt')
  111. if stream:
  112. return MockCompletionsClass.mocked_openai_completion_create_stream(model=model)
  113. return MockCompletionsClass.mocked_openai_completion_create_sync(model=model)