Skip to content

Commit

Permalink
api: implement OpenAI endpoints
Browse files Browse the repository at this point in the history
  • Loading branch information
kevherro committed Apr 21, 2023
1 parent eeae5ae commit 4214a45
Show file tree
Hide file tree
Showing 12 changed files with 294 additions and 76 deletions.
16 changes: 16 additions & 0 deletions internal/api/audio/audio.go
@@ -0,0 +1,16 @@
// MIT License
//
// Copyright (c) 2023 Kevin Herro
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.

// Package audio implements the Audio OpenAI endpoint.
package audio
65 changes: 65 additions & 0 deletions internal/api/chat/chat.go
@@ -0,0 +1,65 @@
// MIT License
//
// Copyright (c) 2023 Kevin Herro
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.

// Package chat implements the Chat OpenAI endpoint.
package chat

const (
_ = "POST"
_ = "https://api.openai.com/v1/chat/completions"
)

type Request struct {
// ID of the model to use.
Model string `json:"model"`

// A list of messages describing the conversation so far.
Messages []Message `json:"messages"`

// The maximum number of tokens to generate in the completion.
// Defaults to 16.
MaxTokens int `json:"max_tokens"`

// What sampling temperature to use, between 0 and 2.
Temperature float64 `json:"temperature"`
}

type Message struct {
// The role of the author of this message. One of system, user,
// or assistant.
Role string `json:"role"`

// The contents of the message.
Content string `json:"content"`
}

type Response struct {
ID string `json:"id"`
Object string `json:"object"`
Created int `json:"created"`
Choices []Choice `json:"choices"`
Usage Usage `json:"usage"`
}

type Choice struct {
Index int `json:"index"`
Message Message `json:"message"`
FinishReason string `json:"finish_reason"`
}

type Usage struct {
PromptTokens int `json:"prompt_tokens"`
CompletionTokens int `json:"completion_tokens"`
TotalTokens int `json:"total_tokens"`
}
39 changes: 26 additions & 13 deletions internal/api/api.go → internal/api/completions/completions.go
Expand Up @@ -12,17 +12,30 @@
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.

// Package api implements models for the OpenAI API.
package api
// Package completions implements the Completions OpenAI endpoint.
package completions

