Compare commits
	
		
			3 Commits
		
	
	
		
			js-in-ts
			...
			custom-ais
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 74494989d2 | ||
|   | e122ad4178 | ||
|   | a8b85cdb0d | 
							
								
								
									
										3
									
								
								packages/backend/src/apps/azure-openai/actions/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								packages/backend/src/apps/azure-openai/actions/index.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | |||||||
|  | import sendPrompt from './send-prompt'; | ||||||
|  |  | ||||||
|  | export default [sendPrompt]; | ||||||
| @@ -0,0 +1,87 @@ | |||||||
|  | import defineAction from '../../../../helpers/define-action'; | ||||||
|  |  | ||||||
|  | const castFloatOrUndefined = (value: string | null) => { | ||||||
|  |   return value === '' ? undefined : parseFloat(value); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | export default defineAction({ | ||||||
|  |   name: 'Send prompt', | ||||||
|  |   key: 'sendPrompt', | ||||||
|  |   description: 'Creates a completion for the provided prompt and parameters.', | ||||||
|  |   arguments: [ | ||||||
|  |     { | ||||||
|  |       label: 'Prompt', | ||||||
|  |       key: 'prompt', | ||||||
|  |       type: 'string' as const, | ||||||
|  |       required: true, | ||||||
|  |       variables: true, | ||||||
|  |       description: 'The text to analyze.' | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       label: 'Temperature', | ||||||
|  |       key: 'temperature', | ||||||
|  |       type: 'string' as const, | ||||||
|  |       required: false, | ||||||
|  |       variables: true, | ||||||
|  |       description: 'What sampling temperature to use, between 0 and 2. Higher values means the model will take more risks. Try 0.9 for more creative applications, and 0 (argmax sampling) for ones with a well-defined answer. We generally recommend altering this or Top P but not both.' | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       label: 'Maximum tokens', | ||||||
|  |       key: 'maxTokens', | ||||||
|  |       type: 'string' as const, | ||||||
|  |       required: false, | ||||||
|  |       variables: true, | ||||||
|  |       description: 'The maximum number of tokens to generate in the completion.' | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       label: 'Stop Sequence', | ||||||
|  |       key: 'stopSequence', | ||||||
|  |       type: 'string' as const, | ||||||
|  |       required: false, | ||||||
|  |       variables: true, | ||||||
|  |       description: 'Single stop sequence where the API will stop generating further tokens. The returned text will not contain the stop sequence.' | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       label: 'Top P', | ||||||
|  |       key: 'topP', | ||||||
|  |       type: 'string' as const, | ||||||
|  |       required: false, | ||||||
|  |       variables: true, | ||||||
|  |       description: 'An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. We generally recommend altering this or temperature but not both.' | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       label: 'Frequency Penalty', | ||||||
|  |       key: 'frequencyPenalty', | ||||||
|  |       type: 'string' as const, | ||||||
|  |       required: false, | ||||||
|  |       variables: true, | ||||||
|  |       description: `Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing frequency in the text so far, decreasing the model's likelihood to repeat the same line verbatim.` | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       label: 'Presence Penalty', | ||||||
|  |       key: 'presencePenalty', | ||||||
|  |       type: 'string' as const, | ||||||
|  |       required: false, | ||||||
|  |       variables: true, | ||||||
|  |       description: `Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear in the text so far, increasing the model's likelihood to talk about new topics.` | ||||||
|  |     }, | ||||||
|  |   ], | ||||||
|  |  | ||||||
|  |   async run($) { | ||||||
|  |     const payload = { | ||||||
|  |       model: $.step.parameters.model as string, | ||||||
|  |       prompt: $.step.parameters.prompt as string, | ||||||
|  |       temperature: castFloatOrUndefined($.step.parameters.temperature as string), | ||||||
|  |       max_tokens: castFloatOrUndefined($.step.parameters.maxTokens as string), | ||||||
|  |       stop: ($.step.parameters.stopSequence as string || null), | ||||||
|  |       top_p: castFloatOrUndefined($.step.parameters.topP as string), | ||||||
|  |       frequency_penalty: castFloatOrUndefined($.step.parameters.frequencyPenalty as string), | ||||||
|  |       presence_penalty: castFloatOrUndefined($.step.parameters.presencePenalty as string), | ||||||
|  |     }; | ||||||
|  |     const { data } = await $.http.post(`/deployments/${$.auth.data.deploymentId}/completions`, payload); | ||||||
|  |  | ||||||
|  |     $.setActionItem({ | ||||||
|  |       raw: data, | ||||||
|  |     }); | ||||||
|  |   }, | ||||||
|  | }); | ||||||
| @@ -0,0 +1,6 @@ | |||||||
|  | <svg width="256px" height="260px" viewBox="0 0 256 260" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid"> | ||||||
|  |     <title>OpenAI</title> | ||||||
|  |     <g> | ||||||
|  |         <path d="M239.183914,106.202783 C245.054304,88.5242096 243.02228,69.1733805 233.607599,53.0998864 C219.451678,28.4588021 190.999703,15.7836129 163.213007,21.739505 C147.554077,4.32145883 123.794909,-3.42398554 100.87901,1.41873898 C77.9631105,6.26146349 59.3690093,22.9572536 52.0959621,45.2214219 C33.8436494,48.9644867 18.0901721,60.392749 8.86672513,76.5818033 C-5.443491,101.182962 -2.19544431,132.215255 16.8986662,153.320094 C11.0060865,170.990656 13.0197283,190.343991 22.4238231,206.422991 C36.5975553,231.072344 65.0680342,243.746566 92.8695738,237.783372 C105.235639,251.708249 123.001113,259.630942 141.623968,259.52692 C170.105359,259.552169 195.337611,241.165718 204.037777,214.045661 C222.28734,210.296356 238.038489,198.869783 247.267014,182.68528 C261.404453,158.127515 258.142494,127.262775 239.183914,106.202783 L239.183914,106.202783 Z M141.623968,242.541207 C130.255682,242.559177 119.243876,238.574642 110.519381,231.286197 L112.054146,230.416496 L163.724595,200.590881 C166.340648,199.056444 167.954321,196.256818 167.970781,193.224005 L167.970781,120.373788 L189.815614,133.010026 C190.034132,133.121423 190.186235,133.330564 190.224885,133.572774 L190.224885,193.940229 C190.168603,220.758427 168.442166,242.484864 141.623968,242.541207 Z M37.1575749,197.93062 C31.456498,188.086359 29.4094818,176.546984 31.3766237,165.342426 L32.9113895,166.263285 L84.6329973,196.088901 C87.2389349,197.618207 90.4682717,197.618207 93.0742093,196.088901 L156.255402,159.663793 L156.255402,184.885111 C156.243557,185.149771 156.111725,185.394602 155.89729,185.550176 L103.561776,215.733903 C80.3054953,229.131632 50.5924954,221.165435 37.1575749,197.93062 Z M23.5493181,85.3811273 C29.2899861,75.4733097 38.3511911,67.9162648 49.1287482,64.0478825 L49.1287482,125.438515 C49.0891492,128.459425 50.6965386,131.262556 53.3237748,132.754232 L116.198014,169.025864 L94.3531808,181.662102 C94.1132325,181.789434 93.8257461,181.789434 93.5857979,181.662102 L41.3526015,151.529534 C18.1419426,138.076098 10.1817681,108.385562 23.5493181,85.125333 L23.5493181,85.3811273 Z M203.0146,127.075598 L139.935725,90.4458545 L161.7294,77.8607748 C161.969348,77.7334434 162.256834,77.7334434 162.496783,77.8607748 L214.729979,108.044502 C231.032329,117.451747 240.437294,135.426109 238.871504,154.182739 C237.305714,172.939368 225.050719,189.105572 207.414262,195.67963 L207.414262,134.288998 C207.322521,131.276867 205.650697,128.535853 203.0146,127.075598 Z M224.757116,94.3850867 L223.22235,93.4642272 L171.60306,63.3828173 C168.981293,61.8443751 165.732456,61.8443751 163.110689,63.3828173 L99.9806554,99.8079259 L99.9806554,74.5866077 C99.9533004,74.3254088 100.071095,74.0701869 100.287609,73.9215426 L152.520805,43.7889738 C168.863098,34.3743518 189.174256,35.2529043 204.642579,46.0434841 C220.110903,56.8340638 227.949269,75.5923959 224.757116,94.1804513 L224.757116,94.3850867 Z M88.0606409,139.097931 L66.2158076,126.512851 C65.9950399,126.379091 65.8450965,126.154176 65.8065367,125.898945 L65.8065367,65.684966 C65.8314495,46.8285367 76.7500605,29.6846032 93.8270852,21.6883055 C110.90411,13.6920079 131.063833,16.2835462 145.5632,28.338998 L144.028434,29.2086986 L92.3579852,59.0343142 C89.7419327,60.5687513 88.1282597,63.3683767 88.1117998,66.4011901 L88.0606409,139.097931 Z M99.9294965,113.5185 L128.06687,97.3011417 L156.255402,113.5185 L156.255402,145.953218 L128.169187,162.170577 L99.9806554,145.953218 L99.9294965,113.5185 Z" fill="#000000"></path> | ||||||
|  |     </g> | ||||||
|  | </svg> | ||||||
| After Width: | Height: | Size: 3.6 KiB | 
							
								
								
									
										58
									
								
								packages/backend/src/apps/azure-openai/auth/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								packages/backend/src/apps/azure-openai/auth/index.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,58 @@ | |||||||
|  | import verifyCredentials from './verify-credentials'; | ||||||
|  | import isStillVerified from './is-still-verified'; | ||||||
|  |  | ||||||
|  | export default { | ||||||
|  |   fields: [ | ||||||
|  |     { | ||||||
|  |       key: 'screenName', | ||||||
|  |       label: 'Screen Name', | ||||||
|  |       type: 'string' as const, | ||||||
|  |       required: true, | ||||||
|  |       readOnly: false, | ||||||
|  |       value: null, | ||||||
|  |       placeholder: null, | ||||||
|  |       description: | ||||||
|  |         'Screen name of your connection to be used on Automatisch UI.', | ||||||
|  |       clickToCopy: false, | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       key: 'yourResourceName', | ||||||
|  |       label: 'Your Resource Name', | ||||||
|  |       type: 'string' as const, | ||||||
|  |       required: true, | ||||||
|  |       readOnly: false, | ||||||
|  |       value: null, | ||||||
|  |       placeholder: null, | ||||||
|  |       description: 'The name of your Azure OpenAI Resource.', | ||||||
|  |       docUrl: 'https://automatisch.io/docs/azure-openai#your-resource-name', | ||||||
|  |       clickToCopy: false, | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       key: 'deploymentId', | ||||||
|  |       label: 'Deployment ID', | ||||||
|  |       type: 'string' as const, | ||||||
|  |       required: true, | ||||||
|  |       readOnly: false, | ||||||
|  |       value: null, | ||||||
|  |       placeholder: null, | ||||||
|  |       description: 'The deployment name you chose when you deployed the model.', | ||||||
|  |       docUrl: 'https://automatisch.io/docs/azure-openai#deployment-id', | ||||||
|  |       clickToCopy: false, | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       key: 'apiKey', | ||||||
|  |       label: 'API Key', | ||||||
|  |       type: 'string' as const, | ||||||
|  |       required: true, | ||||||
|  |       readOnly: false, | ||||||
|  |       value: null, | ||||||
|  |       placeholder: null, | ||||||
|  |       description: 'Azure OpenAI API key of your account.', | ||||||
|  |       docUrl: 'https://automatisch.io/docs/azure-openai#api-key', | ||||||
|  |       clickToCopy: false, | ||||||
|  |     }, | ||||||
|  |   ], | ||||||
|  |  | ||||||
|  |   verifyCredentials, | ||||||
|  |   isStillVerified, | ||||||
|  | }; | ||||||
| @@ -0,0 +1,8 @@ | |||||||
|  | import { IGlobalVariable } from '@automatisch/types'; | ||||||
|  |  | ||||||
|  | const isStillVerified = async ($: IGlobalVariable) => { | ||||||
|  |   await $.http.get('/fine_tuning/jobs'); | ||||||
|  |   return true; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | export default isStillVerified; | ||||||
| @@ -0,0 +1,7 @@ | |||||||
|  | import { IGlobalVariable } from '@automatisch/types'; | ||||||
|  |  | ||||||
|  | const verifyCredentials = async ($: IGlobalVariable) => { | ||||||
|  |   await $.http.get('/fine_tuning/jobs'); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | export default verifyCredentials; | ||||||
| @@ -0,0 +1,15 @@ | |||||||
|  | import { TBeforeRequest } from '@automatisch/types'; | ||||||
|  |  | ||||||
|  | const addAuthHeader: TBeforeRequest = ($, requestConfig) => { | ||||||
|  |   if ($.auth.data?.apiKey) { | ||||||
|  |     requestConfig.headers['api-key'] = $.auth.data.apiKey as string; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   requestConfig.params = { | ||||||
|  |     'api-version': '2023-10-01-preview' | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   return requestConfig; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | export default addAuthHeader; | ||||||
| @@ -0,0 +1,13 @@ | |||||||
|  | import { TBeforeRequest } from '@automatisch/types'; | ||||||
|  |  | ||||||
|  | const setBaseUrl: TBeforeRequest = ($, requestConfig) => { | ||||||
|  |   const yourResourceName = $.auth.data.yourResourceName as string; | ||||||
|  |  | ||||||
|  |   if (yourResourceName) { | ||||||
|  |     requestConfig.baseURL = `https://${yourResourceName}.openai.azure.com/openai`; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   return requestConfig; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | export default setBaseUrl; | ||||||
							
								
								
									
										0
									
								
								packages/backend/src/apps/azure-openai/index.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								packages/backend/src/apps/azure-openai/index.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
								
								
									
										19
									
								
								packages/backend/src/apps/azure-openai/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								packages/backend/src/apps/azure-openai/index.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | |||||||
|  | import defineApp from '../../helpers/define-app'; | ||||||
|  | import setBaseUrl from './common/set-base-url'; | ||||||
|  | import addAuthHeader from './common/add-auth-header'; | ||||||
|  | import auth from './auth'; | ||||||
|  | import actions from './actions'; | ||||||
|  |  | ||||||
|  | export default defineApp({ | ||||||
|  |   name: 'Azure OpenAI', | ||||||
|  |   key: 'azure-openai', | ||||||
|  |   baseUrl: 'https://azure.microsoft.com/en-us/products/ai-services/openai-service', | ||||||
|  |   apiBaseUrl: '', | ||||||
|  |   iconUrl: '{BASE_URL}/apps/azure-openai/assets/favicon.svg', | ||||||
|  |   authDocUrl: 'https://automatisch.io/docs/apps/azure-openai/connection', | ||||||
|  |   primaryColor: '000000', | ||||||
|  |   supportsConnections: true, | ||||||
|  |   beforeRequest: [setBaseUrl, addAuthHeader], | ||||||
|  |   auth, | ||||||
|  |   actions, | ||||||
|  | }); | ||||||
| @@ -105,7 +105,7 @@ export default defineAction({ | |||||||
|       description: `Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing frequency in the text so far, decreasing the model's likelihood to repeat the same line verbatim.` |       description: `Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing frequency in the text so far, decreasing the model's likelihood to repeat the same line verbatim.` | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       label: 'presencePenalty', |       label: 'Presence Penalty', | ||||||
|       key: 'presencePenalty', |       key: 'presencePenalty', | ||||||
|       type: 'string' as const, |       type: 'string' as const, | ||||||
|       required: false, |       required: false, | ||||||
|   | |||||||
| @@ -75,7 +75,7 @@ export default defineAction({ | |||||||
|       description: `Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing frequency in the text so far, decreasing the model's likelihood to repeat the same line verbatim.` |       description: `Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing frequency in the text so far, decreasing the model's likelihood to repeat the same line verbatim.` | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       label: 'presencePenalty', |       label: 'Presence Penalty', | ||||||
|       key: 'presencePenalty', |       key: 'presencePenalty', | ||||||
|       type: 'string' as const, |       type: 'string' as const, | ||||||
|       required: false, |       required: false, | ||||||
|   | |||||||
| @@ -0,0 +1,4 @@ | |||||||
|  | import sendPrompt from './send-prompt'; | ||||||
|  | import sendChatPrompt from './send-chat-prompt'; | ||||||
|  |  | ||||||
|  | export default [sendChatPrompt, sendPrompt]; | ||||||
| @@ -0,0 +1,137 @@ | |||||||
|  | import defineAction from '../../../../helpers/define-action'; | ||||||
|  |  | ||||||
|  | type TMessage = { | ||||||
|  |   role: string; | ||||||
|  |   content: string; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | const castFloatOrUndefined = (value: string | null) => { | ||||||
|  |   return value === '' ? undefined : parseFloat(value); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | export default defineAction({ | ||||||
|  |   name: 'Send chat prompt', | ||||||
|  |   key: 'sendChatPrompt', | ||||||
|  |   description: 'Creates a completion for the provided prompt and parameters.', | ||||||
|  |   arguments: [ | ||||||
|  |     { | ||||||
|  |       label: 'Model', | ||||||
|  |       key: 'model', | ||||||
|  |       type: 'dropdown' as const, | ||||||
|  |       required: true, | ||||||
|  |       variables: true, | ||||||
|  |       source: { | ||||||
|  |         type: 'query', | ||||||
|  |         name: 'getDynamicData', | ||||||
|  |         arguments: [ | ||||||
|  |           { | ||||||
|  |             name: 'key', | ||||||
|  |             value: 'listModels', | ||||||
|  |           }, | ||||||
|  |         ], | ||||||
|  |       }, | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       label: 'Messages', | ||||||
|  |       key: 'messages', | ||||||
|  |       type: 'dynamic' as const, | ||||||
|  |       required: true, | ||||||
|  |       description: 'Add or remove messages as needed', | ||||||
|  |       value: [{ role: 'system', body: '' }], | ||||||
|  |       fields: [ | ||||||
|  |         { | ||||||
|  |           label: 'Role', | ||||||
|  |           key: 'role', | ||||||
|  |           type: 'dropdown' as const, | ||||||
|  |           required: true, | ||||||
|  |           options: [ | ||||||
|  |             { | ||||||
|  |               label: 'System', | ||||||
|  |               value: 'system', | ||||||
|  |             }, | ||||||
|  |             { | ||||||
|  |               label: 'User', | ||||||
|  |               value: 'user', | ||||||
|  |             } | ||||||
|  |           ], | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |           label: 'Content', | ||||||
|  |           key: 'content', | ||||||
|  |           type: 'string' as const, | ||||||
|  |           required: true, | ||||||
|  |           variables: true, | ||||||
|  |         } | ||||||
|  |       ], | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       label: 'Temperature', | ||||||
|  |       key: 'temperature', | ||||||
|  |       type: 'string' as const, | ||||||
|  |       required: false, | ||||||
|  |       variables: true, | ||||||
|  |       description: 'What sampling temperature to use. Higher values mean the model will take more risk. Try 0.9 for more creative applications, and 0 for ones with a well-defined answer. We generally recommend altering this or Top P but not both.' | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       label: 'Maximum tokens', | ||||||
|  |       key: 'maxTokens', | ||||||
|  |       type: 'string' as const, | ||||||
|  |       required: false, | ||||||
|  |       variables: true, | ||||||
|  |       description: 'The maximum number of tokens to generate in the completion.' | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       label: 'Stop Sequence', | ||||||
|  |       key: 'stopSequence', | ||||||
|  |       type: 'string' as const, | ||||||
|  |       required: false, | ||||||
|  |       variables: true, | ||||||
|  |       description: 'Single stop sequence where the API will stop generating further tokens. The returned text will not contain the stop sequence.' | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       label: 'Top P', | ||||||
|  |       key: 'topP', | ||||||
|  |       type: 'string' as const, | ||||||
|  |       required: false, | ||||||
|  |       variables: true, | ||||||
|  |       description: 'An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with Top P probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered.' | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       label: 'Frequency Penalty', | ||||||
|  |       key: 'frequencyPenalty', | ||||||
|  |       type: 'string' as const, | ||||||
|  |       required: false, | ||||||
|  |       variables: true, | ||||||
|  |       description: `Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing frequency in the text so far, decreasing the model's likelihood to repeat the same line verbatim.` | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       label: 'Presence Penalty', | ||||||
|  |       key: 'presencePenalty', | ||||||
|  |       type: 'string' as const, | ||||||
|  |       required: false, | ||||||
|  |       variables: true, | ||||||
|  |       description: `Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear in the text so far, increasing the model's likelihood to talk about new topics.` | ||||||
|  |     }, | ||||||
|  |   ], | ||||||
|  |  | ||||||
|  |   async run($) { | ||||||
|  |     const payload = { | ||||||
|  |       model: $.step.parameters.model as string, | ||||||
|  |       temperature: castFloatOrUndefined($.step.parameters.temperature as string), | ||||||
|  |       max_tokens: castFloatOrUndefined($.step.parameters.maxTokens as string), | ||||||
|  |       stop: ($.step.parameters.stopSequence as string || null), | ||||||
|  |       top_p: castFloatOrUndefined($.step.parameters.topP as string), | ||||||
|  |       frequency_penalty: castFloatOrUndefined($.step.parameters.frequencyPenalty as string), | ||||||
|  |       presence_penalty: castFloatOrUndefined($.step.parameters.presencePenalty as string), | ||||||
|  |       messages: ($.step.parameters.messages as TMessage[]).map(message => ({ | ||||||
|  |         role: message.role, | ||||||
|  |         content: message.content, | ||||||
|  |       })), | ||||||
|  |     }; | ||||||
|  |     const { data } = await $.http.post('/v1/chat/completions', payload); | ||||||
|  |  | ||||||
|  |     $.setActionItem({ | ||||||
|  |       raw: data, | ||||||
|  |     }); | ||||||
|  |   }, | ||||||
|  | }); | ||||||
| @@ -0,0 +1,104 @@ | |||||||
|  | import defineAction from '../../../../helpers/define-action'; | ||||||
|  |  | ||||||
|  | const castFloatOrUndefined = (value: string | null) => { | ||||||
|  |   return value === '' ? undefined : parseFloat(value); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | export default defineAction({ | ||||||
|  |   name: 'Send prompt', | ||||||
|  |   key: 'sendPrompt', | ||||||
|  |   description: 'Creates a completion for the provided prompt and parameters.', | ||||||
|  |   arguments: [ | ||||||
|  |     { | ||||||
|  |       label: 'Model', | ||||||
|  |       key: 'model', | ||||||
|  |       type: 'dropdown' as const, | ||||||
|  |       required: true, | ||||||
|  |       variables: true, | ||||||
|  |       source: { | ||||||
|  |         type: 'query', | ||||||
|  |         name: 'getDynamicData', | ||||||
|  |         arguments: [ | ||||||
|  |           { | ||||||
|  |             name: 'key', | ||||||
|  |             value: 'listModels', | ||||||
|  |           }, | ||||||
|  |         ], | ||||||
|  |       }, | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       label: 'Prompt', | ||||||
|  |       key: 'prompt', | ||||||
|  |       type: 'string' as const, | ||||||
|  |       required: true, | ||||||
|  |       variables: true, | ||||||
|  |       description: 'The text to analyze.' | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       label: 'Temperature', | ||||||
|  |       key: 'temperature', | ||||||
|  |       type: 'string' as const, | ||||||
|  |       required: false, | ||||||
|  |       variables: true, | ||||||
|  |       description: 'What sampling temperature to use. Higher values mean the model will take more risk. Try 0.9 for more creative applications, and 0 for ones with a well-defined answer. We generally recommend altering this or Top P but not both.' | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       label: 'Maximum tokens', | ||||||
|  |       key: 'maxTokens', | ||||||
|  |       type: 'string' as const, | ||||||
|  |       required: false, | ||||||
|  |       variables: true, | ||||||
|  |       description: 'The maximum number of tokens to generate in the completion.' | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       label: 'Stop Sequence', | ||||||
|  |       key: 'stopSequence', | ||||||
|  |       type: 'string' as const, | ||||||
|  |       required: false, | ||||||
|  |       variables: true, | ||||||
|  |       description: 'Single stop sequence where the API will stop generating further tokens. The returned text will not contain the stop sequence.' | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       label: 'Top P', | ||||||
|  |       key: 'topP', | ||||||
|  |       type: 'string' as const, | ||||||
|  |       required: false, | ||||||
|  |       variables: true, | ||||||
|  |       description: 'An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with Top P probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered.' | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       label: 'Frequency Penalty', | ||||||
|  |       key: 'frequencyPenalty', | ||||||
|  |       type: 'string' as const, | ||||||
|  |       required: false, | ||||||
|  |       variables: true, | ||||||
|  |       description: `Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing frequency in the text so far, decreasing the model's likelihood to repeat the same line verbatim.` | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       label: 'Presence Penalty', | ||||||
|  |       key: 'presencePenalty', | ||||||
|  |       type: 'string' as const, | ||||||
|  |       required: false, | ||||||
|  |       variables: true, | ||||||
|  |       description: `Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear in the text so far, increasing the model's likelihood to talk about new topics.` | ||||||
|  |     }, | ||||||
|  |   ], | ||||||
|  |  | ||||||
|  |   async run($) { | ||||||
|  |     const payload = { | ||||||
|  |       model: $.step.parameters.model as string, | ||||||
|  |       prompt: $.step.parameters.prompt as string, | ||||||
|  |       temperature: castFloatOrUndefined($.step.parameters.temperature as string), | ||||||
|  |       max_tokens: castFloatOrUndefined($.step.parameters.maxTokens as string), | ||||||
|  |       stop: ($.step.parameters.stopSequence as string || null), | ||||||
|  |       top_p: castFloatOrUndefined($.step.parameters.topP as string), | ||||||
|  |       frequency_penalty: castFloatOrUndefined($.step.parameters.frequencyPenalty as string), | ||||||
|  |       presence_penalty: castFloatOrUndefined($.step.parameters.presencePenalty as string), | ||||||
|  |     }; | ||||||
|  |     const { data } = await $.http.post('/v1/completions', payload); | ||||||
|  |  | ||||||
|  |     $.setActionItem({ | ||||||
|  |       raw: data, | ||||||
|  |     }); | ||||||
|  |   }, | ||||||
|  | }); | ||||||
| @@ -0,0 +1,6 @@ | |||||||
|  | <svg width="256px" height="260px" viewBox="0 0 256 260" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid"> | ||||||
|  |     <title>OpenAI</title> | ||||||
|  |     <g> | ||||||
|  |         <path d="M239.183914,106.202783 C245.054304,88.5242096 243.02228,69.1733805 233.607599,53.0998864 C219.451678,28.4588021 190.999703,15.7836129 163.213007,21.739505 C147.554077,4.32145883 123.794909,-3.42398554 100.87901,1.41873898 C77.9631105,6.26146349 59.3690093,22.9572536 52.0959621,45.2214219 C33.8436494,48.9644867 18.0901721,60.392749 8.86672513,76.5818033 C-5.443491,101.182962 -2.19544431,132.215255 16.8986662,153.320094 C11.0060865,170.990656 13.0197283,190.343991 22.4238231,206.422991 C36.5975553,231.072344 65.0680342,243.746566 92.8695738,237.783372 C105.235639,251.708249 123.001113,259.630942 141.623968,259.52692 C170.105359,259.552169 195.337611,241.165718 204.037777,214.045661 C222.28734,210.296356 238.038489,198.869783 247.267014,182.68528 C261.404453,158.127515 258.142494,127.262775 239.183914,106.202783 L239.183914,106.202783 Z M141.623968,242.541207 C130.255682,242.559177 119.243876,238.574642 110.519381,231.286197 L112.054146,230.416496 L163.724595,200.590881 C166.340648,199.056444 167.954321,196.256818 167.970781,193.224005 L167.970781,120.373788 L189.815614,133.010026 C190.034132,133.121423 190.186235,133.330564 190.224885,133.572774 L190.224885,193.940229 C190.168603,220.758427 168.442166,242.484864 141.623968,242.541207 Z M37.1575749,197.93062 C31.456498,188.086359 29.4094818,176.546984 31.3766237,165.342426 L32.9113895,166.263285 L84.6329973,196.088901 C87.2389349,197.618207 90.4682717,197.618207 93.0742093,196.088901 L156.255402,159.663793 L156.255402,184.885111 C156.243557,185.149771 156.111725,185.394602 155.89729,185.550176 L103.561776,215.733903 C80.3054953,229.131632 50.5924954,221.165435 37.1575749,197.93062 Z M23.5493181,85.3811273 C29.2899861,75.4733097 38.3511911,67.9162648 49.1287482,64.0478825 L49.1287482,125.438515 C49.0891492,128.459425 50.6965386,131.262556 53.3237748,132.754232 L116.198014,169.025864 L94.3531808,181.662102 C94.1132325,181.789434 93.8257461,181.789434 93.5857979,181.662102 L41.3526015,151.529534 C18.1419426,138.076098 10.1817681,108.385562 23.5493181,85.125333 L23.5493181,85.3811273 Z M203.0146,127.075598 L139.935725,90.4458545 L161.7294,77.8607748 C161.969348,77.7334434 162.256834,77.7334434 162.496783,77.8607748 L214.729979,108.044502 C231.032329,117.451747 240.437294,135.426109 238.871504,154.182739 C237.305714,172.939368 225.050719,189.105572 207.414262,195.67963 L207.414262,134.288998 C207.322521,131.276867 205.650697,128.535853 203.0146,127.075598 Z M224.757116,94.3850867 L223.22235,93.4642272 L171.60306,63.3828173 C168.981293,61.8443751 165.732456,61.8443751 163.110689,63.3828173 L99.9806554,99.8079259 L99.9806554,74.5866077 C99.9533004,74.3254088 100.071095,74.0701869 100.287609,73.9215426 L152.520805,43.7889738 C168.863098,34.3743518 189.174256,35.2529043 204.642579,46.0434841 C220.110903,56.8340638 227.949269,75.5923959 224.757116,94.1804513 L224.757116,94.3850867 Z M88.0606409,139.097931 L66.2158076,126.512851 C65.9950399,126.379091 65.8450965,126.154176 65.8065367,125.898945 L65.8065367,65.684966 C65.8314495,46.8285367 76.7500605,29.6846032 93.8270852,21.6883055 C110.90411,13.6920079 131.063833,16.2835462 145.5632,28.338998 L144.028434,29.2086986 L92.3579852,59.0343142 C89.7419327,60.5687513 88.1282597,63.3683767 88.1117998,66.4011901 L88.0606409,139.097931 Z M99.9294965,113.5185 L128.06687,97.3011417 L156.255402,113.5185 L156.255402,145.953218 L128.169187,162.170577 L99.9806554,145.953218 L99.9294965,113.5185 Z" fill="#000000"></path> | ||||||
|  |     </g> | ||||||
|  | </svg> | ||||||
| After Width: | Height: | Size: 3.6 KiB | 
							
								
								
									
										44
									
								
								packages/backend/src/apps/self-hosted-llm/auth/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								packages/backend/src/apps/self-hosted-llm/auth/index.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,44 @@ | |||||||
|  | import verifyCredentials from './verify-credentials'; | ||||||
|  | import isStillVerified from './is-still-verified'; | ||||||
|  |  | ||||||
|  | export default { | ||||||
|  |   fields: [ | ||||||
|  |     { | ||||||
|  |       key: 'screenName', | ||||||
|  |       label: 'Screen Name', | ||||||
|  |       type: 'string' as const, | ||||||
|  |       required: true, | ||||||
|  |       readOnly: false, | ||||||
|  |       value: null, | ||||||
|  |       placeholder: null, | ||||||
|  |       description: | ||||||
|  |         'Screen name of your connection to be used on Automatisch UI.', | ||||||
|  |       clickToCopy: false, | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       key: 'apiUrl', | ||||||
|  |       label: 'API URL', | ||||||
|  |       type: 'string' as const, | ||||||
|  |       required: true, | ||||||
|  |       readOnly: false, | ||||||
|  |       value: null, | ||||||
|  |       placeholder: null, | ||||||
|  |       docUrl: 'https://automatisch.io/docs/self-hosted-llm#api-url', | ||||||
|  |       clickToCopy: false, | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       key: 'apiKey', | ||||||
|  |       label: 'API Key', | ||||||
|  |       type: 'string' as const, | ||||||
|  |       required: true, | ||||||
|  |       readOnly: false, | ||||||
|  |       value: null, | ||||||
|  |       placeholder: null, | ||||||
|  |       docUrl: 'https://automatisch.io/docs/self-hosted-llm#api-key', | ||||||
|  |       clickToCopy: false, | ||||||
|  |     }, | ||||||
|  |   ], | ||||||
|  |  | ||||||
|  |   verifyCredentials, | ||||||
|  |   isStillVerified, | ||||||
|  | }; | ||||||
| @@ -0,0 +1,8 @@ | |||||||
|  | import { IGlobalVariable } from '@automatisch/types'; | ||||||
|  |  | ||||||
|  | const isStillVerified = async ($: IGlobalVariable) => { | ||||||
|  |   const r = await $.http.get('/v1/models'); | ||||||
|  |   return true; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | export default isStillVerified; | ||||||
| @@ -0,0 +1,7 @@ | |||||||
|  | import { IGlobalVariable } from '@automatisch/types'; | ||||||
|  |  | ||||||
|  | const verifyCredentials = async ($: IGlobalVariable) => { | ||||||
|  |   await $.http.get('/v1/models'); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | export default verifyCredentials; | ||||||
| @@ -0,0 +1,11 @@ | |||||||
|  | import { TBeforeRequest } from '@automatisch/types'; | ||||||
|  |  | ||||||
|  | const addAuthHeader: TBeforeRequest = ($, requestConfig) => { | ||||||
|  |   if ($.auth.data?.apiKey) { | ||||||
|  |     requestConfig.headers.Authorization = `Bearer ${$.auth.data.apiKey}`; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   return requestConfig; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | export default addAuthHeader; | ||||||
| @@ -0,0 +1,11 @@ | |||||||
|  | import { TBeforeRequest } from '@automatisch/types'; | ||||||
|  |  | ||||||
|  | const setBaseUrl: TBeforeRequest = ($, requestConfig) => { | ||||||
|  |   if ($.auth.data.apiUrl) { | ||||||
|  |     requestConfig.baseURL = $.auth.data.apiUrl as string; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   return requestConfig; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | export default setBaseUrl; | ||||||
| @@ -0,0 +1,3 @@ | |||||||
|  | import listModels from './list-models'; | ||||||
|  |  | ||||||
|  | export default [listModels]; | ||||||
| @@ -0,0 +1,19 @@ | |||||||
|  | import { IGlobalVariable } from '@automatisch/types'; | ||||||
|  |  | ||||||
|  | export default { | ||||||
|  |   name: 'List models', | ||||||
|  |   key: 'listModels', | ||||||
|  |  | ||||||
|  |   async run($: IGlobalVariable) { | ||||||
|  |     const response = await $.http.get('/v1/models'); | ||||||
|  |  | ||||||
|  |     const models = response.data.data.map((model: { id: string }) => { | ||||||
|  |       return { | ||||||
|  |         value: model.id, | ||||||
|  |         name: model.id, | ||||||
|  |       }; | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     return { data: models }; | ||||||
|  |   }, | ||||||
|  | }; | ||||||
							
								
								
									
										0
									
								
								packages/backend/src/apps/self-hosted-llm/index.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								packages/backend/src/apps/self-hosted-llm/index.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
								
								
									
										21
									
								
								packages/backend/src/apps/self-hosted-llm/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								packages/backend/src/apps/self-hosted-llm/index.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | |||||||
|  | import defineApp from '../../helpers/define-app'; | ||||||
|  | import addAuthHeader from './common/add-auth-header'; | ||||||
|  | import setBaseUrl from './common/set-base-url'; | ||||||
|  | import auth from './auth'; | ||||||
|  | import actions from './actions'; | ||||||
|  | import dynamicData from './dynamic-data'; | ||||||
|  |  | ||||||
|  | export default defineApp({ | ||||||
|  |   name: 'Self-hosted LLM', | ||||||
|  |   key: 'self-hosted-llm', | ||||||
|  |   baseUrl: '', | ||||||
|  |   apiBaseUrl: '', | ||||||
|  |   iconUrl: '{BASE_URL}/apps/self-hosted-llm/assets/favicon.svg', | ||||||
|  |   authDocUrl: 'https://automatisch.io/docs/apps/self-hosted-llm/connection', | ||||||
|  |   primaryColor: '000000', | ||||||
|  |   supportsConnections: true, | ||||||
|  |   beforeRequest: [setBaseUrl, addAuthHeader], | ||||||
|  |   auth, | ||||||
|  |   actions, | ||||||
|  |   dynamicData, | ||||||
|  | }); | ||||||
| @@ -11,7 +11,9 @@ test.describe('Apps page', () => { | |||||||
|     await applicationsPage.page.getByTestId('apps-loader').waitFor({ |     await applicationsPage.page.getByTestId('apps-loader').waitFor({ | ||||||
|       state: 'detached', |       state: 'detached', | ||||||
|     }); |     }); | ||||||
|     await expect(applicationsPage.page.getByTestId('app-row')).not.toHaveCount(0); |     await expect(applicationsPage.page.getByTestId('app-row')).not.toHaveCount( | ||||||
|  |       0 | ||||||
|  |     ); | ||||||
|  |  | ||||||
|     await applicationsPage.screenshot({ |     await applicationsPage.screenshot({ | ||||||
|       path: 'Applications.png', |       path: 'Applications.png', | ||||||
| @@ -22,27 +24,31 @@ test.describe('Apps page', () => { | |||||||
|     test.beforeEach(async ({ applicationsPage }) => { |     test.beforeEach(async ({ applicationsPage }) => { | ||||||
|       await expect(applicationsPage.addConnectionButton).toBeClickableLink(); |       await expect(applicationsPage.addConnectionButton).toBeClickableLink(); | ||||||
|       await applicationsPage.addConnectionButton.click(); |       await applicationsPage.addConnectionButton.click(); | ||||||
|       await applicationsPage |       await applicationsPage.page | ||||||
|         .page |  | ||||||
|         .getByTestId('search-for-app-loader') |         .getByTestId('search-for-app-loader') | ||||||
|         .waitFor({ state: 'detached' }); |         .waitFor({ state: 'detached' }); | ||||||
|     }); |     }); | ||||||
|  |  | ||||||
|     test('lists applications', async ({ applicationsPage }) => { |     test('lists applications', async ({ applicationsPage }) => { | ||||||
|       const appListItemCount = await applicationsPage.page.getByTestId('app-list-item').count(); |       const appListItemCount = await applicationsPage.page | ||||||
|  |         .getByTestId('app-list-item') | ||||||
|  |         .count(); | ||||||
|       expect(appListItemCount).toBeGreaterThan(10); |       expect(appListItemCount).toBeGreaterThan(10); | ||||||
|  |  | ||||||
|       await applicationsPage.clickAway(); |       await applicationsPage.clickAway(); | ||||||
|     }); |     }); | ||||||
|  |  | ||||||
|     test('searches an application', async ({ applicationsPage }) => { |     test('searches an application', async ({ applicationsPage }) => { | ||||||
|       await applicationsPage.page.getByTestId('search-for-app-text-field').fill('DeepL'); |       await applicationsPage.page | ||||||
|       await applicationsPage |         .getByTestId('search-for-app-text-field') | ||||||
|         .page |         .fill('DeepL'); | ||||||
|  |       await applicationsPage.page | ||||||
|         .getByTestId('search-for-app-loader') |         .getByTestId('search-for-app-loader') | ||||||
|         .waitFor({ state: 'detached' }); |         .waitFor({ state: 'detached' }); | ||||||
|  |  | ||||||
|       await expect(applicationsPage.page.getByTestId('app-list-item')).toHaveCount(1); |       await expect( | ||||||
|  |         applicationsPage.page.getByTestId('app-list-item') | ||||||
|  |       ).toHaveCount(1); | ||||||
|  |  | ||||||
|       await applicationsPage.clickAway(); |       await applicationsPage.clickAway(); | ||||||
|     }); |     }); | ||||||
| @@ -54,8 +60,12 @@ test.describe('Apps page', () => { | |||||||
|       test.setTimeout(60000); |       test.setTimeout(60000); | ||||||
|  |  | ||||||
|       await applicationsPage.page.getByTestId('app-list-item').first().click(); |       await applicationsPage.page.getByTestId('app-list-item').first().click(); | ||||||
|       await expect(applicationsPage.page).toHaveURL('/app/carbone/connections/add?shared=false'); |       await expect(applicationsPage.page).toHaveURL( | ||||||
|       await expect(applicationsPage.page.getByTestId('add-app-connection-dialog')).toBeVisible(); |         '/app/azure-openai/connections/add?shared=false' | ||||||
|  |       ); | ||||||
|  |       await expect( | ||||||
|  |         applicationsPage.page.getByTestId('add-app-connection-dialog') | ||||||
|  |       ).toBeVisible(); | ||||||
|  |  | ||||||
|       await applicationsPage.clickAway(); |       await applicationsPage.clickAway(); | ||||||
|     }); |     }); | ||||||
| @@ -64,11 +74,19 @@ test.describe('Apps page', () => { | |||||||
|       applicationsPage, |       applicationsPage, | ||||||
|     }) => { |     }) => { | ||||||
|       await applicationsPage.page.getByTestId('app-list-item').first().click(); |       await applicationsPage.page.getByTestId('app-list-item').first().click(); | ||||||
|       await expect(applicationsPage.page).toHaveURL('/app/carbone/connections/add?shared=false'); |       await expect(applicationsPage.page).toHaveURL( | ||||||
|       await expect(applicationsPage.page.getByTestId('add-app-connection-dialog')).toBeVisible(); |         '/app/azure-openai/connections/add?shared=false' | ||||||
|  |       ); | ||||||
|  |       await expect( | ||||||
|  |         applicationsPage.page.getByTestId('add-app-connection-dialog') | ||||||
|  |       ).toBeVisible(); | ||||||
|       await applicationsPage.clickAway(); |       await applicationsPage.clickAway(); | ||||||
|       await expect(applicationsPage.page).toHaveURL('/app/carbone/connections'); |       await expect(applicationsPage.page).toHaveURL( | ||||||
|       await expect(applicationsPage.page.getByTestId('add-app-connection-dialog')).toBeHidden(); |         '/app/azure-openai/connections' | ||||||
|  |       ); | ||||||
|  |       await expect( | ||||||
|  |         applicationsPage.page.getByTestId('add-app-connection-dialog') | ||||||
|  |       ).toBeHidden(); | ||||||
|     }); |     }); | ||||||
|   }); |   }); | ||||||
| }); | }); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user