mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-05-07 06:02:09 +08:00
Revert "Automated cherry pick of #23282: [OSPP]feature: Auto deploy llm and d…"
This reverts commit c891d4b23e.
This commit is contained in:
@@ -1,3 +0,0 @@
|
||||
FROM registry.cn-beijing.aliyuncs.com/yunionio/onecloud-base:v0.3.5-1
|
||||
|
||||
ADD ./_output/alpine-build/bin/llm /opt/yunion/bin/llm
|
||||
@@ -30,7 +30,6 @@ import (
|
||||
_ "yunion.io/x/onecloud/cmd/climc/shell/identity"
|
||||
_ "yunion.io/x/onecloud/cmd/climc/shell/image"
|
||||
_ "yunion.io/x/onecloud/cmd/climc/shell/k8s"
|
||||
_ "yunion.io/x/onecloud/cmd/climc/shell/llm"
|
||||
_ "yunion.io/x/onecloud/cmd/climc/shell/logger"
|
||||
_ "yunion.io/x/onecloud/cmd/climc/shell/misc"
|
||||
_ "yunion.io/x/onecloud/cmd/climc/shell/monitor"
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
package llm
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/cmd/climc/shell"
|
||||
modules "yunion.io/x/onecloud/pkg/mcclient/modules/llm"
|
||||
options "yunion.io/x/onecloud/pkg/mcclient/options/llm"
|
||||
)
|
||||
|
||||
func init() {
|
||||
cmd := shell.NewResourceCmd(&modules.Difies)
|
||||
cmd.BatchCreate(new(options.DifyCreateOptions))
|
||||
cmd.List(new(options.DifyListOptions))
|
||||
cmd.Show(new(options.DifyShowOptions))
|
||||
cmd.Delete(new(options.DifyDeleteOptions))
|
||||
cmd.BatchPerform("stop", new(options.DifyStopOptions))
|
||||
cmd.BatchPerform("start", new(options.DifyStartOptions))
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package llm
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/cmd/climc/shell"
|
||||
modules "yunion.io/x/onecloud/pkg/mcclient/modules/llm"
|
||||
base_options "yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
options "yunion.io/x/onecloud/pkg/mcclient/options/llm"
|
||||
)
|
||||
|
||||
func init() {
|
||||
cmd := shell.NewResourceCmd(&modules.DifyModel)
|
||||
cmd.List(new(options.DifyModelListOptions))
|
||||
cmd.Show(new(options.DifyModelShowOptions))
|
||||
cmd.Update(new(options.DifyModelUpdateOptions))
|
||||
cmd.Create(new(options.DifyModelCreateOptions))
|
||||
cmd.Delete(new(options.DifyModelDeleteOptions))
|
||||
cmd.Perform("public", &base_options.BasePublicOptions{})
|
||||
cmd.Perform("private", &base_options.BaseIdOptions{})
|
||||
// cmd.Perform("clone", new(options.DesktopModelCloneOptions))
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
package llm
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/cmd/climc/shell"
|
||||
modules "yunion.io/x/onecloud/pkg/mcclient/modules/llm"
|
||||
base_options "yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
options "yunion.io/x/onecloud/pkg/mcclient/options/llm"
|
||||
)
|
||||
|
||||
func init() {
|
||||
cmd := shell.NewResourceCmd(&modules.LLMImage)
|
||||
cmd.List(new(options.LLMImageListOptions))
|
||||
cmd.Show(new(options.LLMImageShowOptions))
|
||||
cmd.Create(new(options.LLMImageCreateOptions))
|
||||
cmd.Update(new(options.LLMImageUpdateOptions))
|
||||
cmd.Delete(new(options.LLMImageDeleteOptions))
|
||||
cmd.Perform("public", &base_options.BasePublicOptions{})
|
||||
cmd.Perform("private", &base_options.BaseIdOptions{})
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
package llm
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/cmd/climc/shell"
|
||||
modules "yunion.io/x/onecloud/pkg/mcclient/modules/llm"
|
||||
options "yunion.io/x/onecloud/pkg/mcclient/options/llm"
|
||||
)
|
||||
|
||||
func init() {
|
||||
cmd := shell.NewResourceCmd(&modules.LLMs)
|
||||
cmd.BatchCreate(new(options.LLMCreateOptions))
|
||||
cmd.List(new(options.LLMListOptions))
|
||||
cmd.Show(new(options.LLMShowOptions))
|
||||
cmd.Delete(new(options.LLMDeleteOptions))
|
||||
// cmd.Perform("change-model", new(options.LLMChangeModelOptions))
|
||||
cmd.BatchPerform("stop", new(options.LLMStopOptions))
|
||||
cmd.BatchPerform("start", new(options.LLMStartOptions))
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package llm
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/cmd/climc/shell"
|
||||
modules "yunion.io/x/onecloud/pkg/mcclient/modules/llm"
|
||||
base_options "yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
options "yunion.io/x/onecloud/pkg/mcclient/options/llm"
|
||||
)
|
||||
|
||||
func init() {
|
||||
cmd := shell.NewResourceCmd(&modules.LLMModel)
|
||||
cmd.List(new(options.LLMModelListOptions))
|
||||
cmd.Show(new(options.LLMModelShowOptions))
|
||||
cmd.Update(new(options.LLMModelUpdateOptions))
|
||||
cmd.Create(new(options.LLMModelCreateOptions))
|
||||
cmd.Delete(new(options.LLMModelDeleteOptions))
|
||||
cmd.Perform("public", &base_options.BasePublicOptions{})
|
||||
cmd.Perform("private", &base_options.BaseIdOptions{})
|
||||
// cmd.Perform("clone", new(options.DesktopModelCloneOptions))
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/llm/service"
|
||||
"yunion.io/x/onecloud/pkg/util/atexit"
|
||||
)
|
||||
|
||||
func main() {
|
||||
defer atexit.Handle()
|
||||
|
||||
service.StartService()
|
||||
}
|
||||
@@ -45,8 +45,6 @@ const (
|
||||
|
||||
SERVICE_TYPE_APIMAP = "apimap"
|
||||
|
||||
SERVICE_TYPE_LLM = "llm"
|
||||
|
||||
STATUS_UPDATE_TAGS = "update_tags"
|
||||
STATUS_UPDATE_TAGS_FAILED = "update_tags_fail"
|
||||
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
package llm
|
||||
|
||||
type DifyCustomizedEnv struct {
|
||||
Key string `json:"key"`
|
||||
Value string `json:"value"`
|
||||
}
|
||||
|
||||
type DifyCustomized struct {
|
||||
// Define custom environment variables here
|
||||
CustomizedEnvs []*DifyCustomizedEnv `json:"customized_envs,omitempty"`
|
||||
Registry string `json:"registry"`
|
||||
}
|
||||
|
||||
type DifyListInput struct {
|
||||
LLMBaseListInput
|
||||
|
||||
DifyModel string `json:"dify_model"`
|
||||
}
|
||||
|
||||
type DifyCreateInput struct {
|
||||
LLMBaseCreateInput
|
||||
|
||||
DifyModelId string
|
||||
}
|
||||
@@ -1,195 +0,0 @@
|
||||
package llm
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
)
|
||||
|
||||
var (
|
||||
DIFY_SECRET_KEY string
|
||||
DIFY_API_INNER_KEY string
|
||||
DIFY_PLUGIN_SERVER_KEY string
|
||||
DIFY_WEAVIATE_AUTHENTICATION_APIKEY_ALLOWED_KEYS string
|
||||
)
|
||||
|
||||
func init() {
|
||||
skBytes := make([]byte, 32)
|
||||
rand.Read(skBytes)
|
||||
DIFY_SECRET_KEY = "sk-" + hex.EncodeToString(skBytes)
|
||||
|
||||
innerKeyBytes := make([]byte, 32)
|
||||
rand.Read(innerKeyBytes)
|
||||
DIFY_API_INNER_KEY = base64.StdEncoding.EncodeToString(innerKeyBytes)
|
||||
|
||||
pluginKeyBytes := make([]byte, 32)
|
||||
rand.Read(pluginKeyBytes)
|
||||
DIFY_PLUGIN_SERVER_KEY = base64.StdEncoding.EncodeToString(pluginKeyBytes)
|
||||
|
||||
weaviateKeyBytes := make([]byte, 32)
|
||||
rand.Read(weaviateKeyBytes)
|
||||
DIFY_WEAVIATE_AUTHENTICATION_APIKEY_ALLOWED_KEYS = base64.URLEncoding.EncodeToString(weaviateKeyBytes)
|
||||
}
|
||||
|
||||
const (
|
||||
DIFY_POSTGRES_KEY = "postgres"
|
||||
DIFY_REDIS_KEY = "redis"
|
||||
DIFY_API_KEY = "api"
|
||||
DIFY_WORKER_KEY = "worker"
|
||||
DIFY_WORKER_BEAT_KEY = "beat"
|
||||
DIFY_PLUGIN_KEY = "plugin"
|
||||
DIFY_WEB_KEY = "web"
|
||||
DIFY_SSRF_KEY = "ssrf"
|
||||
DIFY_NGINX_KEY = "nginx"
|
||||
DIFY_WEAVIATE_KEY = "weaviate"
|
||||
DIFY_SANDBOX_KEY = "sandbox"
|
||||
)
|
||||
|
||||
const (
|
||||
DIFY_POSTGRES_IMAGE = "/postgres:15-alpine"
|
||||
DIFY_REDIS_IMAGE = "/redis:6-alpine"
|
||||
DIFY_NGINX_IMAGE = "/nginx:latest"
|
||||
DIFY_API_IMAGE = "/langgenius/dify-api:1.7.2"
|
||||
DIFY_PLUGIN_IMAGE = "/langgenius/dify-plugin-daemon:0.2.0-local"
|
||||
DIFY_WEB_IMAGE = "/langgenius/dify-web:1.7.2"
|
||||
DIFY_SANDBOX_IMAGE = "/langgenius/dify-sandbox:0.2.12"
|
||||
DIFY_SSRF_IMAGE = "/ubuntu/squid:latest"
|
||||
DIFY_WEAVIATE_IAMGE = "/semitechnologies/weaviate:1.19.0"
|
||||
)
|
||||
|
||||
const (
|
||||
DIFY_LOCALHOST = "localhost"
|
||||
PIP_MIRROR_URL = "https://mirrors.aliyun.com/pypi/simple"
|
||||
)
|
||||
|
||||
const (
|
||||
DIFY_POSTGRES_PVC_MOUNT_PATH = "/var/lib/postgresql/data"
|
||||
DIFY_POSTGRES_MAX_CONNECTIONS = "100"
|
||||
DIFY_POSTGRES_SHARED_BUFFERS = "128MB"
|
||||
DIFY_POSTGRES_WORK_MEM = "4MB"
|
||||
DIFY_POSTGRES_MAINTENANCE_WORK_MEM = "64MB"
|
||||
DIFY_POSTGRES_EFFECTIVE_CACHE_SIZE = "4096MB"
|
||||
DIFY_POSTGRES_USER = "postgres"
|
||||
DIFY_POSTGRES_PASSWORD = "difyai123456"
|
||||
DIFY_POSTGRES_DB = "dify"
|
||||
DIFY_POSTGRES_PGDATA = "/pgdata"
|
||||
DIFY_POSTGRES_PORT = "5432"
|
||||
)
|
||||
|
||||
const (
|
||||
DIFY_REDISCLI_AUTH = "difyai123456"
|
||||
DIFY_REDIS_PVC_MOUNT_PATH = "/data"
|
||||
DIFY_REDIS_PORT = "6379"
|
||||
)
|
||||
|
||||
const (
|
||||
DIFY_API_PVC_MOUNT_PATH = "/app/api/storage"
|
||||
DIFY_API_MODE = "api"
|
||||
DIFY_API_SENTRY_DSN = ""
|
||||
DIFY_API_SENTRY_TRACES_SAMPLE_RATE = "1.0"
|
||||
DIFY_API_SENTRY_PROFILES_SAMPLE_RATE = "1.0"
|
||||
)
|
||||
|
||||
const (
|
||||
DIFY_WORKER_MODE = "worker"
|
||||
DIFY_WORKER_BEAT_MODE = "beat"
|
||||
)
|
||||
|
||||
const (
|
||||
DIFY_PLUGIN_DB_DATABASE = "dify_plugin"
|
||||
DIFY_PLUGIN_SERVER_PORT = "5002"
|
||||
DIFY_PLUGIN_MAX_PACKAGE_SIZE = "52428800"
|
||||
DIFY_PLUGIN_PPROF_ENABLED = "false"
|
||||
DIFY_PLUGIN_DIFY_INNER_API_URL = "http://localhost:5001"
|
||||
DIFY_PLUGIN_REMOTE_INSTALLING_HOST = "0.0.0.0"
|
||||
DIFY_PLUGIN_REMOTE_INSTALLING_PORT = "5003"
|
||||
DIFY_PLUGIN_WORKING_PATH = "/app/storage/cwd"
|
||||
DIFY_PLUGIN_FORCE_VERIFYING_SIGNATURE = "true"
|
||||
DIFY_PLUGIN_PYTHON_ENV_INIT_TIMEOUT = "120"
|
||||
DIFY_PLUGIN_MAX_EXECUTION_TIMEOUT = "600"
|
||||
DIFY_PLUGIN_STORAGE_TYPE = "local"
|
||||
DIFY_PLUGIN_STORAGE_LOCAL_ROOT = "/app/storage"
|
||||
DIFY_PLUGIN_INSTALLED_PATH = "plugin"
|
||||
DIFY_PLUGIN_PACKAGE_CACHE_PATH = "plugin_packages"
|
||||
DIFY_PLUGIN_MEDIA_CACHE_PATH = "assets"
|
||||
)
|
||||
|
||||
const (
|
||||
DIFY_WEB_CONSOLE_API_URL = ""
|
||||
DIFY_WEB_APP_API_URL = ""
|
||||
DIFY_WEB_SENTRY_DSN = ""
|
||||
DIFY_WEB_NEXT_TELEMETRY_DISABLED = "0"
|
||||
DIFY_WEB_TEXT_GENERATION_TIMEOUT_MS = "60000"
|
||||
DIFY_WEB_CSP_WHITELIST = ""
|
||||
DIFY_WEB_ALLOW_EMBED = "false"
|
||||
DIFY_WEB_ALLOW_UNSAFE_DATA_SCHEME = "false"
|
||||
DIFY_WEB_MARKETPLACE_API_URL = "https://marketplace.dify.ai"
|
||||
DIFY_WEB_MARKETPLACE_URL = "https://marketplace.dify.ai"
|
||||
DIFY_WEB_TOP_K_MAX_VALUE = "10"
|
||||
DIFY_WEB_INDEXING_MAX_SEGMENTATION_TOKENS_LENGTH = "4000"
|
||||
DIFY_WEB_PM2_INSTANCES = "2"
|
||||
DIFY_WEB_LOOP_NODE_MAX_COUNT = "100"
|
||||
DIFY_WEB_MAX_TOOLS_NUM = "10"
|
||||
DIFY_WEB_MAX_PARALLEL_LIMIT = "10"
|
||||
DIFY_WEB_MAX_ITERATIONS_NUM = "99"
|
||||
DIFY_WEB_ENABLE_WEBSITE_JINAREADER = "true"
|
||||
DIFY_WEB_ENABLE_WEBSITE_FIRECRAWL = "true"
|
||||
DIFY_WEB_ENABLE_WEBSITE_WATERCRAWL = "true"
|
||||
)
|
||||
|
||||
const (
|
||||
DIFY_SSRF_MOUNT_PATH = "/etc/squid/"
|
||||
DIFY_SSRF_HTTP_PORT = "3128"
|
||||
DIFY_SSRF_COREDUMP_DIR = "/var/spool/squid"
|
||||
)
|
||||
|
||||
const (
|
||||
DIFY_NGINX_MOUNT_PATH = "/etc/nginx/conf.d"
|
||||
DIFY_NGINX_SERVER_NAME = "_"
|
||||
DIFY_NGINX_PORT = "80"
|
||||
DIFY_NGINX_WORKER_PROCESSES = "auto"
|
||||
DIFY_NGINX_CLIENT_MAX_BODY_SIZE = "100M"
|
||||
DIFY_NGINX_KEEPALIVE_TIMEOUT = "65"
|
||||
DIFY_NGINX_PROXY_READ_TIMEOUT = "3600s"
|
||||
DIFY_NGINX_PROXY_SEND_TIMEOUT = "3600s"
|
||||
)
|
||||
|
||||
const (
|
||||
DIFY_WEAVIATE_PERSISTENCE_DATA_PATH = "/var/lib/weaviate"
|
||||
DIFY_WEAVIATE_QUERY_DEFAULTS_LIMIT = "25"
|
||||
DIFY_WEAVIATE_AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED = "true"
|
||||
DIFY_WEAVIATE_DEFAULT_VECTORIZER_MODULE = "none"
|
||||
DIFY_WEAVIATE_CLUSTER_HOSTNAME = "node1"
|
||||
DIFY_WEAVIATE_AUTHENTICATION_APIKEY_ENABLED = "true"
|
||||
DIFY_WEAVIATE_AUTHENTICATION_APIKEY_USERS = "hello@dify.ai"
|
||||
DIFY_WEAVIATE_AUTHORIZATION_ADMINLIST_ENABLED = "true"
|
||||
DIFY_WEAVIATE_AUTHORIZATION_ADMINLIST_USERS = "hello@dify.ai"
|
||||
)
|
||||
|
||||
const (
|
||||
DIFY_SANDBOX_CONF_MOUNT_PATH = "/conf"
|
||||
DIFY_SANDBOX_DEP_MOUNT_PATH = "/dependencies"
|
||||
DIFY_SANDBOX_API_KEY = "dify-sandbox"
|
||||
DIFY_SANDBOX_GIN_MODE = "release"
|
||||
DIFY_SANDBOX_WORKER_TIMEOUT = "15"
|
||||
DIFY_SANDBOX_ENABLE_NETWORK = "true"
|
||||
DIFY_SANDBOX_HTTP_PROXY = "http://" + DIFY_LOCALHOST + ":" + DIFY_SSRF_HTTP_PORT
|
||||
DIFY_SANDBOX_HTTPS_PROXY = "http://" + DIFY_LOCALHOST + ":" + DIFY_SSRF_HTTP_PORT
|
||||
DIFY_SANDBOX_PORT = "8194"
|
||||
)
|
||||
|
||||
const (
|
||||
DIFY_DEPLOY_REDIS_FAILED = "dify_deploy_redis_failed"
|
||||
DIFY_DEPLOY_POSTGRES_FAILED = "dify_deploy_postgres_failed"
|
||||
DIFY_DEPLOY_API_FAILED = "dify_deploy_api_failed"
|
||||
DIFY_DEPLOY_WORKER_FAILED = "dify_deploy_worker_failed"
|
||||
DIFY_DEPLOY_WORKER_BEAT_FAILED = "dify_deploy_worker_beat_failed"
|
||||
DIFY_DEPLOY_WEB_FAILED = "dify_deploy_web_failed"
|
||||
DIFY_DEPLOY_PLUGIN_FAILED = "dify_deploy_plugin_failed"
|
||||
DIFY_DEPLOY_SANDBOX_FAILED = "dify_deploy_sandbox_failed"
|
||||
DIFY_DEPLOY_SSRF_FAILED = "dify_deploy_ssrf_failed"
|
||||
DIFY_DEPLOY_NGINX_FAILED = "dify_deploy_nginx_failed"
|
||||
DIFY_DEPLOY_WEAVIATE_FAILED = "dify_deploy_weaviate_failed"
|
||||
DIFY_CREATE_FAILED = "create_dify_failed"
|
||||
DIFY_CREATED = "running"
|
||||
)
|
||||
@@ -1,290 +0,0 @@
|
||||
package llm
|
||||
|
||||
const (
|
||||
DIFY_SSRF_ENTRYPINT_SHELL = `
|
||||
mkdir -p /etc/squid
|
||||
|
||||
cat > /etc/squid/squid.conf.template <<'EOF'
|
||||
%s
|
||||
EOF
|
||||
|
||||
echo "[ENTRYPOINT] re-create snakeoil self-signed certificate removed in the build process"
|
||||
if [ ! -f /etc/ssl/private/ssl-cert-snakeoil.key ]; then
|
||||
/usr/sbin/make-ssl-cert generate-default-snakeoil --force-overwrite > /dev/null 2>&1
|
||||
fi
|
||||
|
||||
tail -F /var/log/squid/access.log 2>/dev/null &
|
||||
tail -F /var/log/squid/error.log 2>/dev/null &
|
||||
tail -F /var/log/squid/store.log 2>/dev/null &
|
||||
tail -F /var/log/squid/cache.log 2>/dev/null &
|
||||
|
||||
echo "[ENTRYPOINT] replacing environment variables in the template"
|
||||
awk '{
|
||||
while(match($0, /\${[A-Za-z_][A-Za-z_0-9]*}/)) {
|
||||
var = substr($0, RSTART+2, RLENGTH-3)
|
||||
val = ENVIRON[var]
|
||||
$0 = substr($0, 1, RSTART-1) val substr($0, RSTART+RLENGTH)
|
||||
}
|
||||
print
|
||||
}' /etc/squid/squid.conf.template > /etc/squid/squid.conf
|
||||
|
||||
chown -R "$SQUID_USER":"$SQUID_USER" /etc/squid
|
||||
|
||||
/usr/sbin/squid -Nz
|
||||
echo "[ENTRYPOINT] starting squid"
|
||||
/usr/sbin/squid -f /etc/squid/squid.conf -NYC 1
|
||||
`
|
||||
DIFY_SSRF_SQUID_CONFIGURATION_FILE = `visible_hostname localhost # set visible_hostname to avoid WARNING: Could not determine this machines public hostname.
|
||||
acl localnet src 0.0.0.1-0.255.255.255 # RFC 1122 "this" network (LAN)
|
||||
acl localnet src 10.0.0.0/8 # RFC 1918 local private network (LAN)
|
||||
acl localnet src 100.64.0.0/10 # RFC 6598 shared address space (CGN)
|
||||
acl localnet src 169.254.0.0/16 # RFC 3927 link-local (directly plugged) machines
|
||||
acl localnet src 172.16.0.0/12 # RFC 1918 local private network (LAN)
|
||||
acl localnet src 192.168.0.0/16 # RFC 1918 local private network (LAN)
|
||||
acl localnet src fc00::/7 # RFC 4193 local private network range
|
||||
acl localnet src fe80::/10 # RFC 4291 link-local (directly plugged) machines
|
||||
acl SSL_ports port 443
|
||||
# acl SSL_ports port 1025-65535 # Enable the configuration to resolve this issue: https://github.com/langgenius/dify/issues/12792
|
||||
acl Safe_ports port 80 # http
|
||||
acl Safe_ports port 21 # ftp
|
||||
acl Safe_ports port 443 # https
|
||||
acl Safe_ports port 70 # gopher
|
||||
acl Safe_ports port 210 # wais
|
||||
acl Safe_ports port 1025-65535 # unregistered ports
|
||||
acl Safe_ports port 280 # http-mgmt
|
||||
acl Safe_ports port 488 # gss-http
|
||||
acl Safe_ports port 591 # filemaker
|
||||
acl Safe_ports port 777 # multiling http
|
||||
acl CONNECT method CONNECT
|
||||
acl allowed_domains dstdomain .marketplace.dify.ai
|
||||
http_access allow allowed_domains
|
||||
http_access deny !Safe_ports
|
||||
http_access deny CONNECT !SSL_ports
|
||||
http_access allow localhost manager
|
||||
http_access deny manager
|
||||
http_access allow localhost
|
||||
include /etc/squid/conf.d/*.conf
|
||||
http_access deny all
|
||||
|
||||
################################## Proxy Server ################################
|
||||
http_port ${HTTP_PORT}
|
||||
coredump_dir ${COREDUMP_DIR}
|
||||
refresh_pattern ^ftp: 1440 20% 10080
|
||||
refresh_pattern ^gopher: 1440 0% 1440
|
||||
refresh_pattern -i (/cgi-bin/|\?) 0 0% 0
|
||||
refresh_pattern \/(Packages|Sources)(|\.bz2|\.gz|\.xz)$ 0 0% 0 refresh-ims
|
||||
refresh_pattern \/Release(|\.gpg)$ 0 0% 0 refresh-ims
|
||||
refresh_pattern \/InRelease$ 0 0% 0 refresh-ims
|
||||
refresh_pattern \/(Translation-.*)(|\.bz2|\.gz|\.xz)$ 0 0% 0 refresh-ims
|
||||
refresh_pattern . 0 20% 4320
|
||||
|
||||
|
||||
# cache_dir ufs /var/spool/squid 100 16 256
|
||||
# upstream proxy, set to your own upstream proxy IP to avoid SSRF attacks
|
||||
# cache_peer 172.1.1.1 parent 3128 0 no-query no-digest no-netdb-exchange default
|
||||
|
||||
################################## Reverse Proxy To Sandbox ################################
|
||||
http_port ${REVERSE_PROXY_PORT} accel vhost
|
||||
cache_peer ${SANDBOX_HOST} parent ${SANDBOX_PORT} 0 no-query originserver
|
||||
acl src_all src all
|
||||
http_access allow src_all
|
||||
|
||||
# Unless the option's size is increased, an error will occur when uploading more than two files.
|
||||
client_request_buffer_max_size 100 MB
|
||||
`
|
||||
)
|
||||
|
||||
const (
|
||||
DIFY_NGINX_ENTRYPINT_SHELL = `
|
||||
mkdir -p /etc/nginx
|
||||
cat > /etc/nginx/nginx.conf.template <<'EOF'
|
||||
%s
|
||||
EOF
|
||||
|
||||
cat > /etc/nginx/proxy.conf.template <<'EOF'
|
||||
%s
|
||||
EOF
|
||||
|
||||
cat > /etc/nginx/conf.d/default.conf.template <<'EOF'
|
||||
%s
|
||||
EOF
|
||||
|
||||
env_vars=$(printenv | cut -d= -f1 | sed 's/^/$/g' | paste -sd, -)
|
||||
echo "Substituting variables: $env_vars"
|
||||
|
||||
envsubst "$env_vars" < /etc/nginx/nginx.conf.template > /etc/nginx/nginx.conf
|
||||
envsubst "$env_vars" < /etc/nginx/proxy.conf.template > /etc/nginx/proxy.conf
|
||||
envsubst "$env_vars" < /etc/nginx/conf.d/default.conf.template > /etc/nginx/conf.d/default.conf
|
||||
|
||||
exec nginx -g 'daemon off;'`
|
||||
DIFY_NGINX_NGINX_CONF_FILE = `
|
||||
user nginx;
|
||||
worker_processes ${NGINX_WORKER_PROCESSES};
|
||||
|
||||
error_log /var/log/nginx/error.log notice;
|
||||
pid /var/run/nginx.pid;
|
||||
|
||||
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
|
||||
|
||||
http {
|
||||
include /etc/nginx/mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||
'$status $body_bytes_sent "$http_referer" '
|
||||
'"$http_user_agent" "$http_x_forwarded_for"';
|
||||
|
||||
access_log /var/log/nginx/access.log main;
|
||||
|
||||
sendfile on;
|
||||
#tcp_nopush on;
|
||||
|
||||
keepalive_timeout ${NGINX_KEEPALIVE_TIMEOUT};
|
||||
|
||||
#gzip on;
|
||||
client_max_body_size ${NGINX_CLIENT_MAX_BODY_SIZE};
|
||||
|
||||
include /etc/nginx/conf.d/*.conf;
|
||||
}
|
||||
`
|
||||
DIFY_NGINX_PROXY_CONF_FILE = `
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header X-Forwarded-Port $server_port;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Connection "";
|
||||
proxy_buffering off;
|
||||
proxy_read_timeout ${NGINX_PROXY_READ_TIMEOUT};
|
||||
proxy_send_timeout ${NGINX_PROXY_SEND_TIMEOUT};
|
||||
`
|
||||
DIFY_NGINX_DEFAULT_CONF_FILE = `# Please do not directly edit this file. Instead, modify the .env variables related to NGINX configuration.
|
||||
|
||||
server {
|
||||
listen ${NGINX_PORT};
|
||||
server_name ${NGINX_SERVER_NAME};
|
||||
|
||||
location /console/api {
|
||||
proxy_pass http://localhost:5001;
|
||||
include proxy.conf;
|
||||
}
|
||||
|
||||
location /api {
|
||||
proxy_pass http://localhost:5001;
|
||||
include proxy.conf;
|
||||
}
|
||||
|
||||
location /v1 {
|
||||
proxy_pass http://localhost:5001;
|
||||
include proxy.conf;
|
||||
}
|
||||
|
||||
location /files {
|
||||
proxy_pass http://localhost:5001;
|
||||
include proxy.conf;
|
||||
}
|
||||
|
||||
location /explore {
|
||||
proxy_pass http://localhost:3000;
|
||||
include proxy.conf;
|
||||
}
|
||||
|
||||
location /e/ {
|
||||
proxy_pass http://localhost:5002;
|
||||
proxy_set_header Dify-Hook-Url $scheme://$host$request_uri;
|
||||
include proxy.conf;
|
||||
}
|
||||
|
||||
location / {
|
||||
proxy_pass http://localhost:3000;
|
||||
include proxy.conf;
|
||||
}
|
||||
location /mcp {
|
||||
proxy_pass http://localhost:5001;
|
||||
include proxy.conf;
|
||||
}
|
||||
# placeholder for acme challenge location
|
||||
# ${ACME_CHALLENGE_LOCATION}
|
||||
|
||||
# placeholder for https config defined in https.conf.template
|
||||
# ${HTTPS_CONFIG}
|
||||
}
|
||||
`
|
||||
)
|
||||
|
||||
const (
|
||||
DIFY_SANDBOX_WRITE_CONF_SHELL = `
|
||||
cat > /conf/config.yaml <<'EOF'
|
||||
%s
|
||||
EOF
|
||||
|
||||
cat > /conf/config.yaml.template <<'EOF'
|
||||
%s
|
||||
EOF
|
||||
|
||||
touch /dependencies/python-requirements.txt
|
||||
|
||||
# decompress nodejs
|
||||
tar -xvf $NODE_TAR_XZ -C /opt
|
||||
ln -s $NODE_DIR/bin/node /usr/local/bin/node
|
||||
rm -f $NODE_TAR_XZ
|
||||
|
||||
# start main
|
||||
/main
|
||||
`
|
||||
DIFY_SANDBOX_CONF_FILE = `app:
|
||||
port: 8194
|
||||
debug: True
|
||||
key: dify-sandbox
|
||||
max_workers: 4
|
||||
max_requests: 50
|
||||
worker_timeout: 5
|
||||
python_path: /usr/local/bin/python3
|
||||
enable_network: True # please make sure there is no network risk in your environment
|
||||
allowed_syscalls: # please leave it empty if you have no idea how seccomp works
|
||||
proxy:
|
||||
socks5: ''
|
||||
http: ''
|
||||
https: ''
|
||||
`
|
||||
DIFY_SANDBOX_CONF_TEMP_FILE = `app:
|
||||
port: 8194
|
||||
debug: True
|
||||
key: dify-sandbox
|
||||
max_workers: 4
|
||||
max_requests: 50
|
||||
worker_timeout: 5
|
||||
python_path: /usr/local/bin/python3
|
||||
python_lib_path:
|
||||
- /usr/local/lib/python3.10
|
||||
- /usr/lib/python3.10
|
||||
- /usr/lib/python3
|
||||
- /usr/lib/x86_64-linux-gnu
|
||||
- /etc/ssl/certs/ca-certificates.crt
|
||||
- /etc/nsswitch.conf
|
||||
- /etc/hosts
|
||||
- /etc/resolv.conf
|
||||
- /run/systemd/resolve/stub-resolv.conf
|
||||
- /run/resolvconf/resolv.conf
|
||||
- /etc/localtime
|
||||
- /usr/share/zoneinfo
|
||||
- /etc/timezone
|
||||
# add more paths if needed
|
||||
python_pip_mirror_url: https://pypi.tuna.tsinghua.edu.cn/simple
|
||||
nodejs_path: /usr/local/bin/node
|
||||
enable_network: True
|
||||
allowed_syscalls:
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
# add all the syscalls which you require
|
||||
proxy:
|
||||
socks5: ''
|
||||
http: ''
|
||||
https: ''
|
||||
`
|
||||
)
|
||||
@@ -1,15 +0,0 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package llm // import "yunion.io/x/onecloud/pkg/apis/llm"
|
||||
@@ -1,26 +0,0 @@
|
||||
package llm
|
||||
|
||||
import "yunion.io/x/onecloud/pkg/apis"
|
||||
|
||||
type LLMImageListInput struct {
|
||||
apis.SharableVirtualResourceListInput
|
||||
|
||||
ImageLabel string `json:"image_label"`
|
||||
ImageName string `json:"image_name"`
|
||||
}
|
||||
|
||||
type LLMImageCreateInput struct {
|
||||
apis.SharableVirtualResourceCreateInput
|
||||
|
||||
ImageName string `json:"image_name"`
|
||||
ImageLabel string `json:"image_label"`
|
||||
CredentialId string `json:"credential_id"`
|
||||
}
|
||||
|
||||
type LLMImageUpdateInput struct {
|
||||
apis.SharableVirtualResourceCreateInput
|
||||
|
||||
ImageName *string `json:"image_name,omitempty"`
|
||||
ImageLabel *string `json:"image_label,omitempty"`
|
||||
CredentialId *string `json:"credential_id,omitempty"`
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
package llm
|
||||
|
||||
import "yunion.io/x/onecloud/pkg/apis"
|
||||
|
||||
const (
|
||||
SERVICE_TYPE = "llm"
|
||||
)
|
||||
|
||||
type LLMBaseCreateInput struct {
|
||||
apis.VirtualResourceCreateInput
|
||||
|
||||
PreferHost string
|
||||
AutoStart bool
|
||||
BandwidthMB int `json:"bandwidth_mb"`
|
||||
DebugMode bool `json:"debug_mode"`
|
||||
RootfsUnlimit bool `json:"rootfs_unlimit"`
|
||||
}
|
||||
|
||||
type LLMCreateInput struct {
|
||||
LLMBaseCreateInput
|
||||
|
||||
LLMModelId string
|
||||
LLMImageId string
|
||||
}
|
||||
|
||||
type LLMBaseListInput struct {
|
||||
apis.VirtualResourceListInput
|
||||
apis.EnabledResourceBaseListInput
|
||||
|
||||
Host string `json:"host"`
|
||||
Status []string `json:"status"`
|
||||
|
||||
NoVolume *bool `json:"no_volume"`
|
||||
ListenPort int `json:"listen_port"`
|
||||
PublicIp string `json:"public_ip"`
|
||||
VolumeId string `json:"volume_id"`
|
||||
Unused *bool `json:"unused"`
|
||||
}
|
||||
|
||||
type LLMListInput struct {
|
||||
LLMBaseListInput
|
||||
|
||||
LLMModel string `json:"llm_model"`
|
||||
LLMImage string `json:"llm_image"`
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
package llm
|
||||
|
||||
const (
|
||||
STATUS_READY = "ready"
|
||||
)
|
||||
|
||||
const (
|
||||
/* 未知 */
|
||||
LLM_STATUS_UNKOWN = "unkown"
|
||||
|
||||
/* 创建失败 */
|
||||
LLM_STATUS_CREATE_FAIL = "create_fail"
|
||||
|
||||
/* 启动失败 */
|
||||
LLM_STATUS_START_FAIL = "start_fail"
|
||||
/* 停机失败 */
|
||||
LLM_STATUS_STOP_FAILED = "stop_fail"
|
||||
|
||||
/* 停机 */
|
||||
LLM_STATUS_READY = "ready"
|
||||
/* 运行 */
|
||||
LLM_STATUS_RUNNING = "running"
|
||||
|
||||
LLM_STATUS_CREATING_POD = "creating_pod"
|
||||
LLM_STATUS_CREAT_POD_FAILED = "creat_pod_failed"
|
||||
LLM_STATUS_PULLING_MODEL = "pulling_model"
|
||||
LLM_STATUS_GET_MANIFESTS_FAILED = "get_manifests_failed"
|
||||
LLM_STATUS_DOWNLOADING_BLOBS = "downloading_blobs"
|
||||
LLM_STATUS_DOWNLOADING_BLOBS_FAILED = "downloading_blobs_failed"
|
||||
LLM_STATUS_FETCHING_GGUF_FILE = "fetching_gguf_file"
|
||||
LLM_STATUS_FETCH_GGUF_FILE_FAILED = "fetch_gguf_failed"
|
||||
LLM_STATUS_CREATING_GGUF_MODEL = "creating_gguf_model"
|
||||
LLM_STATUS_CREATE_GGUF_MODEL_FAILED = "create_gguf_model_failed"
|
||||
LLM_STATUS_PULLED_MODEL = "pulled_model"
|
||||
LLM_STATUS_PULL_MODEL_FAILED = "pull_model_failed"
|
||||
LLM_STATUS_START_DELETE = "start_delete"
|
||||
LLM_STATUS_DELETING = "deleting"
|
||||
LLM_STATUS_DELETE_FAILED = "delete_fail"
|
||||
)
|
||||
@@ -1,30 +0,0 @@
|
||||
package llm
|
||||
|
||||
import (
|
||||
"yunion.io/x/pkg/util/sets"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis"
|
||||
)
|
||||
|
||||
type LLMContainerType string
|
||||
|
||||
const (
|
||||
LLM_CONTAINER_OLLAMA LLMContainerType = "ollama"
|
||||
)
|
||||
|
||||
var (
|
||||
LLM_CONTAINER_TYPES = sets.NewString(
|
||||
string(LLM_CONTAINER_OLLAMA),
|
||||
)
|
||||
)
|
||||
|
||||
func IsLLMContainerType(t string) bool {
|
||||
return LLM_CONTAINER_TYPES.Has(t)
|
||||
}
|
||||
|
||||
type LLMContainerCreateInput struct {
|
||||
apis.VirtualResourceCreateInput
|
||||
LLMId string `json:"llm_id"`
|
||||
Type string `json:"type"`
|
||||
CmpId string `json:"cmp_id"`
|
||||
}
|
||||
@@ -1,211 +0,0 @@
|
||||
package llm
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/gotypes"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis"
|
||||
computeapi "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
)
|
||||
|
||||
type HostInfo struct {
|
||||
HostId string
|
||||
Host string
|
||||
HostAccessIp string
|
||||
HostEIP string
|
||||
}
|
||||
|
||||
func init() {
|
||||
gotypes.RegisterSerializable(reflect.TypeOf(&PortMappings{}), func() gotypes.ISerializable {
|
||||
return &PortMappings{}
|
||||
})
|
||||
gotypes.RegisterSerializable(reflect.TypeOf(&Devices{}), func() gotypes.ISerializable {
|
||||
return &Devices{}
|
||||
})
|
||||
gotypes.RegisterSerializable(reflect.TypeOf(&PortMappingEnvs{}), func() gotypes.ISerializable {
|
||||
return &PortMappingEnvs{}
|
||||
})
|
||||
gotypes.RegisterSerializable(reflect.TypeOf(&Envs{}), func() gotypes.ISerializable {
|
||||
return &Envs{}
|
||||
})
|
||||
}
|
||||
|
||||
type PortMappingEnv struct {
|
||||
Key string `json:"key"`
|
||||
ValueFrom string `json:"value_from"`
|
||||
}
|
||||
|
||||
type PortMappingEnvs []PortMappingEnv
|
||||
|
||||
func (pm PortMappingEnvs) String() string {
|
||||
return jsonutils.Marshal(pm).String()
|
||||
}
|
||||
|
||||
func (pm PortMappingEnvs) IsZero() bool {
|
||||
return len(pm) == 0
|
||||
}
|
||||
|
||||
type PortMapping struct {
|
||||
Protocol string `json:"protocol"`
|
||||
ContainerPort int `json:"container_port"`
|
||||
RemoteIps []string `json:"remote_ips"`
|
||||
FirstPortOffset *int `json:"first_port_offset"`
|
||||
Envs []computeapi.GuestPortMappingEnv `json:"envs"`
|
||||
}
|
||||
|
||||
type PortMappings []PortMapping
|
||||
|
||||
func (s PortMappings) String() string {
|
||||
return jsonutils.Marshal(s).String()
|
||||
}
|
||||
|
||||
func (s PortMappings) IsZero() bool {
|
||||
return len(s) == 0
|
||||
}
|
||||
|
||||
type Device struct {
|
||||
DevType string `json:"dev_type"`
|
||||
Model string `json:"model"`
|
||||
DevicePath string `json:"device_path"`
|
||||
}
|
||||
|
||||
type Devices []Device
|
||||
|
||||
func (s Devices) String() string {
|
||||
return jsonutils.Marshal(s).String()
|
||||
}
|
||||
|
||||
func (s Devices) IsZero() bool {
|
||||
return len(s) == 0
|
||||
}
|
||||
|
||||
type Env struct {
|
||||
Key string `json:"key"`
|
||||
Value string `json:"value"`
|
||||
}
|
||||
|
||||
type Envs []Env
|
||||
|
||||
func (s Envs) String() string {
|
||||
return jsonutils.Marshal(s).String()
|
||||
}
|
||||
|
||||
func (s Envs) IsZero() bool {
|
||||
return len(s) == 0
|
||||
}
|
||||
|
||||
type LLMModelDetails struct {
|
||||
apis.SharableVirtualResourceDetails
|
||||
// 当前大模型套餐包含的实例个数。
|
||||
LLMCapacity int
|
||||
Image string
|
||||
ImageLabel string
|
||||
ImageName string
|
||||
|
||||
Template string
|
||||
}
|
||||
|
||||
// type MountedAppResourceDetails struct {
|
||||
// MountedApps []string `json:"mounted_apps"`
|
||||
// }
|
||||
|
||||
type LLMModelBaseCreateInput struct {
|
||||
apis.SharableVirtualResourceCreateInput
|
||||
|
||||
Cpu int `json:"cpu"`
|
||||
Memory int `json:"memory"`
|
||||
|
||||
Bandwidth int `json:"bandwidth"`
|
||||
|
||||
Volumes *Volumes `json:"volumes"`
|
||||
PortMappings *PortMappings `json:"port_mappings"`
|
||||
Devices *Devices `json:"devices"`
|
||||
Envs *Envs `json:"envs"`
|
||||
Properties map[string]string `json:"properties"`
|
||||
}
|
||||
|
||||
type LLMModelBaseUpdateInput struct {
|
||||
apis.SharableVirtualResourceBaseUpdateInput
|
||||
// MountedAppResourceUpdateInput
|
||||
|
||||
Cpu *int `json:"cpu"`
|
||||
Memory *int `json:"memory"`
|
||||
|
||||
// RequstSyncImage *bool `json:"request_sync_image"`
|
||||
|
||||
DiskSizeMB *int `json:"disk_size_mb"`
|
||||
TemplateId *string `json:"template_id"`
|
||||
StorageType *string `json:"storage_type"`
|
||||
Volumes *Volumes `json:"volumes"`
|
||||
|
||||
Bandwidth *int `json:"bandwidth"`
|
||||
PortMappings *PortMappings `json:"port_mappings"`
|
||||
Devices *Devices `json:"devices"`
|
||||
Envs *Envs `json:"envs"`
|
||||
Properties map[string]string `json:"properties"`
|
||||
}
|
||||
|
||||
type LLMModelListInput struct {
|
||||
apis.SharableVirtualResourceListInput
|
||||
// MountedAppResourceListInput
|
||||
|
||||
LLMType string `json:"llm_type"`
|
||||
}
|
||||
|
||||
type LLMModelCreateInput struct {
|
||||
LLMModelBaseCreateInput
|
||||
|
||||
LLMImageId string `json:"llm_image_id"`
|
||||
LLMType string `json:"llm_type"`
|
||||
LLMModelName string `json:"llm_model_name"`
|
||||
}
|
||||
|
||||
type LLMModelUpdateInput struct {
|
||||
LLMModelBaseUpdateInput
|
||||
|
||||
LLMImageId string `json:"llm_image_id"`
|
||||
LLMModelName string `json:"llm_model_name"`
|
||||
}
|
||||
|
||||
// type LLMModelCloneInput struct {
|
||||
// Name string `json:"name"`
|
||||
// }
|
||||
|
||||
// type LLMModelSyncImageRequestTaskInput struct {
|
||||
// Request bool `json:"request"`
|
||||
// }
|
||||
|
||||
type DifyModelListInput struct {
|
||||
apis.SharableVirtualResourceListInput
|
||||
// MountedAppResourceListInput
|
||||
}
|
||||
|
||||
type DifyModelCreateInput struct {
|
||||
LLMModelBaseCreateInput
|
||||
|
||||
PostgresImageId string `json:"postgres_image_id"`
|
||||
RedisImageId string `json:"redis_image_id"`
|
||||
NginxImageId string `json:"nginx_image_id"`
|
||||
DifyApiImageId string `json:"dify_api_image_id"`
|
||||
DifyPluginImageId string `json:"dify_plugin_image_id"`
|
||||
DifyWebImageId string `json:"dify_web_image_id"`
|
||||
DifySandboxImageId string `json:"dify_sandbox_image_id"`
|
||||
DifySSRFImageId string `json:"dify_ssrf_image_id"`
|
||||
DifyWeaviateImageId string `json:"dify_weaviate_image_id"`
|
||||
}
|
||||
|
||||
type DifyModelUpdateInput struct {
|
||||
LLMModelBaseUpdateInput
|
||||
|
||||
PostgresImageId string `json:"postgres_image_id"`
|
||||
RedisImageId string `json:"redis_image_id"`
|
||||
NginxImageId string `json:"nginx_image_id"`
|
||||
DifyApiImageId string `json:"dify_api_image_id"`
|
||||
DifyPluginImageId string `json:"dify_plugin_image_id"`
|
||||
DifyWebImageId string `json:"dify_web_image_id"`
|
||||
DifySandboxImageId string `json:"dify_sandbox_image_id"`
|
||||
DifySSRFImageId string `json:"dify_ssrf_image_id"`
|
||||
DifyWeaviateImageId string `json:"dify_weaviate_image_id"`
|
||||
}
|
||||
@@ -1,111 +0,0 @@
|
||||
package llm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis"
|
||||
)
|
||||
|
||||
type OllamaModelFileSpec struct {
|
||||
Parameter *OllamaModelFileParameter `json:"parameter"`
|
||||
Template *string `json:"template,omitempty"`
|
||||
System *string `json:"system,omitempty"`
|
||||
// Adapter *string `json:"adapter,omitempty"`
|
||||
License *string `json:"license,omitempty"`
|
||||
Message []*OllamaModelFileMessage `json:"message,omitempty"`
|
||||
}
|
||||
|
||||
type OllamaGgufSpec struct {
|
||||
GgufFile string `json:"gguf_file"`
|
||||
Source string `json:"source"`
|
||||
ModelFile *OllamaModelFileSpec `json:"modelfile,omitempty"`
|
||||
}
|
||||
|
||||
// type OllamaPullModelInput struct {
|
||||
// Model string `json:"model"`
|
||||
// Gguf *OllamaGgufSpec `json:"gguf,omitempty"`
|
||||
// }
|
||||
|
||||
// type OllamaCreateInput struct {
|
||||
// compute.ServerCreateInput
|
||||
// OllamaPullModelInput
|
||||
// }
|
||||
|
||||
type OllamaListInput struct {
|
||||
apis.VirtualResourceListInput
|
||||
GuestId string `json:"guest_id"`
|
||||
}
|
||||
|
||||
type OllamaAccessCacheInput struct {
|
||||
ModelName string `json:"model_name"`
|
||||
Blobs []string `json:"blobs"`
|
||||
}
|
||||
|
||||
type OllamaAccessGgufFileInput struct {
|
||||
HostPath string `json:"host_path"`
|
||||
TargetDir string `json:"target_dir"`
|
||||
}
|
||||
|
||||
type OllamaModelFileMessage struct {
|
||||
Role string
|
||||
Content string
|
||||
}
|
||||
|
||||
func (m *OllamaModelFileMessage) ValidateRole() error {
|
||||
switch m.Role {
|
||||
case LLM_OLLAMA_GGUF_MESSAGE_ROLE_SYSTEM,
|
||||
LLM_OLLAMA_GGUF_MESSAGE_ROLE_USER,
|
||||
LLM_OLLAMA_GGUF_MESSAGE_ROLE_ASSISTANT:
|
||||
return nil
|
||||
default:
|
||||
return errors.Errorf("invalid role: %s, must be one of: system, user, assistant", m.Role)
|
||||
}
|
||||
}
|
||||
|
||||
type OllamaModelFileParameter struct {
|
||||
NumCtx *int `json:"num_ctx,omitempty"`
|
||||
RepeatLastN *int `json:"repeat_last_n,omitempty"`
|
||||
RepeatPenalty *float64 `json:"repeat_penalty,omitempty"`
|
||||
Temperature *float64 `json:"temperature,omitempty"`
|
||||
Seed *int `json:"seed,omitempty"`
|
||||
Stop *string `json:"stop,omitempty"`
|
||||
NumPredict *int `json:"num_predict,omitempty"`
|
||||
TopK *int `json:"top_k,omitempty"`
|
||||
TopP *float64 `json:"top_p,omitempty"`
|
||||
MinP *float64 `json:"min_p,omitempty"`
|
||||
}
|
||||
|
||||
func (p *OllamaModelFileParameter) GetParameters() map[string]string {
|
||||
pairs := make(map[string]string)
|
||||
|
||||
addInt := func(key string, val *int) {
|
||||
if val != nil {
|
||||
pairs[key] = fmt.Sprintf("%d", *val)
|
||||
}
|
||||
}
|
||||
addFloat := func(key string, val *float64) {
|
||||
if val != nil {
|
||||
pairs[key] = fmt.Sprintf("%f", *val)
|
||||
}
|
||||
}
|
||||
addString := func(key string, val *string) {
|
||||
if val != nil {
|
||||
pairs[key] = fmt.Sprintf("\"%s\"", *val)
|
||||
}
|
||||
}
|
||||
|
||||
addInt(LLM_OLLAMA_MODELFILE_PARAMETER_NUM_CTX, p.NumCtx)
|
||||
addInt(LLM_OLLAMA_MODELFILE_PARAMETER_REPEAT_LAST_N, p.RepeatLastN)
|
||||
addFloat(LLM_OLLAMA_MODELFILE_PARAMETER_REPEAT_PENALTY, p.RepeatPenalty)
|
||||
addFloat(LLM_OLLAMA_MODELFILE_PARAMETER_TEMPERATURE, p.Temperature)
|
||||
addInt(LLM_OLLAMA_MODELFILE_PARAMETER_SEED, p.Seed)
|
||||
addString(LLM_OLLAMA_MODELFILE_PARAMETER_STOP, p.Stop)
|
||||
addInt(LLM_OLLAMA_MODELFILE_PARAMETER_NUM_PREDICT, p.NumPredict)
|
||||
addInt(LLM_OLLAMA_MODELFILE_PARAMETER_TOP_K, p.TopK)
|
||||
addFloat(LLM_OLLAMA_MODELFILE_PARAMETER_TOP_P, p.TopP)
|
||||
addFloat(LLM_OLLAMA_MODELFILE_PARAMETER_MIN_P, p.MinP)
|
||||
|
||||
return pairs
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
package llm
|
||||
|
||||
const (
|
||||
LLM_OLLAMA = "ollama"
|
||||
LLM_OLLAMA_EXEC_PATH = "/bin/ollama"
|
||||
LLM_OLLAMA_PULL_ACTION = "pull"
|
||||
LLM_OLLAMA_LIST_ACTION = "list"
|
||||
LLM_OLLAMA_CREATE_ACTION = "create"
|
||||
LLM_OLLAMA_EXPORT_ENV_KEY = "OLLAMA_HOST"
|
||||
LLM_OLLAMA_EXPORT_ENV_VALUE = "0.0.0.0:11434"
|
||||
)
|
||||
|
||||
const (
|
||||
LLM_OLLAMA_HOST_PATH = "/opt/ollama-models"
|
||||
LLM_OLLAMA_HOST_MANIFESTS_DIR = "/manifests"
|
||||
LLM_OLLAMA_CACHE_DIR = "/.llm_ollama_cache"
|
||||
LLM_OLLAMA_CACHE_MOUNT_PATH = "/usr/local"
|
||||
LLM_OLLAMA_LIBRARY_BASE_URL = `https://registry.ollama.ai/v2/library/%s`
|
||||
LLM_OLLAMA_BASE_PATH = "/root/.ollama/models"
|
||||
LLM_OLLAMA_BLOBS_DIR = "/blobs"
|
||||
LLM_OLLAMA_MANIFESTS_BASE_PATH = "/manifests/registry.ollama.ai/library"
|
||||
)
|
||||
|
||||
const (
|
||||
LLM_OLLAMA_GGUF_DIR = "/gguf"
|
||||
LLM_OLLAMA_GGUF_SOURCE_HOST = "host"
|
||||
LLM_OLLAMA_GGUF_SOURCE_WEB = "web"
|
||||
LLM_OLLAMA_MODELFILE_NAME = "modelfile"
|
||||
LLM_OLLAMA_GGUF_FROM = "FROM %s\n"
|
||||
LLM_OLLAMA_GGUF_PARAMETER = "PARAMETER %s %s\n"
|
||||
LLM_OLLAMA_GGUF_TEMPLATE = "TEMPLATE \"\"\"%s\"\"\"\n"
|
||||
LLM_OLLAMA_GGUF_SYSTEM = "SYSTEM %s\n"
|
||||
LLM_OLLAMA_GGUF_ADAPTER = "ADAPTER %s\n"
|
||||
LLM_OLLAMA_GGUF_LICENSE = "LICENSE \"\"\"%s\"\"\"\n"
|
||||
LLM_OLLAMA_GGUF_MESSAGE = "MESSAGE %s %s\n"
|
||||
LLM_OLLAMA_GGUF_MESSAGE_ROLE_SYSTEM = "system"
|
||||
LLM_OLLAMA_GGUF_MESSAGE_ROLE_USER = "user"
|
||||
LLM_OLLAMA_GGUF_MESSAGE_ROLE_ASSISTANT = "assistant"
|
||||
)
|
||||
|
||||
const (
|
||||
LLM_OLLAMA_MODELFILE_PARAMETER_NUM_CTX = "num_ctx"
|
||||
LLM_OLLAMA_MODELFILE_PARAMETER_REPEAT_LAST_N = "repeat_last_n"
|
||||
LLM_OLLAMA_MODELFILE_PARAMETER_REPEAT_PENALTY = "repeat_penalty"
|
||||
LLM_OLLAMA_MODELFILE_PARAMETER_TEMPERATURE = "temperature"
|
||||
LLM_OLLAMA_MODELFILE_PARAMETER_SEED = "seed"
|
||||
LLM_OLLAMA_MODELFILE_PARAMETER_STOP = "stop"
|
||||
LLM_OLLAMA_MODELFILE_PARAMETER_NUM_PREDICT = "num_predict"
|
||||
LLM_OLLAMA_MODELFILE_PARAMETER_TOP_K = "top_k"
|
||||
LLM_OLLAMA_MODELFILE_PARAMETER_TOP_P = "top_p"
|
||||
LLM_OLLAMA_MODELFILE_PARAMETER_MIN_P = "min_p"
|
||||
)
|
||||
@@ -1,158 +0,0 @@
|
||||
package llm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/gotypes"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis"
|
||||
computeapi "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
)
|
||||
|
||||
func init() {
|
||||
gotypes.RegisterSerializable(reflect.TypeOf(&Volume{}), func() gotypes.ISerializable {
|
||||
return &Volume{}
|
||||
})
|
||||
gotypes.RegisterSerializable(reflect.TypeOf(&Volumes{}), func() gotypes.ISerializable {
|
||||
return &Volumes{}
|
||||
})
|
||||
gotypes.RegisterSerializable(reflect.TypeOf(&ContainerVolumeRelations{}), func() gotypes.ISerializable {
|
||||
return &ContainerVolumeRelations{}
|
||||
})
|
||||
}
|
||||
|
||||
const (
|
||||
VOLUME_STATUS_READY = computeapi.DISK_READY
|
||||
|
||||
VOLUME_STATUS_START_SYNC_STATUS = "start_syncstatus"
|
||||
VOLUME_STATUS_SYNC_STATUS = "syncstatus"
|
||||
VOLUME_STATUS_SYNC_STATUS_FAILED = "syncstatus_fail"
|
||||
|
||||
VOLUME_STATUS_START_RESET = "start_reset"
|
||||
VOLUME_STATUS_RESETTING = "resetting"
|
||||
VOLUME_STATUS_RESET_FAILED = "reset_fail"
|
||||
|
||||
VOLUME_STATUS_START_RESIZE = "start_resize"
|
||||
VOLUME_STATUS_RESIZING = "resizing"
|
||||
VOLUME_STATUS_RESIZE_FAILED = "resize_fail"
|
||||
|
||||
VOLUME_STATUS_ASSIGNING = "assigning"
|
||||
)
|
||||
|
||||
type VolumeDetails struct {
|
||||
apis.VirtualResourceDetails
|
||||
|
||||
Volume
|
||||
|
||||
Template string
|
||||
|
||||
DesktopId string
|
||||
DesktopName string
|
||||
DesktopStatus string
|
||||
|
||||
Disk string
|
||||
|
||||
StorageId string
|
||||
Storage string
|
||||
StorageStatus string
|
||||
StorageHosts []computeapi.StorageHost
|
||||
|
||||
Hosts []HostInfo
|
||||
|
||||
HostInfo
|
||||
|
||||
InstanceId string
|
||||
InstanceName string
|
||||
}
|
||||
|
||||
type ContainerVolumeRelation struct {
|
||||
MountPath string `json:"mount_path"`
|
||||
SubDirectory string `json:"sub_directory"`
|
||||
Overlay *apis.ContainerVolumeMountDiskOverlay `json:"overlay"`
|
||||
FsUser *int64 `json:"fs_user"`
|
||||
FsGroup *int64 `json:"fs_group"`
|
||||
}
|
||||
|
||||
// key is string format of integer
|
||||
type ContainerVolumeRelations map[string]*ContainerVolumeRelation
|
||||
|
||||
func (s ContainerVolumeRelations) String() string {
|
||||
return jsonutils.Marshal(s).String()
|
||||
}
|
||||
|
||||
func (s ContainerVolumeRelations) IsZero() bool {
|
||||
return len(s) == 0
|
||||
}
|
||||
|
||||
type Volume struct {
|
||||
// db.SStandaloneAnonResourceBase
|
||||
Id string
|
||||
Name string
|
||||
StorageType string
|
||||
TemplateId string
|
||||
SizeMB int
|
||||
// Container index to mount path relation
|
||||
Containers ContainerVolumeRelations `json:"containers"`
|
||||
}
|
||||
|
||||
func (s Volume) String() string {
|
||||
return jsonutils.Marshal(s).String()
|
||||
}
|
||||
|
||||
func (s Volume) IsZero() bool {
|
||||
return s.SizeMB == 0
|
||||
}
|
||||
|
||||
func (s Volume) GetVolumeByContainer(containerIndex int) *ContainerVolumeRelation {
|
||||
if len(s.Containers) == 0 {
|
||||
return nil
|
||||
}
|
||||
key := fmt.Sprintf("%d", containerIndex)
|
||||
return s.Containers[key]
|
||||
}
|
||||
|
||||
type Volumes []Volume
|
||||
|
||||
func (s Volumes) String() string {
|
||||
return jsonutils.Marshal(s).String()
|
||||
}
|
||||
|
||||
func (s Volumes) IsZero() bool {
|
||||
return len(s) == 0
|
||||
}
|
||||
|
||||
type VolumeCreateInput struct {
|
||||
apis.VirtualResourceCreateInput
|
||||
ImageId string
|
||||
Size int
|
||||
StorageType string
|
||||
|
||||
PreferHost string
|
||||
}
|
||||
|
||||
type VolumePerformResetInput struct {
|
||||
SizeGb int `json:"size_gb"`
|
||||
}
|
||||
|
||||
type VolumePerformResizeInput struct {
|
||||
Size string `json:"size"`
|
||||
}
|
||||
|
||||
type VolumeResizeTaskInput struct {
|
||||
SizeMB int `json:"size_mb"`
|
||||
DesktopStatus string `json:"desktop_status"`
|
||||
}
|
||||
|
||||
type VolumeListInput struct {
|
||||
apis.VirtualResourceListInput
|
||||
|
||||
Host string `json:"host"`
|
||||
|
||||
Unused *bool `json:"unused"`
|
||||
|
||||
Size string `json:"size"`
|
||||
|
||||
DesktopId string `json:"desktop_id"`
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
package llm_container // import "yunion.io/x/onecloud/pkg/llm/drivers/llm_container"
|
||||
@@ -1,237 +0,0 @@
|
||||
package llm_container
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"path"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis"
|
||||
computeapi "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
api "yunion.io/x/onecloud/pkg/apis/llm"
|
||||
"yunion.io/x/onecloud/pkg/llm/models"
|
||||
"yunion.io/x/onecloud/pkg/llm/utils"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
)
|
||||
|
||||
func init() {
|
||||
models.RegisterLLMContainerDriver(newOllama())
|
||||
// log.Infoln("registed ollama")
|
||||
}
|
||||
|
||||
type ollama struct{}
|
||||
|
||||
func newOllama() models.ILLMContainerDriver {
|
||||
return new(ollama)
|
||||
}
|
||||
|
||||
func (o *ollama) GetType() api.LLMContainerType {
|
||||
return api.LLM_CONTAINER_OLLAMA
|
||||
}
|
||||
|
||||
func (o *ollama) GetContainerSpec(ctx context.Context, llm *models.SLLM, image *models.SLLMImage, sku *models.SLLMModel, props []string, devices []computeapi.SIsolatedDevice, diskId string) *computeapi.PodContainerCreateInput {
|
||||
spec := computeapi.ContainerSpec{
|
||||
ContainerSpec: apis.ContainerSpec{
|
||||
Image: image.ToContainerImage(),
|
||||
ImageCredentialId: image.CredentialId,
|
||||
EnableLxcfs: true,
|
||||
AlwaysRestart: true,
|
||||
},
|
||||
}
|
||||
|
||||
if len(devices) == 0 && len(*sku.Devices) > 0 {
|
||||
for i := range *sku.Devices {
|
||||
index := i
|
||||
spec.Devices = append(spec.Devices, &computeapi.ContainerDevice{
|
||||
Type: apis.CONTAINER_DEVICE_TYPE_ISOLATED_DEVICE,
|
||||
IsolatedDevice: &computeapi.ContainerIsolatedDevice{
|
||||
Index: &index,
|
||||
},
|
||||
})
|
||||
}
|
||||
} else if len(devices) > 0 {
|
||||
for i := range devices {
|
||||
spec.Devices = append(spec.Devices, &computeapi.ContainerDevice{
|
||||
Type: apis.CONTAINER_DEVICE_TYPE_ISOLATED_DEVICE,
|
||||
IsolatedDevice: &computeapi.ContainerIsolatedDevice{
|
||||
Id: devices[i].Id,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// // process rootfs limit
|
||||
// var diskIndex *int
|
||||
// if len(diskId) == 0 {
|
||||
// diskIndex0 := 0
|
||||
// diskIndex = &diskIndex0
|
||||
// }
|
||||
// if options.Options.EnableRootfsLimit {
|
||||
// if !d.RootfsUnlimit {
|
||||
// spec.RootFs = &apis.ContainerRootfs{
|
||||
// Type: apis.CONTAINER_VOLUME_MOUNT_TYPE_DISK,
|
||||
// Disk: &apis.ContainerVolumeMountDisk{
|
||||
// Index: diskIndex,
|
||||
// Id: diskId,
|
||||
// SubDirectory: "/rootfs-steam",
|
||||
// },
|
||||
// Persistent: false,
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// process volume mounts
|
||||
vols := make([]*apis.ContainerVolumeMount, 0)
|
||||
// appVolIndex := 2
|
||||
// postOverlays, err := d.GetMountedAppsPostOverlay()
|
||||
// if err != nil {
|
||||
// log.Errorf("GetMountedAppsPostOverlay failed %s", err)
|
||||
// }
|
||||
// vols = append(spec.VolumeMounts, GetDiskVolumeMounts(sku.Volumes, appVolIndex, postOverlays)...)
|
||||
|
||||
// udevPath := filepath.Join(GetTmpSocketsHostPath(d.GetName()), "udev")
|
||||
modelName, modelTag, _ := llm.GetLargeLanguageModelName()
|
||||
ctrVols := []*apis.ContainerVolumeMount{
|
||||
{
|
||||
UniqueName: "manifests",
|
||||
Type: apis.CONTAINER_VOLUME_MOUNT_TYPE_HOST_PATH,
|
||||
MountPath: getManifestsPath(modelName, modelTag),
|
||||
HostPath: &apis.ContainerVolumeMountHostPath{
|
||||
Type: apis.CONTAINER_VOLUME_MOUNT_HOST_PATH_TYPE_FILE,
|
||||
Path: path.Join(api.LLM_OLLAMA_HOST_PATH, api.LLM_OLLAMA_HOST_MANIFESTS_DIR, modelName+"-"+modelTag),
|
||||
},
|
||||
ReadOnly: true,
|
||||
},
|
||||
{
|
||||
UniqueName: "blobs",
|
||||
Type: apis.CONTAINER_VOLUME_MOUNT_TYPE_HOST_PATH,
|
||||
MountPath: path.Join(api.LLM_OLLAMA_BASE_PATH, api.LLM_OLLAMA_BLOBS_DIR),
|
||||
HostPath: &apis.ContainerVolumeMountHostPath{
|
||||
Type: apis.CONTAINER_VOLUME_MOUNT_HOST_PATH_TYPE_DIRECTORY,
|
||||
Path: path.Join(api.LLM_OLLAMA_HOST_PATH, api.LLM_OLLAMA_BLOBS_DIR),
|
||||
},
|
||||
ReadOnly: true,
|
||||
},
|
||||
}
|
||||
vols = append(vols, ctrVols...)
|
||||
|
||||
spec.VolumeMounts = vols
|
||||
|
||||
return &computeapi.PodContainerCreateInput{
|
||||
ContainerSpec: spec,
|
||||
}
|
||||
}
|
||||
|
||||
// func (o *ollama) PullModelByInstall(ctx context.Context, userCred mcclient.TokenCredential, llm *models.SLLM, modelName string, modelTag string) error {
|
||||
// return nil
|
||||
// }
|
||||
|
||||
// func (o *ollama) PullModelByGgufFile(ctx context.Context, userCred mcclient.TokenCredential, llm *models.SLLM, ggufFileUrl string, model string) error {
|
||||
// return nil
|
||||
// }
|
||||
|
||||
// func (o *ollama) GetManifests(ctx context.Context, userCred mcclient.TokenCredential, llm *models.SLLM, taskId string) error {
|
||||
// modelName, modelTag, _ := llm.GetLargeLanguageModelName()
|
||||
// suffix := fmt.Sprintf("%s/manifests/%s", modelName, modelTag)
|
||||
// url := fmt.Sprintf(api.LLM_OLLAMA_LIBRARY_BASE_URL, suffix)
|
||||
// ctr, _ := llm.GetLLMContainer()
|
||||
|
||||
// return download(ctx, userCred, ctr.CmpId, taskId, url, getManifestsPath(modelName, modelTag))
|
||||
// }
|
||||
|
||||
// func (o *ollama) AccessBlobsCache(ctx context.Context, userCred mcclient.TokenCredential, llm *models.SLLM, taskId string) error {
|
||||
// ctr, _ := llm.GetLLMContainer()
|
||||
// modelName, modelTag, _ := llm.GetLargeLanguageModelName()
|
||||
// blobs, err := fetchBlobs(ctx, userCred, ctr.CmpId, modelName, modelTag)
|
||||
// if err != nil {
|
||||
// return errors.Wrapf(err, "failed to fetch blobs for model %s:%s", modelName, modelTag)
|
||||
// }
|
||||
|
||||
// input := &api.OllamaAccessCacheInput{
|
||||
// Blobs: blobs,
|
||||
// ModelName: modelName,
|
||||
// }
|
||||
// _, err = ollama_pod.RequestOllamaBlobsCache(ctx, userCred, ctr.CmpId, taskId, input)
|
||||
|
||||
// return err
|
||||
// }
|
||||
|
||||
func (o *ollama) CopyBlobs(ctx context.Context, userCred mcclient.TokenCredential, llm *models.SLLM) error {
|
||||
ctr, _ := llm.GetLLMContainer()
|
||||
modelName, modelTag, _ := llm.GetLargeLanguageModelName()
|
||||
blobs, _ := fetchBlobs(ctx, ctr.CmpId, modelName, modelTag)
|
||||
|
||||
blobsTargetDir := path.Join(api.LLM_OLLAMA_BASE_PATH, api.LLM_OLLAMA_BLOBS_DIR)
|
||||
blobsSrcDir := path.Join(api.LLM_OLLAMA_CACHE_MOUNT_PATH, api.LLM_OLLAMA_CACHE_DIR)
|
||||
|
||||
var commands []string
|
||||
commands = append(commands, fmt.Sprintf("mkdir -p %s", blobsTargetDir))
|
||||
for _, blob := range blobs {
|
||||
src := path.Join(blobsSrcDir, blob)
|
||||
target := path.Join(blobsTargetDir, blob)
|
||||
commands = append(commands, fmt.Sprintf("cp %s %s", src, target))
|
||||
}
|
||||
|
||||
cmd := strings.Join(commands, " && ")
|
||||
if _, err := exec(ctx, ctr.CmpId, "/bin/sh", "-c", cmd); err != nil {
|
||||
return errors.Wrapf(err, "failed to copy blobs to container")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// func download(ctx context.Context, userCred mcclient.TokenCredential, containerId string, taskId string, webUrl string, path string) error {
|
||||
// input := &computeapi.ContainerDownloadFileInput{
|
||||
// WebUrl: webUrl,
|
||||
// Path: path,
|
||||
// }
|
||||
|
||||
// _, err := ollama_pod.RequestDownloadFileIntoContainer(ctx, userCred, containerId, taskId, input)
|
||||
// return err
|
||||
// }
|
||||
|
||||
func exec(ctx context.Context, containerId string, command ...string) (string, error) {
|
||||
// exec command
|
||||
|
||||
input := &computeapi.ContainerExecSyncInput{
|
||||
Command: command,
|
||||
}
|
||||
resp, err := utils.ExecSyncContainer(ctx, containerId, input)
|
||||
|
||||
// check error and return result
|
||||
var rst string
|
||||
if nil != err || resp == nil {
|
||||
return "", errors.Wrapf(err, "LLM exec error")
|
||||
}
|
||||
rst, _ = resp.GetString("stdout")
|
||||
log.Infoln("llm container exec result: ", resp)
|
||||
return rst, nil
|
||||
}
|
||||
|
||||
func getManifestsPath(modelName, modelTag string) string {
|
||||
return path.Join(api.LLM_OLLAMA_BASE_PATH, api.LLM_OLLAMA_MANIFESTS_BASE_PATH, modelName, modelTag)
|
||||
}
|
||||
|
||||
func fetchBlobs(ctx context.Context, containerId string, modelName string, modelTag string) ([]string, error) {
|
||||
manifestContent, err := exec(ctx, containerId, "cat", getManifestsPath(modelName, modelTag))
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to read manifests from container")
|
||||
}
|
||||
|
||||
// find all blobs
|
||||
var results []string
|
||||
re := regexp.MustCompile(`"digest":"(sha256:[^"]*)"`)
|
||||
matches := re.FindAllStringSubmatch(manifestContent, -1)
|
||||
for _, match := range matches {
|
||||
if len(match) > 1 {
|
||||
digest := match[1]
|
||||
processedDigest := strings.Replace(digest, "sha256:", "sha256-", 1)
|
||||
results = append(results, processedDigest)
|
||||
}
|
||||
}
|
||||
|
||||
return results, nil
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
api "yunion.io/x/onecloud/pkg/apis/llm"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
)
|
||||
|
||||
var accessInfoManager *SAccessInfoManager
|
||||
|
||||
func init() {
|
||||
GetAccessInfoManager()
|
||||
}
|
||||
|
||||
func GetAccessInfoManager() *SAccessInfoManager {
|
||||
if accessInfoManager == nil {
|
||||
accessInfoManager = &SAccessInfoManager{
|
||||
SResourceBaseManager: db.NewResourceBaseManager(
|
||||
SAccessInfo{},
|
||||
"access_infos_tbl",
|
||||
"access_info",
|
||||
"access_infos",
|
||||
),
|
||||
}
|
||||
accessInfoManager.SetVirtualObject(accessInfoManager)
|
||||
}
|
||||
return accessInfoManager
|
||||
}
|
||||
|
||||
type SAccessInfoManager struct {
|
||||
db.SResourceBaseManager
|
||||
}
|
||||
|
||||
type SAccessInfo struct {
|
||||
db.SResourceBase
|
||||
|
||||
LLMId string `width:"128" charset:"ascii" nullable:"true" list:"user" create:"admin_optional" update:"user"`
|
||||
|
||||
// 服务监听端口
|
||||
ListenPort int `nullable:"true" create:"optional" list:"user" update:"user"`
|
||||
// 映射到公网的访问端口
|
||||
AccessPort int `nullable:"true" create:"optional" list:"user" update:"user"`
|
||||
|
||||
// 自定义端口类型
|
||||
Protocol string `width:"32" charset:"ascii" nullable:"true" list:"user" create:"admin_optional" update:"user"`
|
||||
|
||||
RemoteIps []string `charset:"ascii" nullable:"true" list:"user" create:"admin_optional" update:"user"`
|
||||
PortMappingEnvs api.PortMappingEnvs `charset:"ascii" nullable:"true" list:"user" create:"admin_optional"`
|
||||
}
|
||||
@@ -1,292 +0,0 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/utils"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
commonapi "yunion.io/x/onecloud/pkg/apis"
|
||||
computeapi "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
api "yunion.io/x/onecloud/pkg/apis/llm"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/auth"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules/compute"
|
||||
)
|
||||
|
||||
var difyManager *SDifyManager
|
||||
|
||||
func init() {
|
||||
GetDifyManager()
|
||||
}
|
||||
|
||||
func GetDifyManager() *SDifyManager {
|
||||
if difyManager != nil {
|
||||
return difyManager
|
||||
}
|
||||
difyManager = &SDifyManager{
|
||||
SLLMBaseManager: NewSLLMBaseManager(
|
||||
SDify{},
|
||||
"difies_tbl",
|
||||
"dify",
|
||||
"difies",
|
||||
),
|
||||
}
|
||||
difyManager.SetVirtualObject(difyManager)
|
||||
return difyManager
|
||||
}
|
||||
|
||||
type SDifyManager struct {
|
||||
SLLMBaseManager
|
||||
}
|
||||
|
||||
type SDify struct {
|
||||
SLLMBase
|
||||
|
||||
DifyModelId string `width:"128" charset:"ascii" nullable:"false" list:"user" create:"required"`
|
||||
}
|
||||
|
||||
func (dm *SDifyManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input *api.DifyCreateInput) (*api.DifyCreateInput, error) {
|
||||
var err error
|
||||
input.LLMBaseCreateInput, err = dm.SLLMBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.LLMBaseCreateInput)
|
||||
if err != nil {
|
||||
return input, errors.Wrap(err, "validate VirtualResourceCreateInput")
|
||||
}
|
||||
model, err := GetDifyModelManager().FetchByIdOrName(ctx, userCred, input.DifyModelId)
|
||||
if err != nil {
|
||||
return input, errors.Wrap(err, "fetch DifyModel")
|
||||
}
|
||||
dModel := model.(*SDifyModel)
|
||||
input.DifyModelId = dModel.Id
|
||||
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (dm *SDifyManager) OnCreateComplete(ctx context.Context, items []db.IModel, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data []jsonutils.JSONObject) {
|
||||
parentTaskId, _ := data[0].GetString("parent_task_id")
|
||||
err := runBatchCreateTask(ctx, items, userCred, data, "DifyBatchCreateTask", parentTaskId)
|
||||
if err != nil {
|
||||
for i := range items {
|
||||
llm := items[i].(*SDify)
|
||||
llm.SetStatus(ctx, userCred, api.LLM_STATUS_CREATE_FAIL, err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (dm *SDifyManager) BatchCreateValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input api.DifyCreateInput) (*jsonutils.JSONDict, error) {
|
||||
data, err := dm.ValidateCreateData(ctx, userCred, ownerId, query, &input)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return data.JSON(data), nil
|
||||
}
|
||||
|
||||
func (dm *SDifyManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQuery, userCred mcclient.TokenCredential, input api.DifyListInput) (*sqlchemy.SQuery, error) {
|
||||
q, err := dm.SLLMBaseManager.ListItemFilter(ctx, q, userCred, input.LLMBaseListInput)
|
||||
if err != nil {
|
||||
return q, errors.Wrap(err, "VirtualResourceBaseManager.ListItemFilter")
|
||||
}
|
||||
if len(input.DifyModel) > 0 {
|
||||
modelObj, err := GetDifyModelManager().FetchByIdOrName(ctx, userCred, input.DifyModel)
|
||||
if err != nil {
|
||||
if errors.Cause(err) == sql.ErrNoRows {
|
||||
return nil, httperrors.NewResourceNotFoundError2(GetDifyModelManager().KeywordPlural(), input.DifyModel)
|
||||
} else {
|
||||
return nil, errors.Wrap(err, "DifyModelManager.FetchByIdOrName")
|
||||
}
|
||||
}
|
||||
q = q.Equals("dify_model_id", modelObj.GetId())
|
||||
}
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (dify *SDify) CustomizeDelete(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
|
||||
return dify.StartDeleteTask(ctx, userCred, "")
|
||||
}
|
||||
|
||||
func (dify *SDify) GetDifyModel(modelId string) (*SDifyModel, error) {
|
||||
if len(modelId) == 0 {
|
||||
modelId = dify.DifyModelId
|
||||
}
|
||||
model, err := GetDifyModelManager().FetchById(modelId)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "fetch DifyModel")
|
||||
}
|
||||
return model.(*SDifyModel), nil
|
||||
}
|
||||
|
||||
func (dify *SDify) GetDifyContainers() []*computeapi.PodContainerCreateInput {
|
||||
keys := []string{
|
||||
api.DIFY_POSTGRES_KEY,
|
||||
api.DIFY_REDIS_KEY,
|
||||
api.DIFY_API_KEY,
|
||||
api.DIFY_WORKER_KEY,
|
||||
api.DIFY_WORKER_BEAT_KEY,
|
||||
api.DIFY_PLUGIN_KEY,
|
||||
api.DIFY_SANDBOX_KEY,
|
||||
api.DIFY_SSRF_KEY,
|
||||
api.DIFY_WEB_KEY,
|
||||
api.DIFY_NGINX_KEY,
|
||||
api.DIFY_WEAVIATE_KEY,
|
||||
}
|
||||
|
||||
var containers []*computeapi.PodContainerCreateInput
|
||||
for _, key := range keys {
|
||||
if c, err := dify.getDifyContainerByContainerKey(key); err == nil {
|
||||
containers = append(containers, c)
|
||||
}
|
||||
}
|
||||
return containers
|
||||
}
|
||||
|
||||
func (dify *SDify) StartCreateTask(ctx context.Context, userCred mcclient.TokenCredential, input api.DifyCreateInput, parentTaskId string) error {
|
||||
dify.SetStatus(ctx, userCred, commonapi.STATUS_CREATING, "")
|
||||
params := jsonutils.Marshal(input).(*jsonutils.JSONDict)
|
||||
var err = func() error {
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "DifyCreateTask", dify, userCred, params, parentTaskId, "", nil)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "NewTask")
|
||||
}
|
||||
return task.ScheduleRun(params)
|
||||
}()
|
||||
if err != nil {
|
||||
dify.SetStatus(ctx, userCred, api.LLM_STATUS_CREATE_FAIL, err.Error())
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (dify *SDify) StartDeleteTask(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
|
||||
dify.SetStatus(ctx, userCred, api.LLM_STATUS_START_DELETE, "StartDeleteTask")
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "DifyDeleteTask", dify, userCred, nil, parentTaskId, "", nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return task.ScheduleRun(nil)
|
||||
}
|
||||
|
||||
func (dify *SDify) ServerCreate(ctx context.Context, userCred mcclient.TokenCredential, input *api.DifyCreateInput) (string, error) {
|
||||
model, err := dify.GetDifyModel(dify.DifyModelId)
|
||||
if nil != err {
|
||||
return "", errors.Wrap(err, "GetDifyModel")
|
||||
}
|
||||
|
||||
// set AutoStart to true
|
||||
input.AutoStart = true
|
||||
data, err := GetDifyPodCreateInput(ctx, userCred, input, dify, model, "")
|
||||
if nil != err {
|
||||
return "", errors.Wrap(err, "GetDifyPodCreateInput")
|
||||
}
|
||||
log.Infoln("PodCreateInput Data: ", jsonutils.Marshal(data).String())
|
||||
|
||||
s := auth.GetSession(ctx, userCred, "")
|
||||
resp, err := compute.Servers.Create(s, jsonutils.Marshal(data))
|
||||
if nil != err {
|
||||
return "", errors.Wrap(err, "Servers.Create")
|
||||
}
|
||||
id, err := resp.GetString("id")
|
||||
if nil != err {
|
||||
return "", errors.Wrap(err, "resp.GetString")
|
||||
}
|
||||
|
||||
return id, nil
|
||||
}
|
||||
|
||||
// func (llm *SDify) ValidateDeleteCondition(ctx context.Context, info jsonutils.JSONObject) error {
|
||||
// instanceId, isBound, err := llm.IsBoundToInstance()
|
||||
// if err != nil {
|
||||
// return errors.Wrap(err, "IsBoundToInstance")
|
||||
// }
|
||||
// if isBound {
|
||||
// return httperrors.NewBadRequestError("llm is bound to instance %s", instanceId)
|
||||
// }
|
||||
// return nil
|
||||
// }
|
||||
|
||||
func (dify *SDify) getDifyContainerByContainerKey(containerKey string) (*computeapi.PodContainerCreateInput, error) {
|
||||
model, err := dify.GetDifyModel("")
|
||||
if nil != err {
|
||||
return nil, err
|
||||
}
|
||||
container, err := getDifyContainersManager().GetContainer(dify.GetName(), containerKey, model)
|
||||
if nil != err {
|
||||
return nil, err
|
||||
}
|
||||
container.AlwaysRestart = true // always restart to solve dependency issue
|
||||
return container, nil
|
||||
}
|
||||
|
||||
func (dify *SDify) PerformStart(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
// can't start while it's already running
|
||||
if utils.IsInStringArray(dify.Status, computeapi.VM_RUNNING_STATUS) {
|
||||
return nil, errors.Wrapf(errors.ErrInvalidStatus, "dify id: %s status: %s", dify.Id, dify.Status)
|
||||
}
|
||||
|
||||
if err := dify.StartStartTask(ctx, userCred, ""); err != nil {
|
||||
return nil, errors.Wrap(err, "StartStartTask")
|
||||
}
|
||||
return jsonutils.Marshal(nil), nil
|
||||
}
|
||||
|
||||
func (dify *SDify) StartStartTask(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "DifyStartTask", dify, userCred, nil, parentTaskId, "", nil)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "NewTask")
|
||||
}
|
||||
return task.ScheduleRun(nil)
|
||||
}
|
||||
|
||||
func (dify *SDify) PerformStop(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
if dify.Status == computeapi.VM_READY {
|
||||
return nil, errors.Wrapf(errors.ErrInvalidStatus, "dify id: %s status: %s", dify.Id, dify.Status)
|
||||
}
|
||||
dify.SetStatus(ctx, userCred, computeapi.VM_START_STOP, "perform stop")
|
||||
err := dify.StartDifyStopTask(ctx, userCred, "")
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "StartStopTask")
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (dify *SDify) StartDifyStopTask(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "DifyStopTask", dify, userCred, nil, parentTaskId, "", nil)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "NewTask")
|
||||
}
|
||||
err = task.ScheduleRun(nil)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "ScheduleRun")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// func (dify *SDify) ContainerCreate(ctx context.Context, userCred mcclient.TokenCredential, containerKey string) (string, error) {
|
||||
// model, err := dify.GetDifyModel("")
|
||||
// if nil != err {
|
||||
// return "", errors.Wrap(err, "GetDifyModel")
|
||||
// }
|
||||
// // get input
|
||||
// input, err := getDifyContainersManager().GetContainer(dify.GetName(), containerKey, model)
|
||||
// if nil != err {
|
||||
// return "", errors.Wrap(err, "GetContainer")
|
||||
// }
|
||||
|
||||
// // create on pod
|
||||
// params := &computeapi.ContainerCreateInput{
|
||||
// Spec: input.ContainerSpec,
|
||||
// }
|
||||
// s := auth.GetSession(ctx, userCred, "")
|
||||
|
||||
// return "", nil
|
||||
// }
|
||||
|
||||
func getDifyContainersManager() *DifyContainersManager {
|
||||
return &DifyContainersManager{}
|
||||
}
|
||||
@@ -1,242 +0,0 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/apis"
|
||||
api "yunion.io/x/onecloud/pkg/apis/llm"
|
||||
)
|
||||
|
||||
var sharedApiWorkerEnvKeyVal []*apis.ContainerKeyValue
|
||||
|
||||
func getSharedApiWorkerEnv(custom *DifyContainerEnv) []*apis.ContainerKeyValue {
|
||||
if sharedApiWorkerEnvKeyVal == nil {
|
||||
sharedApiWorkerEnv := &DifyContainerEnv{
|
||||
"CONSOLE_API_URL": "",
|
||||
"CONSOLE_WEB_URL": "",
|
||||
"SERVICE_API_URL": "",
|
||||
"APP_API_URL": "",
|
||||
"APP_WEB_URL": "",
|
||||
"LANG": "en_US.UTF-8",
|
||||
"LC_ALL": "en_US.UTF-8",
|
||||
"PYTHONIOENCODING": "utf-8",
|
||||
"LOG_LEVEL": "INFO",
|
||||
"LOG_FILE": "/app/logs/server.log",
|
||||
"LOG_FILE_MAX_SIZE": "20",
|
||||
"LOG_FILE_BACKUP_COUNT": "5",
|
||||
"LOG_DATEFORMAT": "%Y-%m-%d %H:%M:%S",
|
||||
"LOG_TZ": "UTC",
|
||||
"DEBUG": "false",
|
||||
"FLASK_DEBUG": "false",
|
||||
"ENABLE_REQUEST_LOGGING": "False",
|
||||
"SECRET_KEY": api.DIFY_SECRET_KEY,
|
||||
"INIT_PASSWORD": "",
|
||||
"DEPLOY_ENV": "PRODUCTION",
|
||||
"CHECK_UPDATE_URL": "https://updates.dify.ai",
|
||||
"OPENAI_API_BASE": "https://api.openai.com/v1",
|
||||
"MIGRATION_ENABLED": "true",
|
||||
"FILES_ACCESS_TIMEOUT": "300",
|
||||
"ACCESS_TOKEN_EXPIRE_MINUTES": "60",
|
||||
"REFRESH_TOKEN_EXPIRE_DAYS": "30",
|
||||
"APP_MAX_ACTIVE_REQUESTS": "0",
|
||||
"APP_MAX_EXECUTION_TIME": "1200",
|
||||
"DIFY_BIND_ADDRESS": "0.0.0.0",
|
||||
"DIFY_PORT": "5001",
|
||||
"SERVER_WORKER_AMOUNT": "1",
|
||||
"SERVER_WORKER_CLASS": "gevent",
|
||||
"SERVER_WORKER_CONNECTIONS": "10",
|
||||
"CELERY_WORKER_CLASS": "",
|
||||
"GUNICORN_TIMEOUT": "360",
|
||||
"CELERY_WORKER_AMOUNT": "",
|
||||
"CELERY_AUTO_SCALE": "false",
|
||||
"CELERY_MAX_WORKERS": "",
|
||||
"CELERY_MIN_WORKERS": "",
|
||||
"API_TOOL_DEFAULT_CONNECT_TIMEOUT": "10",
|
||||
"API_TOOL_DEFAULT_READ_TIMEOUT": "60",
|
||||
"ENABLE_WEBSITE_JINAREADER": api.DIFY_WEB_ENABLE_WEBSITE_JINAREADER,
|
||||
"ENABLE_WEBSITE_FIRECRAWL": api.DIFY_WEB_ENABLE_WEBSITE_FIRECRAWL,
|
||||
"ENABLE_WEBSITE_WATERCRAWL": api.DIFY_WEB_ENABLE_WEBSITE_WATERCRAWL,
|
||||
"DB_USERNAME": api.DIFY_POSTGRES_USER,
|
||||
"DB_PASSWORD": api.DIFY_POSTGRES_PASSWORD,
|
||||
"DB_HOST": api.DIFY_LOCALHOST,
|
||||
"DB_PORT": api.DIFY_POSTGRES_PORT,
|
||||
"DB_DATABASE": "dify",
|
||||
"SQLALCHEMY_POOL_SIZE": "30",
|
||||
"SQLALCHEMY_POOL_RECYCLE": "3600",
|
||||
"SQLALCHEMY_ECHO": "false",
|
||||
"SQLALCHEMY_POOL_PRE_PING": "false",
|
||||
"SQLALCHEMY_POOL_USE_LIFO": "false",
|
||||
"POSTGRES_MAX_CONNECTIONS": api.DIFY_POSTGRES_MAX_CONNECTIONS,
|
||||
"POSTGRES_SHARED_BUFFERS": api.DIFY_POSTGRES_SHARED_BUFFERS,
|
||||
"POSTGRES_WORK_MEM": api.DIFY_POSTGRES_WORK_MEM,
|
||||
"POSTGRES_MAINTENANCE_WORK_MEM": api.DIFY_POSTGRES_MAINTENANCE_WORK_MEM,
|
||||
"POSTGRES_EFFECTIVE_CACHE_SIZE": api.DIFY_POSTGRES_EFFECTIVE_CACHE_SIZE,
|
||||
"REDIS_HOST": api.DIFY_LOCALHOST,
|
||||
"REDIS_PORT": api.DIFY_REDIS_PORT,
|
||||
"REDIS_USERNAME": "",
|
||||
"REDIS_PASSWORD": api.DIFY_REDISCLI_AUTH,
|
||||
"REDIS_USE_SSL": "false",
|
||||
"REDIS_DB": "0",
|
||||
"REDIS_USE_SENTINEL": "false",
|
||||
"REDIS_SENTINELS": "",
|
||||
"REDIS_SENTINEL_SERVICE_NAME": "",
|
||||
"REDIS_SENTINEL_USERNAME": "",
|
||||
"REDIS_SENTINEL_PASSWORD": "",
|
||||
"REDIS_SENTINEL_SOCKET_TIMEOUT": "0.1",
|
||||
"REDIS_USE_CLUSTERS": "false",
|
||||
"REDIS_CLUSTERS": "",
|
||||
"REDIS_CLUSTERS_PASSWORD": "",
|
||||
"CELERY_BROKER_URL": "redis://:" + api.DIFY_REDISCLI_AUTH + "@" + api.DIFY_LOCALHOST + ":" + api.DIFY_REDIS_PORT + "/1",
|
||||
"CELERY_BACKEND": api.DIFY_LOCALHOST,
|
||||
"BROKER_USE_SSL": "false",
|
||||
"CELERY_USE_SENTINEL": "false",
|
||||
"CELERY_SENTINEL_MASTER_NAME": "",
|
||||
"CELERY_SENTINEL_PASSWORD": "",
|
||||
"CELERY_SENTINEL_SOCKET_TIMEOUT": "0.1",
|
||||
"STORAGE_TYPE": "opendal",
|
||||
"OPENDAL_SCHEME": "fs",
|
||||
"OPENDAL_FS_ROOT": "storage",
|
||||
"VECTOR_STORE": "weaviate",
|
||||
"VECTOR_INDEX_NAME_PREFIX": "Vector_index",
|
||||
"WEAVIATE_ENDPOINT": "http://" + api.DIFY_LOCALHOST + ":8080",
|
||||
"WEAVIATE_API_KEY": api.DIFY_WEAVIATE_AUTHENTICATION_APIKEY_ALLOWED_KEYS,
|
||||
"UPLOAD_FILE_SIZE_LIMIT": "15",
|
||||
"UPLOAD_FILE_BATCH_LIMIT": "5",
|
||||
"ETL_TYPE": "dify",
|
||||
"UNSTRUCTURED_API_URL": "",
|
||||
"UNSTRUCTURED_API_KEY": "",
|
||||
"SCARF_NO_ANALYTICS": "true",
|
||||
"PROMPT_GENERATION_MAX_TOKENS": "512",
|
||||
"CODE_GENERATION_MAX_TOKENS": "1024",
|
||||
"PLUGIN_BASED_TOKEN_COUNTING_ENABLED": "false",
|
||||
"MULTIMODAL_SEND_FORMAT": "base64",
|
||||
"UPLOAD_IMAGE_FILE_SIZE_LIMIT": "10",
|
||||
"UPLOAD_VIDEO_FILE_SIZE_LIMIT": "100",
|
||||
"UPLOAD_AUDIO_FILE_SIZE_LIMIT": "50",
|
||||
"API_SENTRY_DSN": api.DIFY_API_SENTRY_DSN,
|
||||
"API_SENTRY_TRACES_SAMPLE_RATE": api.DIFY_API_SENTRY_TRACES_SAMPLE_RATE,
|
||||
"API_SENTRY_PROFILES_SAMPLE_RATE": api.DIFY_API_SENTRY_PROFILES_SAMPLE_RATE,
|
||||
"WEB_SENTRY_DSN": "",
|
||||
"NOTION_INTEGRATION_TYPE": "public",
|
||||
"NOTION_CLIENT_SECRET": "",
|
||||
"NOTION_CLIENT_ID": "",
|
||||
"NOTION_INTERNAL_SECRET": "",
|
||||
"MAIL_TYPE": "resend",
|
||||
"MAIL_DEFAULT_SEND_FROM": "",
|
||||
"RESEND_API_URL": "https://api.resend.com",
|
||||
"RESEND_API_KEY": "your-resend-api-key",
|
||||
"SMTP_SERVER": "",
|
||||
"SMTP_PORT": "465",
|
||||
"SMTP_USERNAME": "",
|
||||
"SMTP_PASSWORD": "",
|
||||
"SMTP_USE_TLS": "true",
|
||||
"SMTP_OPPORTUNISTIC_TLS": "false",
|
||||
"SENDGRID_API_KEY": "",
|
||||
"INDEXING_MAX_SEGMENTATION_TOKENS_LENGTH": api.DIFY_WEB_INDEXING_MAX_SEGMENTATION_TOKENS_LENGTH,
|
||||
"INVITE_EXPIRY_HOURS": "72",
|
||||
"RESET_PASSWORD_TOKEN_EXPIRY_MINUTES": "5",
|
||||
"CHANGE_EMAIL_TOKEN_EXPIRY_MINUTES": "5",
|
||||
"OWNER_TRANSFER_TOKEN_EXPIRY_MINUTES": "5",
|
||||
"CODE_EXECUTION_ENDPOINT": "http://" + api.DIFY_LOCALHOST + ":8194",
|
||||
"CODE_EXECUTION_API_KEY": api.DIFY_SANDBOX_API_KEY,
|
||||
"CODE_MAX_NUMBER": "9223372036854775807",
|
||||
"CODE_MIN_NUMBER": "-9223372036854775808",
|
||||
"CODE_MAX_DEPTH": "5",
|
||||
"CODE_MAX_PRECISION": "20",
|
||||
"CODE_MAX_STRING_LENGTH": "80000",
|
||||
"CODE_MAX_STRING_ARRAY_LENGTH": "30",
|
||||
"CODE_MAX_OBJECT_ARRAY_LENGTH": "30",
|
||||
"CODE_MAX_NUMBER_ARRAY_LENGTH": "1000",
|
||||
"CODE_EXECUTION_CONNECT_TIMEOUT": "10",
|
||||
"CODE_EXECUTION_READ_TIMEOUT": "60",
|
||||
"CODE_EXECUTION_WRITE_TIMEOUT": "10",
|
||||
"TEMPLATE_TRANSFORM_MAX_LENGTH": "80000",
|
||||
"WORKFLOW_MAX_EXECUTION_STEPS": "500",
|
||||
"WORKFLOW_MAX_EXECUTION_TIME": "1200",
|
||||
"WORKFLOW_CALL_MAX_DEPTH": "5",
|
||||
"MAX_VARIABLE_SIZE": "204800",
|
||||
"WORKFLOW_PARALLEL_DEPTH_LIMIT": "3",
|
||||
"WORKFLOW_FILE_UPLOAD_LIMIT": "10",
|
||||
"WORKFLOW_NODE_EXECUTION_STORAGE": "rdbms",
|
||||
"CORE_WORKFLOW_EXECUTION_REPOSITORY": "core.repositories.sqlalchemy_workflow_execution_repository.SQLAlchemyWorkflowExecutionRepository",
|
||||
"CORE_WORKFLOW_NODE_EXECUTION_REPOSITORY": "core.repositories.sqlalchemy_workflow_node_execution_repository.SQLAlchemyWorkflowNodeExecutionRepository",
|
||||
"API_WORKFLOW_NODE_EXECUTION_REPOSITORY": "repositories.sqlalchemy_api_workflow_node_execution_repository.DifyAPISQLAlchemyWorkflowNodeExecutionRepository",
|
||||
"API_WORKFLOW_RUN_REPOSITORY": "repositories.sqlalchemy_api_workflow_run_repository.DifyAPISQLAlchemyWorkflowRunRepository",
|
||||
"HTTP_REQUEST_NODE_MAX_BINARY_SIZE": "10485760",
|
||||
"HTTP_REQUEST_NODE_MAX_TEXT_SIZE": "1048576",
|
||||
"HTTP_REQUEST_NODE_SSL_VERIFY": "True",
|
||||
"RESPECT_XFORWARD_HEADERS_ENABLED": "false",
|
||||
"SSRF_PROXY_HTTP_URL": "http://" + api.DIFY_LOCALHOST + ":3128",
|
||||
"SSRF_PROXY_HTTPS_URL": "http://" + api.DIFY_LOCALHOST + ":3128",
|
||||
"LOOP_NODE_MAX_COUNT": api.DIFY_WEB_LOOP_NODE_MAX_COUNT,
|
||||
"MAX_TOOLS_NUM": api.DIFY_WEB_MAX_TOOLS_NUM,
|
||||
"MAX_PARALLEL_LIMIT": api.DIFY_WEB_MAX_PARALLEL_LIMIT,
|
||||
"MAX_ITERATIONS_NUM": api.DIFY_WEB_MAX_ITERATIONS_NUM,
|
||||
"TEXT_GENERATION_TIMEOUT_MS": api.DIFY_WEB_TEXT_GENERATION_TIMEOUT_MS,
|
||||
"ALLOW_UNSAFE_DATA_SCHEME": api.DIFY_WEB_ALLOW_UNSAFE_DATA_SCHEME,
|
||||
"POSTGRES_USER": "${DB_USERNAME}",
|
||||
"POSTGRES_PASSWORD": "${DB_PASSWORD}",
|
||||
"POSTGRES_DB": "${DB_DATABASE}",
|
||||
"PGDATA": "/var/lib/postgresql/data/pgdata",
|
||||
"SANDBOX_API_KEY": api.DIFY_SANDBOX_API_KEY,
|
||||
"SANDBOX_GIN_MODE": api.DIFY_SANDBOX_GIN_MODE,
|
||||
"SANDBOX_WORKER_TIMEOUT": api.DIFY_SANDBOX_WORKER_TIMEOUT,
|
||||
"SANDBOX_ENABLE_NETWORK": api.DIFY_SANDBOX_ENABLE_NETWORK,
|
||||
"SANDBOX_HTTP_PROXY": api.DIFY_SANDBOX_HTTP_PROXY,
|
||||
"SANDBOX_HTTPS_PROXY": api.DIFY_SANDBOX_HTTPS_PROXY,
|
||||
"SANDBOX_PORT": api.DIFY_SANDBOX_PORT,
|
||||
"WEAVIATE_PERSISTENCE_DATA_PATH": api.DIFY_WEAVIATE_PERSISTENCE_DATA_PATH,
|
||||
"WEAVIATE_QUERY_DEFAULTS_LIMIT": api.DIFY_WEAVIATE_QUERY_DEFAULTS_LIMIT,
|
||||
"WEAVIATE_AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED": api.DIFY_WEAVIATE_AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED,
|
||||
"WEAVIATE_DEFAULT_VECTORIZER_MODULE": api.DIFY_WEAVIATE_DEFAULT_VECTORIZER_MODULE,
|
||||
"WEAVIATE_CLUSTER_HOSTNAME": api.DIFY_WEAVIATE_CLUSTER_HOSTNAME,
|
||||
"WEAVIATE_AUTHENTICATION_APIKEY_ENABLED": api.DIFY_WEAVIATE_AUTHENTICATION_APIKEY_ENABLED,
|
||||
"WEAVIATE_AUTHENTICATION_APIKEY_ALLOWED_KEYS": api.DIFY_WEAVIATE_AUTHENTICATION_APIKEY_ALLOWED_KEYS,
|
||||
"WEAVIATE_AUTHENTICATION_APIKEY_USERS": api.DIFY_WEAVIATE_AUTHENTICATION_APIKEY_USERS,
|
||||
"WEAVIATE_AUTHORIZATION_ADMINLIST_ENABLED": api.DIFY_WEAVIATE_AUTHORIZATION_ADMINLIST_ENABLED,
|
||||
"WEAVIATE_AUTHORIZATION_ADMINLIST_USERS": api.DIFY_WEAVIATE_AUTHORIZATION_ADMINLIST_USERS,
|
||||
"NGINX_SERVER_NAME": api.DIFY_NGINX_SERVER_NAME,
|
||||
"NGINX_PORT": api.DIFY_NGINX_PORT,
|
||||
"NGINX_WORKER_PROCESSES": api.DIFY_NGINX_WORKER_PROCESSES,
|
||||
"NGINX_CLIENT_MAX_BODY_SIZE": api.DIFY_NGINX_CLIENT_MAX_BODY_SIZE,
|
||||
"NGINX_KEEPALIVE_TIMEOUT": api.DIFY_NGINX_KEEPALIVE_TIMEOUT,
|
||||
"NGINX_PROXY_READ_TIMEOUT": api.DIFY_NGINX_PROXY_READ_TIMEOUT,
|
||||
"NGINX_PROXY_SEND_TIMEOUT": api.DIFY_NGINX_PROXY_SEND_TIMEOUT,
|
||||
"SSRF_HTTP_PORT": api.DIFY_SSRF_HTTP_PORT,
|
||||
"SSRF_COREDUMP_DIR": api.DIFY_SSRF_COREDUMP_DIR,
|
||||
"SSRF_REVERSE_PROXY_PORT": api.DIFY_SANDBOX_PORT,
|
||||
"SSRF_SANDBOX_HOST": api.DIFY_LOCALHOST,
|
||||
"SSRF_DEFAULT_TIME_OUT": "5",
|
||||
"SSRF_DEFAULT_CONNECT_TIME_OUT": "5",
|
||||
"SSRF_DEFAULT_READ_TIME_OUT": "5",
|
||||
"SSRF_DEFAULT_WRITE_TIME_OUT": "5",
|
||||
"DB_PLUGIN_DATABASE": api.DIFY_PLUGIN_DB_DATABASE,
|
||||
"PLUGIN_DAEMON_PORT": api.DIFY_PLUGIN_SERVER_PORT,
|
||||
"PLUGIN_DAEMON_KEY": api.DIFY_PLUGIN_SERVER_KEY,
|
||||
"PLUGIN_DAEMON_URL": "http://" + api.DIFY_LOCALHOST + ":" + api.DIFY_PLUGIN_SERVER_PORT,
|
||||
"PLUGIN_MAX_PACKAGE_SIZE": api.DIFY_PLUGIN_MAX_PACKAGE_SIZE,
|
||||
"PLUGIN_PPROF_ENABLED": api.DIFY_PLUGIN_PPROF_ENABLED,
|
||||
"PLUGIN_DEBUGGING_HOST": api.DIFY_PLUGIN_REMOTE_INSTALLING_HOST,
|
||||
"PLUGIN_DEBUGGING_PORT": api.DIFY_PLUGIN_REMOTE_INSTALLING_PORT,
|
||||
"EXPOSE_PLUGIN_DEBUGGING_HOST": api.DIFY_LOCALHOST,
|
||||
"EXPOSE_PLUGIN_DEBUGGING_PORT": api.DIFY_PLUGIN_REMOTE_INSTALLING_PORT,
|
||||
"PLUGIN_DIFY_INNER_API_KEY": api.DIFY_API_INNER_KEY,
|
||||
"PLUGIN_DIFY_INNER_API_URL": "http://" + api.DIFY_LOCALHOST + ":5001",
|
||||
"ENDPOINT_URL_TEMPLATE": "http://" + api.DIFY_LOCALHOST + "/e/{hook_id}",
|
||||
"MARKETPLACE_ENABLED": "true",
|
||||
"MARKETPLACE_API_URL": api.DIFY_WEB_MARKETPLACE_API_URL,
|
||||
"ALLOW_EMBED": api.DIFY_WEB_ALLOW_EMBED,
|
||||
"QUEUE_MONITOR_THRESHOLD": "200",
|
||||
"QUEUE_MONITOR_ALERT_EMAILS": "",
|
||||
"QUEUE_MONITOR_INTERVAL": "30",
|
||||
"ENABLE_CLEAN_EMBEDDING_CACHE_TASK": "false",
|
||||
"ENABLE_CLEAN_UNUSED_DATASETS_TASK": "false",
|
||||
"ENABLE_CREATE_TIDB_SERVERLESS_TASK": "false",
|
||||
"ENABLE_UPDATE_TIDB_SERVERLESS_STATUS_TASK": "false",
|
||||
"ENABLE_CLEAN_MESSAGES": "false",
|
||||
"ENABLE_MAIL_CLEAN_DOCUMENT_NOTIFY_TASK": "false",
|
||||
"ENABLE_DATASETS_QUEUE_MONITOR": "false",
|
||||
"ENABLE_CHECK_UPGRADABLE_PLUGIN_TASK": "true",
|
||||
}
|
||||
sharedApiWorkerEnvKeyVal = sharedApiWorkerEnv.GetContainerEnvs(custom)
|
||||
}
|
||||
return sharedApiWorkerEnvKeyVal
|
||||
}
|
||||
@@ -1,442 +0,0 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"path"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis"
|
||||
computeapi "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
api "yunion.io/x/onecloud/pkg/apis/llm"
|
||||
)
|
||||
|
||||
type DifyContainerEnv map[string]string
|
||||
|
||||
func (envsPtr *DifyContainerEnv) GetContainerEnvs(userCustomizedEnvs *DifyContainerEnv) []*apis.ContainerKeyValue {
|
||||
envs := *envsPtr
|
||||
if len(envs) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
ctrEnvs := make([]*apis.ContainerKeyValue, 0, len(envs))
|
||||
for key, value := range envs {
|
||||
if userCustomizedEnvs != nil && (*userCustomizedEnvs)[key] != "" {
|
||||
value = (*userCustomizedEnvs)[key]
|
||||
}
|
||||
ctrEnvs = append(ctrEnvs, &apis.ContainerKeyValue{
|
||||
Key: key,
|
||||
Value: value,
|
||||
})
|
||||
}
|
||||
return ctrEnvs
|
||||
}
|
||||
|
||||
func (envsPtr *DifyContainerEnv) SetContainerEnv(key, value string) error {
|
||||
if key == "" {
|
||||
return errors.New("environment variable key cannot be empty")
|
||||
}
|
||||
|
||||
if envsPtr == nil {
|
||||
return errors.New("DifyContainerEnv pointer is nil")
|
||||
}
|
||||
|
||||
if *envsPtr == nil {
|
||||
*envsPtr = make(DifyContainerEnv)
|
||||
}
|
||||
|
||||
(*envsPtr)[key] = value
|
||||
return nil
|
||||
}
|
||||
|
||||
func getPVCMount(name, subDir, mountPath string) *apis.ContainerVolumeMount {
|
||||
diskIndex := 0
|
||||
pvc := &apis.ContainerVolumeMount{
|
||||
UniqueName: name + "-data-pvc",
|
||||
Type: apis.CONTAINER_VOLUME_MOUNT_TYPE_DISK,
|
||||
Disk: &apis.ContainerVolumeMountDisk{
|
||||
SubDirectory: subDir,
|
||||
Index: &diskIndex,
|
||||
},
|
||||
MountPath: mountPath,
|
||||
ReadOnly: false,
|
||||
Propagation: apis.MOUNTPROPAGATION_PROPAGATION_PRIVATE,
|
||||
}
|
||||
|
||||
return pvc
|
||||
}
|
||||
|
||||
type DifyContainersManager struct {
|
||||
UserCustomizedEnvs *DifyContainerEnv
|
||||
}
|
||||
|
||||
func _getRegistryImage(imageId string) string {
|
||||
image, err := GetLLMImageManager().FetchById(imageId)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return image.(*SLLMImage).ToContainerImage()
|
||||
}
|
||||
|
||||
func (m *DifyContainersManager) GetContainer(name, containerKey string, sku *SDifyModel) (*computeapi.PodContainerCreateInput, error) {
|
||||
switch containerKey {
|
||||
case api.DIFY_REDIS_KEY:
|
||||
return m._getRedisContainer(name, containerKey, _getRegistryImage(sku.RedisImageId)), nil
|
||||
case api.DIFY_POSTGRES_KEY:
|
||||
return m._getPostgresContainer(name, containerKey, _getRegistryImage(sku.PostgresImageId)), nil
|
||||
case api.DIFY_API_KEY:
|
||||
return m._getApiContainer(name, containerKey, _getRegistryImage(sku.DifyApiImageId)), nil
|
||||
case api.DIFY_WORKER_KEY:
|
||||
return m._getWorkerContainer(name, containerKey, _getRegistryImage(sku.DifyApiImageId)), nil
|
||||
case api.DIFY_WORKER_BEAT_KEY:
|
||||
return m._getWorkerBeatContainer(name, containerKey, _getRegistryImage(sku.DifyApiImageId)), nil
|
||||
case api.DIFY_PLUGIN_KEY:
|
||||
return m._getPluginContainer(name, containerKey, _getRegistryImage(sku.DifyPluginImageId)), nil
|
||||
case api.DIFY_WEB_KEY:
|
||||
return m._getWebContainer(name, containerKey, _getRegistryImage(sku.DifyWebImageId)), nil
|
||||
case api.DIFY_SSRF_KEY:
|
||||
return m._getSsrfContainer(name, containerKey, _getRegistryImage(sku.DifySSRFImageId)), nil
|
||||
case api.DIFY_NGINX_KEY:
|
||||
return m._getNginxContainer(name, containerKey, _getRegistryImage(sku.NginxImageId)), nil
|
||||
case api.DIFY_WEAVIATE_KEY:
|
||||
return m._getWeaviateContainer(name, containerKey, _getRegistryImage(sku.DifyWeaviateImageId)), nil
|
||||
case api.DIFY_SANDBOX_KEY:
|
||||
return m._getSandboxContainer(name, containerKey, _getRegistryImage(sku.DifySandboxImageId)), nil
|
||||
default:
|
||||
return nil, errors.New("unsupported container key")
|
||||
}
|
||||
}
|
||||
|
||||
func (m *DifyContainersManager) _getRedisContainer(name, key, image string) *computeapi.PodContainerCreateInput {
|
||||
// set name and image
|
||||
ctr := &computeapi.PodContainerCreateInput{
|
||||
Name: name + "-" + key,
|
||||
}
|
||||
ctr.Image = image
|
||||
|
||||
// set container environments
|
||||
envs := &DifyContainerEnv{
|
||||
"REDISCLI_AUTH": api.DIFY_REDISCLI_AUTH,
|
||||
}
|
||||
ctr.Envs = envs.GetContainerEnvs(m.UserCustomizedEnvs)
|
||||
|
||||
// set PVC to store data
|
||||
ctr.VolumeMounts = []*apis.ContainerVolumeMount{
|
||||
getPVCMount(key, key, api.DIFY_REDIS_PVC_MOUNT_PATH),
|
||||
}
|
||||
|
||||
// set command
|
||||
ctr.Args = []string{
|
||||
"redis-server", "--requirepass", api.DIFY_REDISCLI_AUTH,
|
||||
}
|
||||
|
||||
return ctr
|
||||
}
|
||||
|
||||
func (m *DifyContainersManager) _getPostgresContainer(name, key, image string) *computeapi.PodContainerCreateInput {
|
||||
// set name and image
|
||||
ctr := &computeapi.PodContainerCreateInput{
|
||||
Name: name + "-" + key,
|
||||
}
|
||||
ctr.Image = image
|
||||
|
||||
// set container environments
|
||||
envs := &DifyContainerEnv{
|
||||
"POSTGRES_USER": api.DIFY_POSTGRES_USER,
|
||||
"POSTGRES_PASSWORD": api.DIFY_POSTGRES_PASSWORD,
|
||||
"POSTGRES_DB": api.DIFY_POSTGRES_DB,
|
||||
"PGDATA": path.Join(api.DIFY_POSTGRES_PVC_MOUNT_PATH, api.DIFY_POSTGRES_PGDATA),
|
||||
}
|
||||
ctr.Envs = envs.GetContainerEnvs(m.UserCustomizedEnvs)
|
||||
|
||||
// set PVC to store data
|
||||
ctr.VolumeMounts = []*apis.ContainerVolumeMount{
|
||||
getPVCMount(key, key, api.DIFY_POSTGRES_PVC_MOUNT_PATH),
|
||||
}
|
||||
|
||||
// set command for ctr
|
||||
ctr.Args = []string{
|
||||
"postgres",
|
||||
"-c", "max_connections=" + api.DIFY_POSTGRES_MAX_CONNECTIONS,
|
||||
"-c", "shared_buffers=" + api.DIFY_POSTGRES_SHARED_BUFFERS,
|
||||
"-c", "work_mem=" + api.DIFY_POSTGRES_WORK_MEM,
|
||||
"-c", "maintenance_work_mem=" + api.DIFY_POSTGRES_MAINTENANCE_WORK_MEM,
|
||||
"-c", "effective_cache_size=" + api.DIFY_POSTGRES_EFFECTIVE_CACHE_SIZE,
|
||||
}
|
||||
|
||||
return ctr
|
||||
}
|
||||
|
||||
func (m *DifyContainersManager) _getApiContainer(name, key, image string) *computeapi.PodContainerCreateInput {
|
||||
// set name and image
|
||||
ctr := &computeapi.PodContainerCreateInput{
|
||||
Name: name + "-" + key,
|
||||
}
|
||||
ctr.Image = image
|
||||
|
||||
// set container environments
|
||||
envs := &DifyContainerEnv{
|
||||
"MODE": api.DIFY_API_MODE,
|
||||
"SENTRY_DSN": api.DIFY_API_SENTRY_DSN,
|
||||
"SENTRY_TRACES_SAMPLE_RATE": api.DIFY_API_SENTRY_TRACES_SAMPLE_RATE,
|
||||
"SENTRY_PROFILES_SAMPLE_RATE": api.DIFY_API_SENTRY_PROFILES_SAMPLE_RATE,
|
||||
"PLUGIN_REMOTE_INSTALL_HOST": api.DIFY_LOCALHOST,
|
||||
"PLUGIN_REMOTE_INSTALL_PORT": api.DIFY_PLUGIN_REMOTE_INSTALLING_PORT,
|
||||
"PLUGIN_MAX_PACKAGE_SIZE": api.DIFY_PLUGIN_MAX_PACKAGE_SIZE,
|
||||
"INNER_API_KEY_FOR_PLUGIN": api.DIFY_API_INNER_KEY,
|
||||
}
|
||||
ctr.Envs = append(getSharedApiWorkerEnv(m.UserCustomizedEnvs), envs.GetContainerEnvs(m.UserCustomizedEnvs)...)
|
||||
|
||||
// set PVC to store data
|
||||
ctr.VolumeMounts = []*apis.ContainerVolumeMount{
|
||||
getPVCMount(key, "api", api.DIFY_API_PVC_MOUNT_PATH),
|
||||
}
|
||||
|
||||
return ctr
|
||||
}
|
||||
|
||||
func (m *DifyContainersManager) _getWorkerContainer(name, key, image string) *computeapi.PodContainerCreateInput {
|
||||
// set name and image
|
||||
ctr := &computeapi.PodContainerCreateInput{
|
||||
Name: name + "-" + key,
|
||||
}
|
||||
ctr.Image = image
|
||||
|
||||
// set container environments
|
||||
envs := &DifyContainerEnv{
|
||||
"MODE": api.DIFY_WORKER_MODE,
|
||||
"SENTRY_DSN": api.DIFY_API_SENTRY_DSN,
|
||||
"SENTRY_TRACES_SAMPLE_RATE": api.DIFY_API_SENTRY_TRACES_SAMPLE_RATE,
|
||||
"SENTRY_PROFILES_SAMPLE_RATE": api.DIFY_API_SENTRY_PROFILES_SAMPLE_RATE,
|
||||
"PLUGIN_MAX_PACKAGE_SIZE": api.DIFY_PLUGIN_MAX_PACKAGE_SIZE,
|
||||
"INNER_API_KEY_FOR_PLUGIN": api.DIFY_API_INNER_KEY,
|
||||
}
|
||||
ctr.Envs = append(getSharedApiWorkerEnv(m.UserCustomizedEnvs), envs.GetContainerEnvs(m.UserCustomizedEnvs)...)
|
||||
|
||||
// set PVC to store data
|
||||
ctr.VolumeMounts = []*apis.ContainerVolumeMount{
|
||||
getPVCMount(key, "api", api.DIFY_API_PVC_MOUNT_PATH),
|
||||
}
|
||||
|
||||
return ctr
|
||||
}
|
||||
|
||||
func (m *DifyContainersManager) _getWorkerBeatContainer(name, key, image string) *computeapi.PodContainerCreateInput {
|
||||
// set name and image
|
||||
ctr := &computeapi.PodContainerCreateInput{
|
||||
Name: name + "-" + key,
|
||||
}
|
||||
ctr.Image = image
|
||||
|
||||
// set container environments
|
||||
envs := &DifyContainerEnv{
|
||||
"MODE": api.DIFY_WORKER_BEAT_MODE,
|
||||
}
|
||||
ctr.Envs = append(getSharedApiWorkerEnv(m.UserCustomizedEnvs), envs.GetContainerEnvs(m.UserCustomizedEnvs)...)
|
||||
|
||||
return ctr
|
||||
}
|
||||
|
||||
func (m *DifyContainersManager) _getPluginContainer(name, key, image string) *computeapi.PodContainerCreateInput {
|
||||
// set name and image
|
||||
ctr := &computeapi.PodContainerCreateInput{
|
||||
Name: name + "-" + key,
|
||||
}
|
||||
ctr.Image = image
|
||||
|
||||
// set container environments
|
||||
envs := &DifyContainerEnv{
|
||||
"DB_DATABASE": api.DIFY_PLUGIN_DB_DATABASE,
|
||||
"SERVER_PORT": api.DIFY_PLUGIN_SERVER_PORT,
|
||||
"SERVER_KEY": api.DIFY_PLUGIN_SERVER_KEY,
|
||||
"MAX_PACKAGE_CACHE_PATH": api.DIFY_PLUGIN_PACKAGE_CACHE_PATH,
|
||||
"PPROF_ENABLED": api.DIFY_PLUGIN_PPROF_ENABLED,
|
||||
"DIFY_INNER_API_URL": api.DIFY_PLUGIN_DIFY_INNER_API_URL,
|
||||
"DIFY_INNER_API_KEY": api.DIFY_API_INNER_KEY,
|
||||
"PLUGIN_REMOTE_INSTALLING_HOST": api.DIFY_PLUGIN_REMOTE_INSTALLING_HOST,
|
||||
"PLUGIN_REMOTE_INSTALLING_PORT": api.DIFY_PLUGIN_REMOTE_INSTALLING_PORT,
|
||||
"PLUGIN_WORKING_PATH": api.DIFY_PLUGIN_WORKING_PATH,
|
||||
"FORCE_VERIFYING_SIGNATURE": api.DIFY_PLUGIN_FORCE_VERIFYING_SIGNATURE,
|
||||
"PYTHON_ENV_INIT_TIMEOUT": api.DIFY_PLUGIN_PYTHON_ENV_INIT_TIMEOUT,
|
||||
"PLUGIN_MAX_EXECUTION_TIMEOUT": api.DIFY_PLUGIN_MAX_EXECUTION_TIMEOUT,
|
||||
"PIP_MIRROR_URL": api.PIP_MIRROR_URL,
|
||||
"PLUGIN_STORAGE_TYPE": api.DIFY_PLUGIN_STORAGE_TYPE,
|
||||
"PLUGIN_STORAGE_LOCAL_ROOT": api.DIFY_PLUGIN_STORAGE_LOCAL_ROOT,
|
||||
"PLUGIN_INSTALLED_PATH": api.DIFY_PLUGIN_INSTALLED_PATH,
|
||||
"PLUGIN_PACKAGE_CACHE_PATH": api.DIFY_PLUGIN_PACKAGE_CACHE_PATH,
|
||||
"PLUGIN_MEDIA_CACHE_PATH": api.DIFY_PLUGIN_MEDIA_CACHE_PATH,
|
||||
}
|
||||
ctr.Envs = append(getSharedApiWorkerEnv(m.UserCustomizedEnvs), envs.GetContainerEnvs(m.UserCustomizedEnvs)...)
|
||||
|
||||
// set PVC to store data
|
||||
ctr.VolumeMounts = []*apis.ContainerVolumeMount{
|
||||
getPVCMount(key, key, api.DIFY_PLUGIN_STORAGE_LOCAL_ROOT),
|
||||
}
|
||||
|
||||
return ctr
|
||||
}
|
||||
|
||||
func (m *DifyContainersManager) _getWebContainer(name, key, image string) *computeapi.PodContainerCreateInput {
|
||||
// set name and image
|
||||
ctr := &computeapi.PodContainerCreateInput{
|
||||
Name: name + "-" + key,
|
||||
}
|
||||
ctr.Image = image
|
||||
|
||||
// set container environments
|
||||
envs := &DifyContainerEnv{
|
||||
"HOSTNAME": "", // set HOSTNAME to empty, to avoid Error: getaddrinfo ENOTFOUND
|
||||
"CONSOLE_API_URL": api.DIFY_WEB_CONSOLE_API_URL,
|
||||
"APP_API_URL": api.DIFY_WEB_APP_API_URL,
|
||||
"SENTRY_DSN": api.DIFY_WEB_SENTRY_DSN,
|
||||
"NEXT_TELEMETRY_DISABLED": api.DIFY_WEB_NEXT_TELEMETRY_DISABLED,
|
||||
"TEXT_GENERATION_TIMEOUT_MS": api.DIFY_WEB_TEXT_GENERATION_TIMEOUT_MS,
|
||||
"CSP_WHITELIST": api.DIFY_WEB_CSP_WHITELIST,
|
||||
"ALLOW_EMBED": api.DIFY_WEB_ALLOW_EMBED,
|
||||
"ALLOW_UNSAFE_DATA_SCHEME": api.DIFY_WEB_ALLOW_UNSAFE_DATA_SCHEME,
|
||||
"MARKETPLACE_API_URL": api.DIFY_WEB_MARKETPLACE_API_URL,
|
||||
"MARKETPLACE_URL": api.DIFY_WEB_MARKETPLACE_URL,
|
||||
"TOP_K_MAX_VALUE": api.DIFY_WEB_TOP_K_MAX_VALUE,
|
||||
"INDEXING_MAX_SEGMENTATION_TOKENS_LENGTH": api.DIFY_WEB_INDEXING_MAX_SEGMENTATION_TOKENS_LENGTH,
|
||||
"PM2_INSTANCES": api.DIFY_WEB_PM2_INSTANCES,
|
||||
"LOOP_NODE_MAX_COUNT": api.DIFY_WEB_LOOP_NODE_MAX_COUNT,
|
||||
"MAX_TOOLS_NUM": api.DIFY_WEB_MAX_TOOLS_NUM,
|
||||
"MAX_PARALLEL_LIMIT": api.DIFY_WEB_MAX_PARALLEL_LIMIT,
|
||||
"MAX_ITERATIONS_NUM": api.DIFY_WEB_MAX_ITERATIONS_NUM,
|
||||
"ENABLE_WEBSITE_JINAREADER": api.DIFY_WEB_ENABLE_WEBSITE_JINAREADER,
|
||||
"ENABLE_WEBSITE_FIRECRAWL": api.DIFY_WEB_ENABLE_WEBSITE_FIRECRAWL,
|
||||
"ENABLE_WEBSITE_WATERCRAWL": api.DIFY_WEB_ENABLE_WEBSITE_WATERCRAWL,
|
||||
}
|
||||
ctr.Envs = envs.GetContainerEnvs(m.UserCustomizedEnvs)
|
||||
|
||||
return ctr
|
||||
}
|
||||
|
||||
func (m *DifyContainersManager) _getSsrfContainer(name, key, image string) *computeapi.PodContainerCreateInput {
|
||||
// set name and image
|
||||
ctr := &computeapi.PodContainerCreateInput{
|
||||
Name: name + "-" + key,
|
||||
}
|
||||
ctr.Image = image
|
||||
|
||||
// set container environments
|
||||
envs := &DifyContainerEnv{
|
||||
// "VISIBLE_HOSTNAME": "localhost", // set VISIBLE_HOSTNAME to localhost, to avoid rDNS test failed
|
||||
"HTTP_PORT": api.DIFY_SSRF_HTTP_PORT,
|
||||
"COREDUMP_DIR": api.DIFY_SSRF_COREDUMP_DIR,
|
||||
"REVERSE_PROXY_PORT": api.DIFY_SANDBOX_PORT,
|
||||
"SANDBOX_HOST": api.DIFY_LOCALHOST,
|
||||
"SANDBOX_PORT": api.DIFY_SANDBOX_PORT,
|
||||
}
|
||||
ctr.Envs = envs.GetContainerEnvs(m.UserCustomizedEnvs)
|
||||
|
||||
// set PVC to store data
|
||||
// ctr.VolumeMounts = []*apis.ContainerVolumeMount{
|
||||
// getPVCMount(key, key, api.SSRF_MOUNT_PATH),
|
||||
// }
|
||||
|
||||
// generate entrypoint
|
||||
entrypointSH := fmt.Sprintf(api.DIFY_SSRF_ENTRYPINT_SHELL, api.DIFY_SSRF_SQUID_CONFIGURATION_FILE)
|
||||
ctr.Command = []string{
|
||||
"/bin/sh", "-c", entrypointSH,
|
||||
}
|
||||
|
||||
return ctr
|
||||
}
|
||||
|
||||
func (m *DifyContainersManager) _getNginxContainer(name, key, image string) *computeapi.PodContainerCreateInput {
|
||||
// set name and image
|
||||
ctr := &computeapi.PodContainerCreateInput{
|
||||
Name: name + "-" + key,
|
||||
}
|
||||
ctr.Image = image
|
||||
|
||||
// set container environments
|
||||
envs := &DifyContainerEnv{
|
||||
"NGINX_SERVER_NAME": api.DIFY_NGINX_SERVER_NAME,
|
||||
"NGINX_PORT": api.DIFY_NGINX_PORT,
|
||||
"NGINX_WORKER_PROCESSES": api.DIFY_NGINX_WORKER_PROCESSES,
|
||||
"NGINX_CLIENT_MAX_BODY_SIZE": api.DIFY_NGINX_CLIENT_MAX_BODY_SIZE,
|
||||
"NGINX_KEEPALIVE_TIMEOUT": api.DIFY_NGINX_KEEPALIVE_TIMEOUT,
|
||||
"NGINX_PROXY_READ_TIMEOUT": api.DIFY_NGINX_PROXY_READ_TIMEOUT,
|
||||
"NGINX_PROXY_SEND_TIMEOUT": api.DIFY_NGINX_PROXY_SEND_TIMEOUT,
|
||||
}
|
||||
ctr.Envs = envs.GetContainerEnvs(m.UserCustomizedEnvs)
|
||||
|
||||
// set PVC to store data
|
||||
ctr.VolumeMounts = []*apis.ContainerVolumeMount{
|
||||
getPVCMount(key, key, api.DIFY_NGINX_MOUNT_PATH),
|
||||
}
|
||||
|
||||
// generate entrypoint
|
||||
entrypointSH := fmt.Sprintf(api.DIFY_NGINX_ENTRYPINT_SHELL, api.DIFY_NGINX_NGINX_CONF_FILE, api.DIFY_NGINX_PROXY_CONF_FILE, api.DIFY_NGINX_DEFAULT_CONF_FILE)
|
||||
ctr.Command = []string{
|
||||
"/bin/sh", "-c", entrypointSH,
|
||||
}
|
||||
|
||||
return ctr
|
||||
}
|
||||
|
||||
func (m *DifyContainersManager) _getWeaviateContainer(name, key, image string) *computeapi.PodContainerCreateInput {
|
||||
// set name and image
|
||||
ctr := &computeapi.PodContainerCreateInput{
|
||||
Name: name + "-" + key,
|
||||
}
|
||||
ctr.Image = image
|
||||
|
||||
// set container environments
|
||||
envs := &DifyContainerEnv{
|
||||
"PERSISTENCE_DATA_PATH": api.DIFY_WEAVIATE_PERSISTENCE_DATA_PATH,
|
||||
"QUERY_DEFAULTS_LIMIT": api.DIFY_WEAVIATE_QUERY_DEFAULTS_LIMIT,
|
||||
"AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED": api.DIFY_WEAVIATE_AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED,
|
||||
"DEFAULT_VECTORIZER_MODULE": api.DIFY_WEAVIATE_DEFAULT_VECTORIZER_MODULE,
|
||||
"CLUSTER_HOSTNAME": api.DIFY_WEAVIATE_CLUSTER_HOSTNAME,
|
||||
"AUTHENTICATION_APIKEY_ENABLED": api.DIFY_WEAVIATE_AUTHENTICATION_APIKEY_ENABLED,
|
||||
"AUTHENTICATION_APIKEY_ALLOWED_KEYS": api.DIFY_WEAVIATE_AUTHENTICATION_APIKEY_ALLOWED_KEYS,
|
||||
"AUTHENTICATION_APIKEY_USERS": api.DIFY_WEAVIATE_AUTHENTICATION_APIKEY_USERS,
|
||||
"AUTHORIZATION_ADMINLIST_ENABLED": api.DIFY_WEAVIATE_AUTHORIZATION_ADMINLIST_ENABLED,
|
||||
"AUTHORIZATION_ADMINLIST_USERS": api.DIFY_WEAVIATE_AUTHORIZATION_ADMINLIST_USERS,
|
||||
}
|
||||
ctr.Envs = envs.GetContainerEnvs(m.UserCustomizedEnvs)
|
||||
|
||||
// set PVC to store data
|
||||
ctr.VolumeMounts = []*apis.ContainerVolumeMount{
|
||||
getPVCMount(key, key, api.DIFY_WEAVIATE_PERSISTENCE_DATA_PATH),
|
||||
}
|
||||
|
||||
return ctr
|
||||
}
|
||||
|
||||
func (m *DifyContainersManager) _getSandboxContainer(name, key, image string) *computeapi.PodContainerCreateInput {
|
||||
// set name and image
|
||||
ctr := &computeapi.PodContainerCreateInput{
|
||||
Name: name + "-" + key,
|
||||
}
|
||||
ctr.Image = image
|
||||
|
||||
// set container environments
|
||||
envs := &DifyContainerEnv{
|
||||
"API_KEY": api.DIFY_SANDBOX_API_KEY,
|
||||
"GIN_MODE": api.DIFY_SANDBOX_GIN_MODE,
|
||||
"WORKER_TIMEOUT": api.DIFY_SANDBOX_WORKER_TIMEOUT,
|
||||
"ENABLE_NETWORK": api.DIFY_SANDBOX_ENABLE_NETWORK,
|
||||
"HTTP_PROXY": api.DIFY_SANDBOX_HTTP_PROXY,
|
||||
"HTTPS_PROXY": api.DIFY_SANDBOX_HTTPS_PROXY,
|
||||
"SANDBOX_PORT": api.DIFY_SANDBOX_PORT,
|
||||
"PIP_MIRROR_URL": api.PIP_MIRROR_URL,
|
||||
}
|
||||
ctr.Envs = envs.GetContainerEnvs(m.UserCustomizedEnvs)
|
||||
|
||||
// set PVC to store data
|
||||
ctr.VolumeMounts = []*apis.ContainerVolumeMount{
|
||||
getPVCMount(key+"conf", key+"conf", api.DIFY_SANDBOX_CONF_MOUNT_PATH),
|
||||
getPVCMount(key+"dep", key+"dep", api.DIFY_SANDBOX_DEP_MOUNT_PATH),
|
||||
}
|
||||
|
||||
// set command
|
||||
writeConfigCommand := fmt.Sprintf(api.DIFY_SANDBOX_WRITE_CONF_SHELL, api.DIFY_SANDBOX_CONF_FILE, api.DIFY_SANDBOX_CONF_TEMP_FILE)
|
||||
ctr.Command = []string{
|
||||
"/bin/sh", "-c", writeConfigCommand,
|
||||
}
|
||||
|
||||
return ctr
|
||||
}
|
||||
@@ -1,125 +0,0 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/llm"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/validators"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
)
|
||||
|
||||
func init() {
|
||||
GetDifyModelManager()
|
||||
}
|
||||
|
||||
var difyModelManager *SDifyModelManager
|
||||
|
||||
func GetDifyModelManager() *SDifyModelManager {
|
||||
if difyModelManager != nil {
|
||||
return difyModelManager
|
||||
}
|
||||
difyModelManager = &SDifyModelManager{
|
||||
SLLMModelBaseManager: NewSLLMModelBaseManager(
|
||||
SDifyModel{},
|
||||
"dify_models_tbl",
|
||||
"dify_model",
|
||||
"dify_models",
|
||||
),
|
||||
}
|
||||
difyModelManager.SetVirtualObject(difyModelManager)
|
||||
return difyModelManager
|
||||
}
|
||||
|
||||
type SDifyModelManager struct {
|
||||
SLLMModelBaseManager
|
||||
}
|
||||
|
||||
type SDifyModel struct {
|
||||
SLLMModelBase
|
||||
|
||||
PostgresImageId string `width:"128" charset:"ascii" nullable:"false" list:"user" create:"required"`
|
||||
RedisImageId string `width:"128" charset:"ascii" nullable:"false" list:"user" create:"required"`
|
||||
NginxImageId string `width:"128" charset:"ascii" nullable:"false" list:"user" create:"required"`
|
||||
DifyApiImageId string `width:"128" charset:"ascii" nullable:"false" list:"user" create:"required"`
|
||||
DifyPluginImageId string `width:"128" charset:"ascii" nullable:"false" list:"user" create:"required"`
|
||||
DifyWebImageId string `width:"128" charset:"ascii" nullable:"false" list:"user" create:"required"`
|
||||
DifySandboxImageId string `width:"128" charset:"ascii" nullable:"false" list:"user" create:"required"`
|
||||
DifySSRFImageId string `width:"128" charset:"ascii" nullable:"false" list:"user" create:"required"`
|
||||
DifyWeaviateImageId string `width:"128" charset:"ascii" nullable:"false" list:"user" create:"required"`
|
||||
}
|
||||
|
||||
func (man *SDifyModelManager) ListItemFilter(
|
||||
ctx context.Context,
|
||||
q *sqlchemy.SQuery,
|
||||
userCred mcclient.TokenCredential,
|
||||
input api.DifyModelListInput,
|
||||
) (*sqlchemy.SQuery, error) {
|
||||
var err error
|
||||
q, err = man.SLLMModelBaseManager.ListItemFilter(ctx, q, userCred, input.SharableVirtualResourceListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "SLLMModelBaseManager.ListItemFilter")
|
||||
}
|
||||
return q, nil
|
||||
}
|
||||
|
||||
// func (man *SDifyModelManager) FetchCustomizeColumns(
|
||||
// ctx context.Context,
|
||||
// userCred mcclient.TokenCredential,
|
||||
// query jsonutils.JSONObject,
|
||||
// objs []interface{},
|
||||
// fields stringutils2.SSortedStrings,
|
||||
// isList bool,
|
||||
// ) []api.LLMModelDetails {
|
||||
|
||||
// }
|
||||
|
||||
func (man *SDifyModelManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input *api.DifyModelCreateInput) (*api.DifyModelCreateInput, error) {
|
||||
var err error
|
||||
input.LLMModelBaseCreateInput, err = man.SLLMModelBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.LLMModelBaseCreateInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SLLMModelBaseManager.ValidateCreateData")
|
||||
}
|
||||
|
||||
for _, imgId := range []*string{&input.PostgresImageId, &input.RedisImageId, &input.NginxImageId, &input.DifyApiImageId, &input.DifyPluginImageId, &input.DifyWebImageId, &input.DifySandboxImageId, &input.DifySSRFImageId, &input.DifyWeaviateImageId} {
|
||||
_, err := validators.ValidateModel(ctx, userCred, GetLLMImageManager(), imgId)
|
||||
if err != nil {
|
||||
return input, errors.Wrapf(err, "validate image_id %s", *imgId)
|
||||
}
|
||||
}
|
||||
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (model *SDifyModel) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.DifyModelUpdateInput) (api.DifyModelUpdateInput, error) {
|
||||
var err error
|
||||
input.LLMModelBaseUpdateInput, err = model.SLLMModelBase.ValidateUpdateData(ctx, userCred, query, input.LLMModelBaseUpdateInput)
|
||||
if err != nil {
|
||||
return input, errors.Wrap(err, "validate LLMModelBaseUpdateInput")
|
||||
}
|
||||
|
||||
for _, imgId := range []*string{&input.PostgresImageId, &input.RedisImageId, &input.NginxImageId, &input.DifyApiImageId, &input.DifyPluginImageId, &input.DifyWebImageId, &input.DifySandboxImageId, &input.DifySSRFImageId, &input.DifyWeaviateImageId} {
|
||||
if *imgId != "" {
|
||||
_, err := validators.ValidateModel(ctx, userCred, GetLLMImageManager(), imgId)
|
||||
if err != nil {
|
||||
return input, errors.Wrapf(err, "validate image_id %s", *imgId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (model *SDifyModel) ValidateDeleteCondition(ctx context.Context, info jsonutils.JSONObject) error {
|
||||
count, err := GetDifyManager().Query().Equals("dify_model_id", model.Id).CountWithError()
|
||||
if nil != err {
|
||||
return errors.Wrap(err, "fetch dify")
|
||||
}
|
||||
if count > 0 {
|
||||
return errors.Wrap(errors.ErrNotSupported, "This model is currently in use")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -1,130 +0,0 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
computeapi "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
api "yunion.io/x/onecloud/pkg/apis/llm"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
)
|
||||
|
||||
func GetDifyPodCreateInput(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
input *api.DifyCreateInput,
|
||||
dify *SDify,
|
||||
sku *SDifyModel,
|
||||
eip string,
|
||||
) (*computeapi.ServerCreateInput, error) {
|
||||
data := computeapi.ServerCreateInput{}
|
||||
data.AutoStart = input.AutoStart
|
||||
data.ServerConfigs = computeapi.NewServerConfigs()
|
||||
data.Hypervisor = computeapi.HYPERVISOR_POD
|
||||
|
||||
postStopCleanupConfgi := PodPostStopCleanupConfig{
|
||||
Dirs: []string{
|
||||
GetTmpHostPath(dify.GetName()),
|
||||
},
|
||||
}
|
||||
data.Metadata = map[string]string{
|
||||
POD_METADATA_POST_STOP_CLEANUP_CONFIG: jsonutils.Marshal(postStopCleanupConfgi).String(),
|
||||
}
|
||||
|
||||
data.VcpuCount = sku.Cpu
|
||||
data.VmemSize = sku.Memory + 1
|
||||
data.Name = input.Name
|
||||
|
||||
// disks
|
||||
data.Disks = make([]*computeapi.DiskConfig, 0)
|
||||
if sku.Volumes != nil && !sku.Volumes.IsZero() {
|
||||
for idx, volume := range *sku.Volumes {
|
||||
data.Disks = append(data.Disks, &computeapi.DiskConfig{
|
||||
DiskType: "data",
|
||||
Format: "raw",
|
||||
Fs: "ext4",
|
||||
SizeMb: volume.SizeMB,
|
||||
Index: idx,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// isolated devices
|
||||
if sku.Devices != nil && !sku.Devices.IsZero() {
|
||||
data.IsolatedDevices = make([]*computeapi.IsolatedDeviceConfig, 0)
|
||||
devices := *sku.Devices
|
||||
for i := 0; i < len(devices); i++ {
|
||||
isolatedDevice := &computeapi.IsolatedDeviceConfig{
|
||||
DevType: devices[i].DevType,
|
||||
Model: devices[i].Model,
|
||||
DevicePath: devices[i].DevicePath,
|
||||
}
|
||||
data.IsolatedDevices = append(data.IsolatedDevices, isolatedDevice)
|
||||
}
|
||||
}
|
||||
|
||||
// port mappings
|
||||
// var portRange *computeapi.GuestPortMappingPortRange
|
||||
portMappings := computeapi.GuestPortMappings{}
|
||||
if sku.PortMappings != nil && !sku.PortMappings.IsZero() {
|
||||
// hostTcpPortRange := computeapi.GuestPortMappingPortRange{
|
||||
// Start: options.Options.HostTcpPortStart,
|
||||
// End: options.Options.HostTcpPortEnd,
|
||||
// }
|
||||
// hostUdpPortRange := computeapi.GuestPortMappingPortRange{
|
||||
// Start: options.Options.HostUdpPortStart,
|
||||
// End: options.Options.HostUdpPortEnd,
|
||||
// }
|
||||
for _, portInfo := range *sku.PortMappings {
|
||||
remoteIps := portInfo.RemoteIps
|
||||
if len(remoteIps) == 0 {
|
||||
remoteIps = nil
|
||||
}
|
||||
// if portInfo.Protocol == "tcp" {
|
||||
// portRange = &hostTcpPortRange
|
||||
// } else {
|
||||
// portRange = &hostUdpPortRange
|
||||
// }
|
||||
portMappings = append(portMappings, &computeapi.GuestPortMapping{
|
||||
Port: portInfo.ContainerPort,
|
||||
Protocol: computeapi.GuestPortMappingProtocol(portInfo.Protocol),
|
||||
RemoteIps: remoteIps,
|
||||
// HostPortRange: portRange,
|
||||
Rule: &computeapi.GuestPortMappingRule{
|
||||
FirstPortOffset: portInfo.FirstPortOffset,
|
||||
},
|
||||
Envs: portInfo.Envs,
|
||||
})
|
||||
}
|
||||
}
|
||||
bandwidth := dify.BandwidthMb
|
||||
if bandwidth == 0 {
|
||||
bandwidth = sku.BandwidthMb
|
||||
}
|
||||
data.Networks = []*computeapi.NetworkConfig{
|
||||
{
|
||||
NetType: computeapi.NETWORK_TYPE_HOSTLOCAL,
|
||||
BwLimit: bandwidth,
|
||||
PortMappings: portMappings,
|
||||
},
|
||||
}
|
||||
|
||||
data.Count = 1
|
||||
data.PreferHost = input.PreferHost
|
||||
|
||||
ctrs := dify.GetDifyContainers()
|
||||
|
||||
data.Pod = &computeapi.PodCreateInput{
|
||||
HostIPC: true,
|
||||
Containers: ctrs,
|
||||
}
|
||||
|
||||
data.ProjectId = input.ProjectId
|
||||
if len(data.ProjectId) == 0 {
|
||||
data.ProjectId = userCred.GetProjectId()
|
||||
data.TenantId = userCred.GetTenantId()
|
||||
}
|
||||
|
||||
return &data, nil
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package models // import "yunion.io/x/onecloud/pkg/llm/models"
|
||||
@@ -1,153 +0,0 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
identityapi "yunion.io/x/onecloud/pkg/apis/identity"
|
||||
api "yunion.io/x/onecloud/pkg/apis/llm"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/llm/options"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/auth"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules/identity"
|
||||
)
|
||||
|
||||
func init() {
|
||||
GetLLMImageManager()
|
||||
}
|
||||
|
||||
var llmImageManager *SLLMImageManager
|
||||
|
||||
func GetLLMImageManager() *SLLMImageManager {
|
||||
if llmImageManager != nil {
|
||||
return llmImageManager
|
||||
}
|
||||
llmImageManager = &SLLMImageManager{
|
||||
SSharableVirtualResourceBaseManager: db.NewSharableVirtualResourceBaseManager(
|
||||
SLLMImage{},
|
||||
"llm_images_tbl",
|
||||
"llm_image",
|
||||
"llm_images",
|
||||
),
|
||||
}
|
||||
llmImageManager.SetVirtualObject(llmImageManager)
|
||||
return llmImageManager
|
||||
}
|
||||
|
||||
type SLLMImageManager struct {
|
||||
db.SSharableVirtualResourceBaseManager
|
||||
}
|
||||
|
||||
type SLLMImage struct {
|
||||
db.SSharableVirtualResourceBase
|
||||
|
||||
ImageName string `width:"128" charset:"utf8" nullable:"false" list:"user" create:"admin_optional" update:"user"`
|
||||
ImageLabel string `width:"64" charset:"utf8" nullable:"false" list:"user" create:"admin_optional" update:"user"`
|
||||
|
||||
CredentialId string `width:"128" charset:"utf8" nullable:"true" list:"user" create:"admin_optional" update:"user"`
|
||||
}
|
||||
|
||||
func fetchImageCredential(ctx context.Context, userCred mcclient.TokenCredential, cid string) (*identityapi.CredentialDetails, error) {
|
||||
s := auth.GetSession(ctx, userCred, options.Options.Region)
|
||||
credJson, err := identity.Credentials.Get(s, cid, nil)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Credentials.Get")
|
||||
}
|
||||
details := identityapi.CredentialDetails{}
|
||||
err = credJson.Unmarshal(&details)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Unmarshal")
|
||||
}
|
||||
return &details, nil
|
||||
}
|
||||
|
||||
func (man *SLLMImageManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input *api.LLMImageCreateInput) (*api.LLMImageCreateInput, error) {
|
||||
var err error
|
||||
input.SharableVirtualResourceCreateInput, err = man.SSharableVirtualResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.SharableVirtualResourceCreateInput)
|
||||
if nil != err {
|
||||
return input, errors.Wrap(err, "validate SharableVirtualResourceCreateInput")
|
||||
}
|
||||
|
||||
if len(input.CredentialId) > 0 {
|
||||
cred, err := fetchImageCredential(ctx, userCred, input.CredentialId)
|
||||
if err != nil {
|
||||
return input, errors.Wrap(err, "fetchImageCredential")
|
||||
}
|
||||
input.CredentialId = cred.Id
|
||||
}
|
||||
|
||||
input.Status = api.STATUS_READY
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (man *SLLMImageManager) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input *api.LLMImageUpdateInput) (*api.LLMImageUpdateInput, error) {
|
||||
var err error
|
||||
input.SharableVirtualResourceCreateInput, err = man.SSharableVirtualResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.SharableVirtualResourceCreateInput)
|
||||
if nil != err {
|
||||
return input, errors.Wrap(err, "validate SharableVirtualResourceCreateInput")
|
||||
}
|
||||
|
||||
if nil != input.CredentialId && len(*input.CredentialId) > 0 {
|
||||
cred, err := fetchImageCredential(ctx, userCred, *input.CredentialId)
|
||||
if err != nil {
|
||||
return input, errors.Wrap(err, "fetchImageCredential")
|
||||
}
|
||||
input.CredentialId = &cred.Id
|
||||
}
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (man *SLLMImageManager) ListItemFilter(
|
||||
ctx context.Context,
|
||||
q *sqlchemy.SQuery,
|
||||
userCred mcclient.TokenCredential,
|
||||
input api.LLMImageListInput,
|
||||
) (*sqlchemy.SQuery, error) {
|
||||
q, err := man.SSharableVirtualResourceBaseManager.ListItemFilter(ctx, q, userCred, input.SharableVirtualResourceListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "SSharableBaseResourceManager.ListItemFilter")
|
||||
}
|
||||
if input.IsPublic != nil {
|
||||
if *input.IsPublic {
|
||||
q = q.IsTrue("is_public")
|
||||
} else {
|
||||
q = q.IsFalse("is_public")
|
||||
}
|
||||
}
|
||||
if len(input.ImageLabel) > 0 {
|
||||
q = q.Equals("image_label", input.ImageLabel)
|
||||
}
|
||||
if len(input.ImageName) > 0 {
|
||||
q = q.Equals("image_name", input.ImageName)
|
||||
}
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (image *SLLMImage) ValidateDeleteCondition(ctx context.Context, info jsonutils.JSONObject) error {
|
||||
for _, field := range []string{"llm_image_id"} {
|
||||
count, err := GetLLMManager().Query().Equals(field, image.Id).CountWithError()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "fetch llms")
|
||||
}
|
||||
if count > 0 {
|
||||
return errors.Wrapf(errors.ErrNotSupported, "This image is currently in use by %s in llms", field)
|
||||
}
|
||||
count, err = GetLLMModelManager().Query().Equals("llm_image_id", image.Id).CountWithError()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "fetch llm models")
|
||||
}
|
||||
if count > 0 {
|
||||
return errors.Wrapf(errors.ErrNotSupported, "This image is currently in use by %s in llm models", field)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (image *SLLMImage) ToContainerImage() string {
|
||||
return fmt.Sprintf("%s:%s", image.ImageName, image.ImageLabel)
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"yunion.io/x/log"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
)
|
||||
|
||||
func InitDB() error {
|
||||
for _, manager := range []db.IModelManager{
|
||||
db.Metadata,
|
||||
|
||||
// DifyManager,
|
||||
// LLMManager,
|
||||
} {
|
||||
err := manager.InitializeData()
|
||||
if err != nil {
|
||||
log.Errorf("Manager %s initializeData fail %s", manager.Keyword(), err)
|
||||
return err
|
||||
} else {
|
||||
log.Infof("Manager %s initializeData PASS!", manager.Keyword())
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -1,321 +0,0 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"strings"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/utils"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
commonapi "yunion.io/x/onecloud/pkg/apis"
|
||||
computeapi "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
api "yunion.io/x/onecloud/pkg/apis/llm"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/auth"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules/compute"
|
||||
)
|
||||
|
||||
var llmManager *SLLMManager
|
||||
|
||||
func init() {
|
||||
GetLLMManager()
|
||||
}
|
||||
|
||||
func GetLLMManager() *SLLMManager {
|
||||
if llmManager != nil {
|
||||
return llmManager
|
||||
}
|
||||
llmManager = &SLLMManager{
|
||||
SLLMBaseManager: NewSLLMBaseManager(
|
||||
SLLM{},
|
||||
"llms_tbl",
|
||||
"llm",
|
||||
"llms",
|
||||
),
|
||||
}
|
||||
llmManager.SetVirtualObject(llmManager)
|
||||
return llmManager
|
||||
}
|
||||
|
||||
type SLLMManager struct {
|
||||
SLLMBaseManager
|
||||
}
|
||||
|
||||
type SLLM struct {
|
||||
SLLMBase
|
||||
|
||||
LLMModelId string `width:"128" charset:"ascii" nullable:"false" list:"user" create:"required"`
|
||||
LLMImageId string `width:"128" charset:"ascii" nullable:"false" list:"user" create:"required"`
|
||||
}
|
||||
|
||||
func (man *SLLMManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input *api.LLMCreateInput) (*api.LLMCreateInput, error) {
|
||||
var err error
|
||||
input.LLMBaseCreateInput, err = man.SLLMBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.LLMBaseCreateInput)
|
||||
if err != nil {
|
||||
return input, errors.Wrap(err, "validate LLMBaseCreateInput")
|
||||
}
|
||||
model, err := GetLLMModelManager().FetchByIdOrName(ctx, userCred, input.LLMModelId)
|
||||
if err != nil {
|
||||
return input, errors.Wrap(err, "fetch LLMModel")
|
||||
}
|
||||
lModel := model.(*SLLMModel)
|
||||
input.LLMModelId = lModel.Id
|
||||
input.LLMImageId = lModel.LLMImageId
|
||||
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (man *SLLMManager) BatchCreateValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input api.LLMCreateInput) (*jsonutils.JSONDict, error) {
|
||||
data, err := man.ValidateCreateData(ctx, userCred, ownerId, query, &input)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return data.JSON(data), nil
|
||||
}
|
||||
|
||||
func (man *SLLMManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQuery, userCred mcclient.TokenCredential, input api.LLMListInput) (*sqlchemy.SQuery, error) {
|
||||
q, err := man.SLLMBaseManager.ListItemFilter(ctx, q, userCred, input.LLMBaseListInput)
|
||||
if err != nil {
|
||||
return q, errors.Wrap(err, "VirtualResourceBaseManager.ListItemFilter")
|
||||
}
|
||||
|
||||
if len(input.LLMModel) > 0 {
|
||||
modelObj, err := GetLLMModelManager().FetchByIdOrName(ctx, userCred, input.LLMModel)
|
||||
if err != nil {
|
||||
if errors.Cause(err) == sql.ErrNoRows {
|
||||
return nil, httperrors.NewResourceNotFoundError2(GetLLMModelManager().KeywordPlural(), input.LLMModel)
|
||||
} else {
|
||||
return nil, errors.Wrap(err, "LLMModelManager.FetchByIdOrName")
|
||||
}
|
||||
}
|
||||
q = q.Equals("llm_model_id", modelObj.GetId())
|
||||
}
|
||||
if len(input.LLMImage) > 0 {
|
||||
imgObj, err := GetLLMImageManager().FetchByIdOrName(ctx, userCred, input.LLMImage)
|
||||
if err != nil {
|
||||
if errors.Cause(err) == sql.ErrNoRows {
|
||||
return nil, httperrors.NewResourceNotFoundError2(GetLLMImageManager().KeywordPlural(), input.LLMImage)
|
||||
} else {
|
||||
return nil, errors.Wrap(err, "LLMImageManager.FetchByIdOrName")
|
||||
}
|
||||
}
|
||||
q = q.Equals("llm_image_id", imgObj.GetId())
|
||||
}
|
||||
|
||||
// if input.Unused != nil {
|
||||
// instanceQ := GetDesktopInstanceManager().Query().SubQuery()
|
||||
// if *input.Unused {
|
||||
// q = q.NotEquals("id", instanceQ.Query(instanceQ.Field("desktop_id")).SubQuery())
|
||||
// } else {
|
||||
// q = q.Join(instanceQ, sqlchemy.Equals(q.Field("id"), instanceQ.Field("desktop_id")))
|
||||
// }
|
||||
// }
|
||||
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (lm *SLLMManager) OnCreateComplete(ctx context.Context, items []db.IModel, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data []jsonutils.JSONObject) {
|
||||
parentTaskId, _ := data[0].GetString("parent_task_id")
|
||||
err := runBatchCreateTask(ctx, items, userCred, data, "LLMBatchCreateTask", parentTaskId)
|
||||
if err != nil {
|
||||
for i := range items {
|
||||
llm := items[i].(*SLLM)
|
||||
llm.SetStatus(ctx, userCred, api.LLM_STATUS_CREATE_FAIL, err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func runBatchCreateTask(
|
||||
ctx context.Context,
|
||||
items []db.IModel,
|
||||
userCred mcclient.TokenCredential,
|
||||
data []jsonutils.JSONObject,
|
||||
taskName string,
|
||||
parentTaskId string,
|
||||
) error {
|
||||
taskItems := make([]db.IStandaloneModel, len(items))
|
||||
for i, t := range items {
|
||||
taskItems[i] = t.(db.IStandaloneModel)
|
||||
}
|
||||
params := jsonutils.NewDict()
|
||||
params.Set("data", jsonutils.NewArray(data...))
|
||||
|
||||
task, err := taskman.TaskManager.NewParallelTask(ctx, taskName, taskItems, userCred, params, parentTaskId, "")
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "NewParallelTask %s", taskName)
|
||||
}
|
||||
|
||||
return task.ScheduleRun(nil)
|
||||
}
|
||||
|
||||
func (llm *SLLM) CustomizeDelete(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
|
||||
return llm.StartDeleteTask(ctx, userCred, "")
|
||||
}
|
||||
|
||||
func (llm *SLLM) GetLLMModel(modelId string) (*SLLMModel, error) {
|
||||
if len(modelId) == 0 {
|
||||
modelId = llm.LLMModelId
|
||||
}
|
||||
model, err := GetLLMModelManager().FetchById(modelId)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "fetch LLMModel")
|
||||
}
|
||||
return model.(*SLLMModel), nil
|
||||
}
|
||||
|
||||
func (llm *SLLM) GetLargeLanguageModelName() (modelName string, modelTag string, err error) {
|
||||
model, err := llm.GetLLMModel("")
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
name := model.LLMModelName
|
||||
parts := strings.Split(name, ":")
|
||||
modelName = parts[0]
|
||||
modelTag = "latest"
|
||||
if len(parts) > 1 {
|
||||
modelTag = parts[1]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (llm *SLLM) GetLLMImage() (*SLLMImage, error) {
|
||||
return llm.getImage(llm.LLMImageId)
|
||||
}
|
||||
|
||||
func (llm *SLLM) GetLLMContainer() (*SLLMContainer, error) {
|
||||
return GetLLMContainerManager().FetchByLLMId(llm.Id)
|
||||
}
|
||||
|
||||
func (llm *SLLM) GetLLMContainerDriver() ILLMContainerDriver {
|
||||
model, _ := llm.GetLLMModel(llm.LLMModelId)
|
||||
return model.GetLLMContainerDriver()
|
||||
}
|
||||
|
||||
func (llm *SLLM) StartCreateTask(ctx context.Context, userCred mcclient.TokenCredential, input api.LLMCreateInput, parentTaskId string) error {
|
||||
llm.SetStatus(ctx, userCred, commonapi.STATUS_CREATING, "")
|
||||
params := jsonutils.Marshal(input).(*jsonutils.JSONDict)
|
||||
var err = func() error {
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "LLMCreateTask", llm, userCred, params, parentTaskId, "", nil)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "NewTask")
|
||||
}
|
||||
return task.ScheduleRun(params)
|
||||
}()
|
||||
if err != nil {
|
||||
llm.SetStatus(ctx, userCred, api.LLM_STATUS_CREATE_FAIL, err.Error())
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (llm *SLLM) StartPullModelTask(ctx context.Context, userCred mcclient.TokenCredential, input *jsonutils.JSONDict, parentTaskId string) error {
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "LLMPullModelTask", llm, userCred, input, parentTaskId, "", nil)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "NewTask")
|
||||
}
|
||||
return task.ScheduleRun(nil)
|
||||
}
|
||||
|
||||
func (llm *SLLM) StartDeleteTask(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
|
||||
llm.SetStatus(ctx, userCred, api.LLM_STATUS_START_DELETE, "StartDeleteTask")
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "LLMDeleteTask", llm, userCred, nil, parentTaskId, "", nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return task.ScheduleRun(nil)
|
||||
}
|
||||
|
||||
func (llm *SLLM) ServerCreate(ctx context.Context, userCred mcclient.TokenCredential, input *api.LLMCreateInput) (string, error) {
|
||||
model, err := llm.GetLLMModel(llm.LLMModelId)
|
||||
if nil != err {
|
||||
return "", errors.Wrap(err, "GetLLMModel")
|
||||
}
|
||||
llmImage, err := llm.GetLLMImage()
|
||||
if nil != err {
|
||||
return "", errors.Wrap(err, "GetLLMImage")
|
||||
}
|
||||
|
||||
data, err := GetLLMPodCreateInput(ctx, userCred, input, llm, model, llmImage, "")
|
||||
if nil != err {
|
||||
return "", errors.Wrap(err, "GetPodCreateInput")
|
||||
}
|
||||
log.Infoln("PodCreateInput Data: ", jsonutils.Marshal(data).String())
|
||||
|
||||
s := auth.GetSession(ctx, userCred, "")
|
||||
resp, err := compute.Servers.Create(s, jsonutils.Marshal(data))
|
||||
if nil != err {
|
||||
return "", errors.Wrap(err, "Servers.Create")
|
||||
}
|
||||
id, err := resp.GetString("id")
|
||||
if nil != err {
|
||||
return "", errors.Wrap(err, "resp.GetString")
|
||||
}
|
||||
|
||||
return id, nil
|
||||
}
|
||||
|
||||
func (llm *SLLM) PerformStart(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
// can't start while it's already running
|
||||
if utils.IsInStringArray(llm.Status, computeapi.VM_RUNNING_STATUS) {
|
||||
return nil, errors.Wrapf(errors.ErrInvalidStatus, "llm id: %s status: %s", llm.Id, llm.Status)
|
||||
}
|
||||
|
||||
if err := llm.StartStartTask(ctx, userCred, ""); err != nil {
|
||||
return nil, errors.Wrap(err, "StartStartTask")
|
||||
}
|
||||
return jsonutils.Marshal(nil), nil
|
||||
}
|
||||
|
||||
func (llm *SLLM) StartStartTask(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "LLMStartTask", llm, userCred, nil, parentTaskId, "", nil)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "NewTask")
|
||||
}
|
||||
return task.ScheduleRun(nil)
|
||||
}
|
||||
|
||||
func (llm *SLLM) PerformStop(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
if llm.Status == computeapi.VM_READY {
|
||||
return nil, errors.Wrapf(errors.ErrInvalidStatus, "llm id: %s status: %s", llm.Id, llm.Status)
|
||||
}
|
||||
llm.SetStatus(ctx, userCred, computeapi.VM_START_STOP, "perform stop")
|
||||
err := llm.StartLLMStopTask(ctx, userCred, "")
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "StartStopTask")
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (llm *SLLM) StartLLMStopTask(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "LLMStopTask", llm, userCred, nil, parentTaskId, "", nil)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "NewTask")
|
||||
}
|
||||
err = task.ScheduleRun(nil)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "ScheduleRun")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// func (llm *SLLM) ValidateDeleteCondition(ctx context.Context, info jsonutils.JSONObject) error {
|
||||
// instanceId, isBound, err := llm.IsBoundToInstance()
|
||||
// if err != nil {
|
||||
// return errors.Wrap(err, "IsBoundToInstance")
|
||||
// }
|
||||
// if isBound {
|
||||
// return httperrors.NewBadRequestError("llm is bound to instance %s", instanceId)
|
||||
// }
|
||||
// return nil
|
||||
// }
|
||||
|
||||
// func (llm *SLLM) WaitContainerStatus(ctx context.Context, userCred mcclient.TokenCredential, targetStatus []string, timeoutSecs int) (*computeapi.SContainer, error) {
|
||||
// return nil, nil
|
||||
// }
|
||||
@@ -1,307 +0,0 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
computeapi "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
api "yunion.io/x/onecloud/pkg/apis/llm"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/llm/options"
|
||||
cloudutil "yunion.io/x/onecloud/pkg/llm/utils"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/auth"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules/compute"
|
||||
computeoptions "yunion.io/x/onecloud/pkg/mcclient/options/compute"
|
||||
"yunion.io/x/onecloud/pkg/util/stringutils2"
|
||||
)
|
||||
|
||||
func NewSLLMBaseManager(dt interface{}, tableName string, keyword string, keywordPlural string) SLLMBaseManager {
|
||||
return SLLMBaseManager{
|
||||
SVirtualResourceBaseManager: db.NewVirtualResourceBaseManager(
|
||||
dt,
|
||||
tableName,
|
||||
keyword,
|
||||
keywordPlural,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
type SLLMBaseManager struct {
|
||||
db.SVirtualResourceBaseManager
|
||||
db.SEnabledResourceBaseManager
|
||||
}
|
||||
|
||||
type SLLMBase struct {
|
||||
db.SVirtualResourceBase
|
||||
db.SEnabledResourceBase
|
||||
|
||||
SvrId string `width:"128" charset:"ascii" nullable:"true" list:"user"`
|
||||
LLMIp string `width:"20" charset:"ascii" nullable:"true" list:"user"`
|
||||
// Hypervisor string `width:"128" charset:"ascii" nullable:"true" list:"user"`
|
||||
Priority int `nullable:"false" default:"100" list:"user"`
|
||||
BandwidthMb int `nullable:"true" list:"user" create:"admin_optional"`
|
||||
|
||||
LastAppProbe time.Time `nullable:"true" list:"user" create:"admin_optional"`
|
||||
|
||||
// 是否请求同步更新镜像
|
||||
SyncImageRequest bool `default:"false" nullable:"false" list:"user" update:"user"`
|
||||
|
||||
VolumeUsedMb int `nullable:"true" list:"user"`
|
||||
VolumeUsedAt time.Time `nullable:"true" list:"user"`
|
||||
|
||||
// 秒装应用配额(可安装的总容量限制)
|
||||
// InstantAppQuotaGb int `list:"user" update:"user" create:"optional" default:"0" nullable:"false"`
|
||||
|
||||
DebugMode bool `default:"false" nullable:"false" list:"user" update:"user"`
|
||||
RootfsUnlimit bool `default:"false" nullable:"false" list:"user" update:"user"`
|
||||
}
|
||||
|
||||
func (man *SLLMBaseManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input api.LLMBaseCreateInput) (api.LLMBaseCreateInput, error) {
|
||||
var err error
|
||||
input.VirtualResourceCreateInput, err = man.SVirtualResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.VirtualResourceCreateInput)
|
||||
if err != nil {
|
||||
return input, errors.Wrap(err, "validate VirtualResourceCreateInput")
|
||||
}
|
||||
|
||||
if len(input.PreferHost) > 0 {
|
||||
s := auth.GetSession(ctx, userCred, "")
|
||||
hostJson, err := compute.Hosts.Get(s, input.PreferHost, nil)
|
||||
if err != nil {
|
||||
return input, errors.Wrap(err, "get host")
|
||||
}
|
||||
hostDetails := computeapi.HostDetails{}
|
||||
if err := hostJson.Unmarshal(&hostDetails); err != nil {
|
||||
return input, errors.Wrap(err, "unmarshal hostDetails")
|
||||
}
|
||||
if hostDetails.Enabled == nil || !*hostDetails.Enabled {
|
||||
return input, errors.Wrap(errors.ErrInvalidStatus, "not enabled")
|
||||
}
|
||||
if hostDetails.HostStatus != computeapi.HOST_ONLINE {
|
||||
return input, errors.Wrap(errors.ErrInvalidStatus, "not online")
|
||||
}
|
||||
if hostDetails.HostType != computeapi.HOST_TYPE_CONTAINER {
|
||||
return input, errors.Wrapf(httperrors.ErrNotAcceptable, "host_type %s not supported", hostDetails.HostType)
|
||||
}
|
||||
input.PreferHost = hostDetails.Id
|
||||
}
|
||||
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func GetServerIdsByHost(ctx context.Context, userCred mcclient.TokenCredential, hostId string) ([]string, error) {
|
||||
s := auth.GetSession(ctx, userCred, options.Options.Region)
|
||||
params := computeoptions.ServerListOptions{}
|
||||
params.Scope = "maxallowed"
|
||||
params.Host = hostId
|
||||
params.Field = []string{"id"}
|
||||
limit := 1024
|
||||
params.Limit = &limit
|
||||
offset := 0
|
||||
total := -1
|
||||
idList := stringutils2.NewSortedStrings(nil)
|
||||
for total < 0 || offset < total {
|
||||
params.Offset = &offset
|
||||
results, err := compute.Servers.List(s, jsonutils.Marshal(params))
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Servers.List")
|
||||
}
|
||||
total = results.Total
|
||||
for i := range results.Data {
|
||||
idStr, _ := results.Data[i].GetString("id")
|
||||
if len(idStr) > 0 {
|
||||
idList = idList.Append(idStr)
|
||||
}
|
||||
}
|
||||
offset += len(results.Data)
|
||||
}
|
||||
return idList, nil
|
||||
}
|
||||
|
||||
func (man *SLLMBaseManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQuery, userCred mcclient.TokenCredential, input api.LLMBaseListInput) (*sqlchemy.SQuery, error) {
|
||||
q, err := man.SVirtualResourceBaseManager.ListItemFilter(ctx, q, userCred, input.VirtualResourceListInput)
|
||||
if err != nil {
|
||||
return q, errors.Wrap(err, "VirtualResourceBaseManager.ListItemFilter")
|
||||
}
|
||||
q, err = man.SEnabledResourceBaseManager.ListItemFilter(ctx, q, userCred, input.EnabledResourceBaseListInput)
|
||||
if err != nil {
|
||||
return q, errors.Wrap(err, "SEnabledResourceBaseManager.ListItemFilter")
|
||||
}
|
||||
|
||||
if len(input.Host) > 0 {
|
||||
serverIds, err := GetServerIdsByHost(ctx, userCred, input.Host)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "GetServerIdsByHost")
|
||||
}
|
||||
q = q.In("svr_id", serverIds)
|
||||
}
|
||||
if len(input.Status) > 0 {
|
||||
s := auth.GetSession(ctx, userCred, options.Options.Region)
|
||||
params := computeoptions.ServerListOptions{}
|
||||
params.Scope = "maxallowed"
|
||||
params.Status = input.Status
|
||||
params.Field = []string{"guest_id"}
|
||||
limit := 1024
|
||||
params.Limit = &limit
|
||||
offset := 0
|
||||
total := -1
|
||||
idList := stringutils2.NewSortedStrings(nil)
|
||||
for total < 0 || offset < total {
|
||||
params.Offset = &offset
|
||||
results, err := compute.Containers.List(s, jsonutils.Marshal(params))
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Containers.List")
|
||||
}
|
||||
total = results.Total
|
||||
for i := range results.Data {
|
||||
idStr, _ := results.Data[i].GetString("guest_id")
|
||||
if len(idStr) > 0 {
|
||||
idList = idList.Append(idStr)
|
||||
}
|
||||
}
|
||||
offset += len(results.Data)
|
||||
}
|
||||
q = q.In("svr_id", idList)
|
||||
}
|
||||
|
||||
if input.NoVolume != nil {
|
||||
volumeQ := GetVolumeManager().Query("llm_id").SubQuery()
|
||||
q = q.LeftJoin(volumeQ, sqlchemy.Equals(q.Field("id"), volumeQ.Field("llm_id")))
|
||||
if *input.NoVolume {
|
||||
q = q.Filter(sqlchemy.IsNull(volumeQ.Field("llm_id")))
|
||||
} else {
|
||||
q = q.Filter(sqlchemy.IsNotNull(volumeQ.Field("llm_id")))
|
||||
}
|
||||
}
|
||||
if len(input.VolumeId) > 0 {
|
||||
volumeObj, err := GetVolumeManager().FetchByIdOrName(ctx, userCred, input.VolumeId)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "VolumeManager.FetchByIdOrName")
|
||||
}
|
||||
vq := GetVolumeManager().Query().SubQuery()
|
||||
q = q.Join(vq, sqlchemy.Equals(q.Field("id"), vq.Field("llm_id")))
|
||||
q = q.Filter(sqlchemy.Equals(vq.Field("id"), volumeObj.GetId()))
|
||||
}
|
||||
|
||||
accessQ := GetAccessInfoManager().Query().SubQuery()
|
||||
if input.ListenPort > 0 {
|
||||
q = q.Join(accessQ, sqlchemy.Equals(q.Field("id"), accessQ.Field("llm_id")))
|
||||
q = q.Filter(sqlchemy.Equals(accessQ.Field("listen_port"), input.ListenPort))
|
||||
}
|
||||
|
||||
if len(input.PublicIp) > 0 {
|
||||
s := auth.GetSession(ctx, userCred, "")
|
||||
hostInput := computeapi.HostListInput{
|
||||
PublicIp: []string{input.PublicIp},
|
||||
}
|
||||
hostInput.Field = []string{"id"}
|
||||
hosts, err := compute.Hosts.List(s, jsonutils.Marshal(hostInput))
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Hosts.List")
|
||||
}
|
||||
if len(hosts.Data) == 0 {
|
||||
return nil, httperrors.NewNotFoundError("Not found host by public_ip %s", input.PublicIp)
|
||||
}
|
||||
hostIds := []string{}
|
||||
for i := range hosts.Data {
|
||||
idStr, _ := hosts.Data[i].GetString("id")
|
||||
if len(idStr) > 0 {
|
||||
hostIds = append(hostIds, idStr)
|
||||
}
|
||||
}
|
||||
if len(hostIds) > 0 {
|
||||
serverIds, err := GetServerIdsByHost(ctx, userCred, hostIds[0])
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "GetServerIdsByHost")
|
||||
}
|
||||
q = q.In("svr_id", serverIds)
|
||||
}
|
||||
}
|
||||
// if input.Unused != nil {
|
||||
// instanceQ := GetDesktopInstanceManager().Query().SubQuery()
|
||||
// if *input.Unused {
|
||||
// q = q.NotEquals("id", instanceQ.Query(instanceQ.Field("desktop_id")).SubQuery())
|
||||
// } else {
|
||||
// q = q.Join(instanceQ, sqlchemy.Equals(q.Field("id"), instanceQ.Field("desktop_id")))
|
||||
// }
|
||||
// }
|
||||
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (llm *SLLMBase) GetServer(ctx context.Context) (*computeapi.ServerDetails, error) {
|
||||
return cloudutil.GetServer(ctx, llm.SvrId)
|
||||
}
|
||||
|
||||
func (llm *SLLMBase) GetVolume() (*SVolume, error) {
|
||||
volume := &SVolume{}
|
||||
err := GetVolumeManager().Query().Equals("llm_id", llm.Id).First(volume)
|
||||
if err != nil {
|
||||
if errors.Cause(err) == sql.ErrNoRows {
|
||||
return nil, errors.Wrap(errors.ErrNotFound, "query volume")
|
||||
}
|
||||
return nil, errors.Wrap(err, "FetchVolume")
|
||||
}
|
||||
volume.SetModelManager(GetVolumeManager(), volume)
|
||||
return volume, nil
|
||||
}
|
||||
|
||||
// 取消自动删除
|
||||
func (llm *SLLMBase) Delete(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (llm *SLLMBase) RealDelete(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
return llm.SVirtualResourceBase.Delete(ctx, userCred)
|
||||
}
|
||||
|
||||
func (llm *SLLMBase) ServerDelete(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
if len(llm.SvrId) == 0 {
|
||||
return nil
|
||||
}
|
||||
s := auth.GetSession(ctx, userCred, "")
|
||||
server, err := llm.GetServer(ctx)
|
||||
if err != nil {
|
||||
if errors.Cause(err) == errors.ErrNotFound {
|
||||
return nil
|
||||
} else {
|
||||
return errors.Wrap(err, "GetServer")
|
||||
}
|
||||
}
|
||||
if server.DisableDelete != nil && *server.DisableDelete {
|
||||
// update to allow delete
|
||||
_, err = compute.Servers.Update(s, llm.SvrId, jsonutils.Marshal(map[string]interface{}{"disable_delete": false}))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "update server to delete")
|
||||
}
|
||||
}
|
||||
_, err = compute.Servers.DeleteWithParam(s, llm.SvrId, jsonutils.Marshal(map[string]interface{}{
|
||||
"override_pending_delete": true,
|
||||
}), nil)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "delete server err:")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (llm *SLLMBase) WaitDelete(ctx context.Context, userCred mcclient.TokenCredential, timeoutSecs int) error {
|
||||
return cloudutil.WaitDelete[computeapi.ServerDetails](ctx, &compute.Servers, llm.SvrId, timeoutSecs)
|
||||
}
|
||||
|
||||
func (llm *SLLMBase) getImage(imageId string) (*SLLMImage, error) {
|
||||
image, err := GetLLMImageManager().FetchById(imageId)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "fetch LLMImage")
|
||||
}
|
||||
return image.(*SLLMImage), nil
|
||||
}
|
||||
|
||||
func (llm *SLLMBase) WaitServerStatus(ctx context.Context, userCred mcclient.TokenCredential, targetStatus []string, timeoutSecs int) (*computeapi.ServerDetails, error) {
|
||||
return cloudutil.WaitServerStatus(ctx, llm.SvrId, targetStatus, timeoutSecs)
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
commonapi "yunion.io/x/onecloud/pkg/apis"
|
||||
api "yunion.io/x/onecloud/pkg/apis/llm"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
)
|
||||
|
||||
var (
|
||||
llmContainerManager *SLLMContainerManager
|
||||
)
|
||||
|
||||
func GetLLMContainerManager() *SLLMContainerManager {
|
||||
if llmContainerManager != nil {
|
||||
return llmContainerManager
|
||||
}
|
||||
m := NewLLMContainerManager(SLLMContainer{}, "llm_container", "llm_containers")
|
||||
llmContainerManager = &m
|
||||
llmContainerManager.SetVirtualObject(llmContainerManager)
|
||||
return llmContainerManager
|
||||
}
|
||||
|
||||
func NewLLMContainerManager(dt interface{}, keyword string, keywordPlural string) SLLMContainerManager {
|
||||
return SLLMContainerManager{
|
||||
SVirtualResourceBaseManager: db.NewVirtualResourceBaseManager(dt, "llm_containers_tbl", keyword, keywordPlural),
|
||||
}
|
||||
}
|
||||
|
||||
type SLLMContainerManager struct {
|
||||
db.SVirtualResourceBaseManager
|
||||
}
|
||||
|
||||
type SLLMContainer struct {
|
||||
db.SVirtualResourceBase
|
||||
|
||||
LLMId string `width:"128" charset:"ascii" nullable:"false" list:"user" primary:"true" create:"required"`
|
||||
CmpId string `width:"128" charset:"ascii" nullable:"true" list:"user" create:"required"`
|
||||
Type string `width:"16" charset:"ascii" list:"user" primary:"true" create:"required"`
|
||||
RunningAppId string `width:"128" charset:"ascii" nullable:"true" list:"user"`
|
||||
}
|
||||
|
||||
func (m *SLLMContainerManager) CreateOnLLM(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
ownerId mcclient.IIdentityProvider,
|
||||
llm *SLLM, cmpId string, svrName string,
|
||||
) (*SLLMContainer, error) {
|
||||
input := &api.LLMContainerCreateInput{
|
||||
LLMId: llm.Id,
|
||||
Type: string(llm.GetLLMContainerDriver().GetType()),
|
||||
CmpId: cmpId,
|
||||
}
|
||||
input.Name = svrName
|
||||
obj, err := db.DoCreate(m, ctx, userCred, nil, jsonutils.Marshal(input), ownerId)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "create llm container")
|
||||
}
|
||||
return obj.(*SLLMContainer), nil
|
||||
}
|
||||
|
||||
func (m *SLLMContainerManager) FetchByLLMId(
|
||||
llmId string,
|
||||
) (*SLLMContainer, error) {
|
||||
lc := &SLLMContainer{}
|
||||
if err := m.Query().Equals("llm_id", llmId).First(lc); err != nil {
|
||||
return nil, errors.Wrapf(err, "query llm container by llm id %s", llmId)
|
||||
}
|
||||
lc.SetModelManager(m, lc)
|
||||
return lc, nil
|
||||
}
|
||||
|
||||
func (lc *SLLMContainer) RealDelete(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
return lc.SVirtualResourceBase.Delete(ctx, userCred)
|
||||
}
|
||||
|
||||
func (lc *SLLMContainer) StartDeleteTask(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "LLMContainerDeleteTask", lc, userCred, nil, parentTaskId, "", nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
lc.SetStatus(ctx, userCred, commonapi.STATUS_DELETING, "")
|
||||
task.ScheduleRun(nil)
|
||||
return nil
|
||||
}
|
||||
@@ -1,90 +0,0 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
|
||||
computeapi "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/apis/llm"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
)
|
||||
|
||||
type drivers struct {
|
||||
drivers *sync.Map
|
||||
}
|
||||
|
||||
func newDrivers() *drivers {
|
||||
return &drivers{
|
||||
drivers: &sync.Map{},
|
||||
}
|
||||
}
|
||||
|
||||
func (d *drivers) GetWithError(typ string) (interface{}, error) {
|
||||
drv, ok := d.drivers.Load(typ)
|
||||
if !ok {
|
||||
return drv, httperrors.NewNotFoundError("app container driver %s not found", typ)
|
||||
}
|
||||
return drv, nil
|
||||
}
|
||||
|
||||
func (d *drivers) Get(typ string) interface{} {
|
||||
drv, err := d.GetWithError(typ)
|
||||
if err != nil {
|
||||
panic(err.Error())
|
||||
}
|
||||
return drv
|
||||
}
|
||||
|
||||
func (d *drivers) Register(typ string, drv interface{}) {
|
||||
d.drivers.Store(typ, drv)
|
||||
}
|
||||
|
||||
func registerDriver[K ~string, D any](drvs *drivers, typ K, drv D) {
|
||||
drvs.Register(string(typ), drv)
|
||||
}
|
||||
|
||||
func getDriver[K ~string, D any](drvs *drivers, typ K) D {
|
||||
return drvs.Get(string(typ)).(D)
|
||||
}
|
||||
|
||||
func getDriverWithError[K ~string, D any](drvs *drivers, typ K) (D, error) {
|
||||
drv, err := drvs.GetWithError(string(typ))
|
||||
if err != nil {
|
||||
return drv.(D), err
|
||||
}
|
||||
return drv.(D), nil
|
||||
}
|
||||
|
||||
type ILLMContainerPullModel interface {
|
||||
// PullModelByInstall(ctx context.Context, userCred mcclient.TokenCredential, llm *SLLM, modelName string, modelTag string) error
|
||||
// PullModelByGgufFile(ctx context.Context, userCred mcclient.TokenCredential, llm *SLLM, ggufFileUrl string, model string) error
|
||||
// DownloadGgufFile(ctx context.Context, userCred mcclient.TokenCredential, llm *SLLM, ggufFileUrl string, ggufFilePath string) error
|
||||
// InstallGgufModel(ctx context.Context, userCred mcclient.TokenCredential, llm *SLLM, ggufFilePath string) error
|
||||
GetManifests(ctx context.Context, userCred mcclient.TokenCredential, llm *SLLM, taskId string) error
|
||||
AccessBlobsCache(ctx context.Context, userCred mcclient.TokenCredential, llm *SLLM, taskId string) error
|
||||
CopyBlobs(ctx context.Context, userCred mcclient.TokenCredential, llm *SLLM) error
|
||||
}
|
||||
|
||||
type ILLMContainerDriver interface {
|
||||
GetType() llm.LLMContainerType
|
||||
GetContainerSpec(ctx context.Context, llm *SLLM, image *SLLMImage, sku *SLLMModel, props []string, devices []computeapi.SIsolatedDevice, diskId string) *computeapi.PodContainerCreateInput
|
||||
|
||||
// ILLMContainerPullModel
|
||||
}
|
||||
|
||||
var (
|
||||
llmContainerDrivers = newDrivers()
|
||||
)
|
||||
|
||||
func RegisterLLMContainerDriver(drv ILLMContainerDriver) {
|
||||
registerDriver(llmContainerDrivers, drv.GetType(), drv)
|
||||
}
|
||||
|
||||
func GetLLMContainerDriver(typ llm.LLMContainerType) ILLMContainerDriver {
|
||||
return getDriver[llm.LLMContainerType, ILLMContainerDriver](llmContainerDrivers, typ)
|
||||
}
|
||||
|
||||
func GetLLMContainerDriverWithError(typ llm.LLMContainerType) (ILLMContainerDriver, error) {
|
||||
return getDriverWithError[llm.LLMContainerType, ILLMContainerDriver](llmContainerDrivers, typ)
|
||||
}
|
||||
@@ -1,199 +0,0 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/llm"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/validators"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/util/stringutils2"
|
||||
)
|
||||
|
||||
func init() {
|
||||
GetLLMModelManager()
|
||||
}
|
||||
|
||||
var llmModelManager *SLLMModelManager
|
||||
|
||||
func GetLLMModelManager() *SLLMModelManager {
|
||||
if llmModelManager != nil {
|
||||
return llmModelManager
|
||||
}
|
||||
llmModelManager = &SLLMModelManager{
|
||||
SLLMModelBaseManager: NewSLLMModelBaseManager(
|
||||
SLLMModel{},
|
||||
"llm_models_tbl",
|
||||
"llm_model",
|
||||
"llm_models",
|
||||
),
|
||||
}
|
||||
llmModelManager.SetVirtualObject(llmModelManager)
|
||||
return llmModelManager
|
||||
}
|
||||
|
||||
type SLLMModelManager struct {
|
||||
SLLMModelBaseManager
|
||||
}
|
||||
|
||||
type SLLMModel struct {
|
||||
SLLMModelBase
|
||||
// SMountedAppsResource
|
||||
|
||||
LLMImageId string `width:"128" charset:"ascii" nullable:"false" list:"user" create:"required"`
|
||||
LLMType string `width:"128" charset:"ascii" nullable:"false" list:"user" create:"required"`
|
||||
LLMModelName string `width:"128" charset:"ascii" nullable:"false" list:"user" create:"required"`
|
||||
}
|
||||
|
||||
func (man *SLLMModelManager) ListItemFilter(
|
||||
ctx context.Context,
|
||||
q *sqlchemy.SQuery,
|
||||
userCred mcclient.TokenCredential,
|
||||
input api.LLMModelListInput,
|
||||
) (*sqlchemy.SQuery, error) {
|
||||
var err error
|
||||
q, err = man.SLLMModelBaseManager.ListItemFilter(ctx, q, userCred, input.SharableVirtualResourceListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "SLLMModelBaseManager.ListItemFilter")
|
||||
}
|
||||
if len(input.LLMType) > 0 {
|
||||
q = q.Equals("llm_type", input.LLMType)
|
||||
}
|
||||
// q, err = man.SMountedAppsResourceManager.ListItemFilter(ctx, q, userCred, input.MountedAppResourceListInput)
|
||||
// if err != nil {
|
||||
// return nil, errors.Wrap(err, "SMountedAppsResourceManager")
|
||||
// }
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (manager *SLLMModelManager) FetchCustomizeColumns(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject,
|
||||
objs []interface{},
|
||||
fields stringutils2.SSortedStrings,
|
||||
isList bool,
|
||||
) []api.LLMModelDetails {
|
||||
// skuIds := []string{}
|
||||
imageIds := []string{}
|
||||
// templateIds := []string{}
|
||||
|
||||
skus := []SLLMModel{}
|
||||
jsonutils.Update(&skus, objs)
|
||||
virows := manager.SSharableVirtualResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
|
||||
for _, sku := range skus {
|
||||
// skuIds = append(skuIds, sku.Id)
|
||||
imageIds = append(imageIds, sku.LLMImageId)
|
||||
// if sku.Volumes != nil && len(*sku.Volumes) > 0 && len((*sku.Volumes)[0].TemplateId) > 0 {
|
||||
// templateIds = append(templateIds, (*sku.Volumes)[0].TemplateId)
|
||||
// }
|
||||
}
|
||||
|
||||
// q := GetLLMManager().Query().In("llm_model_id", skuIds).GroupBy("llm_model_id")
|
||||
// q = q.AppendField(q.Field("llm_model_id"))
|
||||
// q = q.AppendField(sqlchemy.COUNT("llm_capacity"))
|
||||
// details := []struct {
|
||||
// LLMModelId string
|
||||
// LLMCapacity int
|
||||
// }{}
|
||||
// q.All(&details)
|
||||
res := make([]api.LLMModelDetails, len(objs))
|
||||
for i := range skus {
|
||||
res[i].SharableVirtualResourceDetails = virows[i]
|
||||
// for _, v := range details {
|
||||
// if v.LLMModelId == sku.Id {
|
||||
// res[i].LLMCapacity = v.LLMCapacity
|
||||
// break
|
||||
// }
|
||||
// }
|
||||
}
|
||||
{
|
||||
images := make(map[string]SLLMImage)
|
||||
err := db.FetchModelObjectsByIds(GetLLMImageManager(), "id", imageIds, &images)
|
||||
if err == nil {
|
||||
for i, sku := range skus {
|
||||
if image, ok := images[sku.LLMImageId]; ok {
|
||||
res[i].Image = image.Name
|
||||
res[i].ImageLabel = image.ImageLabel
|
||||
res[i].ImageName = image.ImageName
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.Errorf("FetchModelObjectsByIds DesktopImageManager fail %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
// if len(templateIds) > 0 {
|
||||
// templates, err := fetchTemplates(ctx, userCred, templateIds)
|
||||
// if err == nil {
|
||||
// for i, sku := range skus {
|
||||
// if templ, ok := templates[(*sku.Volumes)[0].TemplateId]; ok {
|
||||
// res[i].Template = templ.Name
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
// log.Errorf("fail to retrive image info %s", err)
|
||||
// }
|
||||
// }
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
func (man *SLLMModelManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input *api.LLMModelCreateInput) (*api.LLMModelCreateInput, error) {
|
||||
var err error
|
||||
input.LLMModelBaseCreateInput, err = man.SLLMModelBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.LLMModelBaseCreateInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SLLMModelBaseManager.ValidateCreateData")
|
||||
}
|
||||
if !api.IsLLMContainerType(input.LLMType) {
|
||||
return input, errors.Wrap(httperrors.ErrInputParameter, "llm_type must be one of "+strings.Join(api.LLM_CONTAINER_TYPES.List(), ","))
|
||||
}
|
||||
|
||||
_, err = validators.ValidateModel(ctx, userCred, GetLLMImageManager(), &input.LLMImageId)
|
||||
if err != nil {
|
||||
return input, errors.Wrapf(err, "validate image_id %s", input.LLMImageId)
|
||||
}
|
||||
|
||||
input.Status = api.STATUS_READY
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (model *SLLMModel) GetLLMContainerDriver() ILLMContainerDriver {
|
||||
return GetLLMContainerDriver(api.LLMContainerType(model.LLMType))
|
||||
}
|
||||
|
||||
func (model *SLLMModel) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.LLMModelUpdateInput) (api.LLMModelUpdateInput, error) {
|
||||
var err error
|
||||
input.LLMModelBaseUpdateInput, err = model.SLLMModelBase.ValidateUpdateData(ctx, userCred, query, input.LLMModelBaseUpdateInput)
|
||||
if err != nil {
|
||||
return input, errors.Wrap(err, "validate LLMModelBaseUpdateInput")
|
||||
}
|
||||
|
||||
if input.LLMImageId != "" {
|
||||
imgObj, err := validators.ValidateModel(ctx, userCred, GetLLMImageManager(), &input.LLMImageId)
|
||||
if err != nil {
|
||||
return input, errors.Wrapf(err, "validate image_id %s", input.LLMImageId)
|
||||
}
|
||||
input.LLMImageId = imgObj.GetId()
|
||||
}
|
||||
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (model *SLLMModel) ValidateDeleteCondition(ctx context.Context, info jsonutils.JSONObject) error {
|
||||
count, err := GetLLMManager().Query().Equals("llm_model_id", model.Id).CountWithError()
|
||||
if nil != err {
|
||||
return errors.Wrap(err, "fetch llm")
|
||||
}
|
||||
if count > 0 {
|
||||
return errors.Wrap(errors.ErrNotSupported, "This model is currently in use")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -1,172 +0,0 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis"
|
||||
computeapi "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
api "yunion.io/x/onecloud/pkg/apis/llm"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
)
|
||||
|
||||
const (
|
||||
POD_METADATA_POST_STOP_CLEANUP_CONFIG = "post_stop_cleanup_config"
|
||||
)
|
||||
|
||||
type PodPostStopCleanupConfig struct {
|
||||
Dirs []string `json:"dirs"`
|
||||
}
|
||||
|
||||
func GetLLMPodCreateInput(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
input *api.LLMCreateInput,
|
||||
llm *SLLM,
|
||||
sku *SLLMModel,
|
||||
llmImage *SLLMImage,
|
||||
eip string,
|
||||
) (*computeapi.ServerCreateInput, error) {
|
||||
data := computeapi.ServerCreateInput{}
|
||||
data.AutoStart = input.AutoStart
|
||||
data.ServerConfigs = computeapi.NewServerConfigs()
|
||||
data.Hypervisor = computeapi.HYPERVISOR_POD
|
||||
|
||||
postStopCleanupConfgi := PodPostStopCleanupConfig{
|
||||
Dirs: []string{
|
||||
GetTmpHostPath(llm.GetName()),
|
||||
},
|
||||
}
|
||||
data.Metadata = map[string]string{
|
||||
POD_METADATA_POST_STOP_CLEANUP_CONFIG: jsonutils.Marshal(postStopCleanupConfgi).String(),
|
||||
}
|
||||
|
||||
data.VcpuCount = sku.Cpu
|
||||
data.VmemSize = sku.Memory + 1
|
||||
data.Name = input.Name
|
||||
|
||||
// disks
|
||||
data.Disks = make([]*computeapi.DiskConfig, 0)
|
||||
if sku.Volumes != nil && !sku.Volumes.IsZero() {
|
||||
for idx, volume := range *sku.Volumes {
|
||||
data.Disks = append(data.Disks, &computeapi.DiskConfig{
|
||||
DiskType: "data",
|
||||
Format: "raw",
|
||||
Fs: "ext4",
|
||||
SizeMb: volume.SizeMB,
|
||||
Index: idx,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// isolated devices
|
||||
if sku.Devices != nil && !sku.Devices.IsZero() {
|
||||
data.IsolatedDevices = make([]*computeapi.IsolatedDeviceConfig, 0)
|
||||
devices := *sku.Devices
|
||||
for i := 0; i < len(devices); i++ {
|
||||
isolatedDevice := &computeapi.IsolatedDeviceConfig{
|
||||
DevType: devices[i].DevType,
|
||||
Model: devices[i].Model,
|
||||
DevicePath: devices[i].DevicePath,
|
||||
}
|
||||
data.IsolatedDevices = append(data.IsolatedDevices, isolatedDevice)
|
||||
}
|
||||
}
|
||||
|
||||
// port mappings
|
||||
// var portRange *computeapi.GuestPortMappingPortRange
|
||||
portMappings := computeapi.GuestPortMappings{}
|
||||
if sku.PortMappings != nil && !sku.PortMappings.IsZero() {
|
||||
// hostTcpPortRange := computeapi.GuestPortMappingPortRange{
|
||||
// Start: options.Options.HostTcpPortStart,
|
||||
// End: options.Options.HostTcpPortEnd,
|
||||
// }
|
||||
// hostUdpPortRange := computeapi.GuestPortMappingPortRange{
|
||||
// Start: options.Options.HostUdpPortStart,
|
||||
// End: options.Options.HostUdpPortEnd,
|
||||
// }
|
||||
for _, portInfo := range *sku.PortMappings {
|
||||
remoteIps := portInfo.RemoteIps
|
||||
if len(remoteIps) == 0 {
|
||||
remoteIps = nil
|
||||
}
|
||||
// if portInfo.Protocol == "tcp" {
|
||||
// portRange = &hostTcpPortRange
|
||||
// } else {
|
||||
// portRange = &hostUdpPortRange
|
||||
// }
|
||||
portMappings = append(portMappings, &computeapi.GuestPortMapping{
|
||||
Port: portInfo.ContainerPort,
|
||||
Protocol: computeapi.GuestPortMappingProtocol(portInfo.Protocol),
|
||||
RemoteIps: remoteIps,
|
||||
// HostPortRange: portRange,
|
||||
Rule: &computeapi.GuestPortMappingRule{
|
||||
FirstPortOffset: portInfo.FirstPortOffset,
|
||||
},
|
||||
Envs: portInfo.Envs,
|
||||
})
|
||||
}
|
||||
}
|
||||
bandwidth := llm.BandwidthMb
|
||||
if bandwidth == 0 {
|
||||
bandwidth = sku.BandwidthMb
|
||||
}
|
||||
data.Networks = []*computeapi.NetworkConfig{
|
||||
{
|
||||
NetType: computeapi.NETWORK_TYPE_HOSTLOCAL,
|
||||
BwLimit: bandwidth,
|
||||
PortMappings: portMappings,
|
||||
},
|
||||
}
|
||||
|
||||
data.Count = 1
|
||||
data.PreferHost = input.PreferHost
|
||||
|
||||
// enableLxcfs := true
|
||||
|
||||
lcd := llm.GetLLMContainerDriver()
|
||||
llmContainer := lcd.GetContainerSpec(ctx, llm, llmImage, sku, nil, nil, "")
|
||||
|
||||
data.Pod = &computeapi.PodCreateInput{
|
||||
HostIPC: true,
|
||||
Containers: []*computeapi.PodContainerCreateInput{
|
||||
llmContainer,
|
||||
},
|
||||
}
|
||||
|
||||
data.ProjectId = input.ProjectId
|
||||
if len(data.ProjectId) == 0 {
|
||||
data.ProjectId = userCred.GetProjectId()
|
||||
data.TenantId = userCred.GetTenantId()
|
||||
}
|
||||
|
||||
return &data, nil
|
||||
}
|
||||
|
||||
func NewHostDev(path string) *computeapi.ContainerDevice {
|
||||
return &computeapi.ContainerDevice{
|
||||
Type: apis.CONTAINER_DEVICE_TYPE_HOST,
|
||||
Host: &computeapi.ContainerHostDevice{
|
||||
HostPath: path,
|
||||
ContainerPath: path,
|
||||
Permissions: "rwm",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func NewEnv(key, val string) *apis.ContainerKeyValue {
|
||||
return &apis.ContainerKeyValue{
|
||||
Key: key,
|
||||
Value: val,
|
||||
}
|
||||
}
|
||||
|
||||
func GetTmpHostPath(name string) string {
|
||||
return fmt.Sprintf("/tmp/%s", name)
|
||||
}
|
||||
|
||||
func GetSvrLLMContainer(ctrs []*computeapi.PodContainerDesc) *computeapi.PodContainerDesc {
|
||||
return ctrs[0]
|
||||
}
|
||||
@@ -1,115 +0,0 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis"
|
||||
api "yunion.io/x/onecloud/pkg/apis/llm"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
)
|
||||
|
||||
func NewSLLMModelBaseManager(dt interface{}, tableName string, keyword string, keywordPlural string) SLLMModelBaseManager {
|
||||
return SLLMModelBaseManager{
|
||||
SSharableVirtualResourceBaseManager: db.NewSharableVirtualResourceBaseManager(
|
||||
dt,
|
||||
tableName,
|
||||
keyword,
|
||||
keywordPlural,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
type SLLMModelBaseManager struct {
|
||||
db.SSharableVirtualResourceBaseManager
|
||||
}
|
||||
|
||||
type SLLMModelBase struct {
|
||||
db.SSharableVirtualResourceBase
|
||||
|
||||
BandwidthMb int `nullable:"false" default:"0" create:"optional" list:"user" update:"user"`
|
||||
Cpu int `nullable:"false" default:"1" create:"optional" list:"user" update:"user"`
|
||||
Memory int `nullable:"false" default:"512" create:"optional" list:"user" update:"user"`
|
||||
Volumes *api.Volumes `charset:"utf8" length:"medium" nullable:"true" list:"user" update:"user" create:"optional"`
|
||||
PortMappings *api.PortMappings `charset:"utf8" length:"medium" nullable:"true" list:"user" update:"user" create:"optional"`
|
||||
Devices *api.Devices `charset:"utf8" length:"medium" nullable:"true" list:"user" update:"user" create:"optional"`
|
||||
Envs *api.Envs `charset:"utf8" nullable:"true" list:"user" update:"user" create:"optional"`
|
||||
// Properties
|
||||
Properties map[string]string `charset:"utf8" nullable:"true" list:"user" update:"user" create:"optional"`
|
||||
}
|
||||
|
||||
func (man *SLLMModelBaseManager) ListItemFilter(
|
||||
ctx context.Context,
|
||||
q *sqlchemy.SQuery,
|
||||
userCred mcclient.TokenCredential,
|
||||
input apis.SharableVirtualResourceListInput,
|
||||
) (*sqlchemy.SQuery, error) {
|
||||
var err error
|
||||
q, err = man.SSharableVirtualResourceBaseManager.ListItemFilter(ctx, q, userCred, input)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "SSharableBaseResourceManager.ListItemFilter")
|
||||
}
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (man *SLLMModelBaseManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input api.LLMModelBaseCreateInput) (api.LLMModelBaseCreateInput, error) {
|
||||
var err error
|
||||
input.SharableVirtualResourceCreateInput, err = man.SSharableVirtualResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.SharableVirtualResourceCreateInput)
|
||||
if err != nil {
|
||||
return input, errors.Wrap(err, "SSharableVirtualResourceBaseManager.ValidateCreateData")
|
||||
}
|
||||
if input.Cpu <= 0 {
|
||||
return input, errors.Wrap(httperrors.ErrInputParameter, "cpu must > 0")
|
||||
}
|
||||
if input.Memory <= 0 {
|
||||
return input, errors.Wrap(httperrors.ErrInputParameter, "mem must > 0")
|
||||
}
|
||||
if input.Volumes == nil {
|
||||
return input, errors.Wrap(httperrors.ErrInputParameter, "volumes cannot be empty")
|
||||
}
|
||||
|
||||
input.Status = api.STATUS_READY
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (modelBase *SLLMModelBase) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.LLMModelBaseUpdateInput) (api.LLMModelBaseUpdateInput, error) {
|
||||
var err error
|
||||
input.SharableVirtualResourceBaseUpdateInput, err = modelBase.SSharableVirtualResourceBase.ValidateUpdateData(ctx, userCred, query, input.SharableVirtualResourceBaseUpdateInput)
|
||||
if err != nil {
|
||||
return input, errors.Wrap(err, "validate SharableVirtualResourceBaseUpdateInput")
|
||||
}
|
||||
|
||||
volumes := []api.Volume{}
|
||||
if err := jsonutils.Marshal(modelBase.Volumes).Unmarshal(&volumes); err != nil {
|
||||
return input, errors.Wrapf(err, "Unmarshal Volumes")
|
||||
}
|
||||
for i, volume := range volumes {
|
||||
if input.DiskSizeMB != nil && *input.DiskSizeMB > 0 {
|
||||
volume.SizeMB = *input.DiskSizeMB
|
||||
}
|
||||
// if input.TemplateId != nil {
|
||||
// if len(*input.TemplateId) > 0 {
|
||||
// s := auth.GetSession(ctx, userCred, "")
|
||||
// imgObj, err := imagemodules.Images.Get(s, *input.TemplateId, nil)
|
||||
// if err != nil {
|
||||
// return input, errors.Wrapf(err, "validate template_id %s", *input.TemplateId)
|
||||
// }
|
||||
// volume.TemplateId, _ = imgObj.GetString("id")
|
||||
// } else {
|
||||
// volume.TemplateId = ""
|
||||
// }
|
||||
// }
|
||||
if input.StorageType != nil && len(*input.StorageType) > 0 {
|
||||
volume.StorageType = *input.StorageType
|
||||
}
|
||||
volumes[i] = volume
|
||||
}
|
||||
input.Volumes = (*api.Volumes)(&volumes)
|
||||
|
||||
return input, nil
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
commonapi "yunion.io/x/onecloud/pkg/apis"
|
||||
api "yunion.io/x/onecloud/pkg/apis/llm"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
)
|
||||
|
||||
func init() {
|
||||
GetVolumeManager()
|
||||
}
|
||||
|
||||
var volumeManager *SVolumeManager
|
||||
|
||||
func GetVolumeManager() *SVolumeManager {
|
||||
if volumeManager != nil {
|
||||
return volumeManager
|
||||
}
|
||||
volumeManager = &SVolumeManager{
|
||||
SVirtualResourceBaseManager: db.NewVirtualResourceBaseManager(
|
||||
SVolume{},
|
||||
"volumes_tbl",
|
||||
"llm_volume",
|
||||
"llm_volumes",
|
||||
),
|
||||
}
|
||||
volumeManager.SetVirtualObject(volumeManager)
|
||||
return volumeManager
|
||||
}
|
||||
|
||||
type SVolumeManager struct {
|
||||
db.SVirtualResourceBaseManager
|
||||
// SMountedAppsResourceManager
|
||||
}
|
||||
|
||||
type SVolume struct {
|
||||
db.SVirtualResourceBase
|
||||
// SMountedAppsResource
|
||||
|
||||
LLMId string `width:"128" charset:"ascii" nullable:"true" list:"user" create:"admin_optional" update:"user"`
|
||||
// 存储类型
|
||||
StorageType string `width:"16" charset:"ascii" nullable:"true" list:"user" create:"admin_optional" update:"user"`
|
||||
// 模板ID
|
||||
TemplateId string `width:"128" charset:"ascii" nullable:"true" list:"user" create:"admin_optional" update:"user"`
|
||||
// size in MB
|
||||
SizeMB int `nullable:"false" default:"0" create:"optional" list:"user" update:"user"`
|
||||
SvrId string `width:"128" charset:"ascii" nullable:"true" list:"user"`
|
||||
Containers api.ContainerVolumeRelations `charset:"utf8" nullable:"true" list:"user" create:"optional"`
|
||||
}
|
||||
|
||||
func (volume *SVolume) StartDeleteTask(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "VolumeDeleteTask", volume, userCred, nil, parentTaskId, "", nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
volume.SetStatus(ctx, userCred, commonapi.STATUS_DELETING, "")
|
||||
task.ScheduleRun(nil)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (volume *SVolume) RealDelete(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
return volume.SVirtualResourceBase.Delete(ctx, userCred)
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package options // import "yunion.io/x/onecloud/pkg/llm/options"
|
||||
@@ -1,28 +0,0 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package options
|
||||
|
||||
import common_options "yunion.io/x/onecloud/pkg/cloudcommon/options"
|
||||
|
||||
type LLMOptions struct {
|
||||
common_options.CommonOptions
|
||||
common_options.DBOptions
|
||||
|
||||
StartTaskWorkerCount int `help:"start task worker count" default:"128"`
|
||||
}
|
||||
|
||||
var (
|
||||
Options LLMOptions
|
||||
)
|
||||
@@ -1 +0,0 @@
|
||||
package service // import "yunion.io/x/onecloud/pkg/llm/service"
|
||||
@@ -1,47 +0,0 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/appsrv"
|
||||
"yunion.io/x/onecloud/pkg/appsrv/dispatcher"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/llm/models"
|
||||
)
|
||||
|
||||
func InitHandlers(app *appsrv.Application) {
|
||||
db.InitAllManagers()
|
||||
db.RegistUserCredCacheUpdater()
|
||||
|
||||
taskman.AddTaskHandler("", app)
|
||||
|
||||
for _, manager := range []db.IModelManager{
|
||||
taskman.TaskManager,
|
||||
taskman.SubTaskManager,
|
||||
taskman.TaskObjectManager,
|
||||
taskman.ArchivedTaskManager,
|
||||
|
||||
db.SharedResourceManager,
|
||||
db.UserCacheManager,
|
||||
db.TenantCacheManager,
|
||||
} {
|
||||
db.RegisterModelManager(manager)
|
||||
}
|
||||
|
||||
for _, manager := range []db.IModelManager{
|
||||
db.OpsLog,
|
||||
db.Metadata,
|
||||
|
||||
models.GetLLMImageManager(),
|
||||
models.GetLLMModelManager(),
|
||||
models.GetDifyModelManager(),
|
||||
models.GetVolumeManager(),
|
||||
models.GetAccessInfoManager(),
|
||||
models.GetLLMContainerManager(),
|
||||
models.GetLLMManager(),
|
||||
models.GetDifyManager(),
|
||||
} {
|
||||
db.RegisterModelManager(manager)
|
||||
handler := db.NewModelHandler(manager)
|
||||
dispatcher.AddModelDispatcher("", app, handler)
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"yunion.io/x/log"
|
||||
_ "yunion.io/x/sqlchemy/backends"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/llm"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon"
|
||||
app_common "yunion.io/x/onecloud/pkg/cloudcommon/app"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
common_options "yunion.io/x/onecloud/pkg/cloudcommon/options"
|
||||
_ "yunion.io/x/onecloud/pkg/llm/drivers/llm_container"
|
||||
"yunion.io/x/onecloud/pkg/llm/models"
|
||||
"yunion.io/x/onecloud/pkg/llm/options"
|
||||
_ "yunion.io/x/onecloud/pkg/llm/tasks"
|
||||
)
|
||||
|
||||
// StartService the main service starts
|
||||
func StartService() {
|
||||
opts := &options.Options
|
||||
commonOpts := &opts.CommonOptions
|
||||
dbOpts := &options.Options.DBOptions
|
||||
baseOpts := &opts.BaseOptions
|
||||
common_options.ParseOptions(opts, os.Args, "llm.conf", api.SERVICE_TYPE)
|
||||
|
||||
app_common.InitAuth(commonOpts, func() {
|
||||
log.Infof("Auth complete!!")
|
||||
})
|
||||
|
||||
app := app_common.InitApp(&opts.BaseOptions, false)
|
||||
|
||||
cloudcommon.InitDB(dbOpts)
|
||||
InitHandlers(app)
|
||||
|
||||
db.EnsureAppSyncDB(app, dbOpts, models.InitDB)
|
||||
defer cloudcommon.CloseDB()
|
||||
|
||||
// if !opts.IsSlaveNode {
|
||||
// models.InitializeCronjobs(app.GetContext())
|
||||
// }
|
||||
|
||||
app_common.ServeForeverWithCleanup(app, baseOpts, func() {
|
||||
cloudcommon.CloseDB()
|
||||
})
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
package dify
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/llm"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/llm/models"
|
||||
)
|
||||
|
||||
type DifyBatchCreateTask struct {
|
||||
taskman.STask
|
||||
}
|
||||
|
||||
func init() {
|
||||
taskman.RegisterTask(DifyBatchCreateTask{})
|
||||
}
|
||||
|
||||
func (task *DifyBatchCreateTask) OnInit(ctx context.Context, objs []db.IStandaloneModel, body jsonutils.JSONObject) {
|
||||
task.SetStage("OnDifyCreateCompleteAll", nil)
|
||||
|
||||
inputs := make([]api.DifyCreateInput, 0)
|
||||
task.GetParams().Unmarshal(&inputs, "data")
|
||||
|
||||
for i := range objs {
|
||||
dify := objs[i].(*models.SDify)
|
||||
err := dify.StartCreateTask(ctx, task.UserCred, inputs[i], task.GetTaskId())
|
||||
if err != nil {
|
||||
log.Errorf("start task for %d dify %s(%s) fail %s", i, dify.Id, dify.Name, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (task *DifyBatchCreateTask) OnDifyCreateCompleteAll(ctx context.Context, objs []db.IStandaloneModel, body jsonutils.JSONObject) {
|
||||
task.SetStageComplete(ctx, nil)
|
||||
}
|
||||
@@ -1,154 +0,0 @@
|
||||
package dify
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
computeapi "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
api "yunion.io/x/onecloud/pkg/apis/llm"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/llm/models"
|
||||
"yunion.io/x/onecloud/pkg/util/logclient"
|
||||
)
|
||||
|
||||
type DifyCreateTask struct {
|
||||
taskman.STask
|
||||
}
|
||||
|
||||
func init() {
|
||||
taskman.RegisterTask(DifyCreateTask{})
|
||||
}
|
||||
|
||||
func (task *DifyCreateTask) taskFailed(ctx context.Context, dify *models.SDify, err error) {
|
||||
dify.SetStatus(ctx, task.UserCred, api.LLM_STATUS_CREATE_FAIL, err.Error())
|
||||
db.OpsLog.LogEvent(dify, db.ACT_CREATE, err, task.UserCred)
|
||||
logclient.AddActionLogWithStartable(task, dify, logclient.ACT_CREATE, err, task.UserCred, false)
|
||||
task.SetStageFailed(ctx, jsonutils.NewString(err.Error()))
|
||||
}
|
||||
|
||||
func (task *DifyCreateTask) taskComplete(ctx context.Context, dify *models.SDify, status string) {
|
||||
dify.SetStatus(ctx, task.GetUserCred(), status, "create success")
|
||||
task.SetStageComplete(ctx, nil)
|
||||
}
|
||||
|
||||
func (task *DifyCreateTask) OnInit(ctx context.Context, obj db.IStandaloneModel, body jsonutils.JSONObject) {
|
||||
dify := obj.(*models.SDify)
|
||||
serverCreateInput := api.DifyCreateInput{}
|
||||
err := body.Unmarshal(&serverCreateInput)
|
||||
if err != nil {
|
||||
task.taskFailed(ctx, dify, err)
|
||||
return
|
||||
}
|
||||
|
||||
serverCreateInput.Name = dify.Name
|
||||
serverId, err := dify.ServerCreate(ctx, task.UserCred, &serverCreateInput)
|
||||
if err != nil {
|
||||
task.taskFailed(ctx, dify, err)
|
||||
return
|
||||
}
|
||||
|
||||
db.Update(dify, func() error {
|
||||
dify.SvrId = serverId
|
||||
return nil
|
||||
})
|
||||
dify.SvrId = serverId
|
||||
task.SetStage("OnDifyRefreshStatusComplete", nil)
|
||||
var expectStatus []string
|
||||
if serverCreateInput.AutoStart {
|
||||
expectStatus = []string{computeapi.VM_RUNNING}
|
||||
} else {
|
||||
expectStatus = []string{computeapi.VM_READY}
|
||||
}
|
||||
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
|
||||
server, err := dify.WaitServerStatus(ctx, task.UserCred, expectStatus, 7200)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "WaitServerStatus")
|
||||
}
|
||||
return jsonutils.Marshal(server), nil
|
||||
})
|
||||
}
|
||||
|
||||
func (task *DifyCreateTask) OnDifyRefreshStatusCompleteFailed(ctx context.Context, dify *models.SDify, err jsonutils.JSONObject) {
|
||||
task.taskFailed(ctx, dify, errors.Error(err.String()))
|
||||
}
|
||||
|
||||
func (task *DifyCreateTask) OnDifyRefreshStatusComplete(ctx context.Context, dify *models.SDify, body jsonutils.JSONObject) {
|
||||
server := computeapi.ServerDetails{}
|
||||
err := body.Unmarshal(&server)
|
||||
if err != nil {
|
||||
task.taskFailed(ctx, dify, errors.Wrap(err, "Unmarshal"))
|
||||
return
|
||||
}
|
||||
|
||||
// 创建磁盘
|
||||
for _, disk := range server.DisksInfo {
|
||||
volume := models.SVolume{}
|
||||
volume.SvrId = disk.Id
|
||||
volume.LLMId = dify.Id
|
||||
volume.SizeMB = disk.SizeMb
|
||||
volume.Name = disk.Name
|
||||
volume.StorageType = disk.StorageType
|
||||
volume.Status = computeapi.DISK_READY
|
||||
volume.DomainId = dify.DomainId
|
||||
volume.ProjectId = dify.ProjectId
|
||||
volume.ProjectSrc = dify.ProjectSrc
|
||||
// if len(input.TemplateId) > 0 {
|
||||
volume.TemplateId = disk.ImageId
|
||||
// }
|
||||
// volume.MountedApps = mountedApps
|
||||
|
||||
err := models.GetVolumeManager().TableSpec().Insert(ctx, &volume)
|
||||
if err != nil {
|
||||
task.taskFailed(ctx, dify, errors.Wrap(err, "VolumeManager.TableSpec().Insert"))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 创建访问信息、portmappings
|
||||
if len(server.Nics) > 0 {
|
||||
db.Update(dify, func() error {
|
||||
dify.LLMIp = server.Nics[0].IpAddr
|
||||
return nil
|
||||
})
|
||||
|
||||
for _, portMapping := range server.Nics[0].PortMappings {
|
||||
access := models.SAccessInfo{}
|
||||
access.LLMId = dify.Id
|
||||
|
||||
access.ListenPort = int(portMapping.Port)
|
||||
access.AccessPort = int(*portMapping.HostPort)
|
||||
access.Protocol = string(portMapping.Protocol)
|
||||
access.RemoteIps = portMapping.RemoteIps
|
||||
envs := make([]api.PortMappingEnv, 0)
|
||||
for _, env := range portMapping.Envs {
|
||||
envs = append(envs, api.PortMappingEnv{
|
||||
Key: env.Key,
|
||||
ValueFrom: string(env.ValueFrom),
|
||||
})
|
||||
}
|
||||
access.PortMappingEnvs = envs
|
||||
|
||||
models.GetAccessInfoManager().TableSpec().Insert(ctx, &access)
|
||||
}
|
||||
}
|
||||
|
||||
// // 创建应用容器记录
|
||||
// if len(server.Containers) != 1 {
|
||||
// task.taskFailed(ctx, dify, errors.Errorf("expected 1 containers, but got %d", len(server.Containers)))
|
||||
// return
|
||||
// }
|
||||
// llmCtr := models.GetSvrLLMContainer(server.Containers)
|
||||
// if llmCtr == nil {
|
||||
// task.taskFailed(ctx, dify, errors.Errorf("cannot find app container"))
|
||||
// return
|
||||
// }
|
||||
// if _, err := models.GetLLMContainerManager().CreateOnLLM(ctx, task.GetUserCred(), dify.GetOwnerId(), dify, llmCtr.Id, llmCtr.Name); nil != err {
|
||||
// task.taskFailed(ctx, dify, errors.Wrap(err, "create llm container on llm"))
|
||||
// return
|
||||
// }
|
||||
|
||||
task.taskComplete(ctx, dify, server.Status)
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
package dify
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/llm"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/llm/models"
|
||||
"yunion.io/x/onecloud/pkg/util/logclient"
|
||||
)
|
||||
|
||||
type DifyDeleteTask struct {
|
||||
taskman.STask
|
||||
}
|
||||
|
||||
func init() {
|
||||
taskman.RegisterTask(DifyDeleteTask{})
|
||||
}
|
||||
|
||||
func (task *DifyDeleteTask) taskFailed(ctx context.Context, dify *models.SDify, err error) {
|
||||
dify.SetStatus(ctx, task.UserCred, api.LLM_STATUS_DELETE_FAILED, err.Error())
|
||||
db.OpsLog.LogEvent(dify, db.ACT_DELETE_FAIL, err, task.UserCred)
|
||||
logclient.AddActionLogWithStartable(task, dify, logclient.ACT_DELETE, err, task.UserCred, false)
|
||||
task.SetStageFailed(ctx, jsonutils.NewString(err.Error()))
|
||||
}
|
||||
|
||||
func (task *DifyDeleteTask) OnInit(ctx context.Context, obj db.IStandaloneModel, body jsonutils.JSONObject) {
|
||||
dify := obj.(*models.SDify)
|
||||
dify.SetStatus(ctx, task.UserCred, api.LLM_STATUS_DELETING, "start delete")
|
||||
|
||||
if len(dify.SvrId) == 0 {
|
||||
task.OnDifyRefreshStatusComplete(ctx, dify, nil)
|
||||
return
|
||||
}
|
||||
|
||||
err := dify.ServerDelete(ctx, task.UserCred)
|
||||
if err != nil {
|
||||
task.taskFailed(ctx, dify, err)
|
||||
return
|
||||
}
|
||||
task.SetStage("OnDifyRefreshStatusComplete", nil)
|
||||
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
|
||||
err = dify.WaitDelete(ctx, task.UserCred, 1800)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "llm.WaitDelete")
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
})
|
||||
}
|
||||
|
||||
func (task *DifyDeleteTask) OnDifyRefreshStatusCompleteFailed(ctx context.Context, dify *models.SDify, err jsonutils.JSONObject) {
|
||||
task.taskFailed(ctx, dify, errors.Error(err.String()))
|
||||
}
|
||||
|
||||
func (task *DifyDeleteTask) OnDifyRefreshStatusComplete(ctx context.Context, dify *models.SDify, body jsonutils.JSONObject) {
|
||||
volume, err := dify.GetVolume()
|
||||
if err != nil {
|
||||
if errors.Cause(err) != errors.ErrNotFound {
|
||||
task.taskFailed(ctx, dify, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
if volume != nil {
|
||||
task.SetStage("OnDifyVolumeDeleteComplete", nil)
|
||||
volume.StartDeleteTask(ctx, task.UserCred, task.GetTaskId())
|
||||
} else {
|
||||
task.OnDifyVolumeDeleteComplete(ctx, dify, nil)
|
||||
}
|
||||
}
|
||||
|
||||
func (task *DifyDeleteTask) OnDifyVolumeDeleteCompleteFailed(ctx context.Context, dify *models.SDify, err jsonutils.JSONObject) {
|
||||
task.taskFailed(ctx, dify, errors.Error(err.String()))
|
||||
}
|
||||
|
||||
func (task *DifyDeleteTask) OnDifyVolumeDeleteComplete(ctx context.Context, dify *models.SDify, body jsonutils.JSONObject) {
|
||||
err := dify.RealDelete(ctx, task.UserCred)
|
||||
if err != nil {
|
||||
task.taskFailed(ctx, dify, err)
|
||||
return
|
||||
}
|
||||
task.SetStageComplete(ctx, nil)
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
package dify
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
computeapi "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
api "yunion.io/x/onecloud/pkg/apis/llm"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/llm/models"
|
||||
"yunion.io/x/onecloud/pkg/llm/options"
|
||||
"yunion.io/x/onecloud/pkg/llm/tasks/worker"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/auth"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules/compute"
|
||||
"yunion.io/x/onecloud/pkg/util/logclient"
|
||||
)
|
||||
|
||||
type DifyStartTask struct {
|
||||
taskman.STask
|
||||
}
|
||||
|
||||
func init() {
|
||||
taskman.RegisterTask(DifyStartTask{})
|
||||
}
|
||||
|
||||
func (task *DifyStartTask) taskFailed(ctx context.Context, dify *models.SDify, err string) {
|
||||
dify.SetStatus(ctx, task.UserCred, api.LLM_STATUS_START_FAIL, err)
|
||||
db.OpsLog.LogEvent(dify, db.ACT_START, err, task.UserCred)
|
||||
logclient.AddActionLogWithStartable(task, dify, logclient.ACT_START, err, task.UserCred, false)
|
||||
// llm.NotifyRequest(ctx, task.GetUserCred(), notify.ActionStart, nil, false)
|
||||
task.SetStageFailed(ctx, jsonutils.NewString(err))
|
||||
}
|
||||
|
||||
func (task *DifyStartTask) taskComplete(ctx context.Context, dify *models.SDify) {
|
||||
dify.SetStatus(ctx, task.GetUserCred(), api.LLM_STATUS_RUNNING, "start complete")
|
||||
// llm.NotifyRequest(ctx, task.GetUserCred(), notify.ActionStart, nil, true)
|
||||
task.SetStageComplete(ctx, nil)
|
||||
}
|
||||
|
||||
func (t *DifyStartTask) OnInit(ctx context.Context, obj db.IStandaloneModel, body jsonutils.JSONObject) {
|
||||
t.requestStart(ctx, obj.(*models.SDify))
|
||||
}
|
||||
|
||||
func (t *DifyStartTask) requestStart(ctx context.Context, dify *models.SDify) {
|
||||
s := auth.GetSession(ctx, t.GetUserCred(), options.Options.Region)
|
||||
_, err := compute.Servers.PerformAction(s, dify.SvrId, "start", nil)
|
||||
if err != nil {
|
||||
t.taskFailed(ctx, dify, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
t.SetStage("OnStarted", nil)
|
||||
worker.StartTaskRun(t, func() (jsonutils.JSONObject, error) {
|
||||
_, err := dify.WaitServerStatus(ctx, t.GetUserCred(), []string{computeapi.VM_RUNNING}, 900)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "WaitServerStatus")
|
||||
}
|
||||
// time.Sleep(time.Second)
|
||||
// _, err = d.WaitServerStatus(ctx, task.UserCred, []string{computeapi.VM_RUNNING}, 900)
|
||||
// if err != nil {
|
||||
// return nil, errors.Wrap(err, "WaitServerStatus")
|
||||
// }
|
||||
return nil, nil
|
||||
})
|
||||
// if err := llm.RunModel(ctx, t.GetUserCred()); nil != err {
|
||||
// t.OnStartedFailed(ctx, llm, jsonutils.NewString(err.Error()))
|
||||
// return
|
||||
// }
|
||||
}
|
||||
|
||||
func (t *DifyStartTask) OnStartedFailed(ctx context.Context, dify *models.SDify, err jsonutils.JSONObject) {
|
||||
t.taskFailed(ctx, dify, err.String())
|
||||
}
|
||||
|
||||
func (t *DifyStartTask) OnStarted(ctx context.Context, dify *models.SDify, reason jsonutils.JSONObject) {
|
||||
t.taskComplete(ctx, dify)
|
||||
}
|
||||
@@ -1,96 +0,0 @@
|
||||
package dify
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
computeapi "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
api "yunion.io/x/onecloud/pkg/apis/llm"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/llm/models"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/auth"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules/compute"
|
||||
"yunion.io/x/onecloud/pkg/util/logclient"
|
||||
)
|
||||
|
||||
type DifyStopTask struct {
|
||||
taskman.STask
|
||||
}
|
||||
|
||||
func init() {
|
||||
taskman.RegisterTask(DifyStopTask{})
|
||||
}
|
||||
|
||||
func (task *DifyStopTask) taskFailed(ctx context.Context, dify *models.SDify, err string) {
|
||||
dify.SetStatus(ctx, task.UserCred, api.LLM_STATUS_STOP_FAILED, err)
|
||||
db.OpsLog.LogEvent(dify, db.ACT_STOP, err, task.UserCred)
|
||||
logclient.AddActionLogWithStartable(task, dify, logclient.ACT_VM_STOP, err, task.UserCred, false)
|
||||
// llm.NotifyRequest(ctx, task.GetUserCred(), notify.ActionStop, nil, false)
|
||||
task.SetStageFailed(ctx, jsonutils.NewString(err))
|
||||
}
|
||||
|
||||
func (task *DifyStopTask) taskComplete(ctx context.Context, dify *models.SDify) {
|
||||
if !task.HasParentTask() {
|
||||
dify.SetStatus(ctx, task.GetUserCred(), api.LLM_STATUS_READY, "")
|
||||
}
|
||||
// llm.NotifyRequest(ctx, task.GetUserCred(), notify.ActionStop, nil, true)
|
||||
task.SetStageComplete(ctx, nil)
|
||||
}
|
||||
|
||||
func (task *DifyStopTask) OnInit(ctx context.Context, obj db.IStandaloneModel, body jsonutils.JSONObject) {
|
||||
dify := obj.(*models.SDify)
|
||||
|
||||
srv, err := dify.GetServer(ctx)
|
||||
if err != nil {
|
||||
task.taskFailed(ctx, dify, errors.Wrap(err, "GetServer").Error())
|
||||
return
|
||||
}
|
||||
|
||||
if srv.Status == computeapi.VM_READY {
|
||||
task.taskComplete(ctx, dify)
|
||||
return
|
||||
}
|
||||
|
||||
task.SetStage("OnStopComplete", nil)
|
||||
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
|
||||
s := auth.GetSession(ctx, task.UserCred, "")
|
||||
_, err = compute.Servers.PerformAction(s, dify.SvrId, "stop", nil)
|
||||
if err != nil {
|
||||
task.taskFailed(ctx, dify, err.Error())
|
||||
return nil, errors.Wrap(err, "server perform stop")
|
||||
}
|
||||
_, err := dify.WaitServerStatus(ctx, task.UserCred, []string{computeapi.VM_READY}, 600)
|
||||
if err != nil {
|
||||
if errors.Cause(err) == errors.ErrTimeout {
|
||||
params := computeapi.ServerStopInput{
|
||||
IsForce: true,
|
||||
TimeoutSecs: 10,
|
||||
}
|
||||
_, err = compute.Servers.PerformAction(s, dify.SvrId, "stop", jsonutils.Marshal(params))
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "server perform stop by force")
|
||||
}
|
||||
_, err := dify.WaitServerStatus(ctx, task.UserCred, []string{computeapi.VM_READY}, 600)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "WaitServerStatus 2")
|
||||
}
|
||||
} else {
|
||||
return nil, errors.Wrap(err, "WaitServerStatus")
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
})
|
||||
}
|
||||
|
||||
func (task *DifyStopTask) OnStopComplete(ctx context.Context, obj db.IStandaloneModel, body jsonutils.JSONObject) {
|
||||
dify := obj.(*models.SDify)
|
||||
task.taskComplete(ctx, dify)
|
||||
}
|
||||
|
||||
func (task *DifyStopTask) OnStopCompleteFailed(ctx context.Context, obj db.IStandaloneModel, err jsonutils.JSONObject) {
|
||||
dify := obj.(*models.SDify)
|
||||
task.taskFailed(ctx, dify, err.String())
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
package dify // import "yunion.io/x/onecloud/pkg/llm/tasks/dify"
|
||||
@@ -1,15 +0,0 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package tasks // import "yunion.io/x/onecloud/pkg/llm/tasks"
|
||||
@@ -1 +0,0 @@
|
||||
package llm // import "yunion.io/x/onecloud/pkg/llm/tasks/llm"
|
||||
@@ -1,40 +0,0 @@
|
||||
package llm
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/llm"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/llm/models"
|
||||
)
|
||||
|
||||
type LLMBatchCreateTask struct {
|
||||
taskman.STask
|
||||
}
|
||||
|
||||
func init() {
|
||||
taskman.RegisterTask(LLMBatchCreateTask{})
|
||||
}
|
||||
|
||||
func (task *LLMBatchCreateTask) OnInit(ctx context.Context, objs []db.IStandaloneModel, body jsonutils.JSONObject) {
|
||||
task.SetStage("OnLLMCreateCompleteAll", nil)
|
||||
|
||||
inputs := make([]api.LLMCreateInput, 0)
|
||||
task.GetParams().Unmarshal(&inputs, "data")
|
||||
|
||||
for i := range objs {
|
||||
llm := objs[i].(*models.SLLM)
|
||||
err := llm.StartCreateTask(ctx, task.UserCred, inputs[i], task.GetTaskId())
|
||||
if err != nil {
|
||||
log.Errorf("start task for %d llm %s(%s) fail %s", i, llm.Id, llm.Name, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (task *LLMBatchCreateTask) OnLLMCreateCompleteAll(ctx context.Context, objs []db.IStandaloneModel, body jsonutils.JSONObject) {
|
||||
task.SetStageComplete(ctx, nil)
|
||||
}
|
||||
@@ -1,172 +0,0 @@
|
||||
package llm
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
computeapi "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
api "yunion.io/x/onecloud/pkg/apis/llm"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/llm/models"
|
||||
"yunion.io/x/onecloud/pkg/util/logclient"
|
||||
)
|
||||
|
||||
type LLMCreateTask struct {
|
||||
taskman.STask
|
||||
}
|
||||
|
||||
func init() {
|
||||
taskman.RegisterTask(LLMCreateTask{})
|
||||
}
|
||||
|
||||
func (task *LLMCreateTask) taskFailed(ctx context.Context, llm *models.SLLM, err error) {
|
||||
llm.SetStatus(ctx, task.UserCred, api.LLM_STATUS_CREATE_FAIL, err.Error())
|
||||
db.OpsLog.LogEvent(llm, db.ACT_CREATE, err, task.UserCred)
|
||||
logclient.AddActionLogWithStartable(task, llm, logclient.ACT_CREATE, err, task.UserCred, false)
|
||||
task.SetStageFailed(ctx, jsonutils.NewString(err.Error()))
|
||||
}
|
||||
|
||||
func (task *LLMCreateTask) taskComplete(ctx context.Context, llm *models.SLLM, status string) {
|
||||
llm.SetStatus(ctx, task.GetUserCred(), status, "create success")
|
||||
task.SetStageComplete(ctx, nil)
|
||||
}
|
||||
|
||||
func (task *LLMCreateTask) OnInit(ctx context.Context, obj db.IStandaloneModel, body jsonutils.JSONObject) {
|
||||
llm := obj.(*models.SLLM)
|
||||
serverCreateInput := api.LLMCreateInput{}
|
||||
err := body.Unmarshal(&serverCreateInput)
|
||||
if err != nil {
|
||||
task.taskFailed(ctx, llm, err)
|
||||
return
|
||||
}
|
||||
|
||||
serverCreateInput.Name = llm.Name
|
||||
serverId, err := llm.ServerCreate(ctx, task.UserCred, &serverCreateInput)
|
||||
if err != nil {
|
||||
task.taskFailed(ctx, llm, err)
|
||||
return
|
||||
}
|
||||
|
||||
db.Update(llm, func() error {
|
||||
llm.SvrId = serverId
|
||||
return nil
|
||||
})
|
||||
llm.SvrId = serverId
|
||||
task.SetStage("OnLLMRefreshStatusComplete", nil)
|
||||
var expectStatus []string
|
||||
if serverCreateInput.AutoStart {
|
||||
expectStatus = []string{computeapi.VM_RUNNING}
|
||||
} else {
|
||||
expectStatus = []string{computeapi.VM_READY}
|
||||
}
|
||||
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
|
||||
server, err := llm.WaitServerStatus(ctx, task.UserCred, expectStatus, 7200)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "WaitServerStatus")
|
||||
}
|
||||
return jsonutils.Marshal(server), nil
|
||||
})
|
||||
}
|
||||
|
||||
func (task *LLMCreateTask) OnLLMRefreshStatusCompleteFailed(ctx context.Context, llm *models.SLLM, err jsonutils.JSONObject) {
|
||||
task.taskFailed(ctx, llm, errors.Error(err.String()))
|
||||
}
|
||||
|
||||
func (task *LLMCreateTask) OnLLMRefreshStatusComplete(ctx context.Context, llm *models.SLLM, body jsonutils.JSONObject) {
|
||||
server := computeapi.ServerDetails{}
|
||||
err := body.Unmarshal(&server)
|
||||
if err != nil {
|
||||
task.taskFailed(ctx, llm, errors.Wrap(err, "Unmarshal"))
|
||||
return
|
||||
}
|
||||
|
||||
// 创建磁盘
|
||||
for _, disk := range server.DisksInfo {
|
||||
volume := models.SVolume{}
|
||||
volume.SvrId = disk.Id
|
||||
volume.LLMId = llm.Id
|
||||
volume.SizeMB = disk.SizeMb
|
||||
volume.Name = disk.Name
|
||||
volume.StorageType = disk.StorageType
|
||||
volume.Status = computeapi.DISK_READY
|
||||
volume.DomainId = llm.DomainId
|
||||
volume.ProjectId = llm.ProjectId
|
||||
volume.ProjectSrc = llm.ProjectSrc
|
||||
// if len(input.TemplateId) > 0 {
|
||||
volume.TemplateId = disk.ImageId
|
||||
// }
|
||||
// volume.MountedApps = mountedApps
|
||||
|
||||
err := models.GetVolumeManager().TableSpec().Insert(ctx, &volume)
|
||||
if err != nil {
|
||||
task.taskFailed(ctx, llm, errors.Wrap(err, "VolumeManager.TableSpec().Insert"))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 创建访问信息、portmappings
|
||||
if len(server.Nics) > 0 {
|
||||
db.Update(llm, func() error {
|
||||
llm.LLMIp = server.Nics[0].IpAddr
|
||||
return nil
|
||||
})
|
||||
|
||||
for _, portMapping := range server.Nics[0].PortMappings {
|
||||
access := models.SAccessInfo{}
|
||||
access.LLMId = llm.Id
|
||||
|
||||
access.ListenPort = int(portMapping.Port)
|
||||
access.AccessPort = int(*portMapping.HostPort)
|
||||
access.Protocol = string(portMapping.Protocol)
|
||||
access.RemoteIps = portMapping.RemoteIps
|
||||
envs := make([]api.PortMappingEnv, 0)
|
||||
for _, env := range portMapping.Envs {
|
||||
envs = append(envs, api.PortMappingEnv{
|
||||
Key: env.Key,
|
||||
ValueFrom: string(env.ValueFrom),
|
||||
})
|
||||
}
|
||||
access.PortMappingEnvs = envs
|
||||
|
||||
models.GetAccessInfoManager().TableSpec().Insert(ctx, &access)
|
||||
}
|
||||
}
|
||||
|
||||
// 创建应用容器记录
|
||||
if len(server.Containers) != 1 {
|
||||
task.taskFailed(ctx, llm, errors.Errorf("expected 1 containers, but got %d", len(server.Containers)))
|
||||
return
|
||||
}
|
||||
llmCtr := models.GetSvrLLMContainer(server.Containers)
|
||||
if llmCtr == nil {
|
||||
task.taskFailed(ctx, llm, errors.Errorf("cannot find app container"))
|
||||
return
|
||||
}
|
||||
if _, err := models.GetLLMContainerManager().CreateOnLLM(ctx, task.GetUserCred(), llm.GetOwnerId(), llm, llmCtr.Id, llmCtr.Name); nil != err {
|
||||
task.taskFailed(ctx, llm, errors.Wrap(err, "create llm container on llm"))
|
||||
return
|
||||
}
|
||||
|
||||
task.taskComplete(ctx, llm, server.Status)
|
||||
// // 调用子任务在容器中拉取模型
|
||||
// params := jsonutils.NewDict()
|
||||
// params.Set("status", jsonutils.NewString(server.Status))
|
||||
// task.SetStage("OnLLMPullModel", params)
|
||||
|
||||
// if err := llm.StartPullModelTask(ctx, task.GetUserCred(), nil, task.GetId()); err != nil {
|
||||
// task.taskFailed(ctx, llm, errors.Wrap(err, "StartPullModelTask"))
|
||||
// return
|
||||
// }
|
||||
}
|
||||
|
||||
// func (task *LLMCreateTask) OnLLMPullModelFailed(ctx context.Context, llm *models.SLLM, err jsonutils.JSONObject) {
|
||||
// task.taskFailed(ctx, llm, errors.Error(err.String()))
|
||||
// }
|
||||
|
||||
// func (task *LLMCreateTask) OnLLMPullModel(ctx context.Context, llm *models.SLLM, body jsonutils.JSONObject) {
|
||||
// status, _ := task.GetParams().GetString("status")
|
||||
// task.taskComplete(ctx, llm, status)
|
||||
// }
|
||||
@@ -1,108 +0,0 @@
|
||||
package llm
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/llm"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/llm/models"
|
||||
"yunion.io/x/onecloud/pkg/util/logclient"
|
||||
)
|
||||
|
||||
type LLMDeleteTask struct {
|
||||
taskman.STask
|
||||
}
|
||||
|
||||
func init() {
|
||||
taskman.RegisterTask(LLMDeleteTask{})
|
||||
}
|
||||
|
||||
func (task *LLMDeleteTask) taskFailed(ctx context.Context, llm *models.SLLM, err error) {
|
||||
llm.SetStatus(ctx, task.UserCred, api.LLM_STATUS_DELETE_FAILED, err.Error())
|
||||
db.OpsLog.LogEvent(llm, db.ACT_DELETE_FAIL, err, task.UserCred)
|
||||
logclient.AddActionLogWithStartable(task, llm, logclient.ACT_DELETE, err, task.UserCred, false)
|
||||
task.SetStageFailed(ctx, jsonutils.NewString(err.Error()))
|
||||
}
|
||||
|
||||
func (task *LLMDeleteTask) OnInit(ctx context.Context, obj db.IStandaloneModel, body jsonutils.JSONObject) {
|
||||
llm := obj.(*models.SLLM)
|
||||
llm.SetStatus(ctx, task.UserCred, api.LLM_STATUS_DELETING, "start delete")
|
||||
|
||||
if len(llm.SvrId) == 0 {
|
||||
task.OnLLMRefreshStatusComplete(ctx, llm, nil)
|
||||
return
|
||||
}
|
||||
|
||||
err := llm.ServerDelete(ctx, task.UserCred)
|
||||
if err != nil {
|
||||
task.taskFailed(ctx, llm, err)
|
||||
return
|
||||
}
|
||||
task.SetStage("OnLLMRefreshStatusComplete", nil)
|
||||
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
|
||||
err = llm.WaitDelete(ctx, task.UserCred, 1800)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "llm.WaitDelete")
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
})
|
||||
}
|
||||
|
||||
func (task *LLMDeleteTask) OnLLMRefreshStatusCompleteFailed(ctx context.Context, llm *models.SLLM, err jsonutils.JSONObject) {
|
||||
task.taskFailed(ctx, llm, errors.Error(err.String()))
|
||||
}
|
||||
|
||||
func (task *LLMDeleteTask) OnLLMRefreshStatusComplete(ctx context.Context, llm *models.SLLM, body jsonutils.JSONObject) {
|
||||
volume, err := llm.GetVolume()
|
||||
if err != nil {
|
||||
if errors.Cause(err) != errors.ErrNotFound {
|
||||
task.taskFailed(ctx, llm, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
if volume != nil {
|
||||
task.SetStage("OnLLMVolumeDeleteComplete", nil)
|
||||
volume.StartDeleteTask(ctx, task.UserCred, task.GetTaskId())
|
||||
} else {
|
||||
task.OnLLMVolumeDeleteComplete(ctx, llm, nil)
|
||||
}
|
||||
}
|
||||
|
||||
func (task *LLMDeleteTask) OnLLMVolumeDeleteCompleteFailed(ctx context.Context, llm *models.SLLM, err jsonutils.JSONObject) {
|
||||
task.taskFailed(ctx, llm, errors.Error(err.String()))
|
||||
}
|
||||
|
||||
func (task *LLMDeleteTask) OnLLMVolumeDeleteComplete(ctx context.Context, llm *models.SLLM, body jsonutils.JSONObject) {
|
||||
lc, err := llm.GetLLMContainer()
|
||||
if err != nil {
|
||||
if errors.Cause(err) != errors.ErrNotFound && errors.Cause(err) != sql.ErrNoRows {
|
||||
task.taskFailed(ctx, llm, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
if lc != nil {
|
||||
task.SetStage("OnLLMContainerDeleteComplete", nil)
|
||||
lc.StartDeleteTask(ctx, task.UserCred, task.GetTaskId())
|
||||
} else {
|
||||
task.OnLLMContainerDeleteComplete(ctx, llm, nil)
|
||||
}
|
||||
}
|
||||
|
||||
func (task *LLMDeleteTask) OnLLMContainerDeleteCompleteFailed(ctx context.Context, llm *models.SLLM, err jsonutils.JSONObject) {
|
||||
task.taskFailed(ctx, llm, errors.Error(err.String()))
|
||||
}
|
||||
|
||||
func (task *LLMDeleteTask) OnLLMContainerDeleteComplete(ctx context.Context, llm *models.SLLM, body jsonutils.JSONObject) {
|
||||
err := llm.RealDelete(ctx, task.UserCred)
|
||||
if err != nil {
|
||||
task.taskFailed(ctx, llm, err)
|
||||
return
|
||||
}
|
||||
task.SetStageComplete(ctx, nil)
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
package llm
|
||||
|
||||
// import (
|
||||
// "context"
|
||||
|
||||
// "yunion.io/x/jsonutils"
|
||||
|
||||
// api "yunion.io/x/onecloud/pkg/apis/llm"
|
||||
// "yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
// "yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
// "yunion.io/x/onecloud/pkg/llm/models"
|
||||
// )
|
||||
|
||||
// type LLMInstallGgufTask struct {
|
||||
// LLMBaseTask
|
||||
// }
|
||||
|
||||
// func init() {
|
||||
// taskman.RegisterTask(LLMInstallGgufTask{})
|
||||
// }
|
||||
|
||||
// func (t *LLMInstallGgufTask) OnInit(ctx context.Context, obj db.IStandaloneModel, body jsonutils.JSONObject) {
|
||||
// if err := obj.(*models.SOllama).ConfirmContainerId(ctx, t.GetUserCred()); err != nil {
|
||||
// t.OnGetGgufFileFailed(ctx, obj.(*models.SOllama), jsonutils.NewString(err.Error()))
|
||||
// }
|
||||
// t.requestGetGgufFile(ctx, obj.(*models.SOllama))
|
||||
// }
|
||||
|
||||
// func (t *LLMInstallGgufTask) requestGetGgufFile(ctx context.Context, llm *models.SOllama) {
|
||||
// // Update status
|
||||
// llm.SetStatus(ctx, t.GetUserCred(), api.LLM_STATUS_FETCHING_GGUF_FILE, "")
|
||||
|
||||
// // Distingush whether access gguf file from host or download from web
|
||||
// input := new(api.OllamaGgufSpec)
|
||||
// if err := t.GetParams().Unmarshal(input); nil != err {
|
||||
// t.OnGetGgufFileFailed(ctx, llm, jsonutils.NewString(err.Error()))
|
||||
// return
|
||||
// }
|
||||
|
||||
// switch input.Source {
|
||||
// case api.LLM_OLLAMA_GGUF_SOURCE_WEB:
|
||||
// t.SetStage("OnGetGgufFile", nil)
|
||||
// if err := llm.DownloadGgufFile(ctx, t.GetUserCred(), t.GetId()); nil != err {
|
||||
// t.OnGetGgufFileFailed(ctx, llm, jsonutils.NewString(err.Error()))
|
||||
// return
|
||||
// }
|
||||
// default:
|
||||
// if err := llm.AccessGgufFile(ctx, t.GetUserCred(), t); nil != err {
|
||||
// t.OnGetGgufFileFailed(ctx, llm, jsonutils.NewString(err.Error()))
|
||||
// return
|
||||
// }
|
||||
// t.OnGetGgufFile(ctx, llm, nil)
|
||||
// }
|
||||
// }
|
||||
|
||||
// func (t *LLMInstallGgufTask) OnGetGgufFileFailed(ctx context.Context, llm *models.SOllama, reason jsonutils.JSONObject) {
|
||||
// llm.SetStatus(ctx, t.GetUserCred(), api.LLM_STATUS_FETCH_GGUF_FILE_FAILED, reason.String())
|
||||
// t.SetStageFailed(ctx, reason)
|
||||
// }
|
||||
|
||||
// func (t *LLMInstallGgufTask) OnGetGgufFile(ctx context.Context, llm *models.SOllama, data jsonutils.JSONObject) {
|
||||
// input := new(api.OllamaGgufSpec)
|
||||
// if err := t.GetParams().Unmarshal(input); nil != err {
|
||||
// t.OnCreateModelFailed(ctx, llm, jsonutils.NewString(err.Error()))
|
||||
// return
|
||||
// }
|
||||
|
||||
// llm.SetStatus(ctx, t.GetUserCred(), api.LLM_STATUS_CREATING_GGUF_MODEL, "")
|
||||
|
||||
// if err := llm.InstallGgufModel(ctx, t.GetUserCred(), input.ModelFile); nil != err {
|
||||
// t.OnCreateModelFailed(ctx, llm, jsonutils.NewString(err.Error()))
|
||||
// return
|
||||
// }
|
||||
// t.OnPulledModel(ctx, llm, nil)
|
||||
// }
|
||||
|
||||
// func (t *LLMInstallGgufTask) OnCreateModelFailed(ctx context.Context, llm *models.SOllama, reason jsonutils.JSONObject) {
|
||||
// llm.SetStatus(ctx, t.GetUserCred(), api.LLM_STATUS_CREATE_GGUF_MODEL_FAILED, reason.String())
|
||||
// t.SetStageFailed(ctx, reason)
|
||||
// }
|
||||
|
||||
// func (t *LLMInstallGgufTask) OnPulledModel(ctx context.Context, llm *models.SOllama, data jsonutils.JSONObject) {
|
||||
// llm.SetStatus(ctx, t.GetUserCred(), api.LLM_STATUS_PULLED_MODEL, "")
|
||||
// t.SetStageComplete(ctx, nil)
|
||||
// }
|
||||
@@ -1,74 +0,0 @@
|
||||
package llm
|
||||
|
||||
// import (
|
||||
// "context"
|
||||
|
||||
// "yunion.io/x/jsonutils"
|
||||
|
||||
// api "yunion.io/x/onecloud/pkg/apis/llm"
|
||||
// "yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
// "yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
// "yunion.io/x/onecloud/pkg/llm/models"
|
||||
// )
|
||||
|
||||
// type LLMPullModelTask struct {
|
||||
// taskman.STask
|
||||
// }
|
||||
|
||||
// func (t *LLMPullModelTask) GetLLM() *models.SLLM {
|
||||
// return t.GetObject().(*models.SLLM)
|
||||
// }
|
||||
|
||||
// func (t *LLMPullModelTask) GetLLMContainerDriver() models.ILLMContainerDriver {
|
||||
// return t.GetLLM().GetLLMContainerDriver()
|
||||
// }
|
||||
|
||||
// func init() {
|
||||
// taskman.RegisterTask(LLMPullModelTask{})
|
||||
// }
|
||||
|
||||
// func (t *LLMPullModelTask) OnInit(ctx context.Context, obj db.IStandaloneModel, body jsonutils.JSONObject) {
|
||||
// t.requestGetManifests(ctx, obj.(*models.SLLM))
|
||||
// }
|
||||
|
||||
// func (t *LLMPullModelTask) requestGetManifests(ctx context.Context, llm *models.SLLM) {
|
||||
// // llm.SetStatus(ctx, t.GetUserCred(), api.LLM_STATUS_PULLING_MODEL, "")
|
||||
// t.SetStage("OnGetManifests", nil)
|
||||
|
||||
// if err := t.GetLLMContainerDriver().GetManifests(ctx, t.GetUserCred(), llm, t.GetId()); err != nil {
|
||||
// t.OnGetManifestsFailed(ctx, llm, jsonutils.NewString(err.Error()))
|
||||
// return
|
||||
// }
|
||||
// }
|
||||
|
||||
// func (t *LLMPullModelTask) OnGetManifestsFailed(ctx context.Context, llm *models.SLLM, reason jsonutils.JSONObject) {
|
||||
// llm.SetStatus(ctx, t.GetUserCred(), api.LLM_STATUS_GET_MANIFESTS_FAILED, reason.String())
|
||||
// t.SetStageFailed(ctx, reason)
|
||||
// }
|
||||
|
||||
// func (t *LLMPullModelTask) OnGetManifests(ctx context.Context, llm *models.SLLM, data jsonutils.JSONObject) {
|
||||
// t.SetStage("OnAccessCache", nil)
|
||||
// if err := t.GetLLMContainerDriver().AccessBlobsCache(ctx, t.GetUserCred(), llm, t.GetId()); nil != err {
|
||||
// t.OnAccessCacheFailed(ctx, llm, jsonutils.NewString(err.Error()))
|
||||
// return
|
||||
// }
|
||||
// }
|
||||
|
||||
// func (t *LLMPullModelTask) OnAccessCacheFailed(ctx context.Context, llm *models.SLLM, reason jsonutils.JSONObject) {
|
||||
// llm.SetStatus(ctx, t.GetUserCred(), api.LLM_STATUS_DOWNLOADING_BLOBS_FAILED, reason.String())
|
||||
// t.SetStageFailed(ctx, reason)
|
||||
// }
|
||||
|
||||
// func (t *LLMPullModelTask) OnAccessCache(ctx context.Context, llm *models.SLLM, data jsonutils.JSONObject) {
|
||||
// // log.Infoln("try to find out blobs: ", t.GetParams().String(), data.String())
|
||||
// if err := t.GetLLMContainerDriver().CopyBlobs(ctx, t.GetUserCred(), llm); nil != err {
|
||||
// t.OnAccessCacheFailed(ctx, llm, jsonutils.NewString(err.Error()))
|
||||
// return
|
||||
// }
|
||||
// t.OnPulledModel(ctx, llm, nil)
|
||||
// }
|
||||
|
||||
// func (t *LLMPullModelTask) OnPulledModel(ctx context.Context, llm *models.SLLM, data jsonutils.JSONObject) {
|
||||
// // llm.SetStatus(ctx, t.GetUserCred(), api.LLM_STATUS_PULLED_MODEL, "")
|
||||
// t.SetStageComplete(ctx, nil)
|
||||
// }
|
||||
@@ -1,80 +0,0 @@
|
||||
package llm
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
computeapi "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
api "yunion.io/x/onecloud/pkg/apis/llm"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/llm/models"
|
||||
"yunion.io/x/onecloud/pkg/llm/options"
|
||||
"yunion.io/x/onecloud/pkg/llm/tasks/worker"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/auth"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules/compute"
|
||||
"yunion.io/x/onecloud/pkg/util/logclient"
|
||||
)
|
||||
|
||||
type LLMStartTask struct {
|
||||
taskman.STask
|
||||
}
|
||||
|
||||
func init() {
|
||||
taskman.RegisterTask(LLMStartTask{})
|
||||
}
|
||||
|
||||
func (task *LLMStartTask) taskFailed(ctx context.Context, llm *models.SLLM, err string) {
|
||||
llm.SetStatus(ctx, task.UserCred, api.LLM_STATUS_START_FAIL, err)
|
||||
db.OpsLog.LogEvent(llm, db.ACT_START, err, task.UserCred)
|
||||
logclient.AddActionLogWithStartable(task, llm, logclient.ACT_START, err, task.UserCred, false)
|
||||
// llm.NotifyRequest(ctx, task.GetUserCred(), notify.ActionStart, nil, false)
|
||||
task.SetStageFailed(ctx, jsonutils.NewString(err))
|
||||
}
|
||||
|
||||
func (task *LLMStartTask) taskComplete(ctx context.Context, llm *models.SLLM) {
|
||||
llm.SetStatus(ctx, task.GetUserCred(), api.LLM_STATUS_RUNNING, "start complete")
|
||||
// llm.NotifyRequest(ctx, task.GetUserCred(), notify.ActionStart, nil, true)
|
||||
task.SetStageComplete(ctx, nil)
|
||||
}
|
||||
|
||||
func (t *LLMStartTask) OnInit(ctx context.Context, obj db.IStandaloneModel, body jsonutils.JSONObject) {
|
||||
t.requestStart(ctx, obj.(*models.SLLM))
|
||||
}
|
||||
|
||||
func (t *LLMStartTask) requestStart(ctx context.Context, llm *models.SLLM) {
|
||||
s := auth.GetSession(ctx, t.GetUserCred(), options.Options.Region)
|
||||
_, err := compute.Servers.PerformAction(s, llm.SvrId, "start", nil)
|
||||
if err != nil {
|
||||
t.taskFailed(ctx, llm, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
t.SetStage("OnStarted", nil)
|
||||
worker.StartTaskRun(t, func() (jsonutils.JSONObject, error) {
|
||||
_, err := llm.WaitServerStatus(ctx, t.GetUserCred(), []string{computeapi.VM_RUNNING}, 900)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "WaitServerStatus")
|
||||
}
|
||||
// time.Sleep(time.Second)
|
||||
// _, err = d.WaitServerStatus(ctx, task.UserCred, []string{computeapi.VM_RUNNING}, 900)
|
||||
// if err != nil {
|
||||
// return nil, errors.Wrap(err, "WaitServerStatus")
|
||||
// }
|
||||
return nil, nil
|
||||
})
|
||||
// if err := llm.RunModel(ctx, t.GetUserCred()); nil != err {
|
||||
// t.OnStartedFailed(ctx, llm, jsonutils.NewString(err.Error()))
|
||||
// return
|
||||
// }
|
||||
}
|
||||
|
||||
func (t *LLMStartTask) OnStartedFailed(ctx context.Context, llm *models.SLLM, err jsonutils.JSONObject) {
|
||||
t.taskFailed(ctx, llm, err.String())
|
||||
}
|
||||
|
||||
func (t *LLMStartTask) OnStarted(ctx context.Context, llm *models.SLLM, reason jsonutils.JSONObject) {
|
||||
t.taskComplete(ctx, llm)
|
||||
}
|
||||
@@ -1,96 +0,0 @@
|
||||
package llm
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
computeapi "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
api "yunion.io/x/onecloud/pkg/apis/llm"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/llm/models"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/auth"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules/compute"
|
||||
"yunion.io/x/onecloud/pkg/util/logclient"
|
||||
)
|
||||
|
||||
type LLMStopTask struct {
|
||||
taskman.STask
|
||||
}
|
||||
|
||||
func init() {
|
||||
taskman.RegisterTask(LLMStopTask{})
|
||||
}
|
||||
|
||||
func (task *LLMStopTask) taskFailed(ctx context.Context, llm *models.SLLM, err string) {
|
||||
llm.SetStatus(ctx, task.UserCred, api.LLM_STATUS_STOP_FAILED, err)
|
||||
db.OpsLog.LogEvent(llm, db.ACT_STOP, err, task.UserCred)
|
||||
logclient.AddActionLogWithStartable(task, llm, logclient.ACT_VM_STOP, err, task.UserCred, false)
|
||||
// llm.NotifyRequest(ctx, task.GetUserCred(), notify.ActionStop, nil, false)
|
||||
task.SetStageFailed(ctx, jsonutils.NewString(err))
|
||||
}
|
||||
|
||||
func (task *LLMStopTask) taskComplete(ctx context.Context, llm *models.SLLM) {
|
||||
if !task.HasParentTask() {
|
||||
llm.SetStatus(ctx, task.GetUserCred(), api.LLM_STATUS_READY, "")
|
||||
}
|
||||
// llm.NotifyRequest(ctx, task.GetUserCred(), notify.ActionStop, nil, true)
|
||||
task.SetStageComplete(ctx, nil)
|
||||
}
|
||||
|
||||
func (task *LLMStopTask) OnInit(ctx context.Context, obj db.IStandaloneModel, body jsonutils.JSONObject) {
|
||||
llm := obj.(*models.SLLM)
|
||||
|
||||
srv, err := llm.GetServer(ctx)
|
||||
if err != nil {
|
||||
task.taskFailed(ctx, llm, errors.Wrap(err, "GetServer").Error())
|
||||
return
|
||||
}
|
||||
|
||||
if srv.Status == computeapi.VM_READY {
|
||||
task.taskComplete(ctx, llm)
|
||||
return
|
||||
}
|
||||
|
||||
task.SetStage("OnStopComplete", nil)
|
||||
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
|
||||
s := auth.GetSession(ctx, task.UserCred, "")
|
||||
_, err = compute.Servers.PerformAction(s, llm.SvrId, "stop", nil)
|
||||
if err != nil {
|
||||
task.taskFailed(ctx, llm, err.Error())
|
||||
return nil, errors.Wrap(err, "server perform stop")
|
||||
}
|
||||
_, err := llm.WaitServerStatus(ctx, task.UserCred, []string{computeapi.VM_READY}, 600)
|
||||
if err != nil {
|
||||
if errors.Cause(err) == errors.ErrTimeout {
|
||||
params := computeapi.ServerStopInput{
|
||||
IsForce: true,
|
||||
TimeoutSecs: 10,
|
||||
}
|
||||
_, err = compute.Servers.PerformAction(s, llm.SvrId, "stop", jsonutils.Marshal(params))
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "server perform stop by force")
|
||||
}
|
||||
_, err := llm.WaitServerStatus(ctx, task.UserCred, []string{computeapi.VM_READY}, 600)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "WaitServerStatus 2")
|
||||
}
|
||||
} else {
|
||||
return nil, errors.Wrap(err, "WaitServerStatus")
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
})
|
||||
}
|
||||
|
||||
func (task *LLMStopTask) OnStopComplete(ctx context.Context, obj db.IStandaloneModel, body jsonutils.JSONObject) {
|
||||
llm := obj.(*models.SLLM)
|
||||
task.taskComplete(ctx, llm)
|
||||
}
|
||||
|
||||
func (task *LLMStopTask) OnStopCompleteFailed(ctx context.Context, obj db.IStandaloneModel, err jsonutils.JSONObject) {
|
||||
llm := obj.(*models.SLLM)
|
||||
task.taskFailed(ctx, llm, err.String())
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
package llm_container // import "yunion.io/x/onecloud/pkg/llm/tasks/llm_container"
|
||||
@@ -1,37 +0,0 @@
|
||||
package llm_container
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/llm/models"
|
||||
"yunion.io/x/onecloud/pkg/util/logclient"
|
||||
)
|
||||
|
||||
type LLMContainerDeleteTask struct {
|
||||
taskman.STask
|
||||
}
|
||||
|
||||
func init() {
|
||||
taskman.RegisterTask(LLMContainerDeleteTask{})
|
||||
}
|
||||
|
||||
func (task *LLMContainerDeleteTask) taskFailed(ctx context.Context, lc *models.SLLMContainer, status string, err error) {
|
||||
lc.SetStatus(ctx, task.UserCred, status, err.Error())
|
||||
db.OpsLog.LogEvent(lc, db.ACT_DELETE, err, task.UserCred)
|
||||
logclient.AddActionLogWithStartable(task, lc, logclient.ACT_DELETE, err, task.UserCred, false)
|
||||
task.SetStageFailed(ctx, jsonutils.NewString(err.Error()))
|
||||
}
|
||||
|
||||
func (task *LLMContainerDeleteTask) taskComplete(ctx context.Context, lc *models.SLLMContainer) {
|
||||
lc.RealDelete(ctx, task.GetUserCred())
|
||||
task.SetStageComplete(ctx, nil)
|
||||
}
|
||||
|
||||
func (task *LLMContainerDeleteTask) OnInit(ctx context.Context, obj db.IStandaloneModel, body jsonutils.JSONObject) {
|
||||
lc := obj.(*models.SLLMContainer)
|
||||
task.taskComplete(ctx, lc)
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package tasks
|
||||
|
||||
import (
|
||||
_ "yunion.io/x/onecloud/pkg/llm/tasks/dify"
|
||||
_ "yunion.io/x/onecloud/pkg/llm/tasks/llm"
|
||||
_ "yunion.io/x/onecloud/pkg/llm/tasks/llm_container"
|
||||
_ "yunion.io/x/onecloud/pkg/llm/tasks/volume"
|
||||
)
|
||||
@@ -1 +0,0 @@
|
||||
package volume // import "yunion.io/x/onecloud/pkg/llm/tasks/volume"
|
||||
@@ -1,70 +0,0 @@
|
||||
package volume
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/util/httputils"
|
||||
|
||||
computeapi "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/llm/models"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/auth"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules/compute"
|
||||
"yunion.io/x/onecloud/pkg/util/logclient"
|
||||
)
|
||||
|
||||
type VolumeDeleteTask struct {
|
||||
taskman.STask
|
||||
}
|
||||
|
||||
func init() {
|
||||
taskman.RegisterTask(VolumeDeleteTask{})
|
||||
}
|
||||
|
||||
func (volumeDeleteTask *VolumeDeleteTask) taskFailed(ctx context.Context, volume *models.SVolume, status string, err error) {
|
||||
volume.SetStatus(ctx, volumeDeleteTask.UserCred, status, err.Error())
|
||||
db.OpsLog.LogEvent(volume, db.ACT_DELETE, err, volumeDeleteTask.UserCred)
|
||||
logclient.AddActionLogWithStartable(volumeDeleteTask, volume, logclient.ACT_DELETE, err, volumeDeleteTask.UserCred, false)
|
||||
volumeDeleteTask.SetStageFailed(ctx, jsonutils.NewString(err.Error()))
|
||||
}
|
||||
|
||||
func (volumeDeleteTask *VolumeDeleteTask) taskComplete(ctx context.Context, volume *models.SVolume) {
|
||||
volume.RealDelete(ctx, volumeDeleteTask.GetUserCred())
|
||||
volumeDeleteTask.SetStageComplete(ctx, nil)
|
||||
}
|
||||
|
||||
func (volumeDeleteTask *VolumeDeleteTask) OnInit(ctx context.Context, obj db.IStandaloneModel, body jsonutils.JSONObject) {
|
||||
volume := obj.(*models.SVolume)
|
||||
if len(volume.SvrId) == 0 {
|
||||
volumeDeleteTask.taskComplete(ctx, volume)
|
||||
return
|
||||
}
|
||||
s := auth.GetSession(ctx, volumeDeleteTask.UserCred, "")
|
||||
_, err := compute.Disks.Delete(s, volume.SvrId, nil)
|
||||
if err != nil {
|
||||
if httputils.ErrorCode(err) == 404 {
|
||||
volumeDeleteTask.taskComplete(ctx, volume)
|
||||
return
|
||||
}
|
||||
volumeDeleteTask.taskFailed(ctx, volume, computeapi.DISK_DEALLOC_FAILED, errors.Wrap(err, "wait status"))
|
||||
return
|
||||
}
|
||||
for i := 0; i < 60; i++ {
|
||||
_, err := compute.Disks.GetById(s, volume.SvrId, jsonutils.Marshal(map[string]interface{}{
|
||||
"scope": "max",
|
||||
}))
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "ResourceNotFoundError") {
|
||||
volumeDeleteTask.taskComplete(ctx, volume)
|
||||
return
|
||||
}
|
||||
}
|
||||
time.Sleep(30 * time.Second)
|
||||
}
|
||||
volumeDeleteTask.taskFailed(ctx, volume, computeapi.MODELARTS_POOL_STATUS_TIMEOUT, errors.Wrap(err, "wait status"))
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
package worker // import "yunion.io/x/onecloud/pkg/llm/tasks/worker"
|
||||
@@ -1,38 +0,0 @@
|
||||
package worker
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/appsrv"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/llm/options"
|
||||
)
|
||||
|
||||
var (
|
||||
localTaskWorkerManLock *sync.Mutex
|
||||
|
||||
startTaskWorkerMan *appsrv.SWorkerManager
|
||||
)
|
||||
|
||||
func init() {
|
||||
localTaskWorkerManLock = &sync.Mutex{}
|
||||
}
|
||||
|
||||
func getStartTaskWorkerMan() *appsrv.SWorkerManager {
|
||||
localTaskWorkerManLock.Lock()
|
||||
defer localTaskWorkerManLock.Unlock()
|
||||
|
||||
if startTaskWorkerMan != nil {
|
||||
return startTaskWorkerMan
|
||||
}
|
||||
log.Infof("StartTaskWorkerCount %d", options.Options.StartTaskWorkerCount)
|
||||
startTaskWorkerMan = appsrv.NewWorkerManager("StartTaskWorkerManager", options.Options.StartTaskWorkerCount, 1024, false)
|
||||
return startTaskWorkerMan
|
||||
}
|
||||
|
||||
func StartTaskRun(task taskman.ITask, proc func() (jsonutils.JSONObject, error)) {
|
||||
taskman.LocalTaskRunWithWorkers(task, proc, getStartTaskWorkerMan())
|
||||
}
|
||||
@@ -1,173 +0,0 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/util/httputils"
|
||||
"yunion.io/x/pkg/utils"
|
||||
|
||||
computeapi "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/auth"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modulebase"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules/compute"
|
||||
)
|
||||
|
||||
type ResourceInfo struct {
|
||||
Id string
|
||||
Name string
|
||||
Status string
|
||||
}
|
||||
|
||||
func NewResourceInfo(id, name, status string) ResourceInfo {
|
||||
return ResourceInfo{
|
||||
Id: id,
|
||||
Name: name,
|
||||
Status: status,
|
||||
}
|
||||
}
|
||||
|
||||
func GetResource[R any](ctx context.Context, man modulebase.Manager, id string) (*R, error) {
|
||||
if len(id) == 0 {
|
||||
return nil, errors.Wrapf(httperrors.ErrInvalidStatus, "id is empty")
|
||||
}
|
||||
s := auth.GetAdminSession(ctx, "")
|
||||
resp, err := man.GetById(s, id, jsonutils.Marshal(map[string]interface{}{
|
||||
"scope": "max",
|
||||
}))
|
||||
if err != nil {
|
||||
if httputils.ErrorCode(err) == 404 {
|
||||
return nil, errors.Wrapf(errors.ErrNotFound, "GetById %s", id)
|
||||
}
|
||||
return nil, errors.Wrapf(err, "Get")
|
||||
}
|
||||
res := new(R)
|
||||
if err := resp.Unmarshal(res); err != nil {
|
||||
return nil, errors.Wrap(err, "Unmarshal")
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func PerformResourceAction[R any](ctx context.Context, man modulebase.Manager, id string, action string) (*R, error) {
|
||||
s := auth.GetAdminSession(ctx, "")
|
||||
resp, err := man.PerformAction(s, id, action, nil)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "PerformAction %s %s %s", man.GetKeyword(), id, action)
|
||||
}
|
||||
res := new(R)
|
||||
if err := resp.Unmarshal(res); err != nil {
|
||||
return nil, errors.Wrap(err, "Unmarshal")
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func StopResource[R any](ctx context.Context, man modulebase.Manager, id string) (*R, error) {
|
||||
return PerformResourceAction[R](ctx, man, id, "stop")
|
||||
}
|
||||
|
||||
func StartResource[R any](ctx context.Context, man modulebase.Manager, id string) (*R, error) {
|
||||
return PerformResourceAction[R](ctx, man, id, "start")
|
||||
}
|
||||
|
||||
func WaitResourceStatus[R any](
|
||||
ctx context.Context,
|
||||
man modulebase.Manager,
|
||||
id string,
|
||||
getResInfo func(*R) ResourceInfo,
|
||||
targetStatus []string,
|
||||
timeoutSecs int,
|
||||
intervalSecs int) (*R, error) {
|
||||
expire := time.Now().Add(time.Second * time.Duration(timeoutSecs))
|
||||
for time.Now().Before(expire) {
|
||||
res, err := GetResource[R](ctx, man, id)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "GetResource")
|
||||
}
|
||||
resInfo := getResInfo(res)
|
||||
log.Debugf("Wait %s status %#v target status %v", man.GetKeyword(), resInfo.Status, targetStatus)
|
||||
if utils.IsInStringArray(resInfo.Status, targetStatus) {
|
||||
return res, nil
|
||||
}
|
||||
if strings.Contains(resInfo.Status, "fail") {
|
||||
return nil, errors.Wrapf(errors.ErrInvalidStatus, "resource %s status %s", resInfo.Name, resInfo.Status)
|
||||
}
|
||||
time.Sleep(time.Second * time.Duration(intervalSecs))
|
||||
}
|
||||
return nil, errors.Wrapf(httperrors.ErrTimeout, "wait %s status %s timeout", man.GetKeyword(), targetStatus)
|
||||
}
|
||||
|
||||
func GetContainer(ctx context.Context, id string) (*computeapi.SContainer, error) {
|
||||
return GetResource[computeapi.SContainer](ctx, &compute.Containers, id)
|
||||
}
|
||||
|
||||
func GetServer(ctx context.Context, id string) (*computeapi.ServerDetails, error) {
|
||||
return GetResource[computeapi.ServerDetails](ctx, &compute.Servers, id)
|
||||
}
|
||||
|
||||
func WaitContainerStatus(ctx context.Context, id string, targetStatus []string, timeoutSecs int) (*computeapi.SContainer, error) {
|
||||
return WaitResourceStatus(ctx, &compute.Containers, id, func(ctr *computeapi.SContainer) ResourceInfo {
|
||||
return NewResourceInfo(ctr.Id, ctr.Name, ctr.Status)
|
||||
}, targetStatus, timeoutSecs, 1)
|
||||
}
|
||||
|
||||
func WaitServerStatus(ctx context.Context, id string, targetStatus []string, timeoutSecs int) (*computeapi.ServerDetails, error) {
|
||||
return WaitResourceStatus(ctx, &compute.Servers, id, func(s *computeapi.ServerDetails) ResourceInfo {
|
||||
return NewResourceInfo(s.Id, s.Name, s.Status)
|
||||
}, targetStatus, timeoutSecs, 2)
|
||||
}
|
||||
|
||||
func WaitDelete[R any](ctx context.Context, man modulebase.Manager, id string, timeoutSecs int) error {
|
||||
expire := time.Now().Add(time.Second * time.Duration(timeoutSecs))
|
||||
for time.Now().Before(expire) {
|
||||
_, err := GetResource[R](ctx, man, id)
|
||||
if err != nil {
|
||||
if errors.Cause(err) == errors.ErrNotFound {
|
||||
return nil
|
||||
}
|
||||
return errors.Wrapf(err, "Get %s %s", man.GetKeyword(), id)
|
||||
}
|
||||
time.Sleep(2 * time.Second)
|
||||
}
|
||||
return errors.Wrapf(httperrors.ErrTimeout, "wait %s %s deleted timeout", man.GetKeyword(), id)
|
||||
}
|
||||
|
||||
func UpdateContainer(ctx context.Context, id string, getSpec func(*computeapi.SContainer) *computeapi.ContainerSpec) (*computeapi.SContainer, error) {
|
||||
s := auth.GetAdminSession(ctx, "")
|
||||
ctr, err := GetContainer(ctx, id)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "GetContainer %s", id)
|
||||
}
|
||||
curSpecStr := jsonutils.Marshal(ctr.Spec).String()
|
||||
newSpec := getSpec(ctr)
|
||||
newSpecStr := jsonutils.Marshal(newSpec).String()
|
||||
if curSpecStr != newSpecStr {
|
||||
ctr.Spec = newSpec
|
||||
resp, err := compute.Containers.Update(s, id, jsonutils.Marshal(ctr))
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "UpdateContainer %s", id)
|
||||
}
|
||||
respCtr := new(computeapi.SContainer)
|
||||
if err := resp.Unmarshal(respCtr); err != nil {
|
||||
return nil, errors.Wrapf(err, "Unmarshal")
|
||||
}
|
||||
return respCtr, nil
|
||||
} else {
|
||||
log.Debugf("container spec not changed, skip update container %s spec", ctr.Name)
|
||||
}
|
||||
return ctr, nil
|
||||
}
|
||||
|
||||
func ExecSyncContainer(ctx context.Context, containerId string, input *computeapi.ContainerExecSyncInput) (jsonutils.JSONObject, error) {
|
||||
session := auth.GetAdminSession(ctx, "")
|
||||
output, err := compute.Containers.PerformAction(session, containerId, "exec-sync", jsonutils.Marshal(input))
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "ExecSync")
|
||||
}
|
||||
|
||||
return output, nil
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package utils // import "yunion.io/x/onecloud/pkg/llm/utils"
|
||||
@@ -1,15 +0,0 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package llm // import "yunion.io/x/onecloud/pkg/mcclient/modules/llm"
|
||||
@@ -1,23 +0,0 @@
|
||||
package llm
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modulebase"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
)
|
||||
|
||||
var (
|
||||
Difies DifyManager
|
||||
)
|
||||
|
||||
func init() {
|
||||
Difies = DifyManager{
|
||||
modules.NewLLMManager("dify", "difies",
|
||||
[]string{"ID", "Name", "Guest_ID", "Containers", "Status"},
|
||||
[]string{}),
|
||||
}
|
||||
modules.Register(&Difies)
|
||||
}
|
||||
|
||||
type DifyManager struct {
|
||||
modulebase.ResourceManager
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
package llm
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modulebase"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
)
|
||||
|
||||
type DifyModelManager struct {
|
||||
modulebase.ResourceManager
|
||||
}
|
||||
|
||||
var (
|
||||
DifyModel DifyModelManager
|
||||
)
|
||||
|
||||
func init() {
|
||||
DifyModel = DifyModelManager{
|
||||
ResourceManager: modules.NewLLMManager("dify_model", "dify_models",
|
||||
[]string{},
|
||||
[]string{},
|
||||
),
|
||||
}
|
||||
modules.Register(&DifyModel)
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
package llm
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modulebase"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
)
|
||||
|
||||
type LLMImageManager struct {
|
||||
modulebase.ResourceManager
|
||||
}
|
||||
|
||||
var (
|
||||
LLMImage LLMImageManager
|
||||
)
|
||||
|
||||
func init() {
|
||||
LLMImage = LLMImageManager{
|
||||
ResourceManager: modules.NewLLMManager("llm_image", "llm_images",
|
||||
[]string{},
|
||||
[]string{},
|
||||
),
|
||||
}
|
||||
modules.Register(&LLMImage)
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
package llm
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modulebase"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
)
|
||||
|
||||
var (
|
||||
LLMs LLMManager
|
||||
)
|
||||
|
||||
func init() {
|
||||
LLMs = LLMManager{
|
||||
modules.NewLLMManager("llm", "llms",
|
||||
[]string{},
|
||||
[]string{}),
|
||||
}
|
||||
modules.Register(&LLMs)
|
||||
}
|
||||
|
||||
type LLMManager struct {
|
||||
modulebase.ResourceManager
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
package llm
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modulebase"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
)
|
||||
|
||||
type LLMModelManager struct {
|
||||
modulebase.ResourceManager
|
||||
}
|
||||
|
||||
var (
|
||||
LLMModel LLMModelManager
|
||||
)
|
||||
|
||||
func init() {
|
||||
LLMModel = LLMModelManager{
|
||||
ResourceManager: modules.NewLLMManager("llm_model", "llm_models",
|
||||
[]string{},
|
||||
[]string{},
|
||||
),
|
||||
}
|
||||
modules.Register(&LLMModel)
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package llm
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules/tasks"
|
||||
)
|
||||
|
||||
var LLMTasks tasks.TasksManager
|
||||
var ArchivedLLMTasks tasks.TasksManager
|
||||
|
||||
func init() {
|
||||
LLMTasks, ArchivedLLMTasks = tasks.NewTaskManagers(modules.NewLLMManager)
|
||||
}
|
||||
@@ -180,9 +180,3 @@ func NewAPIMapManager(keyword, keywordPlural string, columns, adminColumns []str
|
||||
BaseManager: *modulebase.NewBaseManager(apis.SERVICE_TYPE_APIMAP, "", "", columns, adminColumns),
|
||||
Keyword: keyword, KeywordPlural: keywordPlural}
|
||||
}
|
||||
|
||||
func NewLLMManager(keyword, keywordPlural string, columns, adminColumns []string) modulebase.ResourceManager {
|
||||
return modulebase.ResourceManager{
|
||||
BaseManager: *modulebase.NewBaseManager(apis.SERVICE_TYPE_LLM, "", "", columns, adminColumns),
|
||||
Keyword: keyword, KeywordPlural: keywordPlural}
|
||||
}
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
package llm
|
||||
|
||||
import (
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
)
|
||||
|
||||
type DifyListOptions struct {
|
||||
LLMBaseListOptions
|
||||
|
||||
DifyModel string `help:"filter by dify model"`
|
||||
}
|
||||
|
||||
func (o *DifyListOptions) Params() (jsonutils.JSONObject, error) {
|
||||
params, err := options.ListStructToParams(o)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if o.Used != nil {
|
||||
params.Set("unused", jsonutils.JSONFalse)
|
||||
}
|
||||
return params, nil
|
||||
}
|
||||
|
||||
type DifyShowOptions struct {
|
||||
options.BaseShowOptions
|
||||
}
|
||||
|
||||
func (o *DifyShowOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return options.StructToParams(o)
|
||||
}
|
||||
|
||||
type DifyCreateOptions struct {
|
||||
LLMBaseCreateOptions
|
||||
|
||||
DIFY_MODEL_ID string `help:"dify model id or name" json:"dify_model_id"`
|
||||
}
|
||||
|
||||
func (o *DifyCreateOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return jsonutils.Marshal(o), nil
|
||||
}
|
||||
|
||||
func (o *DifyCreateOptions) GetCountParam() int {
|
||||
return o.Count
|
||||
}
|
||||
|
||||
type DifyDeleteOptions struct {
|
||||
options.BaseIdOptions
|
||||
}
|
||||
|
||||
func (o *DifyDeleteOptions) GetId() string {
|
||||
return o.ID
|
||||
}
|
||||
|
||||
func (o *DifyDeleteOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return options.StructToParams(o)
|
||||
}
|
||||
|
||||
type DifyStartOptions struct {
|
||||
options.BaseIdsOptions
|
||||
}
|
||||
|
||||
func (o *DifyStartOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return jsonutils.Marshal(o), nil
|
||||
}
|
||||
|
||||
type DifyStopOptions struct {
|
||||
options.BaseIdsOptions
|
||||
}
|
||||
|
||||
func (o *DifyStopOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return jsonutils.Marshal(o), nil
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
package llm
|
||||
|
||||
import (
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
)
|
||||
|
||||
type DifyModelListOptions struct {
|
||||
options.BaseListOptions
|
||||
}
|
||||
|
||||
func (o *DifyModelListOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return options.ListStructToParams(o)
|
||||
}
|
||||
|
||||
type DifyModelShowOptions struct {
|
||||
options.BaseShowOptions
|
||||
}
|
||||
|
||||
func (o *DifyModelShowOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return options.StructToParams(o)
|
||||
}
|
||||
|
||||
type DifyModelCreateOptions struct {
|
||||
LLMModelBaseCreateOptions
|
||||
|
||||
POSTGRES_IMAGE_ID string `json:"postgres_image_id"`
|
||||
REDIS_IMAGE_ID string `json:"redis_image_id"`
|
||||
NGINX_IMAGE_ID string `json:"nginx_image_id"`
|
||||
DIFY_API_IMAGE_ID string `json:"dify_api_image_id"`
|
||||
DIFY_PLUGIN_IMAGE_ID string `json:"dify_plugin_image_id"`
|
||||
DIFY_WEB_IMAGE_ID string `json:"dify_web_image_id"`
|
||||
DIFY_SANDBOX_IMAGE_ID string `json:"dify_sandbox_image_id"`
|
||||
DIFY_SSRF_IMAGE_ID string `json:"dify_ssrf_image_id"`
|
||||
DIFY_WEAVIATE_IMAGE_ID string `json:"dify_weaviate_image_id"`
|
||||
}
|
||||
|
||||
func (o *DifyModelCreateOptions) Params() (jsonutils.JSONObject, error) {
|
||||
dict := jsonutils.NewDict()
|
||||
obj := jsonutils.Marshal(o)
|
||||
obj.Unmarshal(dict)
|
||||
|
||||
o.LLMModelBaseCreateOptions.Params(dict)
|
||||
return dict, nil
|
||||
}
|
||||
|
||||
type DifyModelDeleteOptions struct {
|
||||
options.BaseIdOptions
|
||||
}
|
||||
|
||||
func (o *DifyModelDeleteOptions) GetId() string {
|
||||
return o.ID
|
||||
}
|
||||
|
||||
func (o *DifyModelDeleteOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return options.StructToParams(o)
|
||||
}
|
||||
|
||||
type DifyModelUpdateOptions struct {
|
||||
LLMModelBaseUpdateOptions
|
||||
|
||||
LlmImageId string
|
||||
LlmModelName string
|
||||
}
|
||||
|
||||
func (o *DifyModelUpdateOptions) GetId() string {
|
||||
return o.ID
|
||||
}
|
||||
|
||||
func (o *DifyModelUpdateOptions) Params() (jsonutils.JSONObject, error) {
|
||||
dict := jsonutils.NewDict()
|
||||
obj := jsonutils.Marshal(o)
|
||||
obj.Unmarshal(dict)
|
||||
|
||||
o.LLMModelBaseUpdateOptions.Params(dict)
|
||||
return dict, nil
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package llm // import "yunion.io/x/onecloud/pkg/mcclient/options/llm"
|
||||
@@ -1,60 +0,0 @@
|
||||
package llm
|
||||
|
||||
import (
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
)
|
||||
|
||||
type LLMImageShowOptions struct {
|
||||
options.BaseShowOptions
|
||||
}
|
||||
|
||||
func (o *LLMImageShowOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return options.ListStructToParams(o)
|
||||
}
|
||||
|
||||
type LLMImageListOptions struct {
|
||||
options.BaseListOptions
|
||||
}
|
||||
|
||||
func (o *LLMImageListOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return options.ListStructToParams(o)
|
||||
}
|
||||
|
||||
type LLMImageCreateOptions struct {
|
||||
apis.SharableVirtualResourceCreateInput
|
||||
IMAGE_NAME string
|
||||
IMAGE_LABEL string
|
||||
CredentialId string
|
||||
}
|
||||
|
||||
func (o *LLMImageCreateOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return jsonutils.Marshal(o), nil
|
||||
}
|
||||
|
||||
type LLMImageUpdateOptions struct {
|
||||
apis.SharableVirtualResourceCreateInput
|
||||
|
||||
ID string
|
||||
IMAGE_NAME string
|
||||
IMAGE_LABEL string
|
||||
CredentialId string
|
||||
}
|
||||
|
||||
func (o *LLMImageUpdateOptions) GetId() string {
|
||||
return o.ID
|
||||
}
|
||||
|
||||
func (o *LLMImageUpdateOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return jsonutils.Marshal(o), nil
|
||||
}
|
||||
|
||||
type LLMImageDeleteOptions struct {
|
||||
options.BaseIdOptions
|
||||
}
|
||||
|
||||
func (o *LLMImageDeleteOptions) GetId() string {
|
||||
return o.ID
|
||||
}
|
||||
@@ -1,99 +0,0 @@
|
||||
package llm
|
||||
|
||||
import (
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
)
|
||||
|
||||
type LLMBaseListOptions struct {
|
||||
options.BaseListOptions
|
||||
Host string `help:"filter by host"`
|
||||
LLMStatus []string `help:"filter by server status"`
|
||||
|
||||
ListenPort int `help:"filter by listen port"`
|
||||
PublicIp string `help:"filter by public ip"`
|
||||
VolumeId string `help:"filter by volume id"`
|
||||
Unused *bool `help:"filter by unused"`
|
||||
Used *bool `help:"filter by used"`
|
||||
}
|
||||
|
||||
type LLMListOptions struct {
|
||||
LLMBaseListOptions
|
||||
|
||||
LlmModel string `help:"filter by llm model"`
|
||||
LlmImage string `help:"filter by llm image"`
|
||||
}
|
||||
|
||||
func (o *LLMListOptions) Params() (jsonutils.JSONObject, error) {
|
||||
params, err := options.ListStructToParams(o)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if o.Used != nil {
|
||||
params.Set("unused", jsonutils.JSONFalse)
|
||||
}
|
||||
return params, nil
|
||||
}
|
||||
|
||||
type LLMShowOptions struct {
|
||||
options.BaseShowOptions
|
||||
}
|
||||
|
||||
func (o *LLMShowOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return options.StructToParams(o)
|
||||
}
|
||||
|
||||
type LLMBaseCreateOptions struct {
|
||||
options.BaseCreateOptions
|
||||
|
||||
AutoStart bool
|
||||
ProjectId string
|
||||
PreferHost string
|
||||
|
||||
BandwidthMb int
|
||||
|
||||
Count int `default:"1" help:"batch create count" json:"-"`
|
||||
}
|
||||
|
||||
type LLMCreateOptions struct {
|
||||
LLMBaseCreateOptions
|
||||
|
||||
LLM_MODEL_ID string `help:"llm model id or name" json:"llm_model_id"`
|
||||
}
|
||||
|
||||
func (o *LLMCreateOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return jsonutils.Marshal(o), nil
|
||||
}
|
||||
|
||||
func (o *LLMCreateOptions) GetCountParam() int {
|
||||
return o.Count
|
||||
}
|
||||
|
||||
type LLMDeleteOptions struct {
|
||||
options.BaseIdOptions
|
||||
}
|
||||
|
||||
func (o *LLMDeleteOptions) GetId() string {
|
||||
return o.ID
|
||||
}
|
||||
|
||||
func (o *LLMDeleteOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return options.StructToParams(o)
|
||||
}
|
||||
|
||||
type LLMStartOptions struct {
|
||||
options.BaseIdsOptions
|
||||
}
|
||||
|
||||
func (o *LLMStartOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return jsonutils.Marshal(o), nil
|
||||
}
|
||||
|
||||
type LLMStopOptions struct {
|
||||
options.BaseIdsOptions
|
||||
}
|
||||
|
||||
func (o *LLMStopOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return jsonutils.Marshal(o), nil
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
package llm
|
||||
|
||||
import (
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
)
|
||||
|
||||
type LLMModelListOptions struct {
|
||||
options.BaseListOptions
|
||||
|
||||
LLMType string `json:"llm_type" choices:"ollama"`
|
||||
}
|
||||
|
||||
func (o *LLMModelListOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return options.ListStructToParams(o)
|
||||
}
|
||||
|
||||
type LLMModelShowOptions struct {
|
||||
options.BaseShowOptions
|
||||
}
|
||||
|
||||
func (o *LLMModelShowOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return options.StructToParams(o)
|
||||
}
|
||||
|
||||
type LLMModelCreateOptions struct {
|
||||
LLMModelBaseCreateOptions
|
||||
|
||||
LLM_IMAGE_ID string `json:"llm_image_id"`
|
||||
LLM_TYPE string `json:"llm_type" choices:"ollama"`
|
||||
LLM_MODEL_NAME string `help:"specific model of large language model, for example: qwen3:32b" json:"llm_model_name"`
|
||||
}
|
||||
|
||||
func (o *LLMModelCreateOptions) Params() (jsonutils.JSONObject, error) {
|
||||
dict := jsonutils.NewDict()
|
||||
obj := jsonutils.Marshal(o)
|
||||
obj.Unmarshal(dict)
|
||||
|
||||
o.LLMModelBaseCreateOptions.Params(dict)
|
||||
return dict, nil
|
||||
}
|
||||
|
||||
type LLMModelDeleteOptions struct {
|
||||
options.BaseIdOptions
|
||||
}
|
||||
|
||||
func (o *LLMModelDeleteOptions) GetId() string {
|
||||
return o.ID
|
||||
}
|
||||
|
||||
func (o *LLMModelDeleteOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return options.StructToParams(o)
|
||||
}
|
||||
|
||||
type LLMModelUpdateOptions struct {
|
||||
LLMModelBaseUpdateOptions
|
||||
|
||||
LlmImageId string
|
||||
LlmModelName string
|
||||
}
|
||||
|
||||
func (o *LLMModelUpdateOptions) GetId() string {
|
||||
return o.ID
|
||||
}
|
||||
|
||||
func (o *LLMModelUpdateOptions) Params() (jsonutils.JSONObject, error) {
|
||||
dict := jsonutils.NewDict()
|
||||
obj := jsonutils.Marshal(o)
|
||||
obj.Unmarshal(dict)
|
||||
|
||||
o.LLMModelBaseUpdateOptions.Params(dict)
|
||||
return dict, nil
|
||||
}
|
||||
@@ -1,220 +0,0 @@
|
||||
package llm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis"
|
||||
computeapi "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
api "yunion.io/x/onecloud/pkg/apis/llm"
|
||||
)
|
||||
|
||||
type LLMModelBaseCreateOptions struct {
|
||||
apis.SharableVirtualResourceCreateInput
|
||||
|
||||
CPU int
|
||||
MEMORY int `help:"memory size MB"`
|
||||
DISK_SIZE int `help:"disk size MB"`
|
||||
|
||||
Bandwidth int
|
||||
StorageType string
|
||||
// DiskOverlay string `help:"disk overlay, e.g. /opt/steam-data/base:/opt/steam-data/games"`
|
||||
TemplateId string
|
||||
PortMappings []string `help:"port mapping in the format of protocol:port[:prefix][:first_port_offset][:env_key=env_value], e.g. tcp:5555:192.168.0.0/16:5:WOLF_BASE_PORT=20000"`
|
||||
Devices []string `help:"device info in the format of model[:path[:dev_type]], e.g. 'GeForce RTX 4060'"`
|
||||
|
||||
Env []string `help:"env in format of key=value"`
|
||||
Property []string `help:"extra properties of key=value, e.g. tango32=true"`
|
||||
|
||||
// MountedApps []string `help:"mounted apps, e.g. com.tencent.tmgp.sgame/1.0.0"`
|
||||
|
||||
Entrypoint string `help:"entrypoint"`
|
||||
}
|
||||
|
||||
func (o *LLMModelBaseCreateOptions) Params(dict *jsonutils.JSONDict) error {
|
||||
vol := api.Volume{
|
||||
SizeMB: o.DISK_SIZE,
|
||||
TemplateId: o.TemplateId,
|
||||
StorageType: o.StorageType,
|
||||
}
|
||||
vols := []api.Volume{vol}
|
||||
dict.Set("volumes", jsonutils.Marshal(vols))
|
||||
fetchPortmappings(o.PortMappings, dict)
|
||||
fetchDevices(o.Devices, dict)
|
||||
fetchEnvs(o.Env, dict)
|
||||
fetchProperties(o.Property, dict)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type LLMModelBaseUpdateOptions struct {
|
||||
apis.SharableVirtualResourceBaseUpdateInput
|
||||
|
||||
ID string
|
||||
|
||||
Cpu *int
|
||||
Memory *int `help:"memory size GB"`
|
||||
DiskSize *int `help:"disk size MB"`
|
||||
StorageType string
|
||||
TemplateId string
|
||||
NoTemplate bool `json:"-" help:"remove template"`
|
||||
Bandwidth *int
|
||||
// Dpi *int
|
||||
// Fps *int
|
||||
PortMappings []string `help:"port mapping in the format of protocol:port[:prefix][:first_port_offset], e.g. tcp:5555:192.168.0.0/16,10.10.0.0/16:1000"`
|
||||
Devices []string `help:"device info in the format of model[:path[:dev_type]], e.g. QuadraT2A:/dev/nvme1n1, Device::VASTAITECH_GPU"`
|
||||
Env []string `help:"env in the format of key=value, e.g. AUTHENTICATION_PATH=/bupt-test/"`
|
||||
Property []string `help:"extra properties of key=value, e.g. tango32=true"`
|
||||
|
||||
// MountedApps []string `help:"mounted apps, e.g. com.tencent.tmgp.sgame/1.0.0"`
|
||||
|
||||
SyncImage bool `help:"request sync image" json:"-"`
|
||||
ClearSyncImage bool `help:"request clear sync image flag" json:"-"`
|
||||
|
||||
Entrypoint string `help:"entrypoint"`
|
||||
}
|
||||
|
||||
func (o *LLMModelBaseUpdateOptions) Params(dict *jsonutils.JSONDict) error {
|
||||
if o.NoTemplate {
|
||||
dict.Set("template_id", jsonutils.NewString(""))
|
||||
}
|
||||
if o.SyncImage {
|
||||
dict.Set("request_sync_image", jsonutils.JSONTrue)
|
||||
} else if o.ClearSyncImage {
|
||||
dict.Set("request_sync_image", jsonutils.JSONFalse)
|
||||
}
|
||||
if o.DiskSize != nil && *o.DiskSize > 0 {
|
||||
dict.Set("disk_size_mb", jsonutils.NewInt(int64(*o.DiskSize)))
|
||||
}
|
||||
|
||||
fetchPortmappings(o.PortMappings, dict)
|
||||
fetchDevices(o.Devices, dict)
|
||||
fetchEnvs(o.Env, dict)
|
||||
fetchProperties(o.Property, dict)
|
||||
// fetchMountedApps(o.MountedApps, dict)
|
||||
return nil
|
||||
}
|
||||
|
||||
func fetchPortmappings(pmStrs []string, dict *jsonutils.JSONDict) {
|
||||
pms := make([]api.PortMapping, 0)
|
||||
for _, pm := range pmStrs {
|
||||
segs := strings.Split(pm, ":")
|
||||
if len(segs) > 1 {
|
||||
port, _ := strconv.ParseInt(segs[1], 10, 64)
|
||||
var remoteIps []string
|
||||
if len(segs) > 2 {
|
||||
for _, ip := range strings.Split(segs[2], ",") {
|
||||
ip = strings.TrimSpace(ip)
|
||||
if len(ip) > 0 {
|
||||
remoteIps = append(remoteIps, ip)
|
||||
}
|
||||
}
|
||||
}
|
||||
firstPortOffset := 0
|
||||
var err error
|
||||
if len(segs) > 3 {
|
||||
firstPortOffset, err = strconv.Atoi(segs[3])
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("parse firstPortOffset: %s", err))
|
||||
}
|
||||
}
|
||||
pm := api.PortMapping{
|
||||
Protocol: segs[0],
|
||||
ContainerPort: int(port),
|
||||
RemoteIps: remoteIps,
|
||||
}
|
||||
if firstPortOffset >= 0 {
|
||||
pm.FirstPortOffset = &firstPortOffset
|
||||
}
|
||||
if len(segs) > 4 {
|
||||
envs := make([]computeapi.GuestPortMappingEnv, 0)
|
||||
for _, env := range strings.Split(segs[4], ",") {
|
||||
parts := strings.Split(env, "=")
|
||||
if len(parts) != 2 {
|
||||
panic(fmt.Sprintf("parse env: %s", env))
|
||||
}
|
||||
key := parts[0]
|
||||
valType := parts[1]
|
||||
switch valType {
|
||||
case "port":
|
||||
envs = append(envs, computeapi.GuestPortMappingEnv{Key: key, ValueFrom: computeapi.GuestPortMappingEnvValueFromPort})
|
||||
case "host_port":
|
||||
envs = append(envs, computeapi.GuestPortMappingEnv{Key: key, ValueFrom: computeapi.GuestPortMappingEnvValueFromHostPort})
|
||||
default:
|
||||
panic(fmt.Sprintf("wrong env type: %q", valType))
|
||||
}
|
||||
}
|
||||
pm.Envs = envs
|
||||
}
|
||||
|
||||
pms = append(pms, pm)
|
||||
}
|
||||
}
|
||||
if len(pms) > 0 {
|
||||
dict.Set("port_mappings", jsonutils.Marshal(pms))
|
||||
}
|
||||
}
|
||||
|
||||
func fetchDevices(devStrs []string, dict *jsonutils.JSONDict) {
|
||||
devs := make([]api.Device, 0)
|
||||
for _, dev := range devStrs {
|
||||
segs := strings.Split(dev, ":")
|
||||
if len(segs) > 0 {
|
||||
devpath := ""
|
||||
devType := ""
|
||||
if len(segs) > 1 {
|
||||
devpath = segs[1]
|
||||
}
|
||||
if len(segs) > 2 {
|
||||
devType = segs[2]
|
||||
}
|
||||
devs = append(devs, api.Device{
|
||||
Model: segs[0],
|
||||
DevicePath: devpath,
|
||||
DevType: devType,
|
||||
})
|
||||
}
|
||||
}
|
||||
if len(devs) > 0 {
|
||||
dict.Set("devices", jsonutils.Marshal(devs))
|
||||
}
|
||||
}
|
||||
|
||||
func fetchEnvs(EnvStrs []string, dict *jsonutils.JSONDict) {
|
||||
envs := make(api.Envs, 0)
|
||||
for _, env := range EnvStrs {
|
||||
pos := strings.Index(env, "=")
|
||||
if pos > 0 {
|
||||
key := strings.TrimSpace(env[:pos])
|
||||
val := strings.TrimSpace(env[pos+1:])
|
||||
envs = append(envs, api.Env{Key: key, Value: val})
|
||||
}
|
||||
}
|
||||
if len(envs) > 0 {
|
||||
dict.Set("envs", jsonutils.Marshal(envs))
|
||||
}
|
||||
}
|
||||
|
||||
func fetchProperties(propStrs []string, dict *jsonutils.JSONDict) {
|
||||
props := make(map[string]string, 0)
|
||||
for _, env := range propStrs {
|
||||
pos := strings.Index(env, "=")
|
||||
if pos > 0 {
|
||||
key := strings.TrimSpace(env[:pos])
|
||||
val := strings.TrimSpace(env[pos+1:])
|
||||
props[key] = val
|
||||
}
|
||||
}
|
||||
if len(props) > 0 {
|
||||
dict.Set("properties", jsonutils.Marshal(props))
|
||||
}
|
||||
}
|
||||
|
||||
// func fetchMountedApps(apps []string, dict *jsonutils.JSONDict) {
|
||||
// if len(apps) > 0 {
|
||||
// dict.Set("mounted_apps", jsonutils.Marshal(apps))
|
||||
// }
|
||||
// }
|
||||
@@ -1,59 +0,0 @@
|
||||
#!/bin/bash
|
||||
# 用法:
|
||||
# ./sync-images.sh <targetRegistry>
|
||||
# 示例:
|
||||
# ./sync-images.sh crpi-nf3abu98o8qf9y2x.cn-beijing.personal.cr.aliyuncs.com/eikoh
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
if [ $# -ne 1 ]; then
|
||||
echo "用法: $0 <targetRegistry>"
|
||||
echo "例如: $0 crpi-nf3abu98o8qf9y2x.cn-beijing.personal.cr.aliyuncs.com/eikoh"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
TARGET_REGISTRY="$1"
|
||||
SOURCE_REGISTRY="docker.io"
|
||||
|
||||
# ----------------------------
|
||||
# 要同步的镜像列表
|
||||
# ----------------------------
|
||||
IMAGES=(
|
||||
"nginx:latest"
|
||||
"redis:6-alpine"
|
||||
"postgres:15-alpine"
|
||||
"langgenius/dify-api:1.7.2"
|
||||
"langgenius/dify-sandbox:0.2.12"
|
||||
"langgenius/dify-plugin-daemon:0.2.0-local"
|
||||
"langgenius/dify-web:1.7.2"
|
||||
"ubuntu/squid:latest"
|
||||
"semitechnologies/weaviate:1.19.0"
|
||||
)
|
||||
|
||||
for image in "${IMAGES[@]}"; do
|
||||
# 拆分 name 和 tag
|
||||
if [[ "$image" == *":"* ]]; then
|
||||
name="${image%%:*}" # 冒号前
|
||||
tag="${image##*:}" # 冒号后
|
||||
else
|
||||
name="$image"
|
||||
tag="latest"
|
||||
fi
|
||||
|
||||
short_name="${name##*/}" # 目标镜像只取最后一级名字
|
||||
|
||||
SRC="docker://${SOURCE_REGISTRY}/${name}:${tag}"
|
||||
DST="docker://${TARGET_REGISTRY}/${short_name}:${tag}"
|
||||
|
||||
echo
|
||||
echo "Sync dify image"
|
||||
echo " Source: ${SRC}"
|
||||
echo " Target: ${DST}"
|
||||
echo
|
||||
|
||||
skopeo copy "${SRC}" "${DST}"
|
||||
|
||||
echo "Completed: ${short_name}:${tag}"
|
||||
done
|
||||
|
||||
echo "All images sync completed"
|
||||
Reference in New Issue
Block a user