mirror of
https://github.com/fumiama/deepinfra.git
synced 2026-06-05 00:32:46 +08:00
feat: add Google GenAI API
This commit is contained in:
@@ -3,7 +3,7 @@ Call OpenAI compatible APIs, originally designed for DeepInfra.
|
|||||||
|
|
||||||
## Quick Start
|
## Quick Start
|
||||||
```go
|
```go
|
||||||
api := NewAPI(APIDeepInfra, "PUT YOUR API KEY HERE")
|
api := NewAPI(OpenAIDeepInfra, "PUT YOUR API KEY HERE")
|
||||||
txt, err := api.Request(model.NewOpenAI(model.ModelDeepDeek, model.SeparatorThink, 0.7, 0.9, 1024).
|
txt, err := api.Request(model.NewOpenAI(model.ModelDeepDeek, model.SeparatorThink, 0.7, 0.9, 1024).
|
||||||
System("Be a good assistant.").User("Hello"),
|
System("Be a good assistant.").User("Hello"),
|
||||||
)
|
)
|
||||||
|
|||||||
8
api.go
8
api.go
@@ -8,7 +8,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
APIDeepInfra = "https://api.deepinfra.com/v1/openai/chat/completions"
|
OpenAIDeepInfra = "https://api.deepinfra.com/v1/openai/chat/completions"
|
||||||
|
GenAIGoogle = "https://generativelanguage.googleapis.com/v1beta"
|
||||||
)
|
)
|
||||||
|
|
||||||
type API struct {
|
type API struct {
|
||||||
@@ -21,12 +22,11 @@ func NewAPI(api, key string) API {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (api *API) Request(model Model) (string, error) {
|
func (api *API) Request(model Model) (string, error) {
|
||||||
req, err := http.NewRequest("POST", api.api, model.Body())
|
req, err := http.NewRequest("POST", model.API(api.api, api.key), model.Body())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
req.Header.Add("Content-Type", "application/json")
|
model.Header(api.key, req.Header)
|
||||||
req.Header.Add("Authorization", "Bearer "+api.key)
|
|
||||||
resp, err := http.DefaultClient.Do(req)
|
resp, err := http.DefaultClient.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
|
|||||||
1
model.go
1
model.go
@@ -7,4 +7,5 @@ import (
|
|||||||
type Model interface {
|
type Model interface {
|
||||||
model.Inputer
|
model.Inputer
|
||||||
model.Outputer
|
model.Outputer
|
||||||
|
model.Requester
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package model
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"io"
|
"io"
|
||||||
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Inputer interface {
|
type Inputer interface {
|
||||||
@@ -15,6 +16,11 @@ type Outputer interface {
|
|||||||
OutputRaw() string
|
OutputRaw() string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Requester interface {
|
||||||
|
API(api, key string) string // API decorator
|
||||||
|
Header(key string, h http.Header) // Header decorator
|
||||||
|
}
|
||||||
|
|
||||||
type MessageBuilder[T any] interface {
|
type MessageBuilder[T any] interface {
|
||||||
System(prompt string) T
|
System(prompt string) T
|
||||||
User(prompt string) T
|
User(prompt string) T
|
||||||
@@ -24,5 +30,6 @@ type MessageBuilder[T any] interface {
|
|||||||
type Protocol interface {
|
type Protocol interface {
|
||||||
Inputer
|
Inputer
|
||||||
Outputer
|
Outputer
|
||||||
|
Requester
|
||||||
MessageBuilder[Protocol]
|
MessageBuilder[Protocol]
|
||||||
}
|
}
|
||||||
|
|||||||
120
model/genai.go
Normal file
120
model/genai.go
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
ModelGemini15Flash = "models/gemini-1.5-flash"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Text struct {
|
||||||
|
Text string `json:"text"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Content struct {
|
||||||
|
Parts []Text `json:"parts"`
|
||||||
|
Role string `json:"role,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Content) String() string {
|
||||||
|
sb := strings.Builder{}
|
||||||
|
for _, p := range c.Parts {
|
||||||
|
sb.WriteString(p.Text)
|
||||||
|
}
|
||||||
|
return sb.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
type Candidate struct {
|
||||||
|
Content Content `json:"content"`
|
||||||
|
FinishReason string `json:"finishReason"`
|
||||||
|
Index int `json:"index"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GenAI is Goole API format
|
||||||
|
type GenAI struct {
|
||||||
|
model string `json:"-"`
|
||||||
|
Protocol `json:"-"`
|
||||||
|
// request only
|
||||||
|
Contents []Content `json:"contents,omitempty"`
|
||||||
|
SystemInstruction *Content `json:"systemInstruction,omitempty"`
|
||||||
|
GenerationConfig struct {
|
||||||
|
Temperature float32 `json:"temperature,omitempty"`
|
||||||
|
ResponseMimeType string `json:"responseMimeType,omitempty"`
|
||||||
|
TopP float32 `json:"topP,omitempty"`
|
||||||
|
MaxOutputTokens int `json:"maxOutputTokens,omitempty"`
|
||||||
|
} `json:"generationConfig"`
|
||||||
|
// callback only
|
||||||
|
Candidates []Candidate `json:"candidates,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewGenAI use temp 0.7, topp 0.9, maxn 4096 if you don't know the meaning.
|
||||||
|
func NewGenAI(model string, temp, topp float32, maxn uint) *GenAI {
|
||||||
|
opai := new(GenAI)
|
||||||
|
opai.model = model
|
||||||
|
opai.GenerationConfig.Temperature = temp
|
||||||
|
opai.GenerationConfig.ResponseMimeType = "text/plain"
|
||||||
|
opai.GenerationConfig.TopP = topp
|
||||||
|
opai.GenerationConfig.MaxOutputTokens = int(maxn)
|
||||||
|
return opai
|
||||||
|
}
|
||||||
|
|
||||||
|
func (opai *GenAI) API(api, key string) string {
|
||||||
|
return fmt.Sprintf("%s/%s:generateContent?key=%s", api, opai.model, key)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*GenAI) Header(_ string, h http.Header) {
|
||||||
|
h.Add("Content-Type", "application/json")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (opai *GenAI) Body() *bytes.Buffer {
|
||||||
|
w := bytes.NewBuffer(make([]byte, 0, 8192))
|
||||||
|
err := json.NewEncoder(w).Encode(opai)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return w
|
||||||
|
}
|
||||||
|
|
||||||
|
func (opai *GenAI) Parse(body io.Reader) error {
|
||||||
|
return json.NewDecoder(body).Decode(&opai)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (opai *GenAI) Output() string {
|
||||||
|
if len(opai.Candidates) == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return opai.Candidates[0].Content.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (opai *GenAI) OutputRaw() string {
|
||||||
|
return opai.Output()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (opai *GenAI) System(prompt string) Protocol {
|
||||||
|
opai.SystemInstruction = &Content{
|
||||||
|
Parts: []Text{{prompt}},
|
||||||
|
}
|
||||||
|
return opai
|
||||||
|
}
|
||||||
|
|
||||||
|
func (opai *GenAI) User(prompt string) Protocol {
|
||||||
|
opai.Contents = append(opai.Contents, Content{
|
||||||
|
Parts: []Text{{prompt}},
|
||||||
|
Role: "user",
|
||||||
|
})
|
||||||
|
return opai
|
||||||
|
}
|
||||||
|
|
||||||
|
func (opai *GenAI) Assistant(prompt string) Protocol {
|
||||||
|
opai.Contents = append(opai.Contents, Content{
|
||||||
|
Parts: []Text{{prompt}},
|
||||||
|
Role: "model",
|
||||||
|
})
|
||||||
|
return opai
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"io"
|
"io"
|
||||||
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
// OLLaMA as an specified example.
|
// OLLaMA as an specified example.
|
||||||
@@ -35,6 +36,15 @@ func NewOLLaMA(model, sep string, temp, topp float32, maxn uint) *OLLaMA {
|
|||||||
return opai
|
return opai
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (*OLLaMA) API(api, _ string) string {
|
||||||
|
return api
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*OLLaMA) Header(key string, h http.Header) {
|
||||||
|
h.Add("Content-Type", "application/json")
|
||||||
|
h.Add("Authorization", "Bearer "+key)
|
||||||
|
}
|
||||||
|
|
||||||
func (ollm *OLLaMA) Body() *bytes.Buffer {
|
func (ollm *OLLaMA) Body() *bytes.Buffer {
|
||||||
w := bytes.NewBuffer(make([]byte, 0, 8192))
|
w := bytes.NewBuffer(make([]byte, 0, 8192))
|
||||||
err := json.NewEncoder(w).Encode(ollm)
|
err := json.NewEncoder(w).Encode(ollm)
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"io"
|
"io"
|
||||||
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -49,6 +50,15 @@ func NewOpenAI(model, sep string, temp, topp float32, maxn uint) *OpenAI {
|
|||||||
return opai
|
return opai
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (*OpenAI) API(api, _ string) string {
|
||||||
|
return api
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*OpenAI) Header(key string, h http.Header) {
|
||||||
|
h.Add("Content-Type", "application/json")
|
||||||
|
h.Add("Authorization", "Bearer "+key)
|
||||||
|
}
|
||||||
|
|
||||||
func (opai *OpenAI) Body() *bytes.Buffer {
|
func (opai *OpenAI) Body() *bytes.Buffer {
|
||||||
w := bytes.NewBuffer(make([]byte, 0, 8192))
|
w := bytes.NewBuffer(make([]byte, 0, 8192))
|
||||||
err := json.NewEncoder(w).Encode(opai)
|
err := json.NewEncoder(w).Encode(opai)
|
||||||
|
|||||||
Reference in New Issue
Block a user