mirror of
https://github.com/csunny/DB-GPT.git
synced 2026-07-16 17:15:22 +00:00
feat: merge cli and shell config toml
This commit is contained in:
@@ -177,7 +177,7 @@ MINIMAX_API_KEY=sk-xxx \
|
||||
After installation, start the server with the generated profile config:
|
||||
|
||||
```bash
|
||||
cd ~/.dbgpt/DB-GPT && uv run dbgpt start webserver --config ~/.dbgpt/configs/<profile>.toml
|
||||
cd ~/.dbgpt/DB-GPT && uv run dbgpt start webserver --profile <profile>
|
||||
```
|
||||
|
||||
Then open [http://localhost:5670](http://localhost:5670).
|
||||
|
||||
@@ -168,7 +168,7 @@ MINIMAX_API_KEY=sk-xxx \
|
||||
安装完成后,使用生成的 profile 配置启动服务:
|
||||
|
||||
```bash
|
||||
cd ~/.dbgpt/DB-GPT && uv run dbgpt start webserver --config ~/.dbgpt/configs/<profile>.toml
|
||||
cd ~/.dbgpt/DB-GPT && uv run dbgpt start webserver --profile <profile>
|
||||
```
|
||||
|
||||
然后打开 [http://localhost:5670](http://localhost:5670)。
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[project]
|
||||
name = "dbgpt-acc-auto"
|
||||
version = "0.8.0rc6"
|
||||
version = "0.8.0rc7"
|
||||
description = "Add your description here"
|
||||
authors = [
|
||||
{ name = "csunny", email = "cfqcsunny@gmail.com" }
|
||||
|
||||
@@ -1 +1 @@
|
||||
version = "0.8.0rc6"
|
||||
version = "0.8.0rc7"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# https://github.com/astral-sh/uv/issues/2252#issuecomment-2624150395
|
||||
[project]
|
||||
name = "dbgpt-acc-flash-attn"
|
||||
version = "0.8.0rc6"
|
||||
version = "0.8.0rc7"
|
||||
description = "Add your description here"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.10"
|
||||
|
||||
@@ -1 +1 @@
|
||||
version = "0.8.0rc6"
|
||||
version = "0.8.0rc7"
|
||||
|
||||
94
packages/dbgpt-app/hatch_build.py
Normal file
94
packages/dbgpt-app/hatch_build.py
Normal file
@@ -0,0 +1,94 @@
|
||||
"""Hatch build hook for dbgpt-app.
|
||||
|
||||
Dynamically resolves force-include paths for wheel builds based on the build
|
||||
mode. This is necessary because source paths differ between editable installs
|
||||
(where files live at the repository root) and standard builds from sdist
|
||||
(where files have been copied into the sdist archive).
|
||||
|
||||
Problem solved:
|
||||
- editable (uv sync): root = packages/dbgpt-app/, files at ../../skills/
|
||||
- standard (from sdist): root = /tmp/extracted-sdist/, files at skills/
|
||||
Static pyproject.toml force-include cannot handle both cases.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
from hatchling.builders.hooks.plugin.interface import BuildHookInterface
|
||||
|
||||
|
||||
# Source paths relative to REPO ROOT -> wheel target paths
|
||||
# Used in editable mode where we can reach repo root via ../../
|
||||
_SKILLS_MAP = {
|
||||
"skills/csv-data-analysis": "dbgpt_app/_builtin_skills/csv-data-analysis",
|
||||
"skills/skill-creator": "dbgpt_app/_builtin_skills/skill-creator",
|
||||
"skills/financial-report-analyzer": "dbgpt_app/_builtin_skills/financial-report-analyzer",
|
||||
"skills/walmart-sales-analyzer": "dbgpt_app/_builtin_skills/walmart-sales-analyzer",
|
||||
"skills/agent-browser": "dbgpt_app/_builtin_skills/agent-browser",
|
||||
}
|
||||
|
||||
_EXAMPLES_MAP = {
|
||||
# repo_root_relative_path -> wheel_target
|
||||
"docker/examples/excel/Walmart_Sales.csv": "dbgpt_app/_builtin_examples/excel/Walmart_Sales.csv",
|
||||
"docker/examples/fin_report/pdf/2020-01-23__浙江海翔药业股份有限公司__002099__海翔药业__2019年__年度报告.pdf": "dbgpt_app/_builtin_examples/fin_report/pdf/2020-01-23__浙江海翔药业股份有限公司__002099__海翔药业__2019年__年度报告.pdf",
|
||||
}
|
||||
|
||||
_PILOT_TPL_MAP = {
|
||||
# repo_root_relative_path -> wheel_target
|
||||
"pilot/meta_data/alembic.ini": "dbgpt_app/pilot_template/meta_data/alembic.ini",
|
||||
"pilot/meta_data/alembic/README": "dbgpt_app/pilot_template/meta_data/alembic/README",
|
||||
"pilot/meta_data/alembic/env.py": "dbgpt_app/pilot_template/meta_data/alembic/env.py",
|
||||
"pilot/meta_data/alembic/script.py.mako": "dbgpt_app/pilot_template/meta_data/alembic/script.py.mako",
|
||||
"pilot/benchmark_meta_data/2025_07_27_public_500_standard_benchmark_question_list.xlsx": "dbgpt_app/pilot_template/benchmark_meta_data/2025_07_27_public_500_standard_benchmark_question_list.xlsx",
|
||||
"pilot/examples/Walmart_Sales.db": "dbgpt_app/pilot_template/examples/Walmart_Sales.db",
|
||||
}
|
||||
|
||||
# sdist force-include remaps these paths:
|
||||
# ../../skills/X -> skills/X
|
||||
# ../../docker/examples/X -> examples/X
|
||||
# ../../pilot/X -> pilot_tpl/X
|
||||
_SDIST_REMAP = {
|
||||
"skills/": "skills/", # no change
|
||||
"docker/examples/": "examples/", # strip "docker/"
|
||||
"pilot/": "pilot_tpl/", # pilot -> pilot_tpl
|
||||
}
|
||||
|
||||
|
||||
class CustomBuildHook(BuildHookInterface):
|
||||
"""Dynamically set wheel force-include paths for editable and standard builds."""
|
||||
|
||||
def initialize(self, version, build_data):
|
||||
"""Called by hatchling before building.
|
||||
|
||||
Args:
|
||||
version: "editable" for uv sync / pip install -e .
|
||||
"standard" for uv build / pip wheel
|
||||
build_data: mutable dict; set "force_include" key to inject mappings
|
||||
"""
|
||||
pkg_root = Path(self.root) # packages/dbgpt-app/
|
||||
all_mappings = {**_SKILLS_MAP, **_EXAMPLES_MAP, **_PILOT_TPL_MAP}
|
||||
force_include = {}
|
||||
|
||||
if version == "editable":
|
||||
# Editable: resolve from repo root (two levels up from packages/dbgpt-app/)
|
||||
repo_root = pkg_root.parent.parent
|
||||
for repo_rel_path, wheel_target in all_mappings.items():
|
||||
source = str(repo_root / repo_rel_path)
|
||||
if os.path.exists(source):
|
||||
force_include[source] = wheel_target
|
||||
else:
|
||||
# Standard build from sdist: files were placed at sdist-relative paths
|
||||
# by the sdist force-include config in pyproject.toml
|
||||
for repo_rel_path, wheel_target in all_mappings.items():
|
||||
sdist_path = repo_rel_path
|
||||
for prefix, replacement in _SDIST_REMAP.items():
|
||||
if repo_rel_path.startswith(prefix):
|
||||
sdist_path = replacement + repo_rel_path[len(prefix) :]
|
||||
break
|
||||
source = str(pkg_root / sdist_path)
|
||||
if os.path.exists(source):
|
||||
force_include[source] = wheel_target
|
||||
|
||||
build_data["force_include"] = force_include
|
||||
@@ -1,6 +1,6 @@
|
||||
[project]
|
||||
name = "dbgpt-app"
|
||||
version = "0.8.0rc6"
|
||||
version = "0.8.0rc7"
|
||||
description = "Add your description here"
|
||||
authors = [
|
||||
{ name = "csunny", email = "cfqcsunny@gmail.com" }
|
||||
@@ -82,21 +82,5 @@ exclude = [
|
||||
"../../pilot/benchmark_meta_data/2025_07_27_public_500_standard_benchmark_question_list.xlsx" = "pilot_tpl/benchmark_meta_data/2025_07_27_public_500_standard_benchmark_question_list.xlsx"
|
||||
"../../pilot/examples/Walmart_Sales.db" = "pilot_tpl/examples/Walmart_Sales.db"
|
||||
|
||||
[tool.hatch.build.targets.wheel.force-include]
|
||||
# Builtin skills
|
||||
"skills/csv-data-analysis" = "dbgpt_app/_builtin_skills/csv-data-analysis"
|
||||
"skills/skill-creator" = "dbgpt_app/_builtin_skills/skill-creator"
|
||||
"skills/financial-report-analyzer" = "dbgpt_app/_builtin_skills/financial-report-analyzer"
|
||||
"skills/walmart-sales-analyzer" = "dbgpt_app/_builtin_skills/walmart-sales-analyzer"
|
||||
"skills/agent-browser" = "dbgpt_app/_builtin_skills/agent-browser"
|
||||
# Builtin example files
|
||||
"examples/excel/Walmart_Sales.csv" = "dbgpt_app/_builtin_examples/excel/Walmart_Sales.csv"
|
||||
"examples/fin_report/pdf/2020-01-23__浙江海翔药业股份有限公司__002099__海翔药业__2019年__年度报告.pdf" = "dbgpt_app/_builtin_examples/fin_report/pdf/2020-01-23__浙江海翔药业股份有限公司__002099__海翔药业__2019年__年度报告.pdf"
|
||||
# Pilot workspace template files (provisioned to ~/.dbgpt/workspace/pilot/ on first startup)
|
||||
"pilot_tpl/meta_data/alembic.ini" = "dbgpt_app/pilot_template/meta_data/alembic.ini"
|
||||
"pilot_tpl/meta_data/alembic/README" = "dbgpt_app/pilot_template/meta_data/alembic/README"
|
||||
"pilot_tpl/meta_data/alembic/env.py" = "dbgpt_app/pilot_template/meta_data/alembic/env.py"
|
||||
"pilot_tpl/meta_data/alembic/script.py.mako" = "dbgpt_app/pilot_template/meta_data/alembic/script.py.mako"
|
||||
"pilot_tpl/benchmark_meta_data/2025_07_27_public_500_standard_benchmark_question_list.xlsx" = "dbgpt_app/pilot_template/benchmark_meta_data/2025_07_27_public_500_standard_benchmark_question_list.xlsx"
|
||||
"pilot_tpl/examples/Walmart_Sales.db" = "dbgpt_app/pilot_template/examples/Walmart_Sales.db"
|
||||
[tool.hatch.build.hooks.custom]
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
version = "0.8.0rc6"
|
||||
version = "0.8.0rc7"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[project]
|
||||
name = "dbgpt-client"
|
||||
version = "0.8.0rc6"
|
||||
version = "0.8.0rc7"
|
||||
description = "Add your description here"
|
||||
authors = [
|
||||
{ name = "csunny", email = "cfqcsunny@gmail.com" }
|
||||
|
||||
@@ -1 +1 @@
|
||||
version = "0.8.0rc6"
|
||||
version = "0.8.0rc7"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[project]
|
||||
name = "dbgpt"
|
||||
version = "0.8.0rc6"
|
||||
version = "0.8.0rc7"
|
||||
description = """DB-GPT is an experimental open-source project that uses localized GPT \
|
||||
large models to interact with your data and environment. With this solution, you can be\
|
||||
assured that there is no risk of data leakage, and your data is 100% private and secure.\
|
||||
|
||||
@@ -1 +1 @@
|
||||
version = "0.8.0rc6"
|
||||
version = "0.8.0rc7"
|
||||
|
||||
@@ -155,8 +155,8 @@ def _render_profile_toml(
|
||||
else:
|
||||
embedding_api_url = spec.embedding_api_url
|
||||
|
||||
data_dir = str(dbgpt_home() / "workspace" / "pilot" / "meta_data" / "dbgpt.db")
|
||||
vector_dir = str(dbgpt_home() / "workspace" / "pilot" / "data")
|
||||
data_dir = "pilot/meta_data/dbgpt.db"
|
||||
vector_dir = "pilot/data"
|
||||
|
||||
lines = [
|
||||
f"# DB-GPT configuration — profile: {spec.name}",
|
||||
|
||||
@@ -103,10 +103,10 @@ PROFILES: Dict[str, ProfileSpec] = {
|
||||
llm_model="kimi-k2",
|
||||
llm_provider="proxy/moonshot",
|
||||
llm_api_base="https://api.moonshot.cn/v1",
|
||||
embedding_model="text-embedding-v3",
|
||||
embedding_provider="proxy/tongyi",
|
||||
embedding_api_url="https://dashscope.aliyuncs.com/compatible-mode/v1/embeddings",
|
||||
embedding_env_var="DASHSCOPE_API_KEY",
|
||||
embedding_model="text-embedding-3-small",
|
||||
embedding_provider="proxy/openai",
|
||||
embedding_api_url="https://api.openai.com/v1/embeddings",
|
||||
embedding_env_var="OPENAI_API_KEY",
|
||||
),
|
||||
"qwen": ProfileSpec(
|
||||
name="qwen",
|
||||
|
||||
@@ -86,29 +86,25 @@ class TestDbgptHomeEnvVar:
|
||||
|
||||
|
||||
class TestWorkspacePaths:
|
||||
def test_render_toml_data_path_contains_workspace(self, isolated_dbgpt_home):
|
||||
def test_render_toml_data_path_is_relative(self, isolated_dbgpt_home):
|
||||
from dbgpt.cli._config import _render_profile_toml
|
||||
from dbgpt.cli._profiles import get_profile
|
||||
|
||||
spec = get_profile("openai")
|
||||
content = _render_profile_toml(spec, api_key="test-key")
|
||||
assert "workspace/pilot/meta_data/dbgpt.db" in content
|
||||
# Database and vector paths should be relative
|
||||
assert 'path = "pilot/meta_data/dbgpt.db"' in content
|
||||
assert 'persist_path = "pilot/data"' in content
|
||||
|
||||
def test_render_toml_data_path_not_absolute(self, isolated_dbgpt_home):
|
||||
from dbgpt.cli._config import _render_profile_toml
|
||||
from dbgpt.cli._profiles import get_profile
|
||||
|
||||
spec = get_profile("openai")
|
||||
content = _render_profile_toml(spec, api_key="test-key")
|
||||
assert "workspace/pilot/data" in content
|
||||
|
||||
def test_render_toml_uses_custom_home_in_data_path(self, isolated_dbgpt_home):
|
||||
from dbgpt.cli._config import _render_profile_toml
|
||||
from dbgpt.cli._profiles import get_profile
|
||||
|
||||
spec = get_profile("openai")
|
||||
content = _render_profile_toml(spec, api_key="test-key")
|
||||
# 路径中包含 isolated_dbgpt_home 的字符串
|
||||
assert str(isolated_dbgpt_home) in content
|
||||
assert "workspace/pilot/meta_data/dbgpt.db" in content
|
||||
# Paths should NOT contain workspace prefix (old absolute pattern)
|
||||
assert "workspace/pilot/meta_data" not in content
|
||||
assert "workspace/pilot/data" not in content
|
||||
|
||||
|
||||
class TestExtendedSignature:
|
||||
@@ -218,14 +214,14 @@ class TestExtendedSignature:
|
||||
|
||||
|
||||
class TestKimiEmbeddingEnvVar:
|
||||
def test_kimi_embedding_uses_dashscope_env_var(self, isolated_dbgpt_home):
|
||||
"""Kimi profile should reference DASHSCOPE_API_KEY for embeddings."""
|
||||
def test_kimi_embedding_uses_openai_env_var(self, isolated_dbgpt_home):
|
||||
"""Kimi profile should reference OPENAI_API_KEY for embeddings."""
|
||||
from dbgpt.cli._config import _render_profile_toml
|
||||
from dbgpt.cli._profiles import get_profile
|
||||
|
||||
spec = get_profile("kimi")
|
||||
content = _render_profile_toml(spec, api_key=None)
|
||||
assert "${env:DASHSCOPE_API_KEY:-sk-xxx}" in content
|
||||
assert "${env:OPENAI_API_KEY:-sk-xxx}" in content
|
||||
|
||||
def test_kimi_llm_uses_moonshot_env_var(self, isolated_dbgpt_home):
|
||||
"""Kimi profile LLM section should still reference MOONSHOT_API_KEY."""
|
||||
@@ -248,8 +244,8 @@ class TestKimiEmbeddingEnvVar:
|
||||
data = tomlkit.loads(content)
|
||||
assert data["models"]["embeddings"][0]["api_key"] == "ds-key"
|
||||
|
||||
def test_kimi_embedding_api_url_is_dashscope(self, isolated_dbgpt_home):
|
||||
"""Kimi embedding api_url should point to DashScope."""
|
||||
def test_kimi_embedding_api_url_is_openai(self, isolated_dbgpt_home):
|
||||
"""Kimi embedding api_url should point to OpenAI."""
|
||||
import tomlkit
|
||||
|
||||
from dbgpt.cli._config import _render_profile_toml
|
||||
@@ -259,7 +255,7 @@ class TestKimiEmbeddingEnvVar:
|
||||
content = _render_profile_toml(spec, api_key=None)
|
||||
data = tomlkit.loads(content)
|
||||
assert data["models"]["embeddings"][0]["api_url"] == (
|
||||
"https://dashscope.aliyuncs.com/compatible-mode/v1/embeddings"
|
||||
"https://api.openai.com/v1/embeddings"
|
||||
)
|
||||
|
||||
def test_openai_same_key_used_for_embeddings(self, isolated_dbgpt_home):
|
||||
|
||||
@@ -112,26 +112,23 @@ class TestErrorHandling:
|
||||
|
||||
|
||||
class TestKimiEmbedding:
|
||||
"""Tests for Kimi embedding configuration using DashScope."""
|
||||
"""Tests for Kimi embedding configuration using OpenAI."""
|
||||
|
||||
def test_kimi_embedding_uses_tongyi_provider(self):
|
||||
def test_kimi_embedding_uses_openai_provider(self):
|
||||
p = get_profile("kimi")
|
||||
assert p.embedding_provider == "proxy/tongyi"
|
||||
assert p.embedding_provider == "proxy/openai"
|
||||
|
||||
def test_kimi_embedding_model_is_text_embedding_v3(self):
|
||||
def test_kimi_embedding_model_is_text_embedding_3_small(self):
|
||||
p = get_profile("kimi")
|
||||
assert p.embedding_model == "text-embedding-v3"
|
||||
assert p.embedding_model == "text-embedding-3-small"
|
||||
|
||||
def test_kimi_embedding_api_url_is_dashscope(self):
|
||||
def test_kimi_embedding_api_url_is_openai(self):
|
||||
p = get_profile("kimi")
|
||||
assert (
|
||||
p.embedding_api_url
|
||||
== "https://dashscope.aliyuncs.com/compatible-mode/v1/embeddings"
|
||||
)
|
||||
assert p.embedding_api_url == "https://api.openai.com/v1/embeddings"
|
||||
|
||||
def test_kimi_has_separate_embedding_env_var(self):
|
||||
p = get_profile("kimi")
|
||||
assert p.embedding_env_var == "DASHSCOPE_API_KEY"
|
||||
assert p.embedding_env_var == "OPENAI_API_KEY"
|
||||
assert p.embedding_env_var != p.env_var
|
||||
|
||||
def test_kimi_llm_still_uses_moonshot_env_var(self):
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[project]
|
||||
name = "dbgpt-ext"
|
||||
version = "0.8.0rc6"
|
||||
version = "0.8.0rc7"
|
||||
description = "Add your description here"
|
||||
authors = [
|
||||
{ name = "csunny", email = "cfqcsunny@gmail.com" }
|
||||
|
||||
@@ -1 +1 @@
|
||||
version = "0.8.0rc6"
|
||||
version = "0.8.0rc7"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[project]
|
||||
name = "dbgpt-sandbox"
|
||||
version = "0.8.0rc6"
|
||||
version = "0.8.0rc7"
|
||||
description = "A secure sandbox execution environment for DB-GPT Agent"
|
||||
authors = [
|
||||
{ name = "csunny", email = "cfqcsunny@gmail.com" }
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[project]
|
||||
name = "dbgpt-serve"
|
||||
version = "0.8.0rc6"
|
||||
version = "0.8.0rc7"
|
||||
description = "Add your description here"
|
||||
authors = [
|
||||
{ name = "csunny", email = "cfqcsunny@gmail.com" }
|
||||
|
||||
@@ -1 +1 @@
|
||||
version = "0.8.0rc6"
|
||||
version = "0.8.0rc7"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[project]
|
||||
name = "dbgpt-mono"
|
||||
version = "0.8.0rc6"
|
||||
version = "0.8.0rc7"
|
||||
description = """DB-GPT is an experimental open-source project that uses localized GPT \
|
||||
large models to interact with your data and environment. With this solution, you can be\
|
||||
assured that there is no risk of data leakage, and your data is 100% private and secure.\
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
# ║ 3. Install uv (if not already present) ║
|
||||
# ║ 4. Clone (or update) the DB-GPT repository ║
|
||||
# ║ 5. Run `uv sync` with the extras for the chosen profile ║
|
||||
# ║ 6. Generate a user config from template ║
|
||||
# ║ 6. Generate config via dbgpt setup wizard ║
|
||||
# ║ 7. Print next-steps (start command, URL) ║
|
||||
# ║ ║
|
||||
# ║ What this script does NOT do: ║
|
||||
@@ -56,20 +56,6 @@ _source_lib() {
|
||||
_source_lib "common.sh"
|
||||
_source_lib "profiles.sh"
|
||||
|
||||
# ── Fetch template file ──────────────────────────────────────────────────────
|
||||
# Returns the local path to the template. Downloads from GitHub when needed.
|
||||
_resolve_template() {
|
||||
local name="$1"
|
||||
if [[ -n "${SCRIPT_DIR}" && -f "${SCRIPT_DIR}/templates/${name}" ]]; then
|
||||
echo "${SCRIPT_DIR}/templates/${name}"
|
||||
else
|
||||
local tmp
|
||||
tmp="$(mktemp)"
|
||||
curl -fsSL "${REMOTE_BASE}/templates/${name}" -o "${tmp}"
|
||||
echo "${tmp}"
|
||||
fi
|
||||
}
|
||||
|
||||
# ── Default values ────────────────────────────────────────────────────────────
|
||||
PROFILE=""
|
||||
INSTALL_DIR="${DBGPT_INSTALL_DIR:-${HOME}/.dbgpt}"
|
||||
@@ -79,6 +65,7 @@ USE_EXISTING_REPO="false"
|
||||
MIRROR=""
|
||||
YES="false"
|
||||
START_AFTER_INSTALL="false"
|
||||
USER_CONFIG=""
|
||||
|
||||
# ── Usage ─────────────────────────────────────────────────────────────────────
|
||||
usage() {
|
||||
@@ -89,7 +76,8 @@ Usage:
|
||||
install.sh [options]
|
||||
|
||||
Options:
|
||||
--profile <name> Deployment profile (currently: openai, kimi, minimax)
|
||||
--profile <name> Deployment profile (openai, kimi, qwen, minimax, glm, custom, default)
|
||||
--config <path> Use existing TOML config (skip config generation)
|
||||
--install-dir <path> Where to install (default: ~/.dbgpt)
|
||||
--version <git-ref> Git tag or branch to check out (default: main)
|
||||
--repo-dir <path> Use an existing local DB-GPT checkout
|
||||
@@ -99,7 +87,11 @@ Options:
|
||||
-h, --help Show this help
|
||||
|
||||
Environment variables:
|
||||
OPENAI_API_KEY Automatically injected into OpenAI config
|
||||
OPENAI_API_KEY Automatically injected into OpenAI / custom / default / kimi(embedding) config
|
||||
MOONSHOT_API_KEY Automatically injected into Kimi config
|
||||
DASHSCOPE_API_KEY Automatically injected into Qwen config
|
||||
MINIMAX_API_KEY Automatically injected into MiniMax config
|
||||
ZHIPUAI_API_KEY Automatically injected into GLM config
|
||||
DBGPT_INSTALL_DIR Override default install directory
|
||||
DBGPT_REPO_DIR Reuse an existing local DB-GPT repo
|
||||
DBGPT_VERSION Override default git ref
|
||||
@@ -117,12 +109,21 @@ Examples:
|
||||
# With Kimi / Moonshot API key
|
||||
MOONSHOT_API_KEY=sk-xxx bash install.sh --profile kimi --yes
|
||||
|
||||
# With Minimax API key
|
||||
# With Qwen / DashScope API key
|
||||
DASHSCOPE_API_KEY=sk-xxx bash install.sh --profile qwen --yes
|
||||
|
||||
# With MiniMax API key
|
||||
MINIMAX_API_KEY=sk-xxx bash install.sh --profile minimax --yes
|
||||
|
||||
# With GLM / ZhipuAI API key
|
||||
ZHIPUAI_API_KEY=sk-xxx bash install.sh --profile glm --yes
|
||||
|
||||
# Reuse your current local repo (skip clone/update)
|
||||
OPENAI_API_KEY=sk-xxx bash install.sh --profile openai --repo-dir . --yes
|
||||
|
||||
# Power-user: provide your own config file (skip config generation)
|
||||
bash install.sh --config /path/to/my.toml --profile openai --yes
|
||||
|
||||
# China mirror
|
||||
bash install.sh --profile openai --mirror china
|
||||
EOF
|
||||
@@ -165,6 +166,11 @@ parse_args() {
|
||||
START_AFTER_INSTALL="true"
|
||||
shift
|
||||
;;
|
||||
--config)
|
||||
USER_CONFIG="${2:-}"
|
||||
[[ -z "${USER_CONFIG}" ]] && die "--config requires a value"
|
||||
shift 2
|
||||
;;
|
||||
-h|--help)
|
||||
usage
|
||||
exit 0
|
||||
@@ -213,20 +219,30 @@ step_choose_profile() {
|
||||
printf '%b' "${COLOR_CYAN}Select a deployment profile:${COLOR_RESET}\n"
|
||||
printf ' 1) openai — OpenAI API proxy (recommended)\n'
|
||||
printf ' 2) kimi — Kimi 2.5 via Moonshot API\n'
|
||||
printf ' 3) minimax — MiniMax OpenAI-compatible API\n'
|
||||
printf ' 3) qwen — Qwen via DashScope API\n'
|
||||
printf ' 4) minimax — MiniMax OpenAI-compatible API\n'
|
||||
printf ' 5) glm — GLM-5 via ZhipuAI API\n'
|
||||
printf ' 6) custom — Custom OpenAI-compatible provider\n'
|
||||
printf ' 7) default — Default (OpenAI-compatible)\n'
|
||||
printf ' q) quit\n'
|
||||
printf '\n'
|
||||
printf '%b' "${COLOR_CYAN}Please select a profile by entering the corresponding number:${COLOR_RESET}\n"
|
||||
printf '\n'
|
||||
|
||||
local choice
|
||||
prompt_input "Enter choice [1]: " choice
|
||||
choice="${choice:-1}"
|
||||
|
||||
case "${choice}" in
|
||||
1|openai) PROFILE="openai" ;;
|
||||
2|kimi) PROFILE="kimi" ;;
|
||||
3|minimax) PROFILE="minimax" ;;
|
||||
q|Q) info "Installation cancelled."; exit 0 ;;
|
||||
*) die "Invalid choice: ${choice}" ;;
|
||||
1|openai) PROFILE="openai" ;;
|
||||
2|kimi) PROFILE="kimi" ;;
|
||||
3|qwen) PROFILE="qwen" ;;
|
||||
4|minimax) PROFILE="minimax" ;;
|
||||
5|glm) PROFILE="glm" ;;
|
||||
6|custom) PROFILE="custom" ;;
|
||||
7|default) PROFILE="default" ;;
|
||||
q|Q) info "Installation cancelled."; exit 0 ;;
|
||||
*) die "Invalid choice: ${choice}" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
@@ -266,7 +282,7 @@ step_apply_mirror() {
|
||||
}
|
||||
|
||||
step_prepare_dirs() {
|
||||
mkdir -p "${INSTALL_DIR}/configs"
|
||||
mkdir -p "${INSTALL_DIR}"
|
||||
}
|
||||
|
||||
resolve_repo_dir() {
|
||||
@@ -340,37 +356,46 @@ step_install_deps() {
|
||||
success "Dependencies installed."
|
||||
}
|
||||
|
||||
step_generate_config() {
|
||||
local template_name
|
||||
template_name="$(profile_template "${PROFILE}")"
|
||||
step_check_api_key() {
|
||||
local env_name
|
||||
env_name="$(profile_api_key_env "${PROFILE}")"
|
||||
|
||||
local template_path
|
||||
template_path="$(_resolve_template "${template_name}")"
|
||||
|
||||
local target_path="${INSTALL_DIR}/configs/${template_name}"
|
||||
|
||||
if [[ -f "${target_path}" ]]; then
|
||||
if ! confirm "Config already exists: ${target_path}. Overwrite?"; then
|
||||
info "Keeping existing config."
|
||||
return
|
||||
fi
|
||||
# Primary API key check
|
||||
if [[ -n "${env_name}" ]] && [[ -z "${!env_name:-}" ]]; then
|
||||
warn "Environment variable ${env_name} is not set."
|
||||
warn "The wizard will generate config with a placeholder."
|
||||
warn "Set it before starting: export ${env_name}=sk-xxx"
|
||||
fi
|
||||
|
||||
cp "${template_path}" "${target_path}"
|
||||
# Kimi special handling: also needs OPENAI_API_KEY for embeddings
|
||||
if [[ "${PROFILE}" == "kimi" ]] && [[ -z "${OPENAI_API_KEY:-}" ]]; then
|
||||
warn "Kimi profile also needs OPENAI_API_KEY for embeddings."
|
||||
warn "Set it before starting: export OPENAI_API_KEY=sk-xxx"
|
||||
fi
|
||||
}
|
||||
|
||||
# Inject API key from environment if available
|
||||
local api_key_env api_key_token
|
||||
step_generate_config() {
|
||||
info "Generating configuration via dbgpt setup..."
|
||||
|
||||
local setup_args=(dbgpt setup --profile "${PROFILE}" --yes)
|
||||
|
||||
# If user explicitly provided an API key via environment, pass it through
|
||||
local api_key_env
|
||||
api_key_env="$(profile_api_key_env "${PROFILE}")"
|
||||
api_key_token="$(profile_api_key_token "${PROFILE}")"
|
||||
if [[ -n "${api_key_env}" && -n "${!api_key_env:-}" ]]; then
|
||||
setup_args+=(--api-key "${!api_key_env}")
|
||||
fi
|
||||
|
||||
if [[ -n "${api_key_env}" && -n "${api_key_token}" ]]; then
|
||||
local api_key_value="${!api_key_env:-}"
|
||||
if [[ -n "${api_key_value}" ]]; then
|
||||
replace_token "${target_path}" "${api_key_token}" "${api_key_value}"
|
||||
success "API key injected from \$${api_key_env}."
|
||||
else
|
||||
warn "\$${api_key_env} is not set. Please edit ${target_path} and fill in your API key before starting."
|
||||
fi
|
||||
(
|
||||
cd "${REPO_DIR}"
|
||||
run "Running dbgpt setup..." uv run "${setup_args[@]}"
|
||||
)
|
||||
|
||||
local config_path="${HOME}/.dbgpt/configs/${PROFILE}.toml"
|
||||
if [[ -f "${config_path}" ]]; then
|
||||
success "Config written to ${config_path}"
|
||||
else
|
||||
die "Config generation failed — ${config_path} not found"
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -389,9 +414,7 @@ step_validate() {
|
||||
|
||||
step_print_summary() {
|
||||
local repo_dir="${REPO_DIR}"
|
||||
local template_name
|
||||
template_name="$(profile_template "${PROFILE}")"
|
||||
local config_path="${INSTALL_DIR}/configs/${template_name}"
|
||||
local config_path="${HOME}/.dbgpt/configs/${PROFILE}.toml"
|
||||
|
||||
printf '%b' "
|
||||
${COLOR_GREEN}════════════════════════════════════════════════════════════${COLOR_RESET}
|
||||
@@ -404,11 +427,11 @@ ${COLOR_GREEN}══════════════════════
|
||||
|
||||
${COLOR_CYAN}Next steps:${COLOR_RESET}
|
||||
|
||||
1. Review / edit your config (set API key if not done):
|
||||
1. Review / Edit your config (set Custom API key Or BaseURL if not done):
|
||||
${COLOR_YELLOW}${config_path}${COLOR_RESET}
|
||||
|
||||
2. Start DB-GPT:
|
||||
${COLOR_YELLOW}cd \"${repo_dir}\" && uv run dbgpt start webserver --config \"${config_path}\"${COLOR_RESET}
|
||||
${COLOR_YELLOW}cd \"${repo_dir}\" && uv run dbgpt start webserver --profile ${PROFILE}${COLOR_RESET}
|
||||
|
||||
3. Open your browser:
|
||||
${COLOR_YELLOW}http://localhost:5670${COLOR_RESET}
|
||||
@@ -422,14 +445,14 @@ step_start_if_requested() {
|
||||
fi
|
||||
|
||||
local repo_dir="${REPO_DIR}"
|
||||
local template_name
|
||||
template_name="$(profile_template "${PROFILE}")"
|
||||
local config_path="${INSTALL_DIR}/configs/${template_name}"
|
||||
|
||||
info "Starting DB-GPT server..."
|
||||
(
|
||||
cd "${repo_dir}"
|
||||
exec uv run dbgpt start webserver --config "${config_path}"
|
||||
if [[ -n "${USER_CONFIG:-}" ]]; then
|
||||
exec uv run dbgpt start webserver --config "${USER_CONFIG}"
|
||||
else
|
||||
exec uv run dbgpt start webserver --profile "${PROFILE}"
|
||||
fi
|
||||
)
|
||||
}
|
||||
|
||||
@@ -452,18 +475,39 @@ BANNER
|
||||
parse_args "$@"
|
||||
step_check_platform
|
||||
step_ensure_base_commands
|
||||
step_choose_profile
|
||||
validate_profile "${PROFILE}"
|
||||
step_apply_mirror
|
||||
step_prepare_dirs
|
||||
resolve_repo_dir
|
||||
step_ensure_uv
|
||||
step_clone_or_update_repo
|
||||
step_install_deps
|
||||
step_generate_config
|
||||
step_validate
|
||||
step_print_summary
|
||||
step_start_if_requested
|
||||
|
||||
if [[ -n "${USER_CONFIG:-}" ]]; then
|
||||
[[ -f "${USER_CONFIG}" ]] || die "Config file not found: ${USER_CONFIG}"
|
||||
info "Using user-provided config: ${USER_CONFIG}"
|
||||
if [[ -z "${PROFILE}" ]]; then
|
||||
PROFILE="openai"
|
||||
info "No --profile specified with --config; defaulting to 'openai' for dependency extras."
|
||||
fi
|
||||
validate_profile "${PROFILE}"
|
||||
step_apply_mirror
|
||||
step_prepare_dirs
|
||||
resolve_repo_dir
|
||||
step_ensure_uv
|
||||
step_clone_or_update_repo
|
||||
step_install_deps
|
||||
step_validate
|
||||
step_print_summary
|
||||
step_start_if_requested
|
||||
else
|
||||
step_choose_profile
|
||||
validate_profile "${PROFILE}"
|
||||
step_apply_mirror
|
||||
step_prepare_dirs
|
||||
resolve_repo_dir
|
||||
step_ensure_uv
|
||||
step_clone_or_update_repo
|
||||
step_install_deps
|
||||
step_check_api_key
|
||||
step_generate_config
|
||||
step_validate
|
||||
step_print_summary
|
||||
step_start_if_requested
|
||||
fi
|
||||
}
|
||||
|
||||
main "$@"
|
||||
|
||||
@@ -88,29 +88,3 @@ confirm() {
|
||||
[[ "${answer}" =~ ^[Yy]$ ]]
|
||||
}
|
||||
|
||||
# ── String helpers ────────────────────────────────────────────────────────────
|
||||
|
||||
# Replace a placeholder token inside a file with a real value.
|
||||
# Usage: replace_token <file> <token> <value>
|
||||
# Example: replace_token config.toml "__OPENAI_API_KEY__" "sk-xxx"
|
||||
replace_token() {
|
||||
local file="$1"
|
||||
local token="$2"
|
||||
local value="$3"
|
||||
|
||||
if [[ ! -f "${file}" ]]; then
|
||||
die "replace_token: file not found: ${file}"
|
||||
fi
|
||||
|
||||
# Use python3 for safe in-place replacement (avoids sed portability issues
|
||||
# between macOS and Linux). We pass values through environment variables to
|
||||
# avoid shell-injection via triple-quote escapes.
|
||||
_RT_FILE="${file}" _RT_TOKEN="${token}" _RT_VALUE="${value}" python3 -c "
|
||||
import os
|
||||
from pathlib import Path
|
||||
p = Path(os.environ['_RT_FILE'])
|
||||
text = p.read_text()
|
||||
text = text.replace(os.environ['_RT_TOKEN'], os.environ['_RT_VALUE'])
|
||||
p.write_text(text)
|
||||
"
|
||||
}
|
||||
|
||||
@@ -3,18 +3,17 @@
|
||||
#
|
||||
# Each profile maps to:
|
||||
# 1. A set of uv extras (fed to `uv sync --extra ...`)
|
||||
# 2. A config template under templates/
|
||||
# 3. The official config file path in the repo (for reference)
|
||||
# 2. The API key environment variable name
|
||||
|
||||
# ── Validation ────────────────────────────────────────────────────────────────
|
||||
|
||||
# Currently supported profiles. Extend this list when adding new profiles.
|
||||
readonly SUPPORTED_PROFILES="openai kimi minimax"
|
||||
readonly SUPPORTED_PROFILES="openai kimi qwen minimax glm custom default"
|
||||
|
||||
validate_profile() {
|
||||
local profile="$1"
|
||||
case "${profile}" in
|
||||
openai|kimi|minimax) ;;
|
||||
openai|kimi|qwen|minimax|glm|custom|default) ;;
|
||||
*)
|
||||
die "Unsupported profile: ${profile}. Supported profiles: ${SUPPORTED_PROFILES}"
|
||||
;;
|
||||
@@ -44,6 +43,15 @@ proxy_openai
|
||||
rag
|
||||
storage_chromadb
|
||||
dbgpts
|
||||
EOF
|
||||
;;
|
||||
qwen)
|
||||
cat <<'EOF'
|
||||
base
|
||||
proxy_openai
|
||||
rag
|
||||
storage_chromadb
|
||||
dbgpts
|
||||
EOF
|
||||
;;
|
||||
minimax)
|
||||
@@ -53,6 +61,33 @@ proxy_openai
|
||||
rag
|
||||
storage_chromadb
|
||||
dbgpts
|
||||
EOF
|
||||
;;
|
||||
glm)
|
||||
cat <<'EOF'
|
||||
base
|
||||
proxy_openai
|
||||
rag
|
||||
storage_chromadb
|
||||
dbgpts
|
||||
EOF
|
||||
;;
|
||||
custom)
|
||||
cat <<'EOF'
|
||||
base
|
||||
proxy_openai
|
||||
rag
|
||||
storage_chromadb
|
||||
dbgpts
|
||||
EOF
|
||||
;;
|
||||
default)
|
||||
cat <<'EOF'
|
||||
base
|
||||
proxy_openai
|
||||
rag
|
||||
storage_chromadb
|
||||
dbgpts
|
||||
EOF
|
||||
;;
|
||||
*)
|
||||
@@ -61,31 +96,6 @@ EOF
|
||||
esac
|
||||
}
|
||||
|
||||
# ── Config template name ──────────────────────────────────────────────────────
|
||||
# Returns the template filename (relative to templates/ dir).
|
||||
|
||||
profile_template() {
|
||||
local profile="$1"
|
||||
case "${profile}" in
|
||||
openai) echo "openai.toml" ;;
|
||||
kimi) echo "kimi.toml" ;;
|
||||
minimax) echo "minimax.toml" ;;
|
||||
*) die "No template defined for profile: ${profile}" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# ── Repo config path (for display / fallback) ────────────────────────────────
|
||||
|
||||
profile_repo_config() {
|
||||
local profile="$1"
|
||||
case "${profile}" in
|
||||
openai) echo "configs/dbgpt-proxy-openai.toml" ;;
|
||||
kimi) echo "configs/dbgpt-proxy-moonshot.toml" ;;
|
||||
minimax) echo "configs/dbgpt-proxy-openai.toml" ;;
|
||||
*) die "No repo config path defined for profile: ${profile}" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# ── Environment variable name for API key ─────────────────────────────────────
|
||||
|
||||
profile_api_key_env() {
|
||||
@@ -93,19 +103,11 @@ profile_api_key_env() {
|
||||
case "${profile}" in
|
||||
openai) echo "OPENAI_API_KEY" ;;
|
||||
kimi) echo "MOONSHOT_API_KEY" ;;
|
||||
qwen) echo "DASHSCOPE_API_KEY" ;;
|
||||
minimax) echo "MINIMAX_API_KEY" ;;
|
||||
*) echo "" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# ── Placeholder token in config template ──────────────────────────────────────
|
||||
|
||||
profile_api_key_token() {
|
||||
local profile="$1"
|
||||
case "${profile}" in
|
||||
openai) echo "__OPENAI_API_KEY__" ;;
|
||||
kimi) echo "__MOONSHOT_API_KEY__" ;;
|
||||
minimax) echo "__MINIMAX_API_KEY__" ;;
|
||||
glm) echo "ZHIPUAI_API_KEY" ;;
|
||||
custom) echo "OPENAI_API_KEY" ;;
|
||||
default) echo "OPENAI_API_KEY" ;;
|
||||
*) echo "" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
# DB-GPT Quick Install - Kimi 2.5 Profile
|
||||
# Generated by install.sh. Edit the __PLACEHOLDERS__ below before starting.
|
||||
|
||||
[system]
|
||||
language = "${env:DBGPT_LANG:-en}"
|
||||
api_keys = []
|
||||
|
||||
# Server Configurations
|
||||
[service.web]
|
||||
host = "0.0.0.0"
|
||||
port = 5670
|
||||
|
||||
[service.web.database]
|
||||
type = "sqlite"
|
||||
path = "pilot/meta_data/dbgpt.db"
|
||||
|
||||
[rag.storage]
|
||||
[rag.storage.vector]
|
||||
type = "chroma"
|
||||
persist_path = "pilot/data"
|
||||
|
||||
# Model Configurations
|
||||
[models]
|
||||
[[models.llms]]
|
||||
name = "kimi-k2-turbo-preview"
|
||||
provider = "proxy/moonshot"
|
||||
api_base = "https://api.moonshot.ai/v1"
|
||||
api_key = "__MOONSHOT_API_KEY__"
|
||||
|
||||
[[models.embeddings]]
|
||||
name = "text-embedding-3-small"
|
||||
provider = "proxy/openai"
|
||||
api_url = "https://api.openai.com/v1/embeddings"
|
||||
api_key = "__MOONSHOT_API_KEY__"
|
||||
@@ -1,34 +0,0 @@
|
||||
# DB-GPT Quick Install - OpenAI Profile
|
||||
# Generated by install.sh. Edit the __PLACEHOLDERS__ below before starting.
|
||||
|
||||
[system]
|
||||
language = "${env:DBGPT_LANG:-en}"
|
||||
api_keys = []
|
||||
|
||||
# Server Configurations
|
||||
[service.web]
|
||||
host = "0.0.0.0"
|
||||
port = 5670
|
||||
|
||||
[service.web.database]
|
||||
type = "sqlite"
|
||||
path = "pilot/meta_data/dbgpt.db"
|
||||
|
||||
[rag.storage]
|
||||
[rag.storage.vector]
|
||||
type = "chroma"
|
||||
persist_path = "pilot/data"
|
||||
|
||||
# Model Configurations
|
||||
[models]
|
||||
[[models.llms]]
|
||||
name = "gpt-4o"
|
||||
provider = "proxy/openai"
|
||||
api_base = "https://api.openai.com/v1"
|
||||
api_key = "__OPENAI_API_KEY__"
|
||||
|
||||
[[models.embeddings]]
|
||||
name = "text-embedding-3-small"
|
||||
provider = "proxy/openai"
|
||||
api_url = "https://api.openai.com/v1/embeddings"
|
||||
api_key = "__OPENAI_API_KEY__"
|
||||
Reference in New Issue
Block a user