add db、log support

support embedding for llm
support watch run for js
many other updates
This commit is contained in:
Star 2024-09-29 21:20:28 +08:00
parent 767d87ac3e
commit e69b9a3a12
28 changed files with 1181 additions and 240 deletions

2
ai.go
View File

@ -1,7 +1,7 @@
package ai
import (
"apigo.cc/ai/ai/llm"
"apigo.cc/ai/ai/interface/llm"
_ "apigo.cc/ai/ai/llm/openai"
_ "apigo.cc/ai/ai/llm/zhipu"
"github.com/ssgo/config"

View File

@ -2,9 +2,11 @@ package main
import (
"apigo.cc/ai/ai"
"apigo.cc/ai/ai/ai/watcher"
"apigo.cc/ai/ai/watcher"
"fmt"
_ "github.com/go-sql-driver/mysql"
"github.com/ssgo/u"
_ "modernc.org/sqlite"
"os"
"os/signal"
"path/filepath"

18
go.mod
View File

@ -9,10 +9,13 @@ require (
github.com/fsnotify/fsnotify v1.7.0
github.com/go-resty/resty/v2 v2.15.2
github.com/go-sourcemap/sourcemap v2.1.4+incompatible
github.com/go-sql-driver/mysql v1.5.0
github.com/golang-jwt/jwt/v5 v5.2.1
github.com/google/pprof v0.0.0-20240910150728-a0b0bb1d4134
github.com/sashabaranov/go-openai v1.30.3
github.com/ssgo/config v1.7.7
github.com/ssgo/dao v0.1.1
github.com/ssgo/db v1.7.8
github.com/ssgo/httpclient v1.7.7
github.com/ssgo/log v1.7.7
github.com/ssgo/u v1.7.7
@ -22,12 +25,27 @@ require (
golang.org/x/text v0.18.0
gopkg.in/yaml.v2 v2.4.0
gopkg.in/yaml.v3 v3.0.1
modernc.org/sqlite v1.33.1
)
require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-sqlite3 v1.14.17 // indirect
github.com/mitchellh/mapstructure v1.4.1 // indirect
github.com/ncruces/go-strftime v0.1.9 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/ssgo/standard v1.7.7 // indirect
golang.org/x/sys v0.25.0 // indirect
modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 // indirect
modernc.org/libc v1.55.3 // indirect
modernc.org/mathutil v1.6.0 // indirect
modernc.org/memory v1.8.0 // indirect
modernc.org/strutil v1.2.0 // indirect
modernc.org/token v1.1.0 // indirect
)

View File

@ -1,5 +1,11 @@
package llm
import (
"bytes"
"encoding/binary"
"math"
)
type ChatMessage struct {
Role string
Contents []ChatMessageContent
@ -59,10 +65,11 @@ func (chatConfig *ChatConfig) GetTools() map[string]any {
return chatConfig.Tools
}
type TokenUsage struct {
type Usage struct {
AskTokens int64
AnswerTokens int64
TotalTokens int64
UsedTime int64
}
type MessagesMaker struct {
@ -143,3 +150,38 @@ func (m *MessagesMaker) Video(text string) *MessagesMaker {
}
return m
}
func bin2float64(in []byte) []float64 {
buf := bytes.NewBuffer(in)
out := make([]float64, len(in)/4)
for i := 0; i < len(out); i++ {
var f float32
_ = binary.Read(buf, binary.LittleEndian, &f)
out[i] = float64(f)
}
return out
}
func Similarity(buf1, buf2 []byte) float64 {
a := bin2float64(buf1)
b := bin2float64(buf2)
if len(a) != len(b) {
return 0
}
var dotProduct, magnitudeA, magnitudeB float64
for i := 0; i < len(a); i++ {
dotProduct += a[i] * b[i]
magnitudeA += a[i] * a[i]
magnitudeB += b[i] * b[i]
}
magnitudeA = math.Sqrt(magnitudeA)
magnitudeB = math.Sqrt(magnitudeB)
if magnitudeA == 0 || magnitudeB == 0 {
return 0
}
return dotProduct / (magnitudeA * magnitudeB)
}

View File

@ -35,21 +35,24 @@ type Config struct {
type LLM interface {
Support() Support
Ask(messages []ChatMessage, config ChatConfig, callback func(answer string)) (string, TokenUsage, error)
FastAsk(messages []ChatMessage, callback func(answer string)) (string, TokenUsage, error)
LongAsk(messages []ChatMessage, callback func(answer string)) (string, TokenUsage, error)
BatterAsk(messages []ChatMessage, callback func(answer string)) (string, TokenUsage, error)
BestAsk(messages []ChatMessage, callback func(answer string)) (string, TokenUsage, error)
MultiAsk(messages []ChatMessage, callback func(answer string)) (string, TokenUsage, error)
BestMultiAsk(messages []ChatMessage, callback func(answer string)) (string, TokenUsage, error)
CodeInterpreterAsk(messages []ChatMessage, callback func(answer string)) (string, TokenUsage, error)
WebSearchAsk(messages []ChatMessage, callback func(answer string)) (string, TokenUsage, error)
MakeImage(prompt string, config GCConfig) ([]string, error)
FastMakeImage(prompt string, config GCConfig) ([]string, error)
BestMakeImage(prompt string, config GCConfig) ([]string, error)
MakeVideo(prompt string, config GCConfig) ([]string, []string, error)
FastMakeVideo(prompt string, config GCConfig) ([]string, []string, error)
BestMakeVideo(prompt string, config GCConfig) ([]string, []string, error)
Ask(messages []ChatMessage, config ChatConfig, callback func(answer string)) (string, Usage, error)
FastAsk(messages []ChatMessage, callback func(answer string)) (string, Usage, error)
LongAsk(messages []ChatMessage, callback func(answer string)) (string, Usage, error)
BatterAsk(messages []ChatMessage, callback func(answer string)) (string, Usage, error)
BestAsk(messages []ChatMessage, callback func(answer string)) (string, Usage, error)
MultiAsk(messages []ChatMessage, callback func(answer string)) (string, Usage, error)
BestMultiAsk(messages []ChatMessage, callback func(answer string)) (string, Usage, error)
CodeInterpreterAsk(messages []ChatMessage, callback func(answer string)) (string, Usage, error)
WebSearchAsk(messages []ChatMessage, callback func(answer string)) (string, Usage, error)
MakeImage(prompt string, config GCConfig) ([]string, Usage, error)
FastMakeImage(prompt string, config GCConfig) ([]string, Usage, error)
BestMakeImage(prompt string, config GCConfig) ([]string, Usage, error)
MakeVideo(prompt string, config GCConfig) ([]string, []string, Usage, error)
FastMakeVideo(prompt string, config GCConfig) ([]string, []string, Usage, error)
BestMakeVideo(prompt string, config GCConfig) ([]string, []string, Usage, error)
Embedding(text string, model string) ([]byte, Usage, error)
FastEmbedding(text string) ([]byte, Usage, error)
BestEmbedding(text string) ([]byte, Usage, error)
}
var llmMakers = map[string]func(Config) LLM{}

135
js.go
View File

@ -3,18 +3,24 @@ package ai
import (
"apigo.cc/ai/ai/goja"
"apigo.cc/ai/ai/goja_nodejs/require"
"apigo.cc/ai/ai/interface/llm"
"apigo.cc/ai/ai/js"
"apigo.cc/ai/ai/llm"
"apigo.cc/ai/ai/watcher"
"bytes"
_ "embed"
"encoding/json"
"errors"
"fmt"
"github.com/ssgo/log"
"github.com/ssgo/u"
"os"
"os/signal"
"path/filepath"
"regexp"
"strings"
"syscall"
"text/template"
"time"
)
//go:embed js/lib/ai.ts
@ -32,6 +38,12 @@ var utilTS string
//go:embed js/lib/http.ts
var httpTS string
//go:embed js/lib/log.ts
var logTS string
//go:embed js/lib/db.ts
var dbTS string
func RunFile(file string, args ...any) (any, error) {
return Run(u.ReadFileN(file), file, args...)
}
@ -98,14 +110,22 @@ func (rt *Runtime) requireMod(name string) error {
err = rt.vm.Set("http", js.RequireHTTP())
}
}
if err == nil && (name == "log" || name == "") {
if !rt.required["log"] {
rt.required["log"] = true
err = rt.vm.Set("log", js.RequireLog())
}
}
if err == nil && (name == "db" || name == "") {
if !rt.required["db"] {
rt.required["db"] = true
err = rt.vm.Set("db", js.RequireDB())
}
}
if err == nil && (name == "ai" || name == "") {
if !rt.required["ai"] {
rt.required["ai"] = true
aiList := make(map[string]any)
for name, lm := range llm.List() {
aiList[name] = js.RequireAI(lm)
}
err = rt.vm.Set("ai", aiList)
err = rt.vm.Set("ai", js.RequireAI())
}
}
return err
@ -139,7 +159,9 @@ func (rt *Runtime) makeImport(matcher *regexp.Regexp, code string) (string, int,
func New() *Runtime {
vm := goja.New()
vm.GoData = map[string]any{}
vm.GoData = map[string]any{
"logger": log.New(u.ShortUniqueId()),
}
return &Runtime{
vm: vm,
required: map[string]bool{},
@ -216,6 +238,7 @@ func (rt *Runtime) StartFromCode(code, refFile string) (any, error) {
}
modCode, _, _ = rt.makeImport(importLibMatcher, modCode)
modCode, _, _ = rt.makeImport(requireLibMatcher, modCode)
modCode = importModMatcher.ReplaceAllString(modCode, "let $1 = require('$2')")
return []byte(modCode), modErr
}).Enable(rt.vm)
@ -298,10 +321,108 @@ func ExportForDev() (string, error) {
_ = u.WriteFile(filepath.Join("lib", "file.ts"), fileTS)
_ = u.WriteFile(filepath.Join("lib", "util.ts"), utilTS)
_ = u.WriteFile(filepath.Join("lib", "http.ts"), httpTS)
_ = u.WriteFile(filepath.Join("lib", "log.ts"), logTS)
_ = u.WriteFile(filepath.Join("lib", "db.ts"), dbTS)
return `import {` + strings.Join(exports.LLMList, ", ") + `} from './lib/ai'
import console from './lib/console'
import log from './lib/log'
import util from './lib/util'
import http from './lib/http'
import db from './lib/db'
import file from './lib/file'`, nil
}
//func RunFile(file string, args ...any) (any, error) {
// return Run(u.ReadFileN(file), file, args...)
//}
type WatchRunner struct {
w *watcher.Watcher
}
func (wr *WatchRunner) WaitForKill() {
exitCh := make(chan os.Signal, 1)
closeCh := make(chan bool, 1)
signal.Notify(exitCh, os.Interrupt, syscall.SIGTERM, syscall.SIGINT, syscall.SIGHUP)
go func() {
<-exitCh
closeCh <- true
}()
<-closeCh
wr.w.Stop()
}
func (wr *WatchRunner) Stop() {
wr.w.Stop()
}
func WatchRun(file string, extDirs, extTypes []string, args ...any) (*WatchRunner, error) {
wr := &WatchRunner{}
run := func() {
rt := New()
if wr.w != nil {
rt.SetModuleLoader(func(filename string) string {
filePath := filepath.Dir(filename)
needWatch := true
for _, v := range wr.w.WatchList() {
if v == filePath {
needWatch = false
break
}
}
if needWatch {
fmt.Println(u.BMagenta("[watching module path]"), filePath)
_ = wr.w.Add(filePath)
}
return u.ReadFileN(filename)
})
}
_, err := rt.StartFromFile(file)
result, err := rt.RunMain(args...)
if err != nil {
fmt.Println(u.BRed(err.Error()))
fmt.Println(u.Red(" " + strings.Join(rt.GetCallStack(), "\n ")))
} else if result != nil {
fmt.Println(u.Cyan(u.JsonP(result)))
}
}
var isWaitingRun = false
onChange := func(filename string, event string) {
if !isWaitingRun {
_, _ = os.Stdout.WriteString("\x1b[3;J\x1b[H\x1b[2J")
isWaitingRun = true
go func() {
time.Sleep(time.Millisecond * 10)
isWaitingRun = false
run()
}()
}
fmt.Println(u.BYellow("[changed]"), filename)
}
_, _ = os.Stdout.WriteString("\x1b[3;J\x1b[H\x1b[2J")
watchStartPath := filepath.Dir(file)
fmt.Println(u.BMagenta("[watching root path]"), watchStartPath)
watchDirs := []string{watchStartPath}
watchTypes := []string{"js", "json", "yml"}
if extDirs != nil {
for _, v := range extDirs {
watchDirs = append(watchDirs, v)
}
}
if extTypes != nil {
for _, v := range extTypes {
watchTypes = append(watchTypes, v)
}
}
if w, err := watcher.Start(watchDirs, watchTypes, onChange); err == nil {
wr.w = w
go func() {
run()
}()
return wr, nil
} else {
return nil, err
}
}

136
js/ai.go
View File

@ -2,121 +2,136 @@ package js
import (
"apigo.cc/ai/ai/goja"
"apigo.cc/ai/ai/llm"
"apigo.cc/ai/ai/interface/llm"
"github.com/ssgo/u"
"reflect"
"strings"
)
type ChatResult struct {
llm.TokenUsage
Result string
Error string
func RequireAI() map[string]any {
aiObj := map[string]any{
"similarity": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := MakeArgs(&argsIn, vm).Check(2)
return vm.ToValue(llm.Similarity(args.Bytes(0), args.Bytes(1)))
},
}
for name, lm := range llm.List() {
aiObj[name] = RequireLLM(lm)
}
return aiObj
}
type AIGCResult struct {
Result string
Preview string
Results []string
Previews []string
Error string
}
func RequireAI(lm llm.LLM) map[string]any {
func RequireLLM(lm llm.LLM) map[string]any {
return map[string]any{
"ask": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := MakeArgs(&argsIn, vm).Check(1)
conf, cb := getAskArgs(args.This, vm, args.Arguments)
result, usage, err := lm.Ask(makeChatMessages(args.Arguments), conf, cb)
return vm.ToValue(map[string]any{"tokenUsage": toMap(usage), "result": result, "error": getErrorStr(err)})
return makeChatResult(vm, result, &usage, err)
},
"fastAsk": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := MakeArgs(&argsIn, vm).Check(1)
_, cb := getAskArgs(args.This, vm, args.Arguments)
result, usage, err := lm.FastAsk(makeChatMessages(args.Arguments), cb)
return vm.ToValue(map[string]any{"tokenUsage": toMap(usage), "result": result, "error": getErrorStr(err)})
return makeChatResult(vm, result, &usage, err)
},
"longAsk": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := MakeArgs(&argsIn, vm).Check(1)
_, cb := getAskArgs(args.This, vm, args.Arguments)
result, usage, err := lm.LongAsk(makeChatMessages(args.Arguments), cb)
return vm.ToValue(map[string]any{"tokenUsage": toMap(usage), "result": result, "error": getErrorStr(err)})
return makeChatResult(vm, result, &usage, err)
},
"batterAsk": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := MakeArgs(&argsIn, vm).Check(1)
_, cb := getAskArgs(args.This, vm, args.Arguments)
result, usage, err := lm.BatterAsk(makeChatMessages(args.Arguments), cb)
return vm.ToValue(map[string]any{"tokenUsage": toMap(usage), "result": result, "error": getErrorStr(err)})
return makeChatResult(vm, result, &usage, err)
},
"bestAsk": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := MakeArgs(&argsIn, vm).Check(1)
_, cb := getAskArgs(args.This, vm, args.Arguments)
result, usage, err := lm.BestAsk(makeChatMessages(args.Arguments), cb)
return vm.ToValue(map[string]any{"tokenUsage": toMap(usage), "result": result, "error": getErrorStr(err)})
return makeChatResult(vm, result, &usage, err)
},
"multiAsk": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := MakeArgs(&argsIn, vm).Check(1)
_, cb := getAskArgs(args.This, vm, args.Arguments)
result, usage, err := lm.MultiAsk(makeChatMessages(args.Arguments), cb)
return vm.ToValue(map[string]any{"tokenUsage": toMap(usage), "result": result, "error": getErrorStr(err)})
return makeChatResult(vm, result, &usage, err)
},
"bestMultiAsk": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := MakeArgs(&argsIn, vm).Check(1)
_, cb := getAskArgs(args.This, vm, args.Arguments)
result, usage, err := lm.BestMultiAsk(makeChatMessages(args.Arguments), cb)
return vm.ToValue(map[string]any{"tokenUsage": toMap(usage), "result": result, "error": getErrorStr(err)})
return makeChatResult(vm, result, &usage, err)
},
"codeInterpreterAsk": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := MakeArgs(&argsIn, vm).Check(1)
_, cb := getAskArgs(args.This, vm, args.Arguments)
result, usage, err := lm.CodeInterpreterAsk(makeChatMessages(args.Arguments), cb)
return vm.ToValue(map[string]any{"tokenUsage": toMap(usage), "result": result, "error": getErrorStr(err)})
return makeChatResult(vm, result, &usage, err)
},
"webSearchAsk": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := MakeArgs(&argsIn, vm).Check(1)
_, cb := getAskArgs(args.This, vm, args.Arguments)
result, usage, err := lm.WebSearchAsk(makeChatMessages(args.Arguments), cb)
return vm.ToValue(map[string]any{"tokenUsage": toMap(usage), "result": result, "error": getErrorStr(err)})
return makeChatResult(vm, result, &usage, err)
},
"makeImage": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := MakeArgs(&argsIn, vm).Check(1)
prompt, conf := getAIGCArgs(args.Arguments)
results, err := lm.MakeImage(prompt, conf)
return makeAIGCResult(vm, results, nil, err)
prompt, conf := getGCArgs(args.Arguments)
results, usage, err := lm.MakeImage(prompt, conf)
return makeGCResult(vm, results, nil, &usage, err)
},
"fastMakeImage": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := MakeArgs(&argsIn, vm).Check(1)
prompt, conf := getAIGCArgs(args.Arguments)
results, err := lm.FastMakeImage(prompt, conf)
return makeAIGCResult(vm, results, nil, err)
prompt, conf := getGCArgs(args.Arguments)
results, usage, err := lm.FastMakeImage(prompt, conf)
return makeGCResult(vm, results, nil, &usage, err)
},
"bestMakeImage": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := MakeArgs(&argsIn, vm).Check(1)
prompt, conf := getAIGCArgs(args.Arguments)
results, err := lm.BestMakeImage(prompt, conf)
return makeAIGCResult(vm, results, nil, err)
prompt, conf := getGCArgs(args.Arguments)
results, usage, err := lm.BestMakeImage(prompt, conf)
return makeGCResult(vm, results, nil, &usage, err)
},
"makeVideo": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := MakeArgs(&argsIn, vm).Check(1)
prompt, conf := getAIGCArgs(args.Arguments)
results, previews, err := lm.MakeVideo(prompt, conf)
return makeAIGCResult(vm, results, previews, err)
prompt, conf := getGCArgs(args.Arguments)
results, previews, usage, err := lm.MakeVideo(prompt, conf)
return makeGCResult(vm, results, previews, &usage, err)
},
"fastMakeVideo": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := MakeArgs(&argsIn, vm).Check(1)
prompt, conf := getAIGCArgs(args.Arguments)
results, previews, err := lm.FastMakeVideo(prompt, conf)
return makeAIGCResult(vm, results, previews, err)
prompt, conf := getGCArgs(args.Arguments)
results, previews, usage, err := lm.FastMakeVideo(prompt, conf)
return makeGCResult(vm, results, previews, &usage, err)
},
"bestMakeVideo": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := MakeArgs(&argsIn, vm).Check(1)
prompt, conf := getAIGCArgs(args.Arguments)
results, previews, err := lm.BestMakeVideo(prompt, conf)
return makeAIGCResult(vm, results, previews, err)
prompt, conf := getGCArgs(args.Arguments)
results, previews, usage, err := lm.BestMakeVideo(prompt, conf)
return makeGCResult(vm, results, previews, &usage, err)
},
"embedding": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := MakeArgs(&argsIn, vm).Check(2)
results, usage, err := lm.Embedding(args.Str(0), args.Str(1))
return makeEmbeddingResult(vm, results, &usage, err)
},
"fastEmbedding": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := MakeArgs(&argsIn, vm).Check(1)
results, usage, err := lm.FastEmbedding(args.Str(0))
return makeEmbeddingResult(vm, results, &usage, err)
},
"bestEmbedding": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := MakeArgs(&argsIn, vm).Check(1)
results, usage, err := lm.BestEmbedding(args.Str(0))
return makeEmbeddingResult(vm, results, &usage, err)
},
"support": lm.Support(),
@ -130,7 +145,36 @@ func getErrorStr(err error) string {
return ""
}
func makeAIGCResult(vm *goja.Runtime, results []string, previews []string, err error) goja.Value {
func makeChatResult(vm *goja.Runtime, result string, usage *llm.Usage, err error) goja.Value {
if err != nil {
panic(vm.NewGoError(err))
}
return vm.ToValue(map[string]any{
"result": result,
"askTokens": usage.AskTokens,
"answerTokens": usage.AnswerTokens,
"totalTokens": usage.TotalTokens,
"usedTime": usage.UsedTime,
})
}
func makeEmbeddingResult(vm *goja.Runtime, result []byte, usage *llm.Usage, err error) goja.Value {
if err != nil {
panic(vm.NewGoError(err))
}
return vm.ToValue(map[string]any{
"result": result,
"askTokens": usage.AskTokens,
"answerTokens": usage.AnswerTokens,
"totalTokens": usage.TotalTokens,
"usedTime": usage.UsedTime,
})
}
func makeGCResult(vm *goja.Runtime, results []string, previews []string, usage *llm.Usage, err error) goja.Value {
if err != nil {
panic(vm.NewGoError(err))
}
result := ""
preview := ""
if len(results) > 0 {
@ -148,11 +192,11 @@ func makeAIGCResult(vm *goja.Runtime, results []string, previews []string, err e
"preview": preview,
"results": results,
"previews": previews,
"error": getErrorStr(err),
"usedTime": usage.UsedTime,
})
}
func getAIGCArgs(args []goja.Value) (string, llm.GCConfig) {
func getGCArgs(args []goja.Value) (string, llm.GCConfig) {
prompt := ""
var config llm.GCConfig
if len(args) > 0 {
@ -173,7 +217,7 @@ func getAskArgs(thisArg goja.Value, vm *goja.Runtime, args []goja.Value) (llm.Ch
callback = func(answer string) {
_, _ = cb(thisArg, vm.ToValue(answer))
}
} else {
} else if args[i].ExportType() != nil {
switch args[i].ExportType().Kind() {
case reflect.Map, reflect.Struct:
u.Convert(args[i].Export(), &chatConfig)
@ -192,6 +236,7 @@ func makeChatMessages(args []goja.Value) []llm.ChatMessage {
v := args[0].Export()
vv := reflect.ValueOf(v)
t := args[0].ExportType()
if t != nil {
lastRoleIsUser := false
switch t.Kind() {
// 数组,根据成员类型处理
@ -260,6 +305,7 @@ func makeChatMessages(args []goja.Value) []llm.ChatMessage {
out = append(out, llm.ChatMessage{Role: llm.RoleUser, Contents: []llm.ChatMessageContent{makeChatMessageContent(u.String(v))}})
}
}
}
return out
}

View File

@ -7,9 +7,9 @@ import (
"path/filepath"
)
func toMap(data any) map[string]any {
return u.UnJsonMap(u.FixedJson(data))
}
//func toMap(data any) map[string]any {
// return u.UnJsonMap(u.FixedJson(data))
//}
type Args struct {
This goja.Value
@ -39,6 +39,13 @@ func (args *Args) Int(index int) int {
return 0
}
func (args *Args) Int64(index int) int64 {
if len(args.Arguments) > index {
return u.Int64(args.Arguments[index].Export())
}
return 0
}
func (args *Args) Any(index int) any {
if len(args.Arguments) > index {
return args.Arguments[index].Export()
@ -53,6 +60,20 @@ func (args *Args) Str(index int) string {
return ""
}
func (args *Args) Bytes(index int) []byte {
if len(args.Arguments) > index {
return u.Bytes(args.Arguments[index].Export())
}
return []byte{}
}
func (args *Args) Bool(index int) bool {
if len(args.Arguments) > index {
return u.Bool(args.Arguments[index].Export())
}
return false
}
func (args *Args) Map(index int) map[string]any {
out := map[string]any{}
if len(args.Arguments) > index {
@ -72,6 +93,17 @@ func (args *Args) StrArr(startIndex int) []string {
return make([]string, 0)
}
func (args *Args) Arr(startIndex int) []any {
if len(args.Arguments) > startIndex {
a := make([]any, len(args.Arguments)-startIndex)
for index := startIndex; index < len(args.Arguments); index++ {
a[index-startIndex] = u.String(args.Arguments[index].Export())
}
return a
}
return make([]any, 0)
}
func (args *Args) Map2StrArr(index int) []string {
headerMap := args.Map(index)
headers := make([]string, len(headerMap)*2)
@ -84,6 +116,18 @@ func (args *Args) Map2StrArr(index int) []string {
return headers
}
func (args *Args) Map2Arr(index int) []any {
arrMap := args.Map(index)
arr := make([]any, len(arrMap)*2)
i := 0
for k, v := range arrMap {
arr[i] = k
arr[i+1] = u.String(v)
i += 2
}
return arr
}
func findPath(vm *goja.Runtime, filename string) string {
if u.FileExists(filename) {
return filename
@ -99,3 +143,7 @@ func findPath(vm *goja.Runtime, filename string) string {
}
return filename
}
func (args *Args) Path(index int) string {
return findPath(args.VM, args.Str(index))
}

View File

@ -4,6 +4,7 @@ import (
"apigo.cc/ai/ai/goja"
"fmt"
"github.com/ssgo/u"
"reflect"
"strings"
)
@ -43,19 +44,106 @@ func RequireConsole() map[string]any {
_, _ = fmt.Scanln(&line)
return vm.ToValue(line)
},
"black": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := MakeArgs(&argsIn, vm)
return vm.ToValue(u.Black(fmt.Sprint(args.Arr(0)...)))
},
"red": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := MakeArgs(&argsIn, vm)
return vm.ToValue(u.Red(fmt.Sprint(args.Arr(0)...)))
},
"green": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := MakeArgs(&argsIn, vm)
return vm.ToValue(u.Green(fmt.Sprint(args.Arr(0)...)))
},
"yellow": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := MakeArgs(&argsIn, vm)
return vm.ToValue(u.Yellow(fmt.Sprint(args.Arr(0)...)))
},
"blue": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := MakeArgs(&argsIn, vm)
return vm.ToValue(u.Blue(fmt.Sprint(args.Arr(0)...)))
},
"magenta": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := MakeArgs(&argsIn, vm)
return vm.ToValue(u.Magenta(fmt.Sprint(args.Arr(0)...)))
},
"cyan": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := MakeArgs(&argsIn, vm)
return vm.ToValue(u.Cyan(fmt.Sprint(args.Arr(0)...)))
},
"white": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := MakeArgs(&argsIn, vm)
return vm.ToValue(u.White(fmt.Sprint(args.Arr(0)...)))
},
"dim": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := MakeArgs(&argsIn, vm)
return vm.ToValue(u.Dim(fmt.Sprint(args.Arr(0)...)))
},
"italic": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := MakeArgs(&argsIn, vm)
return vm.ToValue(u.Italic(fmt.Sprint(args.Arr(0)...)))
},
"bBlack": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := MakeArgs(&argsIn, vm)
return vm.ToValue(u.BBlack(fmt.Sprint(args.Arr(0)...)))
},
"bRed": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := MakeArgs(&argsIn, vm)
return vm.ToValue(u.BRed(fmt.Sprint(args.Arr(0)...)))
},
"bGreen": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := MakeArgs(&argsIn, vm)
return vm.ToValue(u.BGreen(fmt.Sprint(args.Arr(0)...)))
},
"bYellow": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := MakeArgs(&argsIn, vm)
return vm.ToValue(u.BYellow(fmt.Sprint(args.Arr(0)...)))
},
"bBlue": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := MakeArgs(&argsIn, vm)
return vm.ToValue(u.BBlue(fmt.Sprint(args.Arr(0)...)))
},
"bMagenta": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := MakeArgs(&argsIn, vm)
return vm.ToValue(u.BMagenta(fmt.Sprint(args.Arr(0)...)))
},
"bCyan": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := MakeArgs(&argsIn, vm)
return vm.ToValue(u.BCyan(fmt.Sprint(args.Arr(0)...)))
},
"bWhite": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := MakeArgs(&argsIn, vm)
return vm.ToValue(u.BWhite(fmt.Sprint(args.Arr(0)...)))
},
}
}
func consolePrint(args goja.FunctionCall, typ string, vm *goja.Runtime) {
arr := make([]any, len(args.Arguments))
textColor := u.TextNone
bgColor := u.BgNone
switch typ {
case "info":
textColor = u.TextCyan
bgColor = u.BgCyan
case "warn":
textColor = u.TextYellow
bgColor = u.BgYellow
case "error":
textColor = u.TextRed
bgColor = u.BgRed
}
if len(args.Arguments) == 1 && args.Argument(0).ExportType().Kind() == reflect.Map {
ex := args.Argument(0).ToObject(vm)
message := ex.Get("message")
stack := ex.Get("stack")
if message != nil && stack != nil {
fmt.Println(u.Color(u.String(message.Export()), textColor, u.BgNone))
fmt.Println(u.Color(u.String(stack.Export()), u.TextWhite, bgColor))
return
}
}
for i, arg := range args.Arguments {
@ -69,7 +157,7 @@ func consolePrint(args goja.FunctionCall, typ string, vm *goja.Runtime) {
if (typ == "warn" || typ == "error" || typ == "debug") && vm != nil {
callStacks := make([]string, 0)
for _, stack := range vm.CaptureCallStack(0, nil) {
callStacks = append(callStacks, u.Color(" "+stack.Position().String(), textColor, u.BgNone))
callStacks = append(callStacks, u.Color(" "+stack.Position().String(), u.TextWhite, bgColor))
}
fmt.Println(arr...)
fmt.Println(strings.Join(callStacks, "\n"))

214
js/db.go Normal file
View File

@ -0,0 +1,214 @@
package js
import (
"apigo.cc/ai/ai/goja"
"github.com/ssgo/dao/dao"
"github.com/ssgo/db"
"github.com/ssgo/log"
"github.com/ssgo/u"
)
func RequireDB() map[string]any {
return map[string]any{
"get": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := MakeArgs(&argsIn, vm).Check(1)
conn := db.GetDB(args.Str(0), getLogger(vm))
return vm.ToValue(makeDBObject(conn, nil, vm))
},
}
}
func makeDBObject(conn *db.DB, tx *db.Tx, vm *goja.Runtime) map[string]any {
obj := map[string]any{
"conn": conn,
"tx": tx,
"query": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args, conn, tx, _ := initDBArgs(argsIn, vm, 1)
var r *db.QueryResult
if tx != nil {
r = tx.Query(args.Str(0), args.Arr(1)...)
} else {
r = conn.Query(args.Str(0), args.Arr(1)...)
}
if r.Error == nil {
return vm.ToValue(makeQueryResult(r, r.MapResults()))
} else {
panic(vm.NewGoError(r.Error))
}
},
"query1": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args, conn, tx, _ := initDBArgs(argsIn, vm, 1)
var r *db.QueryResult
if tx != nil {
r = tx.Query(args.Str(0), args.Arr(1)...)
} else {
r = conn.Query(args.Str(0), args.Arr(1)...)
}
if r.Error == nil {
return vm.ToValue(makeQueryResult(r, r.MapOnR1()))
} else {
panic(vm.NewGoError(r.Error))
}
},
"query11": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args, conn, tx, _ := initDBArgs(argsIn, vm, 1)
var r *db.QueryResult
if tx != nil {
r = tx.Query(args.Str(0), args.Arr(1)...)
} else {
r = conn.Query(args.Str(0), args.Arr(1)...)
}
if r.Error == nil {
a := r.SliceResults()
if len(a) > 0 && len(a[0]) > 0 {
return vm.ToValue(makeQueryResult(r, a[0][0]))
}
return vm.ToValue(nil)
} else {
panic(vm.NewGoError(r.Error))
}
},
"exec": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args, conn, tx, _ := initDBArgs(argsIn, vm, 1)
var r *db.ExecResult
if tx != nil {
r = tx.Exec(args.Str(0), args.Arr(1)...)
} else {
r = conn.Exec(args.Str(0), args.Arr(1)...)
}
if r.Error == nil {
return vm.ToValue(makeExecResult(r))
} else {
panic(vm.NewGoError(r.Error))
}
},
"insert": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args, conn, tx, _ := initDBArgs(argsIn, vm, 2)
var r *db.ExecResult
if tx != nil {
r = tx.Insert(args.Str(0), args.Any(1))
} else {
r = conn.Insert(args.Str(0), args.Any(1))
}
if r.Error == nil {
return vm.ToValue(makeExecResult(r))
} else {
panic(vm.NewGoError(r.Error))
}
},
"replace": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args, conn, tx, _ := initDBArgs(argsIn, vm, 2)
var r *db.ExecResult
if tx != nil {
r = tx.Replace(args.Str(0), args.Any(1))
} else {
r = conn.Replace(args.Str(0), args.Any(1))
}
if r.Error == nil {
return vm.ToValue(makeExecResult(r))
} else {
panic(vm.NewGoError(r.Error))
}
},
"update": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args, conn, tx, _ := initDBArgs(argsIn, vm, 3)
var r *db.ExecResult
if tx != nil {
r = tx.Update(args.Str(0), args.Any(1), args.Str(2), args.Arr(3)...)
} else {
r = conn.Update(args.Str(0), args.Any(1), args.Str(2), args.Arr(3)...)
}
if r.Error == nil {
return vm.ToValue(makeExecResult(r))
} else {
panic(vm.NewGoError(r.Error))
}
},
"delete": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args, conn, tx, _ := initDBArgs(argsIn, vm, 2)
var r *db.ExecResult
if tx != nil {
r = tx.Delete(args.Str(0), args.Str(1), args.Arr(2)...)
} else {
r = conn.Delete(args.Str(0), args.Str(1), args.Arr(2)...)
}
if r.Error == nil {
return vm.ToValue(makeExecResult(r))
} else {
panic(vm.NewGoError(r.Error))
}
},
}
if conn != nil {
obj["make"] = func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args, conn, _, logger := initDBArgs(argsIn, vm, 1)
arg0 := args.Str(0)
tryFile := findPath(vm, arg0)
if u.FileExists(tryFile) {
arg0 = u.ReadFileN(tryFile)
}
if err := dao.MakeDBFromDesc(conn, args.Str(0), logger); err == nil {
return nil
} else {
panic(vm.NewGoError(err))
}
}
obj["destroy"] = func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
_, conn, _, _ := initDBArgs(argsIn, vm, 0)
if err := conn.Destroy(); err == nil {
return nil
} else {
panic(vm.NewGoError(err))
}
}
obj["begin"] = func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
_, conn, _, _ := initDBArgs(argsIn, vm, 0)
return vm.ToValue(makeDBObject(nil, conn.Begin(), vm))
}
}
if tx != nil {
obj["end"] = func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args, _, tx, _ := initDBArgs(argsIn, vm, 1)
if err := tx.Finish(args.Bool(0)); err != nil {
panic(vm.NewGoError(err))
}
return nil
}
}
return obj
}
func makeQueryResult(r *db.QueryResult, result any) map[string]any {
return map[string]any{
"sql": *r.Sql,
"args": r.Args,
"result": result,
}
}
func makeExecResult(r *db.ExecResult) map[string]any {
return map[string]any{
"sql": *r.Sql,
"args": r.Args,
"id": r.Id(),
"changes": r.Changes(),
}
}
func initDBArgs(argsIn goja.FunctionCall, vm *goja.Runtime, checkArgsNum int) (*Args, *db.DB, *db.Tx, *log.Logger) {
args := MakeArgs(&argsIn, vm).Check(checkArgsNum)
logger := getLogger(vm)
conn, _ := args.This.ToObject(vm).Get("conn").Export().(*db.DB)
//if !connOk {
// panic(vm.NewGoError(errors.New("this is not a db object")))
//}
var tx *db.Tx
if conn == nil {
tx, _ = args.This.ToObject(vm).Get("tx").Export().(*db.Tx)
}
return args, conn, tx, logger
}

