/- cookies /+ server, sr=sortug :: |_ key=@t |% ++ key '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' .^(scry:cookies ()) :: follows open AI reference docs as of 07-OCT-2023 ++ api-key (crip "Bearer {(trip key)}") ++ base-url "https://api.openai.com/v1" :: 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 +$ ljson $%([%s @t] [%n @t]) :: Passes each member of list a to gate b, which must produce a unit. Produces a new list with all the results that do not produce ~. ++ clean |* [key=@tas j=?(%s %n) d=(unit)] ?~ d ~ `[key j u.d] :: ++ audio :: |% :: ++ endpoint "/audio" :: +$ response-format $?(%json %text %srt %verbose-json %vtt) :: ++ transcription :: |% :: ++ endpoint "/transcriptions" :: +$ req :: $: file=file :: model=@t :: 'whisper-1' :: language=(unit @t) :: prompt=(unit @t) :: response-format=(unit response-format) :: temperature=(unit @rd) :: 0-1 :: == :: ++ ret %todo :: -- :: ++ translation :: |% :: ++ endpoint "/audio/translation" :: +$ req :: $: file=file :: model=@t :: 'whisper-1' :: prompt=(unit @t) :: response-format=(unit response-format) :: temperature=(unit @rd) :: 0-1 :: == :: -- :: -- ++ test |= text=@t (chat [~[[%system text 'Pepe']] 'gpt-3.5-turbo']) ++ chat |^ request:completions ++ endpoint "/chat" ++ completions |% ++ t |% +$ role $?(%system %user %assistant %function) +$ function-call $: name=@t arguments=@t == +$ function $: description=(unit @t) name=@t parameters=object:json-schema:sortug == +$ logit-bias (map @t @ud) +$ stop $@(@t (list @t)) :: up to 4 sequences +$ message $: =role content=$?(@t ~) :: not optional, but can be null name=@t == +$ request $: messages=(list message) model=@tas :: frequency-penalty=(unit @ud) :: -2.0 to 2.0 :: function-call=(unit function-call) :: functions=(list function) :: logit-bias=(unit logit-bias) :: max-tokens=(unit @ud) :: n=(unit @ud) :: presence-penalty=(unit @ud) :: stop=(unit stop) :: stream=(unit ?) :: SSE, nice :: temperature=(unit @ud) :: top-p=(unit @ud) :: user=(unit @t) == +$ full-response $: id=@t choices=(list choice) created=@da model=@t object=@t :: 'chat.completion.chunk' =usage == +$ usage $: completion-tokens=@ud prompt-tokens=@ud total-tokens=@ud == +$ chunk-response $: id=@t choices=(list choice) created=@da model=@t object=@t :: 'chat.completion.chunk' == +$ choice $: index=@ud =delta =finish-reason == +$ finish-reason $?(%stop %length %content-filter %function-call ~) +$ chunk-choice $: index=@ud =delta =finish-reason == +$ delta $: content=$?(@t ~) =role function-call=(unit function-call) == ++ dejs =, dejs:format =/ de de:json-helpers:sortug |% ++ full |= jon=@t ^- full-response %. (need (de:json:html jon)) %- ot :~ id+so choices+(ar de-choice) created+du model+so object+so usage+de-usage == ++ de-choice %- ot :~ index+ni message+de-delta ['finish_reason' de-finish-reason] == ++ de-usage %- ot :~ ['completion_tokens' ni] ['prompt_tokens' ni] ['total_tokens' ni] == ++ chunk |= jon=@t ^- chunk-response %. (need (de:json:html jon)) %- ot :~ id+so choices+(ar de-chunk-choice) created+du model+so object+so == ++ de-chunk-choice %- ot :~ index+ni delta+de-delta ['finish-reason' de-finish-reason] == ++ de-role %- su %- perk :~(%system %user %assistant %function) ++ de-finish-reason %- maybe:de %- su %- perk :~(%stop %length %content-filter %function-call) ++ de-delta %- ou :~ content+(un (maybe:de so)) role+(un de-role) ['function-call' (ur:de de-function-call)] == ++ de-function-call %- ot :~ name+so arguments+so == -- ++ enjs =, enjs:format |_ req=request ++ $ %- pairs :~ messages+a+(turn messages.req en-msg) model+s+model.req == ++ en-msg |= msg=message %- pairs :~ role+s+role.msg :- %content ?~ content.msg ~ s+content.msg == -- -- ++ endpoint "/completions" ++ request |= req=request:t ^- request:http =/ method %'POST' =/ url %- crip "{base-url}{^endpoint}{endpoint}" =/ headers :~ ['Authorization' api-key] ['Content-type' 'application/json'] == =/ json (enjs:t req) ~& > req=req ~& >> sending=(en:json:html json) =/ body (json-to-octs:server (enjs:t req)) [method url headers `body] -- -- :: ++ embeddings :: |% :: ++ endpoint "/embeddings" :: ++ req %'POST' :: +$ input :: $@ @t (list @t) :: +$ req-type :: $: =input :: model=@tas :: user=(unit @t) :: == :: +$ res :: $: object=@t :: data=(list embed) :: model=@tas :: usage=[prompt-tokens=@ud total-tokens=@ud] :: == :: +$ embed :: $: index=@ud :: embedding=(list @rd) :: TODO make this strings? :: object=@t :: 'embedding' :: == :: ++ res-dejson :: =, dejs:format :: %- ot :: :~ object+so :: model+so :: usage+usage-dejson :: data+(ar embed-dejson) :: == :: ++ usage-dejson :: =, dejs:format :: %- ot :: :~ ['prompt_tokens' ni] :: ['total_tokens' ni] :: == :: ++ embed-dejson :: %- ot :: :~ object+so :: index+ni :: embedding+(ar ne) :: TODO make this strings?? :: == :: -- :: ++ fine-tuning :: |% :: ++ endpoint "/fine_tuning/jobs :: +$ job :: $: id=@t :: created-at=@ud :: error=(unit error) :: fine-tuned-model=(unit @t) :: finished-at=(unit @ud) :: =hyperparameters :: model=@tas :: organization-id=@t :: result-files=(list @t) :: =status :: trained-tokens=(unit @ud) :: training-file=@t :: validation-file=(unit @t) :: == :: +$ job-event :: $: id=@t :: created-at=@ :: level=@t :: 'warn', 'info', ... :: message=@t :: data=(unit job) :: I think :: type=@t :: 'message' :: == :: ++ job-dejson :: =, dejs:format :: %- ot :: :~ id+so :: fine-tuned-model+uso :: finished-at+uso :: hyperparameters+hdj :: model=(se %tas) :: 'organization_id'+so :: 'result_files'+(ar so) :: status+(se %tas) :: 'trained_tokens'+uso :: 'training_file'+so :: 'validation_file'+uso :: == :: ++ job-event-dejson :: %- ot :: :~ id+so :: level+so :: message+so :: data+job-dejson :: == :: ++ uso :: |= j=json :: ?~ j ~ :: ?: ?=(-.j %s) (so j) :: ?: ?=(-.j %n) (ni j) ~ :: ++ hdj :: %- ot :: :~ :- 'n_epochs' :: |= j=json :: ?: ?=(-.j %s) %auto :: ?: ?=(-.j %n) (ni j) :: == :: +$ events-res :: $: data=(list job-event) :: has-more=? :: == :: ++ events-res-dejson :: =, dejs:format :: %- ot :: :~ data+(ar job-event-djson) :: has-more+bo :: == :: +$ status $?(%validating-files %queued %running %succeeded %failed %cancelled) :: +$ hyperparameters [%n-epochs $?(%auto @ud)] :: ++ create :: |% :: ++ endpoint "" :: ++ req %POST :: +$ req-type :: $: model=@tas :: training-file=@t :: hyperparameters=(unit hyperparameters) :: validation-file=(unit @t) :: suffix=(unit @t) :: == :: -- :: ++ get-all :: |_ [after=(unit @t) limit=(unit @ud)] :: ++ endpoint :: ?~ after :: ?~ limit :: :: none :: "" :: :: limit but not after :: "?limit={}" :: ?~ limit :: :: after but not limit :: "?after={(trip u.after)}" :: :: both :: "?limit={}&after={(trip u.after)}" :: ++ req %GET :: ++ res events-res :: ++ dejs events-res-dejson :: -- :: ++ get :: |_ id=@t :: ++ endpoint "/{(trip id)}" :: ++ req %GET :: ++ res job :: ++ res-dejson job-dejson :: -- :: ++ cancel :: |_ id=@t :: ++ endpoint "/{(trip id)}/cancel" :: ++ req %POST :: ++ res job :: ++ res-dejson job-dejson :: -- :: ++ get-events :: |_ [id=@t after=(unit @t) limit=(unit @ud)] :: :: TODO There must be a better way to handle optional query params :: ++ endpoint "/{(trip id)}/events" :: ++ req %GET :: ++ res events-res :: ++ dejs events-res-dejson :: -- :: -- :: ++ files :: |% :: ++ endpoint "/files" :: +$ file-type :: $: id=@t :: bytes=@ud :: created-at=@ud :: filename=@t :: purpose=@t :: 'currently only fine-tune' :: =status :: status-details=(unit @t) :: == :: ++ dejs :: =, dejs:format :: %- ot :: :~ id+so :: bytes+ni :: ['created_at' ni] :: filename+so :: purpose+so :: == :: +$ status $?(%uploaded %processed %pending %error %deleting %deleted) :: ++ get-all :: |% :: ++ endpoint "" :: ++ req %GET :: +$ res (list file-type) :: ++ dejs :: %- ot :: :~ data+(ar ^dejs) :: == :: -- :: ++ upload :: |_ [file=@t purpose=@t] :: file is the actual file, not the name :: ++ endpoint "" :: ++ req %POST :: mulipart wtf :: +$ res file-type :: ++ dejs ^dejs :: -- :: ++ delete :: |_ file-id=@t :: ++ endpoint "/{file-id}" :: ++ req %DELETE :: +$ res :: $: id=@t :: deleted=? :: == :: ++ dejs :: =, dejs:format :: %- ot :: :~ it+so :: deleted+bo :: == :: -- :: ++ get :: |_ file-id=@t :: ++ endpoint "/{file-id}" :: ++ req %GET :: +$ res file-type :: ++ dejs ^dejs :: -- :: ++ content :: |_ file-id=@t :: ++ endpoint "/{file-id}/content" :: ++ req %GET :: +$ res "" :: the file content :: -- :: -- ++ images |% ++ endpoint "/images" ++ t |% +$ image $% [%'b64_json' @t] [%url @t] == +$ response-format $?(%url %b64-json) +$ size $?(%'256x256' %'512x512' %'1024x1024') +$ res $: created=@ud data=(list image) == ++ dejs =, dejs:format |_ jon=@t ++ $ ^- res %. (need (de:json:html jon)) %- ot :~ created+ni data+(ar de-data) == ++ de-data %- of :~ [%'b64_json' so] [%url so] == -- -- ++ create |^ request ++ t |% +$ req $: prompt=@t n=(unit @ud) response-format=(unit response-format:^t) size=(unit size:^t) user=(unit @t) == ++ enjs =, enjs:format |_ =req ++ $ %- pairs :- prompt+s+prompt.req :: %- murn :_ clean :: :~ n+n+n.req :: ['response_format' %s response-format.req] :: size+s+size.req :: user+s+user.req :: == ~ -- -- ++ endpoint "/generations" ++ request |= =req:t ^- request:http =/ method %'POST' =/ url %- crip "{base-url}{^endpoint}{endpoint}" =/ headers :~ ['Authorization' api-key] ['Content-type' 'application/json'] == =/ body (json-to-octs:server (enjs:t req)) [method url headers `body] -- :: ++ edit :: :: TODO guess image is alread octs once it gets here so we just send tha :: :: images must be png, <4mb, square :: |^ request :: ++ t :: |% :: ++ req :: $: image=@t :: prompt=@t :: mask=(unit @t) :: n=(unit @ud) :: size=(unit size) :: response-format=(unit response-format:t) :: user=(unit @t) :: == :: -- :: ++ endpoint "/edits" :: ++ request :: multipart :: ^- request:http :: =/ method %'POST' :: =/ url %- crip "{base-url}{^endpoint}{endpoint}" :: =/ headers :: :~ :: ['Authorization' api-key] :: == :: =/ body ~ :: can we even do multipart :: [method url headers ~] :: -- :: ++ variation :: |_ [image=@t n=(unit @ud) size=(unit size) response-format=(unit response-format) user=(unit @t)] :: ++ endpoint "/variations" :: ++ request :: multipart :: ^- request:http :: =/ method %'POST' :: =/ url %- crip "{base-url}{^endpoint}{endpoint}" :: =/ headers :: :~ :: ['Authorization' api-key] :: == :: =/ body ~ :: can we even do multipart :: [method url headers ~] :: -- -- :: ++ models :: |% :: ++ endpoint "/models" :: ++ request :: ^- request:http :: =/ method %'GET' :: =/ url %- crip "{base-url}{endpoint}" :: =/ headers :: :~ :: ['Authorization' api-key] :: == :: [method url headers ~] :: +$ res (list model-res) :: +$ model-res :: $: id=@t :: created=@ :: unix ts :: object=@t :: always 'model' :: owned-by=@t :: 'openai etc.' :: == :: ++ res-dejson :: =, dejs:format :: %- ot :: :~ object+so :: data+(ar model-res-dejson) :: == :: ++ model-res-dejson :: =, dejs:format :: %- ot :: :~ id+so :: created+ni :: object+so :: owned-by+so :: == :: ++ model :: |_ name=@t :: ++ endpoint "/{name}" :: ++ request :: ^- request:http :: =/ method %'GET' :: =/ url %- crip "{base-url}{^endpoint}{endpoint}" :: =/ headers :: :~ :: ['Authorization' api-key] :: == :: [method url headers ~] :: -- :: ++ delete-model :: |_ name=@t :: ++ endpoint "{name}" :: ++ request :: ^- request:http :: =/ method %'DELETE' :: =/ url %- crip "{base-url}{^endpoint}{endpoint}" :: =/ headers :: :~ :: ['Authorization' api-key] :: == :: [method url headers ~] :: +$ res :: $: id=@t :: object=@t :: 'model' :: deleted=? :: == :: ++ res-dejson :: =, dejs:format :: %- ot :: :~ id+so :: object+so :: deleted+bo :: == :: -- :: -- :: ++ moderation :: |% :: ++ endpoints "/moderations" :: +$ moderation-t :: $: id=@t :: model=@t :: results=(list result) :: == :: +$ result :: $: flagged=? :: =categories :: =category-scores :: == :: +$ categories :: $: sexual=? :: hate=? :: harassment=? :: self-harm=? :: sexual-minors=? :: hate-threatening=? :: violence-graphic=? :: self-harm-intent=? :: self-harm-instructions=? :: harassment-threatening=? :: violence=? :: == :: +$ category-scores :: $: sexual=@rd :: hate=@rd :: harassment=@rd :: self-harm=@rd :: sexual-minors=@rd :: hate-threatening=@rd :: violence-graphic=@rd :: self-harm-intent=@rd :: self-harm-instructions=@rd :: harassment-threatening=@rd :: violence=@rd :: == :: ++ dejs :: =, dejs:format :: %- ot :: :~ id+so :: model+(se %tas) :: results+(ar de-result) :: == :: ++ de-result :: =, dejs:format :: %- ot :: :~ flagged+bo :: categories+de-categories :: ['category_scores' de-category-scores] :: == :: ++ de-categories :: =, dejs:format :: %- ot :: :~ sexual+bo :: hate+bo :: harassment+bo :: self-harm+bo :: 'sexual/minors'+bo :: 'hate/threatening'+bo :: 'violence/graphic'+bo :: 'self-harm/intent'+bo :: 'self-harm/instructions'+bo :: 'harassment/threatening'+bo :: violence+bo :: == :: ++ de-category-scores :: =, dejs:format :: %- ot :: :~ sexual+ne :: hate+ne :: harassment+ne :: self-harm+ne :: 'sexual/minors'+ne :: 'hate/threatening'+ne :: 'violence/graphic'+ne :: 'self-harm/intent'+ne :: 'self-harm/instructions'+ne :: 'harassment/threatening'+ne :: violence+ne :: == :: ++ create :: |_ =req :: ++ endpoint "" :: ++ request :: ^- request:http :: =/ method %'POST' :: =/ url %- crip "{base-url}{^endpoint}{endpoint}" :: =/ headers :: :~ :: ['content-type' 'application/json'] :: ['Authorization' api-key] :: == :: =/ body (json-to-octs:server (enjs req)) :: [method url headers `body] :: +$ input $@ @t (list @t) :: +$ model $?(%text-moderation-stable %text-moderation-latest) :: +$ req :: $: =input :: model=(unit model) :: == :: ++ enjs :: =, enjs:format :: %- pairs :: :~ input+s+(en-input input.req) :: == :: ++ en-input :: =, enjs:format :: ?^ input.req a+(turn input |=(s=@t s+s)) :: s+input :: +$ res moderation-t :: ++ dejs ^dejs :: -- :: -- --