-
Notifications
You must be signed in to change notification settings - Fork 666
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #495 from trheyi/main
[add] moapi process and api
- Loading branch information
Showing
17 changed files
with
570 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
package moapi | ||
|
||
import "github.com/yaoapp/gou/api" | ||
|
||
var dsl = []byte(` | ||
{ | ||
"name": "Moapi API", | ||
"description": "The API for Moapi", | ||
"version": "1.0.0", | ||
"guard": "bearer-jwt", | ||
"group": "__moapi/v1", | ||
"paths": [ | ||
{ | ||
"path": "/images/generations", | ||
"method": "POST", | ||
"process": "moapi.images.Generations", | ||
"in": ["$payload.model", "$payload.prompt", ":payload"], | ||
"out": { "status": 200, "type": "application/json" } | ||
} | ||
] | ||
} | ||
`) | ||
|
||
func registerAPI() error { | ||
_, err := api.LoadSource("<moapi.v1>.yao", dsl, "moapi.v1") | ||
return err | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,169 @@ | ||
package moapi | ||
|
||
// *** WARNING *** | ||
// Temporarily: change after the moapi is open source | ||
// | ||
|
||
import ( | ||
"fmt" | ||
|
||
jsoniter "github.com/json-iterator/go" | ||
"github.com/yaoapp/gou/http" | ||
"github.com/yaoapp/yao/config" | ||
"github.com/yaoapp/yao/share" | ||
) | ||
|
||
// Mirrors list all the mirrors | ||
var cacheMirrors = []*Mirror{} | ||
var cacheApps = []*App{} | ||
var cacheMirrorsMap = map[string]*Mirror{} | ||
|
||
// Models list all the models | ||
var Models = []string{ | ||
"gpt-4-1106-preview", | ||
"gpt-4-1106-vision-preview", | ||
"gpt-4", | ||
"gpt-4-32k", | ||
|
||
"gpt-3.5-turbo", | ||
"gpt-3.5-turbo-1106", | ||
"gpt-3.5-turbo-instruct", | ||
|
||
"dall-e-3", | ||
"dall-e-2", | ||
|
||
"tts-1", | ||
"tts-1-hd", | ||
|
||
"text-moderation-latest", | ||
"text-moderation-stable", | ||
|
||
"text-embedding-ada-002", | ||
"whisper-1", | ||
} | ||
|
||
// Load load the moapi | ||
func Load(cfg config.Config) error { | ||
return registerAPI() | ||
} | ||
|
||
// Mirrors list all the mirrors | ||
func Mirrors(cache bool) ([]*Mirror, error) { | ||
if cache && len(cacheMirrors) > 0 { | ||
return cacheMirrors, nil | ||
} | ||
|
||
bytes, err := httpGet("/api/moapi/mirrors") | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
err = jsoniter.Unmarshal(bytes, &cacheMirrors) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
for _, mirror := range cacheMirrors { | ||
cacheMirrorsMap[mirror.Host] = mirror | ||
} | ||
|
||
return cacheMirrors, nil | ||
} | ||
|
||
// Apps list all the apps | ||
func Apps(cache bool) ([]*App, error) { | ||
if cache && len(cacheApps) > 0 { | ||
return cacheApps, nil | ||
} | ||
|
||
mirrors := SelectMirrors() | ||
bytes, err := httpGet("/api/moapi/apps", mirrors...) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
err = jsoniter.Unmarshal(bytes, &cacheApps) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
channel := Channel() | ||
if channel != "" { | ||
for i := range cacheApps { | ||
cacheApps[i].Homepage = cacheApps[i].Homepage + "?channel=" + channel | ||
} | ||
} | ||
|
||
return cacheApps, nil | ||
} | ||
|
||
// Homepage get the home page url with the invite code | ||
func Homepage() string { | ||
channel := Channel() | ||
if channel == "" { | ||
return "https://store.moapi.ai" | ||
} | ||
return "https://store.moapi.ai" + "?channel=" + channel | ||
} | ||
|
||
// Channel get the channel | ||
func Channel() string { | ||
|
||
return share.App.Moapi.Channel | ||
} | ||
|
||
// SelectMirrors select the mirrors | ||
func SelectMirrors() []*Mirror { | ||
|
||
if share.App.Moapi.Mirrors == nil || len(share.App.Moapi.Mirrors) == 0 { | ||
return []*Mirror{} | ||
} | ||
|
||
_, err := Mirrors(true) | ||
if err != nil { | ||
return []*Mirror{} | ||
} | ||
|
||
// pick the mirrors | ||
var result []*Mirror | ||
for _, host := range share.App.Moapi.Mirrors { | ||
if mirror, ok := cacheMirrorsMap[host]; ok { | ||
if mirror.Status == "on" { | ||
result = append(result, mirror) | ||
} | ||
} | ||
} | ||
|
||
return result | ||
} | ||
|
||
// httpGet get the data from the api | ||
func httpGet(api string, mirrors ...*Mirror) ([]byte, error) { | ||
return httpGetRetry(api, mirrors, 0) | ||
} | ||
|
||
func httpGetRetry(api string, mirrors []*Mirror, retryTimes int) ([]byte, error) { | ||
|
||
url := "https://" + share.MoapiHosts[retryTimes] + api | ||
if len(mirrors) > retryTimes { | ||
url = "https://" + mirrors[retryTimes].Host + api | ||
} | ||
|
||
secret := share.App.Moapi.Secret | ||
organization := share.App.Moapi.Organization | ||
|
||
http := http.New(url) | ||
http.SetHeader("Authorization", "Bearer "+secret) | ||
http.SetHeader("Content-Type", "application/json") | ||
http.SetHeader("Moapi-Organization", organization) | ||
|
||
resp := http.Get() | ||
if resp.Code >= 500 { | ||
if retryTimes > 3 { | ||
return nil, fmt.Errorf("Moapi Server Error: %s", resp.Data) | ||
} | ||
return httpGetRetry(api, mirrors, retryTimes+1) | ||
} | ||
|
||
return jsoniter.Marshal(resp.Data) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
package moapi | ||
|
||
import ( | ||
"github.com/yaoapp/gou/process" | ||
"github.com/yaoapp/kun/exception" | ||
"github.com/yaoapp/kun/utils" | ||
"github.com/yaoapp/yao/openai" | ||
) | ||
|
||
func init() { | ||
process.RegisterGroup("moapi", map[string]process.Handler{ | ||
"images.generations": ImagesGenerations, | ||
}) | ||
} | ||
|
||
// ImagesGenerations Generate images | ||
func ImagesGenerations(process *process.Process) interface{} { | ||
|
||
process.ValidateArgNums(2) | ||
model := process.ArgsString(0) | ||
prompt := process.ArgsString(1) | ||
option := process.ArgsMap(2, map[string]interface{}{}) | ||
|
||
if model == "" { | ||
exception.New("ImagesGenerations error: model is required", 400).Throw() | ||
} | ||
|
||
if prompt == "" { | ||
exception.New("ImagesGenerations error: prompt is required", 400).Throw() | ||
} | ||
|
||
ai, err := openai.NewMoapi(model) | ||
if err != nil { | ||
exception.New("ImagesGenerations error: %s", 400, err).Throw() | ||
} | ||
|
||
option["prompt"] = prompt | ||
option["model"] = model | ||
option["response_format"] = "url" | ||
|
||
res, ex := ai.ImagesGenerations(prompt, option) | ||
if ex != nil { | ||
utils.Dump(ex) | ||
ex.Throw() | ||
} | ||
|
||
return res | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package moapi | ||
|
||
// Mirror is the mirror info | ||
type Mirror struct { | ||
Name string `json:"name"` | ||
Host string `json:"host"` | ||
Area string `json:"area"` // area code | ||
Latency int `json:"latency"` // ms | ||
Status string `json:"status"` // on, slow, off, | ||
} | ||
|
||
// App is the app info | ||
type App struct { | ||
Name string `json:"name"` | ||
UpdatedAt int64 `json:"updated_at"` | ||
CreatedAt int64 `json:"created_at"` | ||
Country string `json:"country"` | ||
Creator string `json:"creator"` | ||
Description string `json:"description"` | ||
Version string `json:"version"` | ||
Short string `json:"short"` | ||
Icon string `json:"icon"` | ||
Homepage string `json:"homepage"` | ||
Images []string `json:"images,omitempty"` | ||
Videos []string `json:"videos,omitempty"` | ||
Stat AppStat `json:"stat,omitempty"` | ||
Languages []string `json:"languages"` | ||
} | ||
|
||
// AppStat is the app stat info | ||
type AppStat struct { | ||
Downloads int `json:"downloads"` | ||
Stars int `json:"stars"` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.