View File

@ -3,13 +3,14 @@ package js
import (
"apigo.cc/ai/ai/goja"
"github.com/ssgo/u"
"os"
)
func RequireFile() map[string]any {
return map[string]any{
"read": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := MakeArgs(&argsIn, vm).Check(1)
if r, err := u.ReadFile(findPath(vm, args.Str(0))); err == nil {
if r, err := u.ReadFile(args.Path(0)); err == nil {
return vm.ToValue(r)
} else {
panic(vm.NewGoError(err))
@ -17,7 +18,7 @@ func RequireFile() map[string]any {
},
"write": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := MakeArgs(&argsIn, vm).Check(2)
if err := u.WriteFileBytes(findPath(vm, args.Str(0)), u.Bytes(args.Any(0))); err == nil {
if err := u.WriteFileBytes(args.Path(0), u.Bytes(args.Any(0))); err == nil {
return nil
} else {
panic(vm.NewGoError(err))
@ -25,19 +26,49 @@ func RequireFile() map[string]any {
},
"dir": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := MakeArgs(&argsIn, vm).Check(1)
if r, err := u.ReadDir(findPath(vm, args.Str(0))); err == nil {
return vm.ToValue(r)
if r, err := u.ReadDir(args.Path(0)); err == nil {
list := make([]map[string]any, len(r))
for i, info := range r {
list[i] = makeFileInfo(&info)
}
return vm.ToValue(list)
} else {
panic(vm.NewGoError(err))
}
},
"stat": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := MakeArgs(&argsIn, vm).Check(1)
return vm.ToValue(u.GetFileInfo(findPath(vm, args.Str(0))))
return vm.ToValue(makeFileInfo(u.GetFileInfo(args.Path(0))))
},
"find": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := MakeArgs(&argsIn, vm).Check(1)
return vm.ToValue(findPath(vm, args.Str(0)))
return vm.ToValue(args.Path(0))
},
"remove": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := MakeArgs(&argsIn, vm).Check(1)
if err := os.RemoveAll(args.Path(0)); err == nil {
return nil
} else {
panic(vm.NewGoError(err))
}
},
"copy": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := MakeArgs(&argsIn, vm).Check(2)
if err := u.CopyFile(args.Path(0), args.Path(1)); err == nil {
return nil
} else {
panic(vm.NewGoError(err))
}
},
}
}
func makeFileInfo(info *u.FileInfo) map[string]any {
return map[string]any{
"name": info.Name,
"size": info.Size,
"fullName": info.FullName,
"isDir": info.IsDir,
"modTime": info.ModTime.UnixMilli(),
}
}

View File

@ -5,11 +5,14 @@ let {{.}}: LLM
{{- end}}
export default {
similarity,
{{- range .LLMList}}
{{.}},
{{- end}}
}
function similarity(a: any, b: any): number{return 0}
interface ChatConfig {
model: string
ratio: number
@ -24,7 +27,7 @@ interface ChatResult {
askTokens: number
answerTokens: number
totalTokens: number
error: string
usedTime: number
}
interface GCConfig {
@ -38,7 +41,15 @@ interface GCResult {
preview: string
results: Array<string>
previews: Array<string>
error: string
usedTime: number
}
interface EmbeddingResult {
result: string
askTokens: number
answerTokens: number
totalTokens: number
usedTime: number
}
interface Support {
@ -68,5 +79,8 @@ interface LLM {
makeVideo(prompt: string, config?: GCConfig): GCResult
fastMakeVideo(prompt: string, config?: GCConfig): GCResult
bestMakeVideo(prompt: string, config?: GCConfig): GCResult
embedding(text: string, model: string): EmbeddingResult
fastEmbedding(text: string): EmbeddingResult
bestEmbedding(text: string): EmbeddingResult
support: Support
}

View File

@ -9,6 +9,24 @@ export default {
warn,
error,
input,
black,
red,
green,
yellow,
blue,
magenta,
cyan,
white,
dim,
italic,
bBlack,
bRed,
bGreen,
bYellow,
bBlue,
bMagenta,
bCyan,
bWhite,
}
function print(...data: any[]): void {}
@ -19,3 +37,22 @@ function info(...data: any[]): void {}
function warn(...data: any[]): void {}
function error(...data: any[]): void {}
function input(...data: any[]): string {return ''}
function black(...data: any[]): string {return ''}
function red(...data: any[]): string {return ''}
function green(...data: any[]): string {return ''}
function yellow(...data: any[]): string {return ''}
function blue(...data: any[]): string {return ''}
function magenta(...data: any[]): string {return ''}
function cyan(...data: any[]): string {return ''}
function white(...data: any[]): string {return ''}
function dim(...data: any[]): string {return ''}
function italic(...data: any[]): string {return ''}
function bBlack(...data: any[]): string {return ''}
function bRed(...data: any[]): string {return ''}
function bGreen(...data: any[]): string {return ''}
function bYellow(...data: any[]): string {return ''}
function bBlue(...data: any[]): string {return ''}
function bMagenta(...data: any[]): string {return ''}
function bCyan(...data: any[]): string {return ''}
function bWhite(...data: any[]): string {return ''}

58
js/lib/db.ts Normal file
View File

@ -0,0 +1,58 @@
// just for develop
export default {
get,
}
function get(dbName: string): DB {return null}
interface DB {
make(descFileOrContent: string): Array<Object>
query(sql: string, ...args:any): QueryResult
query1(sql: string, ...args:any): QueryResult1
query11(sql: string, ...args:any): QueryResult11
exec(sql: string, ...args:any): ExecResult
insert(table: string, data:Object): ExecResult
replace(table: string, data:Object): ExecResult
update(table: string, data:Object, where: string, ...args:any): ExecResult
delete(table: string, where: string, ...args:any): ExecResult
destroy(): void
begin(): Tx
}
interface Tx {
query(sql: string, ...args:any): QueryResult
query1(sql: string, ...args:any): QueryResult1
query11(sql: string, ...args:any): QueryResult11
exec(sql: string, ...args:any): ExecResult
insert(table: string, data:Object): ExecResult
replace(table: string, data:Object): ExecResult
update(table: string, data:Object, where: string, ...args:any): ExecResult
delete(table: string, where: string, ...args:any): ExecResult
end(ok:boolean): void
}
interface QueryResult {
sql: string
args: Array<any>
result: Array<Object>
}
interface QueryResult1 {
sql: string
args: Array<any>
result: Object
}
interface QueryResult11 {
sql: string
args: Array<any>
result: any
}
interface ExecResult {
sql: string
args: Array<any>
id: number
changes: number
}

View File

@ -4,7 +4,10 @@ export default {
read,
write,
dir,
stat
stat,
find,
remove,
copy
}
function read(filename: string): string {return ''}
@ -12,11 +15,13 @@ function write(filename: string, data: any): void {}
function dir(filename: string): Array<FileInfo> {return null}
function stat(filename: string): FileInfo {return null}
function find(filename: string): string {return ''}
function remove(filename: string): void {}
function copy(from: string, to: string): void {}
interface FileInfo {
Name: string
FullName: string
IsDir: boolean
Size: number
ModTime: number
name: string
fullName: string
isDir: boolean
size: number
modTime: number
}

13
js/lib/log.ts Normal file
View File

@ -0,0 +1,13 @@
// just for develop
export default {
debug,
info,
warn,
error,
}
function debug(message:string, info?:Object): void {}
function info(message:string, info?:Object): void {}
function warn(message:string, info?:Object): void {}
function error(message:string, info?:Object): void {}

View File

@ -6,6 +6,8 @@ export default {
unJson,
yaml,
unYaml,
load,
save,
base64,
unBase64,
urlBase64,
@ -24,7 +26,11 @@ export default {
sha256,
sha512,
tpl,
shell
shell,
toDatetime,
fromDatetime,
toDate,
fromDate
}
function json(data:any): string {return ''}
@ -32,6 +38,8 @@ function jsonP(data:any): string {return ''}
function unJson(data:string): any {return null}
function yaml(data:any): string {return ''}
function unYaml(data:string): any {return null}
function load(filename:string): any {return null}
function save(filename:string, data:any) {}
function base64(data:any): string {return ''}
function unBase64(data:string): any {return null}
function urlBase64(data:any): string {return ''}
@ -51,3 +59,7 @@ function sha256(data:any): string {return ''}
function sha512(data:any): string {return ''}
function tpl(text:string, data:any, functions?:Object): string {return ''}
function shell(cmd:string, ...args:string[]): string[] {return []}
function toDatetime(timestamp:number): string {return ''}
function fromDatetime(datetimeStr:string): number {return 0}
function toDate(timestamp:number): string {return ''}
function fromDate(dateStr:string): number {return 0}

40
js/log.go Normal file
View File

@ -0,0 +1,40 @@
package js
import (
"apigo.cc/ai/ai/goja"
"github.com/ssgo/log"
)
func RequireLog() map[string]any {
return map[string]any{
"info": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := MakeArgs(&argsIn, vm).Check(1)
getLogger(vm).Info(args.Str(0), args.Map2Arr(1)...)
return nil
},
"warn": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := MakeArgs(&argsIn, vm).Check(1)
getLogger(vm).Warning(args.Str(0), args.Map2Arr(1)...)
return nil
},
"error": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := MakeArgs(&argsIn, vm).Check(1)
getLogger(vm).Error(args.Str(0), args.Map2Arr(1)...)
return nil
},
"debug": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := MakeArgs(&argsIn, vm).Check(1)
getLogger(vm).Debug(args.Str(0), args.Map2Arr(1)...)
return nil
},
}
}
func getLogger(vm *goja.Runtime) *log.Logger {
if vm.GoData["logger"] != nil {
if logger, ok := vm.GoData["logger"].(*log.Logger); ok {
return logger
}
}
return log.DefaultLogger
}

View File

@ -9,6 +9,7 @@ import (
"gopkg.in/yaml.v3"
"strings"
"text/template"
"time"
)
func RequireUtil() map[string]any {
@ -104,7 +105,7 @@ func RequireUtil() map[string]any {
},
"unBase64": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := MakeArgs(&argsIn, vm).Check(1)
return vm.ToValue(u.UnBase64String(args.Str(0)))
return vm.ToValue(u.UnBase64(args.Str(0)))
},
"urlBase64": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := MakeArgs(&argsIn, vm).Check(1)
@ -112,7 +113,7 @@ func RequireUtil() map[string]any {
},
"unUrlBase64": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := MakeArgs(&argsIn, vm).Check(1)
return vm.ToValue(u.UnUrlBase64String(args.Str(0)))
return vm.ToValue(u.UnUrlBase64(args.Str(0)))
},
"hex": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := MakeArgs(&argsIn, vm).Check(1)
@ -121,7 +122,7 @@ func RequireUtil() map[string]any {
"unHex": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := MakeArgs(&argsIn, vm).Check(1)
if r, err := hex.DecodeString(args.Str(0)); err == nil {
return vm.ToValue(string(r))
return vm.ToValue(r)
} else {
panic(vm.NewGoError(err))
}
@ -129,7 +130,7 @@ func RequireUtil() map[string]any {
"aes": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := MakeArgs(&argsIn, vm).Check(3)
if r, err := u.EncryptAesBytes(u.Bytes(args.Arguments[0].Export()), u.Bytes(args.Arguments[1].Export()), u.Bytes(args.Arguments[2].Export())); err == nil {
return vm.ToValue(string(r))
return vm.ToValue(r)
} else {
panic(vm.NewGoError(err))
}
@ -137,7 +138,7 @@ func RequireUtil() map[string]any {
"unAes": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := MakeArgs(&argsIn, vm).Check(3)
if r, err := u.DecryptAesBytes(u.Bytes(args.Arguments[0].Export()), u.Bytes(args.Arguments[1].Export()), u.Bytes(args.Arguments[2].Export())); err == nil {
return vm.ToValue(string(r))
return vm.ToValue(r)
} else {
panic(vm.NewGoError(err))
}
@ -145,7 +146,7 @@ func RequireUtil() map[string]any {
"gzip": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := MakeArgs(&argsIn, vm).Check(1)
if r, err := u.Gzip(u.Bytes(args.Arguments[0].Export())); err == nil {
return vm.ToValue(string(r))
return vm.ToValue(r)
} else {
panic(vm.NewGoError(err))
}
@ -153,7 +154,7 @@ func RequireUtil() map[string]any {
"gunzip": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := MakeArgs(&argsIn, vm).Check(1)
if r, err := u.Gunzip(u.Bytes(args.Arguments[0].Export())); err == nil {
return vm.ToValue(string(r))
return vm.ToValue(r)
} else {
panic(vm.NewGoError(err))
}
@ -232,5 +233,40 @@ func RequireUtil() map[string]any {
panic(vm.NewGoError(err))
}
},
"toDatetime": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := MakeArgs(&argsIn, vm).Check(1)
return vm.ToValue(time.UnixMilli(args.Int64(0)).Format("2006-01-02 15:04:05"))
},
"fromDatetime": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := MakeArgs(&argsIn, vm).Check(1)
timeStr := args.Str(0)
if len(timeStr) > 19 {
timeStr = timeStr[0:19]
}
if strings.ContainsRune(timeStr, 'T') {
timeStr = strings.ReplaceAll(timeStr, "T", " ")
}
if tm, err := time.ParseInLocation("2006-01-02 15:04:05", timeStr, time.Local); err == nil {
return vm.ToValue(tm.UnixMilli())
} else {
panic(vm.NewGoError(err))
}
},
"toDate": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := MakeArgs(&argsIn, vm).Check(1)
return vm.ToValue(time.UnixMilli(args.Int64(0)).Format("2006-01-02"))
},
"fromDate": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := MakeArgs(&argsIn, vm).Check(1)
timeStr := args.Str(0)
if len(timeStr) > 10 {
timeStr = timeStr[0:10]
}
if tm, err := time.ParseInLocation("2006-01-02", timeStr, time.Local); err == nil {
return vm.ToValue(tm.UnixMilli())
} else {
panic(vm.NewGoError(err))
}
},
}
}

