openai_completion.py 4.7 KB

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