type CompletionRequest struct {
Prompt string `json:"prompt"`
Model string `json:"model"`
MaxTokens int `json:"max_tokens"`
const (
_ = "POST"
_ = "https://api.openai.com/v1/completions"
)

type Request struct {
// ID of the model to use.
Model string `json:"model"`

// The prompt(s) to generate completions for.
Prompt string `json:"prompt"`

// The maximum number of tokens to generate in the completion.
// Defaults to 16.
MaxTokens int `json:"max_tokens"`

// What sampling temperature to use, between 0 and 2.
Temperature float64 `json:"temperature"`
}

type CompletionResponse struct {
type Response struct {
ID string `json:"id"`
Object string `json:"object"`
CreatedAt int64 `json:"created_at"`
Expand All @@ -32,12 +45,6 @@ type CompletionResponse struct {
Conversation Conversation `json:"conversation"`
}

type Choice struct {
Text string `json:"text"`
Index int `json:"index"`
LogProb float64 `json:"logproba"`
}

type Completion struct {
ID string `json:"id"`
CreatedAt int64 `json:"created_at"`
Expand All @@ -46,6 +53,12 @@ type Completion struct {
Choices []Choice `json:"choices"`
}

type Choice struct {
Text string `json:"text"`
Index int `json:"index"`
LogProb float64 `json:"logproba"`
}

type Conversation struct {
ID string `json:"id"`
CreatedAt int64 `json:"created_at"`
Expand Down
16 changes: 16 additions & 0 deletions internal/api/edits/edits.go
@@ -0,0 +1,16 @@
// MIT License
//
// Copyright (c) 2023 Kevin Herro
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.

// Package edits implements the Edits OpenAI endpoint.
package edits
16 changes: 16 additions & 0 deletions internal/api/embeddings/embeddings.go
@@ -0,0 +1,16 @@
// MIT License
//
// Copyright (c) 2023 Kevin Herro
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.

// Package embeddings implements the Embeddings OpenAI endpoint.
package embeddings
16 changes: 16 additions & 0 deletions internal/api/files/files.go
@@ -0,0 +1,16 @@
// MIT License
//
// Copyright (c) 2023 Kevin Herro
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.

// Package files implements the Files OpenAI endpoint.
package files
16 changes: 16 additions & 0 deletions internal/api/images/images.go
@@ -0,0 +1,16 @@
// MIT License
//
// Copyright (c) 2023 Kevin Herro
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.

// Package images implements the Images OpenAI endpoint.
package images
31 changes: 31 additions & 0 deletions internal/api/models/models.go
@@ -0,0 +1,31 @@
// MIT License
//
// Copyright (c) 2023 Kevin Herro
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.

// Package models implements the Models OpenAI endpoint.
package models

const (
_ = "GET"
_ = "https://api.openai.com/v1/models"
)

type Request struct{}

type Call interface {
ParseTokens(input []string) ([]string, error)
}

func (r Request) ParseTokens(input []string) ([]string, error) {
return nil, nil
}
67 changes: 67 additions & 0 deletions internal/driver/api.go
@@ -0,0 +1,67 @@
package driver

import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"os"
"strings"

"github.com/kevherro/vyx/internal/api/completions"
)

const (
url = "www.openai.com"
model = "model"
)

func parseTokens(input []string) ([]string, error) {
prompt := strings.Join(input, " ")
cfg := currentConfig()
payload := &completions.Request{
Prompt: prompt,
Model: model,
MaxTokens: cfg.MaxTokens,
Temperature: cfg.Temperature,
}

jsonData, err := json.Marshal(payload)
if err != nil {
return nil, err
}

req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
if err != nil {
return nil, err
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", os.Getenv("OPENAI_API_KEY")))

client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()

body, _ := io.ReadAll(resp.Body)

var completionResponse completions.Response
err = json.Unmarshal(body, &completionResponse)
if err != nil {
return nil, err
}

if len(completionResponse.Choices) == 0 {
if os.Getenv("OPENAI_API_KEY") == "" {
return strings.Fields("vyx: missing OPENAI_API_KEY"), nil
}
return strings.Fields("vyx: unable to generate a response"), nil
}
choice := completionResponse.Choices[0]
text := choice.Text

return strings.Fields(text), nil
}
15 changes: 15 additions & 0 deletions internal/driver/cli.go
@@ -0,0 +1,15 @@
// MIT License
//
// Copyright (c) 2023 Kevin Herro
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.

package driver
12 changes: 9 additions & 3 deletions internal/driver/config.go
Expand Up @@ -16,6 +16,7 @@ package driver

import (
"fmt"
"math"
"reflect"
"strconv"
"strings"
Expand All @@ -30,6 +31,7 @@ type config struct {
Output string `json:"-"`

// OpenAI API options.
Endpoint string `json:"endpoint,omitempty"` // The OpenAI endpoint to use.
MaxTokens int `json:"max_tokens,omitempty"` // The maximum number of tokens to generate in the completion.
Temperature float64 `json:"temperature,omitempty"` // What sampling temperature to use, between 0 and 2.
}
Expand Down Expand Up @@ -97,7 +99,8 @@ func (c *config) set(f configField, value string) error {
// It is not affected by flags and interactive assignments.
func defaultConfig() config {
return config{
MaxTokens: 2048,
Endpoint: "chat",
MaxTokens: math.MaxInt32,
Temperature: 1,
}
}
Expand Down Expand Up @@ -181,14 +184,17 @@ func init() {

// choices holds the list of allowed values for config fields that
// can take on one of a bounded set of values.
choices := map[string][]string{}
choices := map[string][]string{
"endpoint": {"chat", "completions", "models"},
}

// urlParam holds the mapping from a config field name to the URL
// parameter used to hold that config field. If no entry is present
// for a name, the corresponding field is not saved in URLs.
urlParam := map[string]string{
"endpoint": "endpoint",
"max_tokens": "maxtokens",
"temperature": "t",
"temperature": "temp",
}

d := defaultConfig()
Expand Down

0 comments on commit 4214a45

Please sign in to comment.