View File

@ -1,64 +1,68 @@
package openai
import (
"apigo.cc/ai/ai/llm"
"apigo.cc/ai/ai/interface/llm"
"bytes"
"context"
"encoding/binary"
"fmt"
"github.com/sashabaranov/go-openai"
"github.com/ssgo/log"
"strings"
"time"
)
func (lm *LLM) FastAsk(messages []llm.ChatMessage, callback func(answer string)) (string, llm.TokenUsage, error) {
func (lm *LLM) FastAsk(messages []llm.ChatMessage, callback func(answer string)) (string, llm.Usage, error) {
return lm.Ask(messages, llm.ChatConfig{
Model: ModelGPT_4o_mini_2024_07_18,
}, callback)
}
func (lm *LLM) LongAsk(messages []llm.ChatMessage, callback func(answer string)) (string, llm.TokenUsage, error) {
func (lm *LLM) LongAsk(messages []llm.ChatMessage, callback func(answer string)) (string, llm.Usage, error) {
return lm.Ask(messages, llm.ChatConfig{
Model: ModelGPT_4_32k_0613,
}, callback)
}
func (lm *LLM) BatterAsk(messages []llm.ChatMessage, callback func(answer string)) (string, llm.TokenUsage, error) {
func (lm *LLM) BatterAsk(messages []llm.ChatMessage, callback func(answer string)) (string, llm.Usage, error) {
return lm.Ask(messages, llm.ChatConfig{
Model: ModelGPT_4_turbo,
}, callback)
}
func (lm *LLM) BestAsk(messages []llm.ChatMessage, callback func(answer string)) (string, llm.TokenUsage, error) {
func (lm *LLM) BestAsk(messages []llm.ChatMessage, callback func(answer string)) (string, llm.Usage, error) {
return lm.Ask(messages, llm.ChatConfig{
Model: ModelGPT_4o_2024_08_06,
}, callback)
}
func (lm *LLM) MultiAsk(messages []llm.ChatMessage, callback func(answer string)) (string, llm.TokenUsage, error) {
func (lm *LLM) MultiAsk(messages []llm.ChatMessage, callback func(answer string)) (string, llm.Usage, error) {
return lm.Ask(messages, llm.ChatConfig{
Model: ModelGPT_4o_mini_2024_07_18,
}, callback)
}
func (lm *LLM) BestMultiAsk(messages []llm.ChatMessage, callback func(answer string)) (string, llm.TokenUsage, error) {
func (lm *LLM) BestMultiAsk(messages []llm.ChatMessage, callback func(answer string)) (string, llm.Usage, error) {
return lm.Ask(messages, llm.ChatConfig{
Model: ModelGPT_4o_2024_08_06,
}, callback)
}
func (lm *LLM) CodeInterpreterAsk(messages []llm.ChatMessage, callback func(answer string)) (string, llm.TokenUsage, error) {
func (lm *LLM) CodeInterpreterAsk(messages []llm.ChatMessage, callback func(answer string)) (string, llm.Usage, error) {
return lm.Ask(messages, llm.ChatConfig{
Model: ModelGPT_4o,
Tools: map[string]any{llm.ToolCodeInterpreter: nil},
}, callback)
}
func (lm *LLM) WebSearchAsk(messages []llm.ChatMessage, callback func(answer string)) (string, llm.TokenUsage, error) {
func (lm *LLM) WebSearchAsk(messages []llm.ChatMessage, callback func(answer string)) (string, llm.Usage, error) {
return lm.Ask(messages, llm.ChatConfig{
Model: ModelGPT_4o_mini_2024_07_18,
Tools: map[string]any{llm.ToolWebSearch: nil},
}, callback)
}
func (lm *LLM) Ask(messages []llm.ChatMessage, config llm.ChatConfig, callback func(answer string)) (string, llm.TokenUsage, error) {
func (lm *LLM) Ask(messages []llm.ChatMessage, config llm.ChatConfig, callback func(answer string)) (string, llm.Usage, error) {
openaiConf := openai.DefaultConfig(lm.config.ApiKey)
if lm.config.Endpoint != "" {
openaiConf.BaseURL = lm.config.Endpoint
@ -124,7 +128,7 @@ func (lm *LLM) Ask(messages []llm.ChatMessage, config llm.ChatConfig, callback f
r, err := c.CreateChatCompletionStream(context.Background(), opt)
if err == nil {
results := make([]string, 0)
usage := llm.TokenUsage{}
usage := llm.Usage{}
for {
if r2, err := r.Recv(); err == nil {
if r2.Choices != nil {
@ -147,26 +151,75 @@ func (lm *LLM) Ask(messages []llm.ChatMessage, config llm.ChatConfig, callback f
return strings.Join(results, ""), usage, nil
} else {
log.DefaultLogger.Error(err.Error())
return "", llm.TokenUsage{}, err
return "", llm.Usage{}, err
}
} else {
r, err := c.CreateChatCompletion(context.Background(), opt)
if err == nil {
t1 := time.Now().UnixMilli()
if r, err := c.CreateChatCompletion(context.Background(), opt); err == nil {
t2 := time.Now().UnixMilli() - t1
results := make([]string, 0)
if r.Choices != nil {
for _, ch := range r.Choices {
results = append(results, ch.Message.Content)
}
}
return strings.Join(results, ""), llm.TokenUsage{
return strings.Join(results, ""), llm.Usage{
AskTokens: int64(r.Usage.PromptTokens),
AnswerTokens: int64(r.Usage.CompletionTokens),
TotalTokens: int64(r.Usage.TotalTokens),
UsedTime: t2,
}, nil
} else {
//fmt.Println(u.BMagenta(err.Error()), u.BMagenta(u.JsonP(r)))
return "", llm.TokenUsage{}, err
return "", llm.Usage{}, err
}
}
}
func (lm *LLM) FastEmbedding(text string) ([]byte, llm.Usage, error) {
return lm.Embedding(text, string(openai.AdaEmbeddingV2))
}
func (lm *LLM) BestEmbedding(text string) ([]byte, llm.Usage, error) {
return lm.Embedding(text, string(openai.LargeEmbedding3))
}
func (lm *LLM) Embedding(text, model string) ([]byte, llm.Usage, error) {
fmt.Println(111, model, text)
openaiConf := openai.DefaultConfig(lm.config.ApiKey)
if lm.config.Endpoint != "" {
openaiConf.BaseURL = lm.config.Endpoint
}
c := openai.NewClientWithConfig(openaiConf)
req := openai.EmbeddingRequest{
Input: text,
Model: openai.EmbeddingModel(model),
User: "",
EncodingFormat: "",
Dimensions: 0,
}
t1 := time.Now().UnixMilli()
if r, err := c.CreateEmbeddings(context.Background(), req); err == nil {
t2 := time.Now().UnixMilli() - t1
buf := new(bytes.Buffer)
if r.Data != nil {
for _, ch := range r.Data {
for _, v := range ch.Embedding {
_ = binary.Write(buf, binary.LittleEndian, v)
}
}
}
fmt.Println(len(buf.Bytes()))
return buf.Bytes(), llm.Usage{
AskTokens: int64(r.Usage.PromptTokens),
AnswerTokens: int64(r.Usage.CompletionTokens),
TotalTokens: int64(r.Usage.TotalTokens),
UsedTime: t2,
}, nil
} else {
fmt.Println(err.Error())
return nil, llm.Usage{}, err
}
}

View File

@ -1,7 +1,7 @@
package openai
import (
"apigo.cc/ai/ai/llm"
"apigo.cc/ai/ai/interface/llm"
"github.com/sashabaranov/go-openai"
)

View File

@ -1,32 +1,33 @@
package openai
import (
"apigo.cc/ai/ai/llm"
"apigo.cc/ai/ai/interface/llm"
"context"
"github.com/sashabaranov/go-openai"
"strings"
"time"
)
// func (lm *LLM) FastMakeImage(prompt, size, refImage string) ([]string, error) {
// func (lm *LLM) FastMakeImage(prompt, size, refImage string) ([]string, llm.Usage, error) {
// return lm.MakeImage(ModelDallE3Std, prompt, size, refImage)
// }
//
// func (lm *LLM) BestMakeImage(prompt, size, refImage string) ([]string, error) {
// func (lm *LLM) BestMakeImage(prompt, size, refImage string) ([]string, llm.Usage, error) {
// return lm.MakeImage(ModelDallE3HD, prompt, size, refImage)
// }
//
// func (lm *LLM) MakeImage(model, prompt, size, refImage string) ([]string, error) {
func (lm *LLM) FastMakeImage(prompt string, config llm.GCConfig) ([]string, error) {
// func (lm *LLM) MakeImage(model, prompt, size, refImage string) ([]string, llm.Usage, error) {
func (lm *LLM) FastMakeImage(prompt string, config llm.GCConfig) ([]string, llm.Usage, error) {
config.Model = ModelDallE3Std
return lm.MakeImage(prompt, config)
}
func (lm *LLM) BestMakeImage(prompt string, config llm.GCConfig) ([]string, error) {
func (lm *LLM) BestMakeImage(prompt string, config llm.GCConfig) ([]string, llm.Usage, error) {
config.Model = ModelDallE3HD
return lm.MakeImage(prompt, config)
}
func (lm *LLM) MakeImage(prompt string, config llm.GCConfig) ([]string, error) {
func (lm *LLM) MakeImage(prompt string, config llm.GCConfig) ([]string, llm.Usage, error) {
openaiConf := openai.DefaultConfig(lm.config.ApiKey)
if lm.config.Endpoint != "" {
openaiConf.BaseURL = lm.config.Endpoint
@ -43,6 +44,7 @@ func (lm *LLM) MakeImage(prompt string, config llm.GCConfig) ([]string, error) {
quality = openai.CreateImageQualityHD
model = model[0 : len(model)-3]
}
t1 := time.Now().UnixMilli()
r, err := c.CreateImage(context.Background(), openai.ImageRequest{
Prompt: prompt,
Model: model,
@ -51,25 +53,31 @@ func (lm *LLM) MakeImage(prompt string, config llm.GCConfig) ([]string, error) {
Style: style,
ResponseFormat: openai.CreateImageResponseFormatURL,
})
t2 := time.Now().UnixMilli() - t1
if err == nil {
results := make([]string, 0)
for _, item := range r.Data {
results = append(results, item.URL)
}
return results, nil
return results, llm.Usage{
AskTokens: 0,
AnswerTokens: 0,
TotalTokens: 0,
UsedTime: t2,
}, nil
} else {
return nil, err
return nil, llm.Usage{}, err
}
}
func (lm *LLM) FastMakeVideo(prompt string, config llm.GCConfig) ([]string, []string, error) {
func (lm *LLM) FastMakeVideo(prompt string, config llm.GCConfig) ([]string, []string, llm.Usage, error) {
return lm.MakeVideo(prompt, config)
}
func (lm *LLM) BestMakeVideo(prompt string, config llm.GCConfig) ([]string, []string, error) {
func (lm *LLM) BestMakeVideo(prompt string, config llm.GCConfig) ([]string, []string, llm.Usage, error) {
return lm.MakeVideo(prompt, config)
}
func (lm *LLM) MakeVideo(prompt string, config llm.GCConfig) ([]string, []string, error) {
return nil, nil, nil
func (lm *LLM) MakeVideo(prompt string, config llm.GCConfig) ([]string, []string, llm.Usage, error) {
return nil, nil, llm.Usage{}, nil
}

View File

@ -1,67 +1,70 @@
package zhipu
import (
"apigo.cc/ai/ai/llm"
"apigo.cc/ai/ai/interface/llm"
"apigo.cc/ai/ai/llm/zhipu/zhipu"
"bytes"
"context"
"encoding/binary"
"strings"
"time"
)
func (lm *LLM) FastAsk(messages []llm.ChatMessage, callback func(answer string)) (string, llm.TokenUsage, error) {
func (lm *LLM) FastAsk(messages []llm.ChatMessage, callback func(answer string)) (string, llm.Usage, error) {
return lm.Ask(messages, llm.ChatConfig{
Model: ModelGLM4Flash,
}, callback)
}
func (lm *LLM) LongAsk(messages []llm.ChatMessage, callback func(answer string)) (string, llm.TokenUsage, error) {
func (lm *LLM) LongAsk(messages []llm.ChatMessage, callback func(answer string)) (string, llm.Usage, error) {
return lm.Ask(messages, llm.ChatConfig{
Model: ModelGLM4Long,
}, callback)
}
func (lm *LLM) BatterAsk(messages []llm.ChatMessage, callback func(answer string)) (string, llm.TokenUsage, error) {
func (lm *LLM) BatterAsk(messages []llm.ChatMessage, callback func(answer string)) (string, llm.Usage, error) {
return lm.Ask(messages, llm.ChatConfig{
Model: ModelGLM4Plus,
}, callback)
}
func (lm *LLM) BestAsk(messages []llm.ChatMessage, callback func(answer string)) (string, llm.TokenUsage, error) {
func (lm *LLM) BestAsk(messages []llm.ChatMessage, callback func(answer string)) (string, llm.Usage, error) {
return lm.Ask(messages, llm.ChatConfig{
Model: ModelGLM40520,
}, callback)
}
func (lm *LLM) MultiAsk(messages []llm.ChatMessage, callback func(answer string)) (string, llm.TokenUsage, error) {
func (lm *LLM) MultiAsk(messages []llm.ChatMessage, callback func(answer string)) (string, llm.Usage, error) {
return lm.Ask(messages, llm.ChatConfig{
Model: ModelGLM4VPlus,
}, callback)
}
func (lm *LLM) BestMultiAsk(messages []llm.ChatMessage, callback func(answer string)) (string, llm.TokenUsage, error) {
func (lm *LLM) BestMultiAsk(messages []llm.ChatMessage, callback func(answer string)) (string, llm.Usage, error) {
return lm.Ask(messages, llm.ChatConfig{
Model: ModelGLM4V,
}, callback)
}
func (lm *LLM) CodeInterpreterAsk(messages []llm.ChatMessage, callback func(answer string)) (string, llm.TokenUsage, error) {
func (lm *LLM) CodeInterpreterAsk(messages []llm.ChatMessage, callback func(answer string)) (string, llm.Usage, error) {
return lm.Ask(messages, llm.ChatConfig{
Model: ModelGLM4AllTools,
Tools: map[string]any{llm.ToolCodeInterpreter: nil},
}, callback)
}
func (lm *LLM) WebSearchAsk(messages []llm.ChatMessage, callback func(answer string)) (string, llm.TokenUsage, error) {
func (lm *LLM) WebSearchAsk(messages []llm.ChatMessage, callback func(answer string)) (string, llm.Usage, error) {
return lm.Ask(messages, llm.ChatConfig{
Model: ModelGLM4AllTools,
Tools: map[string]any{llm.ToolWebSearch: nil},
}, callback)
}
func (lm *LLM) Ask(messages []llm.ChatMessage, config llm.ChatConfig, callback func(answer string)) (string, llm.TokenUsage, error) {
func (lm *LLM) Ask(messages []llm.ChatMessage, config llm.ChatConfig, callback func(answer string)) (string, llm.Usage, error) {
config.SetDefault(&lm.config.ChatConfig)
c, err := zhipu.NewClient(zhipu.WithAPIKey(lm.config.ApiKey), zhipu.WithBaseURL(lm.config.Endpoint))
if err != nil {
return "", llm.TokenUsage{}, err
return "", llm.Usage{}, err
}
cc := c.ChatCompletion(config.GetModel())
@ -126,19 +129,60 @@ func (lm *LLM) Ask(messages []llm.ChatMessage, config llm.ChatConfig, callback f
})
}
t1 := time.Now().UnixMilli()
if r, err := cc.Do(context.Background()); err == nil {
t2 := time.Now().UnixMilli() - t1
results := make([]string, 0)
if r.Choices != nil {
for _, ch := range r.Choices {
results = append(results, ch.Message.Content)
}
}
return strings.Join(results, ""), llm.TokenUsage{
return strings.Join(results, ""), llm.Usage{
AskTokens: r.Usage.PromptTokens,
AnswerTokens: r.Usage.CompletionTokens,
TotalTokens: r.Usage.TotalTokens,
UsedTime: t2,
}, nil
} else {
return "", llm.TokenUsage{}, err
return "", llm.Usage{}, err
}
}
func (lm *LLM) FastEmbedding(text string) ([]byte, llm.Usage, error) {
return lm.Embedding(text, ModelEmbedding3)
}
func (lm *LLM) BestEmbedding(text string) ([]byte, llm.Usage, error) {
return lm.Embedding(text, ModelEmbedding3)
}
func (lm *LLM) Embedding(text, model string) ([]byte, llm.Usage, error) {
c, err := zhipu.NewClient(zhipu.WithAPIKey(lm.config.ApiKey), zhipu.WithBaseURL(lm.config.Endpoint))
if err != nil {
return nil, llm.Usage{}, err
}
cc := c.Embedding(model)
cc.SetInput(text)
t1 := time.Now().UnixMilli()
if r, err := cc.Do(context.Background()); err == nil {
t2 := time.Now().UnixMilli() - t1
buf := new(bytes.Buffer)
if r.Data != nil {
for _, ch := range r.Data {
for _, v := range ch.Embedding {
_ = binary.Write(buf, binary.LittleEndian, float32(v))
}
}
}
return buf.Bytes(), llm.Usage{
AskTokens: r.Usage.PromptTokens,
AnswerTokens: r.Usage.CompletionTokens,
TotalTokens: r.Usage.TotalTokens,
UsedTime: t2,
}, nil
} else {
return nil, llm.Usage{}, err
}
}

View File

@ -1,7 +1,7 @@
package zhipu
import (
"apigo.cc/ai/ai/llm"
"apigo.cc/ai/ai/interface/llm"
"apigo.cc/ai/ai/llm/zhipu/zhipu"
)

View File

@ -1,69 +1,75 @@
package zhipu
import (
"apigo.cc/ai/ai/llm"
"apigo.cc/ai/ai/interface/llm"
"apigo.cc/ai/ai/llm/zhipu/zhipu"
"context"
"errors"
"time"
)
func (lm *LLM) FastMakeImage(prompt string, config llm.GCConfig) ([]string, error) {
func (lm *LLM) FastMakeImage(prompt string, config llm.GCConfig) ([]string, llm.Usage, error) {
config.Model = ModelCogView3Plus
return lm.MakeImage(prompt, config)
}
func (lm *LLM) BestMakeImage(prompt string, config llm.GCConfig) ([]string, error) {
func (lm *LLM) BestMakeImage(prompt string, config llm.GCConfig) ([]string, llm.Usage, error) {
config.Model = ModelCogView3
return lm.MakeImage(prompt, config)
}
func (lm *LLM) MakeImage(prompt string, config llm.GCConfig) ([]string, error) {
func (lm *LLM) MakeImage(prompt string, config llm.GCConfig) ([]string, llm.Usage, error) {
c, err := zhipu.NewClient(zhipu.WithAPIKey(lm.config.ApiKey), zhipu.WithBaseURL(lm.config.Endpoint))
if err != nil {
return nil, err
return nil, llm.Usage{}, err
}
config.SetDefault(&lm.config.GCConfig)
cc := c.ImageGeneration(config.Model).SetPrompt(prompt)
cc.SetSize(config.GetSize())
t1 := time.Now().UnixMilli()
if r, err := cc.Do(context.Background()); err == nil {
t2 := time.Now().UnixMilli() - t1
results := make([]string, 0)
for _, item := range r.Data {
results = append(results, item.URL)
}
return results, nil
return results, llm.Usage{
UsedTime: t2,
}, nil
} else {
return nil, err
return nil, llm.Usage{}, err
}
}
func (lm *LLM) FastMakeVideo(prompt string, config llm.GCConfig) ([]string, []string, error) {
func (lm *LLM) FastMakeVideo(prompt string, config llm.GCConfig) ([]string, []string, llm.Usage, error) {
config.Model = ModelCogVideoX
return lm.MakeVideo(prompt, config)
}
func (lm *LLM) BestMakeVideo(prompt string, config llm.GCConfig) ([]string, []string, error) {
func (lm *LLM) BestMakeVideo(prompt string, config llm.GCConfig) ([]string, []string, llm.Usage, error) {
config.Model = ModelCogVideoX
return lm.MakeVideo(prompt, config)
}
func (lm *LLM) MakeVideo(prompt string, config llm.GCConfig) ([]string, []string, error) {
func (lm *LLM) MakeVideo(prompt string, config llm.GCConfig) ([]string, []string, llm.Usage, error) {
c, err := zhipu.NewClient(zhipu.WithAPIKey(lm.config.ApiKey), zhipu.WithBaseURL(lm.config.Endpoint))
if err != nil {
return nil, nil, err
return nil, nil, llm.Usage{}, err
}
config.SetDefault(&lm.config.GCConfig)
cc := c.VideoGeneration(config.Model).SetPrompt(prompt)
cc.SetImageURL(config.GetRef())
t1 := time.Now().UnixMilli()
if resp, err := cc.Do(context.Background()); err == nil {
t2 := time.Now().UnixMilli() - t1
for i := 0; i < 1200; i++ {
r, err := c.AsyncResult(resp.ID).Do(context.Background())
if err != nil {
return nil, nil, err
return nil, nil, llm.Usage{}, err
}
if r.TaskStatus == zhipu.VideoGenerationTaskStatusSuccess {
covers := make([]string, 0)
@ -72,15 +78,17 @@ func (lm *LLM) MakeVideo(prompt string, config llm.GCConfig) ([]string, []string
results = append(results, item.URL)
covers = append(covers, item.CoverImageURL)
}
return results, covers, nil
return results, covers, llm.Usage{
UsedTime: t2,
}, nil
}
if r.TaskStatus == zhipu.VideoGenerationTaskStatusFail {
return nil, nil, errors.New("fail on task " + resp.ID)
return nil, nil, llm.Usage{}, errors.New("fail on task " + resp.ID)
}
time.Sleep(3 * time.Second)
}
return nil, nil, errors.New("timeout on task " + resp.ID)
return nil, nil, llm.Usage{}, errors.New("timeout on task " + resp.ID)
} else {
return nil, nil, err
return nil, nil, llm.Usage{}, err
}
}

View File

@ -2,8 +2,8 @@ package tests
import (
"apigo.cc/ai/ai"
llm2 "apigo.cc/ai/ai/interface/llm"
"apigo.cc/ai/ai/js"
"apigo.cc/ai/ai/llm"
"encoding/hex"
"fmt"
"github.com/ssgo/u"
@ -39,13 +39,13 @@ func TestAgent(t *testing.T) {
}
func testChat(t *testing.T, llmName string) {
lm := llm.Get(llmName)
lm := llm2.Get(llmName)
if lm == nil {
t.Fatal("agent is nil")
t.Fatal("interface is nil")
}
r, usage, err := lm.FastAsk(llm.Messages().User().Text("你是什么模型,请给出具体名称、版本号").Make(), func(text string) {
r, usage, err := lm.FastAsk(llm2.Messages().User().Text("你是什么模型,请给出具体名称、版本号").Make(), func(text string) {
fmt.Print(u.BCyan(text))
fmt.Print(" ")
})
@ -60,13 +60,13 @@ func testChat(t *testing.T, llmName string) {
}
func testCode(t *testing.T, llmName string) {
lm := llm.Get(llmName)
lm := llm2.Get(llmName)
if lm == nil {
t.Fatal("agent is nil")
t.Fatal("interface is nil")
}
r, usage, err := lm.CodeInterpreterAsk(llm.Messages().User().Text("计算[5,10,20,700,99,310,978,100]的平均值和方差。").Make(), func(text string) {
r, usage, err := lm.CodeInterpreterAsk(llm2.Messages().User().Text("计算[5,10,20,700,99,310,978,100]的平均值和方差。").Make(), func(text string) {
fmt.Print(u.BCyan(text))
fmt.Print(" ")
})
@ -81,13 +81,13 @@ func testCode(t *testing.T, llmName string) {
}
func testSearch(t *testing.T, llmName string) {
lm := llm.Get(llmName)
lm := llm2.Get(llmName)
if lm == nil {
t.Fatal("agent is nil")
t.Fatal("interface is nil")
}
r, usage, err := lm.WebSearchAsk(llm.Messages().User().Text("今天上海的天气怎么样?").Make(), func(text string) {
r, usage, err := lm.WebSearchAsk(llm2.Messages().User().Text("今天上海的天气怎么样?").Make(), func(text string) {
fmt.Print(u.BCyan(text))
fmt.Print(" ")
})
@ -102,10 +102,10 @@ func testSearch(t *testing.T, llmName string) {
}
func testAskWithImage(t *testing.T, llmName, imageFile string) {
lm := llm.Get(llmName)
lm := llm2.Get(llmName)
if lm == nil {
t.Fatal("agent is nil")
t.Fatal("interface is nil")
}
ask := `请回答
@ -114,7 +114,7 @@ func testAskWithImage(t *testing.T, llmName, imageFile string) {
3正在用什么软件播放什么歌谁演唱的歌曲的大意是
4后面的浏览器中正在浏览什么内容猜测一下我浏览这个网页是想干嘛
`
r, usage, err := lm.MultiAsk(llm.Messages().User().Text(ask).Image("data:image/jpeg;base64,"+u.Base64(u.ReadFileBytesN(imageFile))).Make(), func(text string) {
r, usage, err := lm.MultiAsk(llm2.Messages().User().Text(ask).Image("data:image/jpeg;base64,"+u.Base64(u.ReadFileBytesN(imageFile))).Make(), func(text string) {
fmt.Print(u.BCyan(text))
fmt.Print(" ")
})
@ -129,10 +129,10 @@ func testAskWithImage(t *testing.T, llmName, imageFile string) {
}
func testAskWithVideo(t *testing.T, llmName, videoFile string) {
lm := llm.Get(llmName)
lm := llm2.Get(llmName)
if lm == nil {
t.Fatal("agent is nil")
t.Fatal("interface is nil")
}
ask := `请回答
@ -140,7 +140,7 @@ func testAskWithVideo(t *testing.T, llmName, videoFile string) {
4后面的浏览器中正在浏览什么内容猜测一下我浏览这个网页是想干嘛
`
r, usage, err := lm.MultiAsk(llm.Messages().User().Text(ask).Video("data:video/mp4,"+u.Base64(u.ReadFileBytesN(videoFile))).Make(), func(text string) {
r, usage, err := lm.MultiAsk(llm2.Messages().User().Text(ask).Video("data:video/mp4,"+u.Base64(u.ReadFileBytesN(videoFile))).Make(), func(text string) {
fmt.Print(u.BCyan(text))
fmt.Print(" ")
})
@ -155,13 +155,13 @@ func testAskWithVideo(t *testing.T, llmName, videoFile string) {
}
func testMakeImage(t *testing.T, llmName, prompt, refImage string) {
lm := llm.Get(llmName)
lm := llm2.Get(llmName)
if lm == nil {
t.Fatal("agent is nil")
t.Fatal("interface is nil")
}
r, err := lm.FastMakeImage(prompt, llm.GCConfig{
r, err := lm.FastMakeImage(prompt, llm2.GCConfig{
Size: "1024x1024",
})
@ -176,13 +176,13 @@ func testMakeImage(t *testing.T, llmName, prompt, refImage string) {
}
func testMakeVideo(t *testing.T, llmName, prompt, refImage string) {
lm := llm.Get(llmName)
lm := llm2.Get(llmName)
if lm == nil {
t.Fatal("agent is nil")
t.Fatal("interface is nil")
}
r, covers, err := lm.FastMakeVideo(prompt, llm.GCConfig{
r, covers, err := lm.FastMakeVideo(prompt, llm2.GCConfig{
Size: "1280x720",
Ref: refImage,
})