GPT-backend/main.go
2024-06-13 12:35:57 +02:00

203 lines
4.7 KiB
Go

package main
import (
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"strings"
"github.com/gin-gonic/gin"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/client"
)
type Hosts struct {
Hosts []Host `json:"hosts"`
}
type Host struct {
Name string `json:"name"`
IP string `json:"ip"`
Port string `json:"port"`
Containers []Container `json:"containers"`
}
type Containers struct {
Containers []Container `json:"containers"`
}
type Container struct {
Name string `json:"names"`
Port int `json:"port"`
IP string `json:"ip"`
Image string `json:"image"`
ID string `json:"id"`
Status string `json:"status"`
State string `json:"state"`
}
type Details struct {
Parent_model string `json:"parent_model"`
Format string `json:"format"`
Family string `json:"family"`
Families []string `json:"families"`
Parameter_size string `json:"parameter_size"`
Quantization_level string `json:"quantization_level"`
}
type Model struct {
Container string `json:"container"`
Name string `json:"name"`
Model string `json:"model"`
Modified_at string `json:"modified_at"`
Size int `json:"size"`
Details Details `json:"details"`
Ip string `json:"ip"`
Port int `json:"port"`
State string `json:"state"`
}
type Models struct {
Models []Model `json:"models"`
}
func get_ollama_tags(hosts Hosts) (Models, error) {
var ctr Containers
for _, host := range hosts.Hosts {
fmt.Printf("HOST: %s -> %s\n", host.Name, host.IP)
ctr.Adds(get_ollama_containers(host, false))
// ctr = append(ctr, get_ollama_containers(host)...)
// fmt.Println(ctr)
}
retval := []Model{}
for _, ollama := range ctr.Containers {
// fmt.Println(ollama)
if ollama.State != "running" {
retval = append(retval, Model{Ip: ollama.IP, Port: ollama.Port, State: "stopped"})
} else {
url := fmt.Sprintf("http://%s:%d/api/tags", ollama.IP, ollama.Port)
resp, err := http.Get(url)
if err != nil {
return Models{}, fmt.Errorf("failed to get %s: %v", url, err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return Models{}, fmt.Errorf("failed to read body: %v", err)
}
mods := Models{}
err = json.Unmarshal(body, &mods)
if err != nil {
return Models{}, fmt.Errorf("failed to unmarshal JSON: %v", err)
}
fmt.Printf("%+v\n", mods)
for n := range mods.Models {
mods.Models[n].Ip = ollama.IP
mods.Models[n].Port = ollama.Port
mods.Models[n].State = "running"
mods.Models[n].Container = ollama.Name
fmt.Printf("mod: %s - %s:%d\n", mods.Models[n].Name, mods.Models[n].Ip, mods.Models[n].Port)
}
retval = append(retval, mods.Models...)
}
}
return Models{Models: retval}, nil
}
func get_ollama_containers(host Host, all bool) Containers {
ctr_list := Containers{}
// fmt.Printf("%s -> %s\n", host.Name, host.IP)
cli, err := client.NewClientWithOpts(client.WithHost(fmt.Sprintf("tcp://%s:%s", host.IP, host.Port)))
if err != nil {
fmt.Println(err)
return ctr_list
}
defer cli.Close()
containers, err := cli.ContainerList(context.Background(), container.ListOptions{All: all})
if err != nil {
fmt.Println(err)
return ctr_list
}
for _, ctr := range containers {
if strings.Contains(ctr.Names[0], "ollama") { //&& ctr.Image == "ollama/ollama" {
c := Container{ID: ctr.ID, Name: ctr.Names[0], Image: ctr.Image, State: ctr.State, Status: ctr.Status}
if ctr.State == "running" {
// fmt.Println(ctr.Ports[0])
c.Port = int(ctr.Ports[0].PublicPort)
}
c.IP = host.IP
ctr_list.Add(c)
// ctr_list = append(ctr_list, c)
}
}
// fmt.Println(ctr_list)
return ctr_list
}
func (h *Hosts) Add(name string, ip string, port string) {
h.Hosts = append(h.Hosts, Host{Name: name, IP: ip, Port: port})
}
func (c *Containers) Add(ctr Container) {
c.Containers = append(c.Containers, ctr)
}
func (c *Containers) Adds(ctrs Containers) {
c.Containers = append(c.Containers, ctrs.Containers...)
}
func (h *Hosts) Init() {
h.Add("thor", "192.168.55.13", "2375")
h.Add("ironman", "192.168.55.10", "2375")
}
func main() {
port := "4000"
hosts := Hosts{}
hosts.Init()
r := gin.Default()
r.GET("/api/tags", func(c *gin.Context) {
models, err := get_ollama_tags(hosts)
if err != nil {
panic(err)
}
c.JSON(200, models)
})
sapp := r.Group("/_app")
sapp.Static("/", "./static/_app")
static := r.Group("/static")
static.Static("/", "./static/static")
r.StaticFile("/", "./static/index.html")
r.StaticFile("/favicon.png", "./static/favicon.png")
r.ForwardedByClientIP = true
fmt.Println("Starting server on port " + port)
r.Run(":" + port)
fmt.Print("END")
}