test_llm.py 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  1. import os
  2. from collections.abc import Generator
  3. import pytest
  4. from core.model_runtime.entities.llm_entities import LLMResult, LLMResultChunk, LLMResultChunkDelta
  5. from core.model_runtime.entities.message_entities import (
  6. AssistantPromptMessage,
  7. ImagePromptMessageContent,
  8. PromptMessageTool,
  9. SystemPromptMessage,
  10. TextPromptMessageContent,
  11. UserPromptMessage,
  12. )
  13. from core.model_runtime.entities.model_entities import AIModelEntity, ModelType
  14. from core.model_runtime.errors.validate import CredentialsValidateFailedError
  15. from core.model_runtime.model_providers.__base.large_language_model import LargeLanguageModel
  16. from core.model_runtime.model_providers.openai.llm.llm import OpenAILargeLanguageModel
  17. """FOR MOCK FIXTURES, DO NOT REMOVE"""
  18. from tests.integration_tests.model_runtime.__mock.openai import setup_openai_mock
  19. def test_predefined_models():
  20. model = OpenAILargeLanguageModel()
  21. model_schemas = model.predefined_models()
  22. assert len(model_schemas) >= 1
  23. assert isinstance(model_schemas[0], AIModelEntity)
  24. @pytest.mark.parametrize('setup_openai_mock', [['chat']], indirect=True)
  25. def test_validate_credentials_for_chat_model(setup_openai_mock):
  26. model = OpenAILargeLanguageModel()
  27. with pytest.raises(CredentialsValidateFailedError):
  28. model.validate_credentials(
  29. model='gpt-3.5-turbo',
  30. credentials={
  31. 'openai_api_key': 'invalid_key'
  32. }
  33. )
  34. model.validate_credentials(
  35. model='gpt-3.5-turbo',
  36. credentials={
  37. 'openai_api_key': os.environ.get('OPENAI_API_KEY')
  38. }
  39. )
  40. @pytest.mark.parametrize('setup_openai_mock', [['completion']], indirect=True)
  41. def test_validate_credentials_for_completion_model(setup_openai_mock):
  42. model = OpenAILargeLanguageModel()
  43. with pytest.raises(CredentialsValidateFailedError):
  44. model.validate_credentials(
  45. model='text-davinci-003',
  46. credentials={
  47. 'openai_api_key': 'invalid_key'
  48. }
  49. )
  50. model.validate_credentials(
  51. model='text-davinci-003',
  52. credentials={
  53. 'openai_api_key': os.environ.get('OPENAI_API_KEY')
  54. }
  55. )
  56. @pytest.mark.parametrize('setup_openai_mock', [['completion']], indirect=True)
  57. def test_invoke_completion_model(setup_openai_mock):
  58. model = OpenAILargeLanguageModel()
  59. result = model.invoke(
  60. model='gpt-3.5-turbo-instruct',
  61. credentials={
  62. 'openai_api_key': os.environ.get('OPENAI_API_KEY'),
  63. 'openai_api_base': 'https://api.openai.com'
  64. },
  65. prompt_messages=[
  66. UserPromptMessage(
  67. content='Hello World!'
  68. )
  69. ],
  70. model_parameters={
  71. 'temperature': 0.0,
  72. 'max_tokens': 1
  73. },
  74. stream=False,
  75. user="abc-123"
  76. )
  77. assert isinstance(result, LLMResult)
  78. assert len(result.message.content) > 0
  79. assert model._num_tokens_from_string('gpt-3.5-turbo-instruct', result.message.content) == 1
  80. @pytest.mark.parametrize('setup_openai_mock', [['completion']], indirect=True)
  81. def test_invoke_stream_completion_model(setup_openai_mock):
  82. model = OpenAILargeLanguageModel()
  83. result = model.invoke(
  84. model='gpt-3.5-turbo-instruct',
  85. credentials={
  86. 'openai_api_key': os.environ.get('OPENAI_API_KEY'),
  87. 'openai_organization': os.environ.get('OPENAI_ORGANIZATION'),
  88. },
  89. prompt_messages=[
  90. UserPromptMessage(
  91. content='Hello World!'
  92. )
  93. ],
  94. model_parameters={
  95. 'temperature': 0.0,
  96. 'max_tokens': 100
  97. },
  98. stream=True,
  99. user="abc-123"
  100. )
  101. assert isinstance(result, Generator)
  102. for chunk in result:
  103. assert isinstance(chunk, LLMResultChunk)
  104. assert isinstance(chunk.delta, LLMResultChunkDelta)
  105. assert isinstance(chunk.delta.message, AssistantPromptMessage)
  106. assert len(chunk.delta.message.content) > 0 if chunk.delta.finish_reason is None else True
  107. @pytest.mark.parametrize('setup_openai_mock', [['chat']], indirect=True)
  108. def test_invoke_chat_model(setup_openai_mock):
  109. model = OpenAILargeLanguageModel()
  110. result = model.invoke(
  111. model='gpt-3.5-turbo',
  112. credentials={
  113. 'openai_api_key': os.environ.get('OPENAI_API_KEY')
  114. },
  115. prompt_messages=[
  116. SystemPromptMessage(
  117. content='You are a helpful AI assistant.',
  118. ),
  119. UserPromptMessage(
  120. content='Hello World!'
  121. )
  122. ],
  123. model_parameters={
  124. 'temperature': 0.0,
  125. 'top_p': 1.0,
  126. 'presence_penalty': 0.0,
  127. 'frequency_penalty': 0.0,
  128. 'max_tokens': 10
  129. },
  130. stop=['How'],
  131. stream=False,
  132. user="abc-123"
  133. )
  134. assert isinstance(result, LLMResult)
  135. assert len(result.message.content) > 0
  136. for chunk in model._llm_result_to_stream(result):
  137. assert isinstance(chunk, LLMResultChunk)
  138. assert isinstance(chunk.delta, LLMResultChunkDelta)
  139. assert isinstance(chunk.delta.message, AssistantPromptMessage)
  140. assert len(chunk.delta.message.content) > 0 if chunk.delta.finish_reason is None else True
  141. @pytest.mark.parametrize('setup_openai_mock', [['chat']], indirect=True)
  142. def test_invoke_chat_model_with_vision(setup_openai_mock):
  143. model = OpenAILargeLanguageModel()
  144. result = model.invoke(
  145. model='gpt-4-vision-preview',
  146. credentials={
  147. 'openai_api_key': os.environ.get('OPENAI_API_KEY')
  148. },
  149. prompt_messages=[
  150. SystemPromptMessage(
  151. content='You are a helpful AI assistant.',
  152. ),
  153. UserPromptMessage(
  154. content=[
  155. TextPromptMessageContent(
  156. data='Hello World!',
  157. ),
  158. ImagePromptMessageContent(
  159. data='data:image/png;base64,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'
  160. )
  161. ]
  162. )
  163. ],
  164. model_parameters={
  165. 'temperature': 0.0,
  166. 'max_tokens': 100
  167. },
  168. stream=False,
  169. user="abc-123"
  170. )
  171. assert isinstance(result, LLMResult)
  172. assert len(result.message.content) > 0
  173. @pytest.mark.parametrize('setup_openai_mock', [['chat']], indirect=True)
  174. def test_invoke_chat_model_with_tools(setup_openai_mock):
  175. model = OpenAILargeLanguageModel()
  176. result = model.invoke(
  177. model='gpt-3.5-turbo',
  178. credentials={
  179. 'openai_api_key': os.environ.get('OPENAI_API_KEY')
  180. },
  181. prompt_messages=[
  182. SystemPromptMessage(
  183. content='You are a helpful AI assistant.',
  184. ),
  185. UserPromptMessage(
  186. content="what's the weather today in London?",
  187. )
  188. ],
  189. model_parameters={
  190. 'temperature': 0.0,
  191. 'max_tokens': 100
  192. },
  193. tools=[
  194. PromptMessageTool(
  195. name='get_weather',
  196. description='Determine weather in my location',
  197. parameters={
  198. "type": "object",
  199. "properties": {
  200. "location": {
  201. "type": "string",
  202. "description": "The city and state e.g. San Francisco, CA"
  203. },
  204. "unit": {
  205. "type": "string",
  206. "enum": [
  207. "c",
  208. "f"
  209. ]
  210. }
  211. },
  212. "required": [
  213. "location"
  214. ]
  215. }
  216. ),
  217. PromptMessageTool(
  218. name='get_stock_price',
  219. description='Get the current stock price',
  220. parameters={
  221. "type": "object",
  222. "properties": {
  223. "symbol": {
  224. "type": "string",
  225. "description": "The stock symbol"
  226. }
  227. },
  228. "required": [
  229. "symbol"
  230. ]
  231. }
  232. )
  233. ],
  234. stream=False,
  235. user="abc-123"
  236. )
  237. assert isinstance(result, LLMResult)
  238. assert isinstance(result.message, AssistantPromptMessage)
  239. assert len(result.message.tool_calls) > 0
  240. @pytest.mark.parametrize('setup_openai_mock', [['chat']], indirect=True)
  241. def test_invoke_stream_chat_model(setup_openai_mock):
  242. model = OpenAILargeLanguageModel()
  243. result = model.invoke(
  244. model='gpt-3.5-turbo',
  245. credentials={
  246. 'openai_api_key': os.environ.get('OPENAI_API_KEY')
  247. },
  248. prompt_messages=[
  249. SystemPromptMessage(
  250. content='You are a helpful AI assistant.',
  251. ),
  252. UserPromptMessage(
  253. content='Hello World!'
  254. )
  255. ],
  256. model_parameters={
  257. 'temperature': 0.0,
  258. 'max_tokens': 100
  259. },
  260. stream=True,
  261. user="abc-123"
  262. )
  263. assert isinstance(result, Generator)
  264. for chunk in result:
  265. assert isinstance(chunk, LLMResultChunk)
  266. assert isinstance(chunk.delta, LLMResultChunkDelta)
  267. assert isinstance(chunk.delta.message, AssistantPromptMessage)
  268. assert len(chunk.delta.message.content) > 0 if chunk.delta.finish_reason is None else True
  269. if chunk.delta.finish_reason is not None:
  270. assert chunk.delta.usage is not None
  271. assert chunk.delta.usage.completion_tokens > 0
  272. def test_get_num_tokens():
  273. model = OpenAILargeLanguageModel()
  274. num_tokens = model.get_num_tokens(
  275. model='gpt-3.5-turbo-instruct',
  276. credentials={
  277. 'openai_api_key': os.environ.get('OPENAI_API_KEY')
  278. },
  279. prompt_messages=[
  280. UserPromptMessage(
  281. content='Hello World!'
  282. )
  283. ]
  284. )
  285. assert num_tokens == 3
  286. num_tokens = model.get_num_tokens(
  287. model='gpt-3.5-turbo',
  288. credentials={
  289. 'openai_api_key': os.environ.get('OPENAI_API_KEY')
  290. },
  291. prompt_messages=[
  292. SystemPromptMessage(
  293. content='You are a helpful AI assistant.',
  294. ),
  295. UserPromptMessage(
  296. content='Hello World!'
  297. )
  298. ],
  299. tools=[
  300. PromptMessageTool(
  301. name='get_weather',
  302. description='Determine weather in my location',
  303. parameters={
  304. "type": "object",
  305. "properties": {
  306. "location": {
  307. "type": "string",
  308. "description": "The city and state e.g. San Francisco, CA"
  309. },
  310. "unit": {
  311. "type": "string",
  312. "enum": [
  313. "c",
  314. "f"
  315. ]
  316. }
  317. },
  318. "required": [
  319. "location"
  320. ]
  321. }
  322. ),
  323. ]
  324. )
  325. assert num_tokens == 72
  326. @pytest.mark.parametrize('setup_openai_mock', [['chat', 'remote']], indirect=True)
  327. def test_fine_tuned_models(setup_openai_mock):
  328. model = OpenAILargeLanguageModel()
  329. remote_models = model.remote_models(credentials={
  330. 'openai_api_key': os.environ.get('OPENAI_API_KEY')
  331. })
  332. if not remote_models:
  333. assert isinstance(remote_models, list)
  334. else:
  335. assert isinstance(remote_models[0], AIModelEntity)
  336. for llm_model in remote_models:
  337. if llm_model.model_type == ModelType.LLM:
  338. break
  339. assert isinstance(llm_model, AIModelEntity)
  340. # test invoke
  341. result = model.invoke(
  342. model=llm_model.model,
  343. credentials={
  344. 'openai_api_key': os.environ.get('OPENAI_API_KEY')
  345. },
  346. prompt_messages=[
  347. SystemPromptMessage(
  348. content='You are a helpful AI assistant.',
  349. ),
  350. UserPromptMessage(
  351. content='Hello World!'
  352. )
  353. ],
  354. model_parameters={
  355. 'temperature': 0.0,
  356. 'max_tokens': 100
  357. },
  358. stream=False,
  359. user="abc-123"
  360. )
  361. assert isinstance(result, LLMResult)
  362. def test__get_num_tokens_by_gpt2():
  363. model = OpenAILargeLanguageModel()
  364. num_tokens = model._get_num_tokens_by_gpt2('Hello World!')
  365. assert num_tokens == 3