Skip to content

Commit 683c3a2

Browse files
authored
Adds basic translator and api schemas (#27)
This migrates the translation logic from the PoC code in poc-showcasing branch. Nothing special in here - just the manual translation plus the barebone API definitions for each OpenAI and AWS Bedrock. Just in case anyway curious about why not using OpenAPI generator for the OpenAI part, here's the comment in the apischema/openai package: ``` // Package openai contains the followings are the OpenAI API schema definitions. // Note that we intentionally do not use the code generation tools like OpenAPI Generator not only to keep the code simple // but also because the OpenAI's OpenAPI definition is not compliant with the spec and the existing tools do not work well. ``` Especially, the OpenAPI schema is a bit tricky especially on the streaming=true/false conditionals. Given that only a few endpoints will be supported here anyways, it's not that problematic to have the manually written data structure. --------- Signed-off-by: Takeshi Yoneda <[email protected]>
1 parent 6bd91fc commit 683c3a2

File tree

10 files changed

+1253
-0
lines changed

10 files changed

+1253
-0
lines changed

go.mod

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ module github.com/envoyproxy/ai-gateway
33
go 1.23.2
44

55
require (
6+
github.com/aws/aws-sdk-go v1.55.5
7+
github.com/envoyproxy/go-control-plane v0.13.1
68
github.com/stretchr/testify v1.10.0
79
k8s.io/apimachinery v0.31.3
810
sigs.k8s.io/controller-runtime v0.19.3
@@ -12,8 +14,10 @@ require (
1214
require (
1315
github.com/beorn7/perks v1.0.1 // indirect
1416
github.com/cespare/xxhash/v2 v2.3.0 // indirect
17+
github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b // indirect
1518
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
1619
github.com/emicklei/go-restful/v3 v3.12.0 // indirect
20+
github.com/envoyproxy/protoc-gen-validate v1.1.0 // indirect
1721
github.com/evanphx/json-patch/v5 v5.9.0 // indirect
1822
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
1923
github.com/go-logr/logr v1.4.2 // indirect
@@ -36,6 +40,7 @@ require (
3640
github.com/modern-go/reflect2 v1.0.2 // indirect
3741
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
3842
github.com/pkg/errors v0.9.1 // indirect
43+
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect
3944
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
4045
github.com/prometheus/client_golang v1.19.1 // indirect
4146
github.com/prometheus/client_model v0.6.1 // indirect
@@ -53,6 +58,8 @@ require (
5358
golang.org/x/text v0.20.0 // indirect
5459
golang.org/x/time v0.5.0 // indirect
5560
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
61+
google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 // indirect
62+
google.golang.org/grpc v1.66.2 // indirect
5663
google.golang.org/protobuf v1.34.2 // indirect
5764
gopkg.in/inf.v0 v0.9.1 // indirect
5865
gopkg.in/yaml.v2 v2.4.0 // indirect

go.sum

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,21 @@
1+
github.com/aws/aws-sdk-go v1.55.5 h1:KKUZBfBoyqy5d3swXyiC7Q76ic40rYcbqH7qjh59kzU=
2+
github.com/aws/aws-sdk-go v1.55.5/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU=
13
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
24
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
35
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
46
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
7+
github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b h1:ga8SEFjZ60pxLcmhnThWgvH2wg8376yUJmPhEH4H3kw=
8+
github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8=
59
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
610
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
711
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
812
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
913
github.com/emicklei/go-restful/v3 v3.12.0 h1:y2DdzBAURM29NFF94q6RaY4vjIH1rtwDapwQtU84iWk=
1014
github.com/emicklei/go-restful/v3 v3.12.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
15+
github.com/envoyproxy/go-control-plane v0.13.1 h1:vPfJZCkob6yTMEgS+0TwfTUfbHjfy/6vOJ8hUWX/uXE=
16+
github.com/envoyproxy/go-control-plane v0.13.1/go.mod h1:X45hY0mufo6Fd0KW3rqsGvQMw58jvjymeCzBU3mWyHw=
17+
github.com/envoyproxy/protoc-gen-validate v1.1.0 h1:tntQDh69XqOCOZsDz0lVJQez/2L6Uu2PdjCQwWCJ3bM=
18+
github.com/envoyproxy/protoc-gen-validate v1.1.0/go.mod h1:sXRDRVmzEbkM7CVcM06s9shE/m23dg3wzjl0UWqJ2q4=
1119
github.com/evanphx/json-patch v5.7.0+incompatible h1:vgGkfT/9f8zE6tvSCe74nfpAVDQ2tG6yudJd8LBksgI=
1220
github.com/evanphx/json-patch v5.7.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
1321
github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg=
@@ -46,6 +54,8 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
4654
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
4755
github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4=
4856
github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
57+
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
58+
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
4959
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
5060
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
5161
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
@@ -71,6 +81,8 @@ github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk=
7181
github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0=
7282
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
7383
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
84+
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo=
85+
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8=
7486
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
7587
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
7688
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
@@ -143,6 +155,10 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T
143155
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
144156
gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw=
145157
gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY=
158+
google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 h1:BwIjyKYGsK9dMCBOorzRri8MQwmi7mT9rGHsCEinZkA=
159+
google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY=
160+
google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo=
161+
google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y=
146162
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
147163
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
148164
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package awsbedrock
2+
3+
import (
4+
"encoding/json"
5+
"strings"
6+
)
7+
8+
// ConverseRequest is defined in the AWS Bedrock API:
9+
// https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_Converse.html#API_runtime_Converse_RequestBody
10+
type ConverseRequest struct {
11+
Messages []Message `json:"messages,omitempty"`
12+
}
13+
14+
// Message is defined in the AWS Bedrock API:
15+
// https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_Message.html#bedrock-Type-runtime_Message-content
16+
type Message struct {
17+
Role string `json:"role,omitempty"`
18+
Content []ContentBlock `json:"content,omitempty"`
19+
}
20+
21+
// ContentBlock is defined in the AWS Bedrock API:
22+
// https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_ContentBlock.html
23+
type ContentBlock struct {
24+
Text string `json:"text,omitempty"`
25+
}
26+
27+
// ConverseResponse is defined in the AWS Bedrock API:
28+
// https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_Converse.html#API_runtime_Converse_ResponseElements
29+
type ConverseResponse struct {
30+
Output ConverseResponseOutput `json:"output,omitempty"`
31+
Usage TokenUsage `json:"usage,omitempty"`
32+
}
33+
34+
// ConverseResponseOutput is defined in the AWS Bedrock API:
35+
// https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_ConverseOutput.html
36+
type ConverseResponseOutput struct {
37+
Message Message `json:"message,omitempty"`
38+
}
39+
40+
// TokenUsage is defined in the AWS Bedrock API:
41+
// https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_TokenUsage.html
42+
type TokenUsage struct {
43+
InputTokens int `json:"inputTokens,omitempty"`
44+
OutputTokens int `json:"outputTokens,omitempty"`
45+
TotalTokens int `json:"totalTokens,omitempty"`
46+
}
47+
48+
// ConverseStreamEvent is the union of all possible event types in the AWS Bedrock API:
49+
// https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_ConverseStream.html
50+
type ConverseStreamEvent struct {
51+
ContentBlockIndex int `json:"contentBlockIndex,omitempty"`
52+
Delta *ConverseStreamEventContentBlockDelta `json:"delta,omitempty"`
53+
Role *string `json:"role,omitempty"`
54+
StopReason *string `json:"stopReason,omitempty"`
55+
Usage *TokenUsage `json:"usage,omitempty"`
56+
}
57+
58+
// String implements fmt.Stringer.
59+
func (c ConverseStreamEvent) String() string {
60+
buf, _ := json.Marshal(c)
61+
return strings.ReplaceAll(string(buf), ",", ", ")
62+
}
63+
64+
// ConverseStreamEventContentBlockDelta is defined in the AWS Bedrock API:
65+
// https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_ContentBlockDelta.html
66+
type ConverseStreamEventContentBlockDelta struct {
67+
Text string `json:"text,omitempty"`
68+
}

internal/apischema/openai/openai.go

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
// Package openai contains the followings are the OpenAI API schema definitions.
2+
// Note that we intentionally do not use the code generation tools like OpenAPI Generator not only to keep the code simple
3+
// but also because the OpenAI's OpenAPI definition is not compliant with the spec and the existing tools do not work well.
4+
package openai
5+
6+
import (
7+
"encoding/json"
8+
"strings"
9+
)
10+
11+
// ChatCompletionRequest represents a request to /v1/chat/completions.
12+
// https://platform.openai.com/docs/api-reference/chat/create
13+
type ChatCompletionRequest struct {
14+
// Model is described in the OpenAI API documentation:
15+
// https://platform.openai.com/docs/api-reference/chat/create#chat-create-model
16+
Model string `json:"model"`
17+
18+
// Messages is described in the OpenAI API documentation:
19+
// https://platform.openai.com/docs/api-reference/chat/create#chat-create-messages
20+
Messages []ChatCompletionRequestMessage `json:"messages"`
21+
22+
// Stream is described in the OpenAI API documentation:
23+
// https://platform.openai.com/docs/api-reference/chat/create#chat-create-stream
24+
Stream bool `json:"stream,omitempty"`
25+
}
26+
27+
// ChatCompletionRequestMessage represents a message in a ChatCompletionRequest.
28+
// https://platform.openai.com/docs/api-reference/chat/create#chat-create-messages
29+
type ChatCompletionRequestMessage struct {
30+
// Role is the role of the message. The role of the message (whether it represents the user or the AI).
31+
Role string `json:"role,omitempty"`
32+
// Content is the content of the message. Mainly this is a string, but it can be more complex.
33+
Content any `json:"content,omitempty"`
34+
}
35+
36+
// ChatCompletionResponse represents a response from /v1/chat/completions.
37+
// https://platform.openai.com/docs/api-reference/chat/object
38+
type ChatCompletionResponse struct {
39+
// Choices are described in the OpenAI API documentation:
40+
// https://platform.openai.com/docs/api-reference/chat/object#chat/object-choices
41+
Choices []ChatCompletionResponseChoice `json:"choices,omitempty"`
42+
43+
// Object is always "chat.completion" for completions.
44+
// https://platform.openai.com/docs/api-reference/chat/object#chat/object-object
45+
Object string `json:"object,omitempty"`
46+
47+
// Usage is described in the OpenAI API documentation:
48+
// https://platform.openai.com/docs/api-reference/chat/object#chat/object-usage
49+
Usage ChatCompletionResponseUsage `json:"usage,omitempty"`
50+
}
51+
52+
// ChatCompletionResponseChoice is described in the OpenAI API documentation:
53+
// https://platform.openai.com/docs/api-reference/chat/object#chat/object-choices
54+
type ChatCompletionResponseChoice struct {
55+
// Message is described in the OpenAI API documentation:
56+
// https://platform.openai.com/docs/api-reference/chat/object#chat/object-choices
57+
Message ChatCompletionResponseChoiceMessage `json:"message,omitempty"`
58+
}
59+
60+
// ChatCompletionResponseChoiceMessage is described in the OpenAI API documentation:
61+
// https://platform.openai.com/docs/api-reference/chat/object#chat/object-choices
62+
type ChatCompletionResponseChoiceMessage struct {
63+
Content *string `json:"content,omitempty"`
64+
Role string `json:"role,omitempty"`
65+
}
66+
67+
// ChatCompletionResponseUsage is described in the OpenAI API documentation:
68+
// https://platform.openai.com/docs/api-reference/chat/object#chat/object-usage
69+
type ChatCompletionResponseUsage struct {
70+
CompletionTokens int `json:"completion_tokens,omitempty"`
71+
PromptTokens int `json:"prompt_tokens,omitempty"`
72+
TotalTokens int `json:"total_tokens,omitempty"`
73+
}
74+
75+
// ChatCompletionResponseChunk is described in the OpenAI API documentation:
76+
// https://platform.openai.com/docs/api-reference/chat/streaming#chat-create-messages
77+
type ChatCompletionResponseChunk struct {
78+
// Choices are described in the OpenAI API documentation:
79+
// https://platform.openai.com/docs/api-reference/chat/streaming#chat/streaming-choices
80+
Choices []ChatCompletionResponseChunkChoice `json:"choices,omitempty"`
81+
82+
// Object is always "chat.completion.chunk" for completions.
83+
// https://platform.openai.com/docs/api-reference/chat/streaming#chat/streaming-object
84+
Object string `json:"object,omitempty"`
85+
86+
// Usage is described in the OpenAI API documentation:
87+
// https://platform.openai.com/docs/api-reference/chat/streaming#chat/streaming-usage
88+
Usage *ChatCompletionResponseUsage `json:"usage,omitempty"`
89+
}
90+
91+
// String implements fmt.Stringer.
92+
func (c *ChatCompletionResponseChunk) String() string {
93+
buf, _ := json.Marshal(c)
94+
return strings.ReplaceAll(string(buf), ",", ", ")
95+
}
96+
97+
// ChatCompletionResponseChunkChoice is described in the OpenAI API documentation:
98+
// https://platform.openai.com/docs/api-reference/chat/streaming#chat/streaming-choices
99+
type ChatCompletionResponseChunkChoice struct {
100+
Delta *ChatCompletionResponseChunkChoiceDelta `json:"delta,omitempty"`
101+
}
102+
103+
// ChatCompletionResponseChunkChoiceDelta is described in the OpenAI API documentation:
104+
// https://platform.openai.com/docs/api-reference/chat/streaming#chat/streaming-choices
105+
type ChatCompletionResponseChunkChoiceDelta struct {
106+
Content *string `json:"content,omitempty"`
107+
Role *string `json:"role,omitempty"`
108+
}

0 commit comments

Comments
 (0)