diff --git a/apps/scheduler/call/choice.py b/apps/scheduler/call/choice/choice.py similarity index 65% rename from apps/scheduler/call/choice.py rename to apps/scheduler/call/choice/choice.py index 62b6d84e6d1577f0fb1b0ddea5ab5b2e905e16ca..c493ea80eae245d7200b82919c3abd4d5d0abade 100644 --- a/apps/scheduler/call/choice.py +++ b/apps/scheduler/call/choice/choice.py @@ -1,6 +1,7 @@ -"""工具:使用大模型或使用程序做出判断 +""" +工具:使用大模型或使用程序做出判断 -Copyright (c) Huawei Technologies Co., Ltd. 2023-2024. All rights reserved. +Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. """ from enum import Enum diff --git a/apps/scheduler/call/cmd/assembler.py b/apps/scheduler/call/cmd/assembler.py index d1f774187ae52a1eed34ca275e0ff9b549aec6d9..26294f6df9a254c9dc63349209d9e3b71063ea01 100644 --- a/apps/scheduler/call/cmd/assembler.py +++ b/apps/scheduler/call/cmd/assembler.py @@ -1,7 +1,9 @@ -"""BTDL:命令行组装器 +""" +BTDL:命令行组装器 -Copyright (c) Huawei Technologies Co., Ltd. 2023-2024. All rights reserved. +Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. """ + import string from typing import Any, Literal, Optional diff --git a/apps/scheduler/call/cmd/cmd.py b/apps/scheduler/call/cmd/cmd.py index 7a23a574ab8f53e0a6cd8995692960d7da7182b2..a7d1951f8399cb67ad2722d4143a42be86f1ca06 100644 --- a/apps/scheduler/call/cmd/cmd.py +++ b/apps/scheduler/call/cmd/cmd.py @@ -1,8 +1,10 @@ -"""工具:自然语言生成命令 +""" +工具:自然语言生成命令 -Copyright (c) Huawei Technologies Co., Ltd. 2023-2024. All rights reserved. +Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. """ -from typing import Any, Optional + +from typing import Any from pydantic import BaseModel, Field @@ -12,7 +14,7 @@ from apps.scheduler.call.core import CoreCall class _CmdParams(BaseModel): """Cmd工具的参数""" - exec_name: Optional[str] = Field(default=None, description="命令中可执行文件的名称,可选") + exec_name: str | None = Field(default=None, description="命令中可执行文件的名称,可选") args: list[str] = Field(default=[], description="命令中可执行文件的参数(例如 `--help`),可选") @@ -27,6 +29,6 @@ class Cmd(CoreCall): name: str = "cmd" description: str = "根据BTDL描述文件,生成命令。" - async def exec(self, _slot_data: dict[str, Any]) -> _CmdOutput: + async def _exec(self, _slot_data: dict[str, Any]) -> _CmdOutput: """调用Cmd工具""" pass diff --git a/apps/scheduler/call/cmd/solver.py b/apps/scheduler/call/cmd/solver.py index 6cc75700465e5115bcc3b671f4c2531ecc73e651..4c3f12a6f2539bfbbb83b5ca1d8be562899d4c7d 100644 --- a/apps/scheduler/call/cmd/solver.py +++ b/apps/scheduler/call/cmd/solver.py @@ -1,6 +1,6 @@ """命令行解析器 -Copyright (c) Huawei Technologies Co., Ltd. 2023-2024. All rights reserved. +Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. """ import copy import re diff --git a/apps/scheduler/call/output/output.py b/apps/scheduler/call/output/output.py new file mode 100644 index 0000000000000000000000000000000000000000..62bfad9d4704eca02576786cf57ac45fe7bb3773 --- /dev/null +++ b/apps/scheduler/call/output/output.py @@ -0,0 +1,40 @@ +"""输出工具:将文字和结构化数据输出至前端""" +from collections.abc import AsyncGenerator +from typing import Annotated, Any, ClassVar + +from pydantic import Field + +from apps.entities.enum_var import CallOutputType +from apps.entities.scheduler import CallOutputChunk, CallVars +from apps.scheduler.call.core import CoreCall +from apps.scheduler.call.output.schema import OutputInput, OutputOutput + + +class Output(CoreCall, input_type=OutputInput, output_type=OutputOutput): + """输出工具""" + + name: ClassVar[Annotated[str, Field(description="工具名称", exclude=True, frozen=True)]] = "输出" + description: ClassVar[Annotated[str, Field(description="工具描述", exclude=True, frozen=True)]] = "将文字和结构化数据输出至前端" + + template: str = Field(description="输出模板(只能使用直接变量引用)") + + + async def _init(self, syscall_vars: CallVars) -> dict[str, Any]: + """初始化工具""" + self._text: AsyncGenerator[str, None] = kwargs["text"] + self._data: dict[str, Any] = kwargs["data"] + + return { + "text": self._text, + "data": self._data, + } + + + async def _exec(self, input_data: dict[str, Any]) -> AsyncGenerator[CallOutputChunk, None]: + """执行工具""" + yield CallOutputChunk( + type=CallOutputType.TEXT, + content=OutputOutput( + output=self._text, + ).model_dump(by_alias=True, exclude_none=True), + ) diff --git a/apps/scheduler/call/output/schema.py b/apps/scheduler/call/output/schema.py new file mode 100644 index 0000000000000000000000000000000000000000..468c07ed4c0f4e9e6ebade2b863898fa8d61f8ae --- /dev/null +++ b/apps/scheduler/call/output/schema.py @@ -0,0 +1,15 @@ +"""输出工具的数据结构""" + +from pydantic import Field + +from apps.scheduler.call.core import DataBase + + +class OutputInput(DataBase): + """输出工具的输入""" + + +class OutputOutput(DataBase): + """输出工具的输出""" + + output: str = Field(description="输出工具的输出") diff --git a/deploy/chart/euler_copilot/configs/framework/.env b/deploy/chart/euler_copilot/configs/framework/.env deleted file mode 100644 index a12d7a824c78150c751547d675a71389566f96c6..0000000000000000000000000000000000000000 --- a/deploy/chart/euler_copilot/configs/framework/.env +++ /dev/null @@ -1,93 +0,0 @@ -# DEPLOY -DEPLOY_MODE=local -COOKIE_MODE=domain - -# Redis -REDIS_HOST=redis-db.{{ .Release.Namespace }}.svc.cluster.local -REDIS_PORT=6379 -REDIS_PWD=${redis-password} - -# OIDC -{{- $loginType := .Values.login.type | default "authhub" -}} -{{- if eq $loginType "bypass" }} -DISABLE_LOGIN=False -DEFAULT_USER= {{ .Values.login.uid }} -{{- else if eq $loginType "authhub" }} -OIDC_USER_URL=http://authhub-backend-service.{{ .Release.Namespace }}.svc.cluster.local:11120/oauth2/introspect -OIDC_TOKEN_URL=http://authhub-backend-service.{{ .Release.Namespace }}.svc.cluster.local:11120/oauth2/token -OIDC_REFRESH_TOKEN_URL=http://authhub-backend-service.{{ .Release.Namespace }}.svc.cluster.local:11120/oauth2/refresh-token -OIDC_REDIRECT_URL="https://{{ default "authhub.eulercopilot.local" .Values.domain.authhub }}/oauth2/authorize?client_id=${clientId}&redirect_uri=https://{{ default "www.eulercopilot.local" .Values.domain.euler_copilot }}/api/auth/login&scope=openid offline_access&access_type=offline&response_type=code&prompt=consent&state=235345&nonce=loser" -{{- else }} -OIDC_USER_URL={{ .Values.login.oidc.user_url }} -OIDC_TOKEN_URL={{ .Values.login.oidc.token_url }} -OIDC_REFRESH_TOKEN_URL={{ .Values.login.oidc.refresh_url }} -OIDC_REDIRECT_URL={{ .Values.login.oidc.redirect }} -{{- end }} -OIDC_APP_ID=${clientId} -OIDC_APP_SECRET=${clientSecret} -EULER_LOGIN_API=https://{{ default "www.eulercopilot.local" .Values.domain.euler_copilot }}/api/auth/login -OIDC_ACCESS_TOKEN_EXPIRE_TIME=1440 -OIDC_REFRESH_TOKEN_EXPIRE_TIME=1440 -SESSION_TTL=30 - -# Logging -LOG="stdout" - -# Embedding -EMBEDDING_TYPE={{ default "openai" .Values.models.embedding.type }} -EMBEDDING_URL={{ .Values.models.embedding.url }} -EMBEDDING_KEY={{ .Values.models.embedding.key }} -EMBEDDING_MODEL={{ .Values.models.embedding.name }} - - -# RAG -RAG_HOST="http://rag-service.{{ .Release.Namespace }}.svc.cluster.local:9988" - -# FastAPI -DOMAIN={{ default "www.eulercopilot.local" .Values.domain.euler_copilot }} -JWT_KEY=${jwtKey} - -# 风控 -DETECT_TYPE= - -# CSRF -ENABLE_CSRF=False - -# MongoDB -MONGODB_HOST=mongo-db.{{ .Release.Namespace }}.svc.cluster.local -MONGODB_PORT=27017 -MONGODB_USER=euler_copilot -MONGODB_PWD=${mongo-password} -MONGODB_DATABASE=euler_copilot - -# PostgreSQL -POSTGRES_HOST=pgsql-db.{{ .Release.Namespace }}.svc.cluster.local:5432 -POSTGRES_DATABASE=postgres -POSTGRES_USER=postgres -POSTGRES_PWD=${pgsql-password} - -# MinIO -MINIO_ENDPOINT=minio-service.{{ .Release.Namespace }}.svc.cluster.local:9000 -MINIO_ACCESS_KEY=minioadmin -MINIO_SECRET_KEY=${minio-password} - -# Security -HALF_KEY1=${halfKey1} -HALF_KEY2=${halfKey2} -HALF_KEY3=${halfKey3} - -# 问答模型配置 -LLM_MAX_TOKENS={{ .Values.models.answer.max_tokens }} -LLM_MODEL={{ .Values.models.answer.name }} -LLM_URL={{ .Values.models.answer.url }}/v1 -LLM_KEY={{ .Values.models.answer.key }} -# FunctionCall模型配置 -SCHEDULER_BACKEND={{ default "ollama" .Values.models.functioncall.backend }} -SCHEDULER_MODEL={{ default .Values.models.answer.name .Values.models.functioncall.name }} -SCHEDULER_URL={{ default .Values.models.answer.url .Values.models.functioncall.url }} -SCHEDULER_API_KEY={{ default .Values.models.answer.key .Values.models.functioncall.key }} -SCHEDULER_MAX_TOKENS={{default .Values.models.answer.max_tokens .Values.models.functioncall.max_tokens }} - -# Agent -SEMANTICS_DIR=/euler-copilot-frame/apps/semantics -SQL_URL= diff --git a/deploy/chart/euler_copilot/configs/framework/config.toml b/deploy/chart/euler_copilot/configs/framework/config.toml new file mode 100644 index 0000000000000000000000000000000000000000..de196be845ef6547944f56aa5147f17b3bb2ab33 --- /dev/null +++ b/deploy/chart/euler_copilot/configs/framework/config.toml @@ -0,0 +1,65 @@ +[deploy] +mode = 'local' +cookie = 'domain' +data_dir = '/app/data' + +[login] +provider = 'authhub' +[login.settings] +host = 'https://{{ default "authhub.eulercopilot.local" .Values.domain.authhub }}' +host_inner = 'http://authhub-backend-service.{{ .Release.Namespace }}.svc.cluster.local:11120' +login_api = 'https://{{ default "www.eulercopilot.local" .Values.domain.euler_copilot }}/api/auth/login' +app_id = '${clientId}' +app_secret = '${clientSecret}' + +[fastapi] +domain = '{{ default "www.eulercopilot.local" .Values.domain.euler_copilot }}' +session_ttl = 30 +csrf = false + +[security] +half_key1 = '${halfKey1}' +half_key2 = '${halfKey2}' +half_key3 = '${halfKey3}' +jwt_key = '${jwtKey}' + +[embedding] +type = '{{ default "openai" .Values.models.embedding.type }}' +endpoint = '{{ .Values.models.embedding.endpoint }}' +api_key = '{{ .Values.models.embedding.key }}' +model = '{{ default "bge-m3" .Values.models.embedding.model }}' + +[rag] +rag_service = 'http://rag-service.{{ .Release.Namespace }}.svc.cluster.local:9988' + +[mongodb] +host = 'mongo-db.{{ .Release.Namespace }}.svc.cluster.local' +port = 27017 +user = 'euler_copilot' +password = '${mongo-password}' +database = 'euler_copilot' + +[minio] +endpoint = 'minio-service.{{ .Release.Namespace }}.svc.cluster.local:9000' +access_key = 'minioadmin' +secret_key = '${minio-password}' +secure = false + +[llm] +endpoint = '{{ .Values.models.answer.endpoint }}' +key = '{{ .Values.models.answer.key }}' +model = '{{ .Values.models.answer.name }}' +max_tokens = {{ default 8192 .Values.models.answer.maxTokens }} +temperature = {{ default 0.7 .Values.models.answer.temperature }} + +[function_call] +backend = '{{ default "ollama" .Values.models.functionCall.backend }}' +endpoint = '{{ .Values.models.functionCall.endpoint }}' +model = '{{ .Values.models.functionCall.model }}' +api_key = '{{ .Values.models.functionCall.key }}' +max_tokens = {{ default .Values.models.answer.maxTokens .Values.models.functionCall.maxTokens }} +temperature = {{ default 0.7 .Values.models.functionCall.temperature }} + +[check] +enable = false +words_list = "" diff --git a/deploy/chart/euler_copilot/configs/framework/copy-config.yaml b/deploy/chart/euler_copilot/configs/framework/copy-config.yaml index 4198e2fe1d6d5b4149acece444dddddf52a37433..44f422a71fbf2a57457880e9c70bcb82bd025984 100644 --- a/deploy/chart/euler_copilot/configs/framework/copy-config.yaml +++ b/deploy/chart/euler_copilot/configs/framework/copy-config.yaml @@ -1,6 +1,6 @@ copy: - - from: /config/.env - to: /config-rw/.env + - from: /config/config.toml + to: /config-rw/config.toml mode: uid: 1001 gid: 1001 diff --git a/deploy/chart/euler_copilot/configs/rag/.env b/deploy/chart/euler_copilot/configs/rag/.env index 5b1607ff7a0803920b75e6b49fa7b2666e0ba278..46965ad116d2da214f7ff3ef2c904dc314223cb6 100644 --- a/deploy/chart/euler_copilot/configs/rag/.env +++ b/deploy/chart/euler_copilot/configs/rag/.env @@ -25,7 +25,7 @@ TASK_RETRY_TIME=3 # Embedding EMBEDDING_TYPE={{ default "openai" .Values.models.embedding.type }} -EMBEDDING_ENDPOINT={{ .Values.models.embedding.url }}/v1/embeddings +EMBEDDING_ENDPOINT={{ .Values.models.embedding.endpoint }}/v1/embeddings EMBEDDING_API_KEY={{ .Values.models.embedding.key }} EMBEDDING_MODEL_NAME={{ .Values.models.embedding.name }} @@ -46,6 +46,6 @@ HALF_KEY3=${halfKey3} #LLM config MODEL_1_MODEL_NAME={{ .Values.models.answer.name }} MODEL_1_MODEL_TYPE=deepseek -MODEL_1_OPENAI_API_BASE={{ .Values.models.answer.url }}/v1 +MODEL_1_OPENAI_API_BASE={{ .Values.models.answer.endpoint }}/v1 MODEL_1_OPENAI_API_KEY={{ default "" .Values.models.answer.key }} -MODEL_1_MAX_TOKENS={{ default 2048 .Values.models.answer.max_tokens }} +MODEL_1_MAX_TOKENS={{ default 2048 .Values.models.answer.maxTokens }} diff --git a/deploy/chart/euler_copilot/templates/framework/framework-config.yaml b/deploy/chart/euler_copilot/templates/framework/framework-config.yaml index 1cab8899465edcbcabe22551601df3130f40ce70..7fff831b0d991b0fbb175eb8ea44086d265ec43a 100644 --- a/deploy/chart/euler_copilot/templates/framework/framework-config.yaml +++ b/deploy/chart/euler_copilot/templates/framework/framework-config.yaml @@ -5,8 +5,8 @@ metadata: name: framework-config namespace: {{ .Release.Namespace }} data: - .env: |- -{{ tpl (.Files.Get "configs/framework/.env") . | indent 4 }} + config.toml: |- +{{ tpl (.Files.Get "configs/framework/config.toml") . | indent 4 }} copy-config.yaml: |- {{ tpl (.Files.Get "configs/framework/copy-config.yaml") . | indent 4 }} {{- end -}} \ No newline at end of file diff --git a/deploy/chart/euler_copilot/templates/framework/framework-storage.yaml b/deploy/chart/euler_copilot/templates/framework/framework-storage.yaml index 039971624b5aa0df94c34ba38253693732120430..db5732acac9ad370e2d39880929e314d5a4aec52 100644 --- a/deploy/chart/euler_copilot/templates/framework/framework-storage.yaml +++ b/deploy/chart/euler_copilot/templates/framework/framework-storage.yaml @@ -8,11 +8,11 @@ metadata: spec: storageClassName: {{ default "local-path" .Values.globals.storageClass }} capacity: - storage: {{ default "5Gi" .Values.storage.framework_semantics.size }} + storage: {{ default "5Gi" .Values.storage.frameworkSemantics.size }} accessModes: - ReadWriteOnce hostPath: - path: {{ default "/home/eulercopilot/semantics" .Values.storage.framework_semantics.path }} + path: {{ default "/app/data" .Values.storage.frameworkSemantics.path }} --- apiVersion: v1 @@ -26,5 +26,5 @@ spec: - ReadWriteOnce resources: requests: - storage: {{ default "5Gi" .Values.storage.framework_semantics.size }} + storage: {{ default "5Gi" .Values.storage.frameworkSemantics.size }} {{- end -}} \ No newline at end of file diff --git a/deploy/chart/euler_copilot/templates/framework/framework.yaml b/deploy/chart/euler_copilot/templates/framework/framework.yaml index 1e36f105cfe03a8ae7bf97a657083eee72986a70..84676ae0d9c0957dc82db590017f8d9cdbbdd829 100644 --- a/deploy/chart/euler_copilot/templates/framework/framework.yaml +++ b/deploy/chart/euler_copilot/templates/framework/framework.yaml @@ -60,14 +60,14 @@ spec: env: - name: TZ value: "Asia/Shanghai" - # - name: PROD - # value: "enable" + - name: CONFIG + value: "/app/config/config.toml" volumeMounts: - - mountPath: /euler-copilot-frame/config + - mountPath: /app/config name: framework-shared - mountPath: /tmp name: framework-tmp-volume - - mountPath: /euler-copilot-frame/apps/semantics + - mountPath: /app/data name: framework-semantics-vl securityContext: readOnlyRootFilesystem: {{ default false .Values.euler_copilot.framework.readOnly }} @@ -86,12 +86,12 @@ spec: {{ toYaml .Values.euler_copilot.framework.resourceLimits | nindent 14 }} initContainers: - name: framework-copy - image: {{ .Values.euler_copilot.secret_inject.image | default (printf "%s/neocopilot/secret_inject:dev-%s" (.Values.globals.imageRegistry | default "hub.oepkgs.net") (ternary "arm" "x86" (eq (.Values.globals.arch | default "x86") "arm"))) }} + image: {{ .Values.euler_copilot.secretInject.image | default (printf "%s/neocopilot/secret_inject:dev-%s" (.Values.globals.imageRegistry | default "hub.oepkgs.net") (ternary "arm" "x86" (eq (.Values.globals.arch | default "x86") "arm"))) }} imagePullPolicy: {{ default "IfNotPresent" .Values.globals.imagePullPolicy }} volumeMounts: - - mountPath: /config/.env + - mountPath: /config/config.toml name: framework-config - subPath: .env + subPath: config.toml - mountPath: /app/config.yaml name: framework-config subPath: copy-config.yaml diff --git a/deploy/chart/euler_copilot/templates/rag/rag.yaml b/deploy/chart/euler_copilot/templates/rag/rag.yaml index 1e19c508e671d292e4cb72dccdd1d32460d9ee2b..a3672bb863be065fa2bee97892d77506c0b8f7e5 100644 --- a/deploy/chart/euler_copilot/templates/rag/rag.yaml +++ b/deploy/chart/euler_copilot/templates/rag/rag.yaml @@ -64,7 +64,7 @@ spec: {{ toYaml .Values.euler_copilot.rag.resourceLimits | nindent 14 }} initContainers: - name: rag-copy-secret - image: {{ .Values.euler_copilot.secret_inject.image | default (printf "%s/neocopilot/secret_inject:dev-%s" (.Values.globals.imageRegistry | default "hub.oepkgs.net") (ternary "arm" "x86" (eq (.Values.globals.arch | default "x86") "arm"))) }} + image: {{ .Values.euler_copilot.secretInject.image | default (printf "%s/neocopilot/secret_inject:dev-%s" (.Values.globals.imageRegistry | default "hub.oepkgs.net") (ternary "arm" "x86" (eq (.Values.globals.arch | default "x86") "arm"))) }} imagePullPolicy: {{ default "IfNotPresent" .Values.globals.imagePullPolicy }} volumeMounts: - mountPath: /config/.env diff --git a/deploy/chart/euler_copilot/templates/serviceaccount.yaml b/deploy/chart/euler_copilot/templates/serviceaccount.yaml deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/deploy/chart/euler_copilot/values.yaml b/deploy/chart/euler_copilot/values.yaml index 64524e6030e5d289e1b4b462e02bc503ccf1f433..385a7bfa79882719477ff7f8befcb1d88d5c903e 100644 --- a/deploy/chart/euler_copilot/values.yaml +++ b/deploy/chart/euler_copilot/values.yaml @@ -13,37 +13,37 @@ models: # 用于问答的大模型;需要为OpenAI兼容接口 answer: # [必填] 接口URL(无需带上“v1”后缀) - url: + endpoint: # [必填] 接口API Key;默认置空 key: # [必填] 模型名称 name: # [必填] 模型最大上下文数;建议>=8192 - ctx_length: 8192 + ctxLength: 8192 # 模型最大输出长度,建议>=2048 - max_tokens: 2048 + maxTokens: 2048 # 用于Function Call的模型;建议使用特定推理框架 - functioncall: + functionCall: # 推理框架类型,默认为ollama # 可用的框架类型:["vllm", "sglang", "ollama", "openai"] backend: # 模型地址;不填则与问答模型一致 - url: + endpoint: # API Key;不填则与问答模型一致 key: # 模型名称;不填则与问答模型一致 name: # 模型最大上下文数;不填则与问答模型一致 - ctx_length: + ctxLength: # 模型最大输出长度;不填则与问答模型一致 - max_tokens: + maxTokens: # 用于数据向量化(Embedding)的模型 embedding: # 推理框架类型,默认为openai # [必填] Embedding接口类型:["openai", "mindie"] type: # [必填] Embedding URL(需要带上“v1”后缀) - url: + endpoint: # [必填] Embedding 模型API Key key: # [必填] Embedding 模型名称 @@ -51,27 +51,12 @@ models: # 登录设置 login: - # 登录类型;默认为authhub - # 可用的类型:["authhub", "oidc", "linux", "bypass"] - type: - # 固定UID设置,仅在type为bypass时有效 - uid: - # 客户端ID设置,仅在type为authhub和oidc时有效 + # 客户端ID设置,仅在type为authhub时有效 client: # [必填] 客户端ID id: # [必填] 客户端密钥 secret: - # OIDC设置,仅在type为oidc时有效 - oidc: - # OIDC AccessToken获取地址 - token_url: - # OIDC UserToken获取地址 - user_url: - # OIDC RefreshToken地址 - refresh_url: - # OIDC登录跳转地址 - redirect: # 域名设置 domain: @@ -83,7 +68,7 @@ domain: # 存储设置 storage: # 语义接口 - framework_semantics: + frameworkSemantics: # 语义接口地址 path: # 语义接口存储大小,默认为5GB @@ -91,7 +76,7 @@ storage: euler_copilot: # 配置文件工具 - secret_inject: + secretInject: # 镜像设置;默认为hub.oepkgs.net/neocopilot/secret_inject:dev-x86 # 镜像标签:["dev-x86", "dev-arm"] image: