diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 3ca80641c..040d6bc20 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -20,22 +20,22 @@ repos:
stages: [commit]
pass_filenames: false
args: []
- - id: python-test-doc
- name: Python Doc Test
- entry: make test-doc
- language: system
- exclude: '^dbgpt/app/static/|^web/'
- types: [python]
- stages: [commit]
- pass_filenames: false
- args: []
- - id: python-lint-mypy
- name: Python Lint mypy
- entry: make mypy
- language: system
- exclude: '^dbgpt/app/static/|^web/'
- types: [python]
- stages: [commit]
- pass_filenames: false
- args: []
-
+# - id: python-test-doc
+# name: Python Doc Test
+# entry: make test-doc
+# language: system
+# exclude: '^dbgpt/app/static/|^web/'
+# types: [python]
+# stages: [commit]
+# pass_filenames: false
+# args: []
+# - id: python-lint-mypy
+# name: Python Lint mypy
+# entry: make mypy
+# language: system
+# exclude: '^dbgpt/app/static/|^web/'
+# types: [python]
+# stages: [commit]
+# pass_filenames: false
+# args: []
+#
diff --git a/Makefile b/Makefile
index a6c7163cd..5cfa23186 100644
--- a/Makefile
+++ b/Makefile
@@ -91,7 +91,7 @@ test: $(VENV)/.testenv ## Run unit tests
.PHONY: test-doc
test-doc: $(VENV)/.testenv ## Run doctests
# -k "not test_" skips tests that are not doctests.
- $(VENV_BIN)/pytest --doctest-modules -k "not test_" dbgpt/core
+ $(VENV_BIN)/pytest --doctest-modules -k "not test_" packages
.PHONY: mypy
mypy: $(VENV)/.testenv ## Run mypy checks
diff --git a/docker/compose_examples/ha-cluster-docker-compose.yml b/docker/compose_examples/ha-cluster-docker-compose.yml
index 9398e5adb..f0899626f 100644
--- a/docker/compose_examples/ha-cluster-docker-compose.yml
+++ b/docker/compose_examples/ha-cluster-docker-compose.yml
@@ -154,6 +154,25 @@ services:
restart: unless-stopped
networks:
- dbgptnet
+ apiserver:
+ image: eosphorosai/dbgpt-openai:latest
+ command: dbgpt start apiserver -c /root/configs/ha-model-cluster.toml
+ environment:
+ - CONTROLLER_ADDR=http://controller-1:8000,http://controller-2:8000
+ depends_on:
+ - controller-1
+ - controller-2
+ - llm-worker
+ - embedding-worker
+ volumes:
+ - ../../:/app
+ - ./conf/ha-model-cluster.toml:/root/configs/ha-model-cluster.toml
+ ports:
+ - 8100:8100/tcp
+ restart: unless-stopped
+ networks:
+ - dbgptnet
+ ipc: host
volumes:
dbgpt-init-scripts:
dbgpt-myql-db:
diff --git a/docs/docs/api/chat.md b/docs/docs/api/chat.md
index 36b161183..4980fc970 100644
--- a/docs/docs/api/chat.md
+++ b/docs/docs/api/chat.md
@@ -22,6 +22,7 @@ import TabItem from '@theme/TabItem';
values={[
{label: 'Curl', value: 'curl'},
{label: 'Python', value: 'python'},
+ {label: 'Python(OpenAI SDK)', value: 'openai-sdk'},
]
}>
@@ -54,8 +55,40 @@ async for data in client.chat_stream(
print(data)
```
+
+
+
+```python
+from openai import OpenAI
+DBGPT_API_KEY = "dbgpt"
+
+client = OpenAI(
+ api_key=DBGPT_API_KEY,
+ base_url="http://localhost:5670/api/v2"
+)
+response = client.chat.completions.create(
+ model="gpt-4o",
+ messages=[
+ {
+ "role": "user",
+ "content": "Hello",
+ },
+ ],
+ extra_body={
+ "chat_mode": "chat_normal",
+ },
+ stream=True,
+ max_tokens=2048,
+)
+
+for chunk in response:
+ delta_content = chunk.choices[0].delta.content
+ print(delta_content, end="", flush=True)
+```
+
+
### Chat Completion Stream Response
```commandline
data: {"id": "chatcmpl-ba6fb52e-e5b2-11ee-b031-acde48001122", "model": "gpt-4o", "choices": [{"index": 0, "delta": {"role": "assistant", "content": "Hello"}}]}
@@ -110,6 +143,8 @@ from dbgpt_client import Client
DBGPT_API_KEY = "dbgpt"
client = Client(api_key=DBGPT_API_KEY)
response = await client.chat(model="gpt-4o" ,messages="hello")
+print(response)
+await client.aclose()
```
diff --git a/docs/docs/api/datasource.md b/docs/docs/api/datasource.md
index ee2cdc5f6..ef46edd44 100644
--- a/docs/docs/api/datasource.md
+++ b/docs/docs/api/datasource.md
@@ -21,6 +21,7 @@ import TabItem from '@theme/TabItem';
values={[
{label: 'Curl', value: 'curl'},
{label: 'Python', value: 'python'},
+ {label: 'Python(OpenAI SDK)', value: 'openai-sdk'},
]
}>
@@ -56,6 +57,40 @@ res = client.chat(
)
```
+
+
+
+```python
+from openai import OpenAI
+
+DBGPT_API_KEY = "dbgpt"
+DB_NAME="{your_db_name}"
+
+client = OpenAI(
+ api_key=DBGPT_API_KEY,
+ base_url="http://localhost:5670/api/v2"
+)
+response = client.chat.completions.create(
+ model="gpt-4o",
+ messages=[
+ {
+ "role": "user",
+ "content": "Hello",
+ },
+ ],
+ extra_body={
+ "chat_mode": "chat_data",
+ "chat_param": DB_NAME,
+ },
+ stream=True,
+ max_tokens=2048,
+)
+
+for chunk in response:
+ delta_content = chunk.choices[0].delta.content
+ print(delta_content, end="", flush=True)
+```
+
#### Chat Completion Response
diff --git a/docs/docs/api/flow.md b/docs/docs/api/flow.md
index e4695c65b..4174285e8 100644
--- a/docs/docs/api/flow.md
+++ b/docs/docs/api/flow.md
@@ -21,6 +21,7 @@ import TabItem from '@theme/TabItem';
values={[
{label: 'Curl', value: 'curl'},
{label: 'Python', value: 'python'},
+ {label: 'Python(OpenAI SDK)', value: 'openai-sdk'},
]
}>
@@ -34,7 +35,7 @@ curl -X POST "http://localhost:5670/api/v2/chat/completions" \
-H "Authorization: Bearer $DBGPT_API_KEY" \
-H "accept: application/json" \
-H "Content-Type: application/json" \
- -d "{\"messages\":\"Hello\",\"model\":\"chatgpt_proxyllm\", \"chat_mode\": \"chat_flow\", \"chat_param\": \"$FLOW_ID\"}"
+ -d "{\"messages\":\"Hello\",\"model\":\"gpt-4o\", \"chat_mode\": \"chat_flow\", \"chat_param\": \"$FLOW_ID\"}"
```
@@ -50,18 +51,53 @@ FLOW_ID="{YOUR_FLOW_ID}"
client = Client(api_key=DBGPT_API_KEY)
async for data in client.chat_stream(
messages="Introduce AWEL",
- model="chatgpt_proxyllm",
+ model="gpt-4o",
chat_mode="chat_flow",
chat_param=FLOW_ID
):
print(data)
```
+
+
+
+
+```python
+from openai import OpenAI
+
+DBGPT_API_KEY = "dbgpt"
+FLOW_ID="{YOUR_FLOW_ID}"
+
+client = OpenAI(
+ api_key=DBGPT_API_KEY,
+ base_url="http://localhost:5670/api/v2"
+)
+response = client.chat.completions.create(
+ model="gpt-4o",
+ messages=[
+ {
+ "role": "user",
+ "content": "Hello",
+ },
+ ],
+ extra_body={
+ "chat_mode": "chat_flow",
+ "chat_param": FLOW_ID,
+ },
+ stream=True,
+ max_tokens=2048,
+)
+
+for chunk in response:
+ delta_content = chunk.choices[0].delta.content
+ print(delta_content, end="", flush=True)
+```
+
#### Chat Completion Stream Response
```commandline
-data: {"id": "579f8862-fc4b-481e-af02-a127e6d036c8", "created": 1710918094, "model": "chatgpt_proxyllm", "choices": [{"index": 0, "delta": {"role": "assistant", "content": "\n\n"}}]}
+data: {"id": "579f8862-fc4b-481e-af02-a127e6d036c8", "created": 1710918094, "model": "gpt-4o", "choices": [{"index": 0, "delta": {"role": "assistant", "content": "\n\n"}}]}
```
### Create Flow
diff --git a/docs/docs/api/introduction.md b/docs/docs/api/introduction.md
index be99631d8..1a2883fa2 100644
--- a/docs/docs/api/introduction.md
+++ b/docs/docs/api/introduction.md
@@ -2,7 +2,7 @@
This is the introduction to the DB-GPT API documentation. You can interact with the API through HTTP requests from any language, via our official Python Client bindings.
-# Authentication
+## Authentication
The DB-GPT API uses API keys for authentication. Visit your API Keys page to retrieve the API key you'll use in your requests.
Production requests must be routed through your own backend server where your API key can be securely loaded from an environment variable or key management service.
@@ -34,10 +34,18 @@ API_KEYS - The list of API keys that are allowed to access the API. Each of the
API_KEYS=dbgpt
```
-## Installation
+## Using the DB-GPT official Python Client
+
If you use Python, you should install the official DB-GPT Client package from PyPI:
```bash
-pip install "dbgpt[client]>=0.5.2"
+pip install "dbgpt-client>=0.7.1rc0"
```
+## Using the OpenAI Python SDK
+
+In some chat cases, you can use the OpenAI Python SDK to interact with the DB-GPT API. The DB-GPT API is compatible with the OpenAI API.
+
+```bash
+pip install openai
+```
\ No newline at end of file
diff --git a/docs/docs/api/knowledge.md b/docs/docs/api/knowledge.md
index e0e9876df..35af366bb 100644
--- a/docs/docs/api/knowledge.md
+++ b/docs/docs/api/knowledge.md
@@ -21,6 +21,7 @@ import TabItem from '@theme/TabItem';
values={[
{label: 'Curl', value: 'curl'},
{label: 'Python', value: 'python'},
+ {label: 'Python(OpenAI SDK)', value: 'openai-sdk'},
]
}>
@@ -57,6 +58,41 @@ async for data in client.chat_stream(
print(data)
```
+
+
+
+
+```python
+from openai import OpenAI
+
+DBGPT_API_KEY = "dbgpt"
+SPACE_NAME="{YOUR_SPACE_NAME}"
+
+client = OpenAI(
+ api_key=DBGPT_API_KEY,
+ base_url="http://localhost:5670/api/v2"
+)
+response = client.chat.completions.create(
+ model="gpt-4o",
+ messages=[
+ {
+ "role": "user",
+ "content": "Hello",
+ },
+ ],
+ extra_body={
+ "chat_mode": "chat_knowledge",
+ "chat_param": SPACE_NAME,
+ },
+ stream=True,
+ max_tokens=2048,
+)
+
+for chunk in response:
+ delta_content = chunk.choices[0].delta.content
+ print(delta_content, end="", flush=True)
+```
+
#### Chat Completion Response
diff --git a/docs/docs/application/advanced_tutorial/api.md b/docs/docs/application/advanced_tutorial/api.md
index 53cc524ab..0a6870b45 100644
--- a/docs/docs/application/advanced_tutorial/api.md
+++ b/docs/docs/application/advanced_tutorial/api.md
@@ -13,11 +13,13 @@ In the DB-GPT project, we defined a service-oriented multi-model management fram
```python
import openai
-openai.api_key = "EMPTY"
-openai.api_base = "http://127.0.0.1:8100/api/v1"
-model = "vicuna-13b-v1.5"
+model = "Qwen/QwQ-32B"
-completion = openai.ChatCompletion.create(
+client = openai.OpenAI(
+ api_key="EMPTY",
+ base_url="http://127.0.0.1:8100/api/v1",
+)
+completion = client.chat.completions.create(
model=model,
messages=[{"role": "user", "content": "hello"}]
)
diff --git a/docs/docs/installation/advanced_usage/Llamacpp_server.md b/docs/docs/installation/advanced_usage/Llamacpp_server.md
index 63c74719a..bbbc389e0 100644
--- a/docs/docs/installation/advanced_usage/Llamacpp_server.md
+++ b/docs/docs/installation/advanced_usage/Llamacpp_server.md
@@ -6,13 +6,37 @@ which supports concurrent requests and continuous batching inference.
## Install dependencies
-```bash
-pip install -e ".[llama_cpp_server]"
-```
-If you want to accelerate the inference speed, and you have a GPU, you can install the following dependencies:
+You can add the extra `--extra "llama_cpp_server"` to install the dependencies needed for llama-cpp server.
+
+If you has a Nvidia GPU, you can enable the CUDA support by setting the environment variable `CMAKE_ARGS="-DGGML_CUDA=ON"`.
```bash
-CMAKE_ARGS="-DGGML_CUDA=ON" pip install -e ".[llama_cpp_server]"
+# Use uv to install dependencies needed for llama-cpp
+# Install core dependencies and select desired extensions
+CMAKE_ARGS="-DGGML_CUDA=ON" uv sync --all-packages \
+--extra "base" \
+--extra "hf" \
+--extra "cuda121" \
+--extra "llama_cpp_server" \
+--extra "rag" \
+--extra "storage_chromadb" \
+--extra "quant_bnb" \
+--extra "dbgpts"
+```
+
+Otherwise, run the following command to install dependencies without CUDA support.
+
+```bash
+# Use uv to install dependencies needed for llama-cpp
+# Install core dependencies and select desired extensions
+uv sync --all-packages \
+--extra "base" \
+--extra "hf" \
+--extra "llama_cpp_server" \
+--extra "rag" \
+--extra "storage_chromadb" \
+--extra "quant_bnb" \
+--extra "dbgpts"
```
## Download the model
@@ -25,16 +49,17 @@ wget https://huggingface.co/Qwen/Qwen2.5-0.5B-Instruct-GGUF/resolve/main/qwen2.5
## Modify configuration file
-In the `.env` configuration file, modify the inference type of the model to start `llama.cpp` inference.
+Just modify you config file to use the `llama.cpp.server` provider.
-```bash
-LLM_MODEL=qwen2.5-0.5b-instruct
-LLM_MODEL_PATH=/tmp/qwen2.5-0.5b-instruct-q4_k_m.gguf
-MODEL_TYPE=llama_cpp_server
-```
-
-## Start the DB-GPT server
-
-```bash
-python dbgpt/app/dbgpt_server.py
+```toml
+# Model Configurations
+[models]
+[[models.llms]]
+name = "qwen2.5-0.5b-instruct-q4_k_m.gguf"
+provider = "llama.cpp.server"
+# If not provided, the model will be downloaded from the Hugging Face model hub
+# uncomment the following line to specify the model path in the local file system
+# https://huggingface.co/bartowski/DeepSeek-R1-Distill-Qwen-1.5B-GGUF
+# path = "the-model-path-in-the-local-file-system"
+path = "/tmp/qwen2.5-0.5b-instruct-q4_k_m.gguf"
```
\ No newline at end of file
diff --git a/docs/docs/installation/advanced_usage/More_proxyllms.md b/docs/docs/installation/advanced_usage/More_proxyllms.md
index c50f6f9b0..956ecf810 100644
--- a/docs/docs/installation/advanced_usage/More_proxyllms.md
+++ b/docs/docs/installation/advanced_usage/More_proxyllms.md
@@ -1,7 +1,10 @@
-# ProxyLLMs
-DB-GPT can be deployed on servers with lower hardware through proxy LLMs, and now dbgpt support many proxy llms, such as OpenAI、Azure、Wenxin、Tongyi、Zhipu and so on.
+# Proxy LLMs
-### Proxy model
+DB-GPT can be deployed on servers with lower hardware requirements through proxy LLMs. DB-GPT supports many proxy LLMs, such as OpenAI, Azure, DeepSeek, Ollama, and more.
+
+## Installation and Configuration
+
+Installing DB-GPT with proxy LLM support requires using the `uv` package manager for a faster and more stable dependency management experience.
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
@@ -9,156 +12,274 @@ import TabItem from '@theme/TabItem';
-
- Install dependencies
+
-```python
-pip install -e ".[openai]"
+### Install Dependencies
+
+```bash
+# Use uv to install dependencies needed for OpenAI proxy
+uv sync --all-packages \
+--extra "base" \
+--extra "proxy_openai" \
+--extra "rag" \
+--extra "storage_chromadb" \
+--extra "dbgpts"
```
-Download embedding model
+### Configure OpenAI
-```python
-cd DB-GPT
-mkdir models and cd models
-git clone https://huggingface.co/GanymedeNil/text2vec-large-chinese
+Edit the `configs/dbgpt-proxy-openai.toml` configuration file to specify your OpenAI API key:
+
+```toml
+# Model Configurations
+[models]
+[[models.llms]]
+name = "gpt-3.5-turbo"
+provider = "proxy/openai"
+api_key = "your-openai-api-key"
+# Optional: To use GPT-4, change the name to "gpt-4" or "gpt-4-turbo"
+
+[[models.embeddings]]
+name = "text-embedding-ada-002"
+provider = "proxy/openai"
+api_key = "your-openai-api-key"
```
-Configure the proxy and modify LLM_MODEL, PROXY_API_URL and API_KEY in the `.env`file
+### Run Webserver
-```python
-# .env
-LLM_MODEL=chatgpt_proxyllm
-PROXY_API_KEY={your-openai-sk}
-PROXY_SERVER_URL=https://api.openai.com/v1/chat/completions
-# If you use gpt-4
-# PROXYLLM_BACKEND=gpt-4
+```bash
+uv run dbgpt start webserver --config configs/dbgpt-proxy-openai.toml
```
+
+
-
- Install dependencies
+### Install Dependencies
-```python
-pip install -e ".[openai]"
+```bash
+# Use uv to install dependencies needed for Azure OpenAI proxy
+uv sync --all-packages \
+--extra "base" \
+--extra "proxy_openai" \
+--extra "rag" \
+--extra "storage_chromadb" \
+--extra "dbgpts"
```
-Download embedding model
+### Configure Azure OpenAI
-```python
-cd DB-GPT
-mkdir models and cd models
-git clone https://huggingface.co/GanymedeNil/text2vec-large-chinese # change this to other embedding model if needed.
+Edit the `configs/dbgpt-proxy-azure.toml` configuration file to specify your Azure OpenAI settings:
+
+```toml
+# Model Configurations
+[models]
+[[models.llms]]
+name = "gpt-35-turbo" # or your deployment model name
+provider = "proxy/openai"
+api_base = "https://your-resource-name.openai.azure.com/"
+api_key = "your-azure-openai-api-key"
+api_version = "2023-05-15" # or your specific API version
+api_type = "azure"
```
-Configure the proxy and modify LLM_MODEL, PROXY_API_URL and API_KEY in the `.env`file
+### Run Webserver
-```python
-# .env
-LLM_MODEL=proxyllm
-PROXY_API_KEY=xxxx
-PROXY_API_BASE=https://xxxxxx.openai.azure.com/
-PROXY_API_TYPE=azure
-PROXY_SERVER_URL=xxxx
-PROXY_API_VERSION=2023-05-15
-PROXYLLM_BACKEND=gpt-35-turbo
-API_AZURE_DEPLOYMENT=xxxx[deployment_name]
+```bash
+uv run dbgpt start webserver --config configs/dbgpt-proxy-azure.toml
```
+
+
-
-Install dependencies
+### Install Dependencies
-```python
-pip install dashscope
+```bash
+# Use uv to install dependencies needed for DeepSeek proxy
+uv sync --all-packages \
+--extra "base" \
+--extra "proxy_openai" \
+--extra "rag" \
+--extra "storage_chromadb" \
+--extra "dbgpts"
```
-Download embedding model
+### Configure DeepSeek
-```python
-cd DB-GPT
-mkdir models and cd models
+Edit the `configs/dbgpt-proxy-deepseek.toml` configuration file to specify your DeepSeek API key:
-# embedding model
-git clone https://huggingface.co/GanymedeNil/text2vec-large-chinese
-or
-git clone https://huggingface.co/moka-ai/m3e-large
+```toml
+# Model Configurations
+[models]
+[[models.llms]]
+# name = "deepseek-chat"
+name = "deepseek-reasoner"
+provider = "proxy/deepseek"
+api_key = "your-deepseek-api-key"
```
-Configure the proxy and modify LLM_MODEL, PROXY_API_URL and API_KEY in the `.env`file
+### Run Webserver
-```python
-# .env
-# Aliyun tongyiqianwen
-LLM_MODEL=tongyi_proxyllm
-TONGYI_PROXY_API_KEY={your-tongyi-sk}
-PROXY_SERVER_URL={your_service_url}
+```bash
+uv run dbgpt start webserver --config configs/dbgpt-proxy-deepseek.toml
```
+
-
-Install dependencies
+
-```python
-pip install zhipuai
+### Install Dependencies
+
+```bash
+# Use uv to install dependencies needed for Ollama proxy
+uv sync --all-packages \
+--extra "base" \
+--extra "proxy_ollama" \
+--extra "rag" \
+--extra "storage_chromadb" \
+--extra "dbgpts"
```
-Download embedding model
+### Configure Ollama
-```python
-cd DB-GPT
-mkdir models and cd models
+Edit the `configs/dbgpt-proxy-ollama.toml` configuration file to specify your Ollama API base:
-# embedding model
-git clone https://huggingface.co/GanymedeNil/text2vec-large-chinese
-or
-git clone https://huggingface.co/moka-ai/m3e-large
+```toml
+# Model Configurations
+[models]
+[[models.llms]]
+name = "llama3" # or any other model available in your Ollama instance
+provider = "proxy/ollama"
+api_base = "http://localhost:11434" # your-ollama-api-base
+
+[[models.embeddings]]
+name = "nomic-embed-text" # or any other embedding model in Ollama
+provider = "proxy/ollama"
+api_base = "http://localhost:11434" # your-ollama-api-base
```
-Configure the proxy and modify LLM_MODEL, PROXY_API_URL and API_KEY in the `.env`file
+### Run Webserver
-```python
-# .env
-LLM_MODEL=zhipu_proxyllm
-PROXY_SERVER_URL={your_service_url}
-ZHIPU_MODEL_VERSION={version}
-ZHIPU_PROXY_API_KEY={your-zhipu-sk}
+```bash
+uv run dbgpt start webserver --config configs/dbgpt-proxy-ollama.toml
```
+
+
-
+### Install Dependencies
-Download embedding model
-
-```python
-cd DB-GPT
-mkdir models and cd models
-
-# embedding model
-git clone https://huggingface.co/GanymedeNil/text2vec-large-chinese
-or
-git clone https://huggingface.co/moka-ai/m3e-large
+```bash
+# Use uv to install dependencies needed for Aliyun Qwen (Tongyi) proxy
+uv sync --all-packages \
+--extra "base" \
+--extra "proxy_tongyi" \
+--extra "rag" \
+--extra "storage_chromadb" \
+--extra "dbgpts"
```
-Configure the proxy and modify LLM_MODEL, MODEL_VERSION, API_KEY and API_SECRET in the `.env`file
+### Configure Qwen
-```python
-# .env
-LLM_MODEL=wenxin_proxyllm
-WEN_XIN_MODEL_VERSION={version} # ERNIE-Bot or ERNIE-Bot-turbo
-WEN_XIN_API_KEY={your-wenxin-sk}
-WEN_XIN_API_SECRET={your-wenxin-sct}
+Create or edit a configuration file (e.g., `configs/dbgpt-proxy-tongyi.toml`):
+
+```toml
+# Model Configurations
+[models]
+[[models.llms]]
+name = "qwen-turbo" # or qwen-max, qwen-plus
+provider = "proxy/tongyi"
+api_key = "your-tongyi-api-key"
```
+
+### Run Webserver
+
+```bash
+uv run dbgpt start webserver --config configs/dbgpt-proxy-tongyi.toml
+```
+
+
+
+
+### Install Dependencies
+
+```bash
+# Use uv to install dependencies needed for Zhipu (ChatGLM) proxy
+uv sync --all-packages \
+--extra "base" \
+--extra "proxy_zhipu" \
+--extra "rag" \
+--extra "storage_chromadb" \
+--extra "dbgpts"
+```
+
+### Configure ChatGLM
+
+Create or edit a configuration file (e.g., `configs/dbgpt-proxy-zhipu.toml`):
+
+```toml
+# Model Configurations
+[models]
+[[models.llms]]
+name = "glm-4" # or other available model versions
+provider = "proxy/zhipu"
+api_key = "your-zhipu-api-key"
+```
+
+### Run Webserver
+
+```bash
+uv run dbgpt start webserver --config configs/dbgpt-proxy-zhipu.toml
+```
+
+
+
+
+### Install Dependencies
+
+```bash
+# Use uv to install dependencies needed for Baidu WenXin proxy
+uv sync --all-packages \
+--extra "base" \
+--extra "proxy_openai" \
+--extra "rag" \
+--extra "storage_chromadb" \
+--extra "dbgpts"
+```
+
+### Configure WenXin
+
+Create or edit a configuration file (e.g., `configs/dbgpt-proxy-wenxin.toml`):
+
+```toml
+# Model Configurations
+[models]
+[[models.llms]]
+name = "ERNIE-Bot-4.0" # or ernie-bot, ernie-bot-turbo
+provider = "proxy/wenxin"
+api_key = "your-wenxin-api-key"
+api_secret = "your-wenxin-api-secret"
+```
+
+### Run Webserver
+
+```bash
+uv run dbgpt start webserver --config configs/dbgpt-proxy-wenxin.toml
+```
+
-
:::info note
+If you are in the China region, you can add `--index-url=https://pypi.tuna.tsinghua.edu.cn/simple` at the end of the `uv sync` command for faster package downloads.
+:::
-⚠️ Be careful not to overwrite the contents of the `.env` configuration file
-:::
\ No newline at end of file
+## Visit Website
+
+After starting the webserver, open your browser and visit [`http://localhost:5670`](http://localhost:5670)
\ No newline at end of file
diff --git a/docs/docs/installation/advanced_usage/OpenAI_SDK_call.md b/docs/docs/installation/advanced_usage/OpenAI_SDK_call.md
index be0cd95dd..1a4446e57 100644
--- a/docs/docs/installation/advanced_usage/OpenAI_SDK_call.md
+++ b/docs/docs/installation/advanced_usage/OpenAI_SDK_call.md
@@ -38,9 +38,27 @@ Chat
curl http://127.0.0.1:8100/api/v1/chat/completions \
-H "Authorization: Bearer EMPTY" \
-H "Content-Type: application/json" \
--d '{"model": "glm-4-9b-chat", "messages": [{"role": "user", "content": "hello"}]}'
+-d '{
+ "model": "Qwen/Qwen2.5-Coder-32B-Instruct",
+ "messages": [{"role": "user", "content": "hello"}]
+}'
```
+:::tip
+Stream Chat
+:::
+```bash
+curl http://127.0.0.1:8100/api/v1/chat/completions \
+-H "Authorization: Bearer EMPTY" \
+-H "Content-Type: application/json" \
+-d '{
+ "model": "Qwen/Qwen2.5-Coder-32B-Instruct",
+ "stream": true,
+ "messages": [{"role": "user", "content": "hello"}]
+}'
+```
+
+
:::tip
Embedding
:::
@@ -49,7 +67,7 @@ curl http://127.0.0.1:8100/api/v1/embeddings \
-H "Authorization: Bearer EMPTY" \
-H "Content-Type: application/json" \
-d '{
- "model": "text2vec",
+ "model": "BAAI/bge-large-zh-v1.5",
"input": "Hello world!"
}'
```
@@ -59,11 +77,13 @@ curl http://127.0.0.1:8100/api/v1/embeddings \
```bash
import openai
-openai.api_key = "EMPTY"
-openai.api_base = "http://127.0.0.1:8100/api/v1"
-model = "glm-4-9b-chat"
+model = "Qwen/Qwen2.5-Coder-32B-Instruct"
-completion = openai.ChatCompletion.create(
+client = openai.OpenAI(
+ api_key="EMPTY",
+ base_url="http://127.0.0.1:8100/api/v1",
+)
+completion = client.chat.completions.create(
model=model,
messages=[{"role": "user", "content": "hello"}]
)
diff --git a/docs/docs/installation/advanced_usage/ollama.md b/docs/docs/installation/advanced_usage/ollama.md
index f432d7054..3e1ac9386 100644
--- a/docs/docs/installation/advanced_usage/ollama.md
+++ b/docs/docs/installation/advanced_usage/ollama.md
@@ -20,22 +20,31 @@ ollama pull nomic-embed-text
3. install ollama package.
```bash
-pip install ollama
+# Use uv to install dependencies needed for Ollama proxy
+uv sync --all-packages \
+--extra "base" \
+--extra "proxy_ollama" \
+--extra "rag" \
+--extra "storage_chromadb" \
+--extra "dbgpts"
```
-### Use ollama proxy model in DB-GPT `.env` file
+### Configure the model
-```bash
-LLM_MODEL=ollama_proxyllm
-PROXY_SERVER_URL=http://127.0.0.1:11434
-PROXYLLM_BACKEND="qwen:0.5b"
-PROXY_API_KEY=not_used
-EMBEDDING_MODEL=proxy_ollama
-proxy_ollama_proxy_server_url=http://127.0.0.1:11434
-proxy_ollama_proxy_backend="nomic-embed-text:latest"
-```
+Modify you toml config file to use the `ollama` provider.
-### run dbgpt server
-```bash
-python dbgpt/app/dbgpt_server.py
+```toml
+# Model Configurations
+[models]
+[[models.llms]]
+name = "qwen:0.5b"
+provider = "proxy/ollama"
+api_base = "http://localhost:11434"
+api_key = ""
+
+[[models.embeddings]]
+name = "bge-m3:latest"
+provider = "proxy/ollama"
+api_url = "http://localhost:11434"
+api_key = ""
```
\ No newline at end of file
diff --git a/docs/docs/installation/advanced_usage/vLLM_inference.md b/docs/docs/installation/advanced_usage/vLLM_inference.md
index cb9783340..5d6d578c5 100644
--- a/docs/docs/installation/advanced_usage/vLLM_inference.md
+++ b/docs/docs/installation/advanced_usage/vLLM_inference.md
@@ -2,19 +2,35 @@
DB-GPT supports [vLLM](https://github.com/vllm-project/vllm) inference, a fast and easy-to-use LLM inference and service library.
## Install dependencies
-`vLLM` is an optional dependency in DB-GPT. You can install it manually through the following command.
+`vLLM` is an optional dependency in DB-GPT. You can install it by adding the extra `--extra "vllm"` when installing dependencies.
```bash
-pip install -e ".[vllm]"
+# Use uv to install dependencies needed for vllm
+# Install core dependencies and select desired extensions
+uv sync --all-packages \
+--extra "base" \
+--extra "hf" \
+--extra "cuda121" \
+--extra "vllm" \
+--extra "rag" \
+--extra "storage_chromadb" \
+--extra "quant_bnb" \
+--extra "dbgpts"
```
## Modify configuration file
-In the `.env` configuration file, modify the inference type of the model to start `vllm` inference.
-```bash
-LLM_MODEL=glm-4-9b-chat
-MODEL_TYPE=vllm
-# modify the following configuration if you possess GPU resources
-# gpu_memory_utilization=0.8
+
+After installing the dependencies, you can modify your configuration file to use the `vllm` provider.
+
+```toml
+# Model Configurations
+[models]
+[[models.llms]]
+name = "THUDM/glm-4-9b-chat-hf"
+provider = "vllm"
+# If not provided, the model will be downloaded from the Hugging Face model hub
+# uncomment the following line to specify the model path in the local file system
+# path = "the-model-path-in-the-local-file-system"
```
For more information about the list of models supported by `vLLM`, please refer to the [vLLM supported model document](https://docs.vllm.ai/en/latest/models/supported_models.html#supported-models).
diff --git a/docs/docs/quickstart.md b/docs/docs/quickstart.md
index d635cb40f..63e39e5f4 100644
--- a/docs/docs/quickstart.md
+++ b/docs/docs/quickstart.md
@@ -85,6 +85,12 @@ uv sync --all-packages \
--extra "dbgpts" \
--index-url=https://pypi.tuna.tsinghua.edu.cn/simple
```
+And we recommend you to configure you pypi index to environment variable `UV_INDEX_URL`
+example:
+```bash
+echo "export UV_INDEX_URL=https://pypi.tuna.tsinghua.edu.cn/simple" >> ~/.bashrc
+```
+
This tutorial assumes that you can establish network communication with the dependency download sources.
:::
diff --git a/packages/dbgpt-accelerator/dbgpt-acc-auto/pyproject.toml b/packages/dbgpt-accelerator/dbgpt-acc-auto/pyproject.toml
index 38505a241..9a58dee2e 100644
--- a/packages/dbgpt-accelerator/dbgpt-acc-auto/pyproject.toml
+++ b/packages/dbgpt-accelerator/dbgpt-acc-auto/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "dbgpt-acc-auto"
-version = "0.7.0"
+version = "0.7.1"
description = "Add your description here"
authors = [
{ name = "csunny", email = "cfqcsunny@gmail.com" }
diff --git a/packages/dbgpt-accelerator/dbgpt-acc-auto/src/dbgpt_acc_auto/_version.py b/packages/dbgpt-accelerator/dbgpt-acc-auto/src/dbgpt_acc_auto/_version.py
index 7a0c9fe2d..691a48ccc 100644
--- a/packages/dbgpt-accelerator/dbgpt-acc-auto/src/dbgpt_acc_auto/_version.py
+++ b/packages/dbgpt-accelerator/dbgpt-acc-auto/src/dbgpt_acc_auto/_version.py
@@ -1 +1 @@
-version = "0.7.0"
+version = "0.7.1"
diff --git a/packages/dbgpt-accelerator/dbgpt-acc-flash-attn/pyproject.toml b/packages/dbgpt-accelerator/dbgpt-acc-flash-attn/pyproject.toml
index ba4834e6c..c03c90da0 100644
--- a/packages/dbgpt-accelerator/dbgpt-acc-flash-attn/pyproject.toml
+++ b/packages/dbgpt-accelerator/dbgpt-acc-flash-attn/pyproject.toml
@@ -2,7 +2,7 @@
# https://github.com/astral-sh/uv/issues/2252#issuecomment-2624150395
[project]
name = "dbgpt-acc-flash-attn"
-version = "0.7.0"
+version = "0.7.1"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.10"
diff --git a/packages/dbgpt-accelerator/dbgpt-acc-flash-attn/src/dbgpt_acc_flash_attn/_version.py b/packages/dbgpt-accelerator/dbgpt-acc-flash-attn/src/dbgpt_acc_flash_attn/_version.py
index 7a0c9fe2d..691a48ccc 100644
--- a/packages/dbgpt-accelerator/dbgpt-acc-flash-attn/src/dbgpt_acc_flash_attn/_version.py
+++ b/packages/dbgpt-accelerator/dbgpt-acc-flash-attn/src/dbgpt_acc_flash_attn/_version.py
@@ -1 +1 @@
-version = "0.7.0"
+version = "0.7.1"
diff --git a/packages/dbgpt-app/pyproject.toml b/packages/dbgpt-app/pyproject.toml
index 19f49f960..a6b4a01b5 100644
--- a/packages/dbgpt-app/pyproject.toml
+++ b/packages/dbgpt-app/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "dbgpt-app"
-version = "0.7.0"
+version = "0.7.1"
description = "Add your description here"
authors = [
{ name = "csunny", email = "cfqcsunny@gmail.com" }
diff --git a/packages/dbgpt-app/src/dbgpt_app/_version.py b/packages/dbgpt-app/src/dbgpt_app/_version.py
index 7a0c9fe2d..691a48ccc 100644
--- a/packages/dbgpt-app/src/dbgpt_app/_version.py
+++ b/packages/dbgpt-app/src/dbgpt_app/_version.py
@@ -1 +1 @@
-version = "0.7.0"
+version = "0.7.1"
diff --git a/packages/dbgpt-client/pyproject.toml b/packages/dbgpt-client/pyproject.toml
index aa3dccf77..753d2ee2b 100644
--- a/packages/dbgpt-client/pyproject.toml
+++ b/packages/dbgpt-client/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "dbgpt-client"
-version = "0.7.0"
+version = "0.7.1"
description = "Add your description here"
authors = [
{ name = "csunny", email = "cfqcsunny@gmail.com" }
@@ -9,7 +9,17 @@ license = "MIT"
readme = "README.md"
requires-python = ">= 3.10"
-dependencies = ["dbgpt-serve"]
+dependencies = [
+ "dbgpt[client,cli]",
+ "dbgpt_ext",
+ "shortuuid",
+ # 2.0.29 not support duckdb now
+ "SQLAlchemy>=2.0.25, <2.0.29",
+ # for cache
+ "msgpack",
+ # for AWEL operator serialization
+ "cloudpickle",
+]
[project.urls]
Homepage = "https://github.com/eosphoros-ai/DB-GPT"
diff --git a/packages/dbgpt-client/src/dbgpt_client/_version.py b/packages/dbgpt-client/src/dbgpt_client/_version.py
index 7a0c9fe2d..691a48ccc 100644
--- a/packages/dbgpt-client/src/dbgpt_client/_version.py
+++ b/packages/dbgpt-client/src/dbgpt_client/_version.py
@@ -1 +1 @@
-version = "0.7.0"
+version = "0.7.1"
diff --git a/packages/dbgpt-client/src/dbgpt_client/evaluation.py b/packages/dbgpt-client/src/dbgpt_client/evaluation.py
index 586113856..0a09e1ba6 100644
--- a/packages/dbgpt-client/src/dbgpt_client/evaluation.py
+++ b/packages/dbgpt-client/src/dbgpt_client/evaluation.py
@@ -1,14 +1,41 @@
"""Evaluation."""
-from typing import List
+from typing import List, Optional
+from dbgpt._private.pydantic import BaseModel, Field
from dbgpt.core.interface.evaluation import EvaluationResult
from dbgpt.core.schema.api import Result
-from dbgpt_serve.evaluate.api.schemas import EvaluateServeRequest
from .client import Client, ClientException
+class EvaluateServeRequest(BaseModel):
+ evaluate_code: Optional[str] = Field(None, description="evaluation code")
+ scene_key: Optional[str] = Field(None, description="evaluation scene key")
+ scene_value: Optional[str] = Field(None, description="evaluation scene value")
+ datasets_name: Optional[str] = Field(None, description="evaluation datasets name")
+ datasets: Optional[List[dict]] = Field(None, description="datasets")
+ evaluate_metrics: Optional[List[str]] = Field(
+ None, description="evaluation metrics"
+ )
+ context: Optional[dict] = Field(None, description="The context of the evaluate")
+ user_name: Optional[str] = Field(None, description="user name")
+ user_id: Optional[str] = Field(None, description="user id")
+ sys_code: Optional[str] = Field(None, description="system code")
+ parallel_num: Optional[int] = Field(None, description="system code")
+ state: Optional[str] = Field(None, description="evaluation state")
+ result: Optional[str] = Field(None, description="evaluation result")
+ storage_type: Optional[str] = Field(None, comment="datasets storage type")
+ average_score: Optional[str] = Field(None, description="evaluation average score")
+ log_info: Optional[str] = Field(None, description="evaluation log_info")
+ gmt_create: Optional[str] = Field(None, description="create time")
+ gmt_modified: Optional[str] = Field(None, description="create time")
+
+
+class EvaluateServeResponse(EvaluateServeRequest):
+ """EvaluateServeResponse."""
+
+
async def run_evaluation(
client: Client, request: EvaluateServeRequest
) -> List[EvaluationResult]:
diff --git a/packages/dbgpt-core/pyproject.toml b/packages/dbgpt-core/pyproject.toml
index 8169399a1..ca9ebdea7 100644
--- a/packages/dbgpt-core/pyproject.toml
+++ b/packages/dbgpt-core/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "dbgpt"
-version = "0.7.0"
+version = "0.7.1"
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.\
@@ -83,6 +83,7 @@ framework = [
"gTTS==2.3.1",
"pymysql",
"jsonschema",
+ "python-jsonpath",
# TODO move transformers to default
"tokenizers>=0.14",
"alembic==1.12.0",
diff --git a/packages/dbgpt-core/src/dbgpt/_version.py b/packages/dbgpt-core/src/dbgpt/_version.py
index 7a0c9fe2d..691a48ccc 100644
--- a/packages/dbgpt-core/src/dbgpt/_version.py
+++ b/packages/dbgpt-core/src/dbgpt/_version.py
@@ -1 +1 @@
-version = "0.7.0"
+version = "0.7.1"
diff --git a/packages/dbgpt-core/src/dbgpt/core/interface/llm.py b/packages/dbgpt-core/src/dbgpt/core/interface/llm.py
index 66ec91459..c0dde4c5f 100644
--- a/packages/dbgpt-core/src/dbgpt/core/interface/llm.py
+++ b/packages/dbgpt-core/src/dbgpt/core/interface/llm.py
@@ -249,6 +249,34 @@ class MediaContent:
"""Create a MediaContent object from thinking."""
return cls(type="thinking", object=MediaObject(data=text, format="text"))
+ @classmethod
+ def parse_content(
+ cls,
+ content: Union[
+ "MediaContent", List["MediaContent"], Dict[str, Any], List[Dict[str, Any]]
+ ],
+ ) -> Union["MediaContent", List["MediaContent"]]:
+ def _parse_dict(obj_dict: Union[MediaContent, Dict[str, Any]]) -> MediaContent:
+ if isinstance(obj_dict, MediaContent):
+ return obj_dict
+ content_object = obj_dict.get("object")
+ if not content_object:
+ raise ValueError(f"Failed to parse {obj_dict}, no object found")
+ if isinstance(content_object, dict):
+ content_object = MediaObject(
+ data=content_object.get("data"),
+ format=content_object.get("format", "text"),
+ )
+ return cls(
+ type=obj_dict.get("type", "text"),
+ object=content_object,
+ )
+
+ if isinstance(content, list):
+ return [_parse_dict(c) for c in content]
+ else:
+ return _parse_dict(content)
+
def get_text(self) -> str:
"""Get the text."""
if self.type == MediaContentType.TEXT:
@@ -322,7 +350,11 @@ class ModelOutput:
self,
error_code: int,
text: Optional[str] = None,
- content: Optional[MediaContent] = None,
+ content: Optional[
+ Union[
+ MediaContent, List[MediaContent], Dict[str, Any], List[Dict[str, Any]]
+ ]
+ ] = None,
**kwargs,
):
if text is not None and content is not None:
@@ -330,7 +362,7 @@ class ModelOutput:
elif text is not None:
self.content = MediaContent.build_text(text)
elif content is not None:
- self.content = content
+ self.content = MediaContent.parse_content(content)
else:
raise ValueError("Must pass either text or content")
self.error_code = error_code
diff --git a/packages/dbgpt-core/src/dbgpt/core/interface/message.py b/packages/dbgpt-core/src/dbgpt/core/interface/message.py
index 312b3ef87..620b42368 100755
--- a/packages/dbgpt-core/src/dbgpt/core/interface/message.py
+++ b/packages/dbgpt-core/src/dbgpt/core/interface/message.py
@@ -3,6 +3,7 @@
from __future__ import annotations
from abc import ABC, abstractmethod
+from collections.abc import Iterable
from datetime import datetime
from typing import Callable, Dict, List, Optional, Tuple, Union, cast
@@ -14,6 +15,8 @@ from dbgpt.core.interface.storage import (
StorageItem,
)
+from ..schema.types import ChatCompletionMessageParam
+
class BaseMessage(BaseModel, ABC):
"""Message object."""
@@ -179,9 +182,145 @@ class ModelMessage(BaseModel):
)
return result
+ @staticmethod
+ def _parse_openai_system_message(
+ message: ChatCompletionMessageParam,
+ ) -> List[ModelMessage]:
+ """Parse system message from OpenAI format.
+
+ Args:
+ message (ChatCompletionMessageParam): The OpenAI message
+
+ Returns:
+ List[ModelMessage]: The model messages
+ """
+ content = message["content"]
+ result = []
+ if isinstance(content, str):
+ result.append(
+ ModelMessage(role=ModelMessageRoleType.SYSTEM, content=content)
+ )
+ elif isinstance(content, Iterable):
+ for item in content:
+ if isinstance(item, str):
+ result.append(
+ ModelMessage(role=ModelMessageRoleType.SYSTEM, content=item)
+ )
+ elif isinstance(item, dict) and "type" in item:
+ type = item["type"]
+ if type == "text" and "text" in item:
+ result.append(
+ ModelMessage(
+ role=ModelMessageRoleType.SYSTEM, content=item["text"]
+ )
+ )
+ else:
+ raise ValueError(
+ f"Unknown message type: {item} of system message"
+ )
+ else:
+ raise ValueError(f"Unknown message type: {item} of system message")
+ else:
+ raise ValueError(f"Unknown content type: {message} of system message")
+ return result
+
+ @staticmethod
+ def _parse_openai_user_message(
+ message: ChatCompletionMessageParam,
+ ) -> List[ModelMessage]:
+ """Parse user message from OpenAI format.
+
+ Args:
+ message (ChatCompletionMessageParam): The OpenAI message
+
+ Returns:
+ List[ModelMessage]: The model messages
+ """
+ result = []
+ content = message["content"]
+ if isinstance(content, str):
+ result.append(
+ ModelMessage(role=ModelMessageRoleType.HUMAN, content=content)
+ )
+ elif isinstance(content, Iterable):
+ for item in content:
+ if isinstance(item, str):
+ result.append(
+ ModelMessage(role=ModelMessageRoleType.HUMAN, content=item)
+ )
+ elif isinstance(item, dict) and "type" in item:
+ type = item["type"]
+ if type == "text" and "text" in item:
+ result.append(
+ ModelMessage(
+ role=ModelMessageRoleType.HUMAN, content=item["text"]
+ )
+ )
+ elif type == "image_url":
+ raise ValueError("Image message is not supported now")
+ elif type == "input_audio":
+ raise ValueError("Input audio message is not supported now")
+ else:
+ raise ValueError(
+ f"Unknown message type: {item} of human message"
+ )
+ else:
+ raise ValueError(f"Unknown message type: {item} of humman message")
+ else:
+ raise ValueError(f"Unknown content type: {message} of humman message")
+ return result
+
+ @staticmethod
+ def _parse_assistant_message(
+ message: ChatCompletionMessageParam,
+ ) -> List[ModelMessage]:
+ """Parse assistant message from OpenAI format.
+
+ Args:
+ message (ChatCompletionMessageParam): The OpenAI message
+
+ Returns:
+ List[ModelMessage]: The model messages
+ """
+ result = []
+ content = message["content"]
+ if isinstance(content, str):
+ result.append(ModelMessage(role=ModelMessageRoleType.AI, content=content))
+ elif isinstance(content, Iterable):
+ for item in content:
+ if isinstance(item, str):
+ result.append(
+ ModelMessage(role=ModelMessageRoleType.AI, content=item)
+ )
+ elif isinstance(item, dict) and "type" in item:
+ type = item["type"]
+ if type == "text" and "text" in item:
+ result.append(
+ ModelMessage(
+ role=ModelMessageRoleType.AI, content=item["text"]
+ )
+ )
+ elif type == "refusal" and "refusal" in item:
+ result.append(
+ ModelMessage(
+ role=ModelMessageRoleType.AI, content=item["refusal"]
+ )
+ )
+ else:
+ raise ValueError(
+ f"Unknown message type: {item} of assistant message"
+ )
+ else:
+ raise ValueError(
+ f"Unknown message type: {item} of assistant message"
+ )
+ else:
+ raise ValueError(f"Unknown content type: {message} of assistant message")
+ return result
+
@staticmethod
def from_openai_messages(
- messages: Union[str, List[Dict[str, str]]],
+ messages: Union[str, List[ChatCompletionMessageParam]],
) -> List["ModelMessage"]:
"""Openai message format to current ModelMessage format."""
if isinstance(messages, str):
@@ -189,19 +328,18 @@ class ModelMessage(BaseModel):
result = []
for message in messages:
msg_role = message["role"]
- content = message["content"]
if msg_role == "system":
- result.append(
- ModelMessage(role=ModelMessageRoleType.SYSTEM, content=content)
- )
+ result.extend(ModelMessage._parse_openai_system_message(message))
elif msg_role == "user":
- result.append(
- ModelMessage(role=ModelMessageRoleType.HUMAN, content=content)
- )
+ result.extend(ModelMessage._parse_openai_user_message(message))
elif msg_role == "assistant":
- result.append(
- ModelMessage(role=ModelMessageRoleType.AI, content=content)
+ result.extend(ModelMessage._parse_assistant_message(message))
+ elif msg_role == "function":
+ raise ValueError(
+ "Function role is not supported in ModelMessage format"
)
+ elif msg_role == "tool":
+ raise ValueError("Tool role is not supported in ModelMessage format")
else:
raise ValueError(f"Unknown role: {msg_role}")
return result
diff --git a/packages/dbgpt-core/src/dbgpt/core/schema/api.py b/packages/dbgpt-core/src/dbgpt/core/schema/api.py
index 76fbf88d0..35bd15cc1 100644
--- a/packages/dbgpt-core/src/dbgpt/core/schema/api.py
+++ b/packages/dbgpt-core/src/dbgpt/core/schema/api.py
@@ -7,6 +7,8 @@ from typing import Any, Dict, Generic, List, Literal, Optional, TypeVar, Union
from dbgpt._private.pydantic import BaseModel, Field, model_to_dict
+from .types import ChatCompletionMessageParam
+
T = TypeVar("T")
@@ -47,14 +49,13 @@ class Result(BaseModel, Generic[T]):
return model_to_dict(self, **kwargs)
-_ChatCompletionMessageType = Union[str, List[Dict[str, str]], List[str]]
-
-
class APIChatCompletionRequest(BaseModel):
"""Chat completion request entity."""
model: str = Field(..., description="Model name")
- messages: _ChatCompletionMessageType = Field(..., description="User input messages")
+ messages: Union[str, List[ChatCompletionMessageParam]] = Field(
+ ..., description="User input messages"
+ )
temperature: Optional[float] = Field(
0.7,
description="What sampling temperature to use, between 0 and 2. Higher values "
diff --git a/packages/dbgpt-core/src/dbgpt/core/schema/types.py b/packages/dbgpt-core/src/dbgpt/core/schema/types.py
new file mode 100644
index 000000000..de56f849c
--- /dev/null
+++ b/packages/dbgpt-core/src/dbgpt/core/schema/types.py
@@ -0,0 +1,214 @@
+"""Adapted from OpenAI API types.
+
+All types are adapted from the OpenAI API types. They will be used to provide the OpenAI
+compatible types for the DB-GPT apiserver.
+
+Note: the are not the internal types of the DB-GPT.
+"""
+
+from typing import Iterable, Optional, TypeAlias, Union
+
+from typing_extensions import Literal, Required, TypedDict
+
+
+class ChatCompletionContentPartTextParam(TypedDict, total=False):
+ text: Required[str]
+ """The text content."""
+
+ type: Required[Literal["text"]]
+ """The type of the content part."""
+
+
+class ImageURL(TypedDict, total=False):
+ url: Required[str]
+ """Either a URL of the image or the base64 encoded image data."""
+
+ detail: Literal["auto", "low", "high"]
+ """Specifies the detail level of the image.
+
+ Learn more in the
+ [Vision guide](https://platform.openai.com/docs/guides/vision#low-or-high-fidelity-image-understanding).
+ """
+
+
+class ChatCompletionContentPartImageParam(TypedDict, total=False):
+ image_url: Required[ImageURL]
+
+ type: Required[Literal["image_url"]]
+ """The type of the content part."""
+
+
+class InputAudio(TypedDict, total=False):
+ data: Required[str]
+ """Base64 encoded audio data."""
+
+ format: Required[Literal["wav", "mp3"]]
+ """The format of the encoded audio data. Currently supports "wav" and "mp3"."""
+
+
+class ChatCompletionContentPartInputAudioParam(TypedDict, total=False):
+ input_audio: Required[InputAudio]
+
+ type: Required[Literal["input_audio"]]
+ """The type of the content part. Always `input_audio`."""
+
+
+class Function(TypedDict, total=False):
+ arguments: Required[str]
+ """
+ The arguments to call the function with, as generated by the model in JSON
+ format. Note that the model does not always generate valid JSON, and may
+ hallucinate parameters not defined by your function schema. Validate the
+ arguments in your code before calling your function.
+ """
+
+ name: Required[str]
+ """The name of the function to call."""
+
+
+class FunctionCall(TypedDict, total=False):
+ arguments: Required[str]
+ """
+ The arguments to call the function with, as generated by the model in JSON
+ format. Note that the model does not always generate valid JSON, and may
+ hallucinate parameters not defined by your function schema. Validate the
+ arguments in your code before calling your function.
+ """
+
+ name: Required[str]
+ """The name of the function to call."""
+
+
+class ChatCompletionMessageToolCallParam(TypedDict, total=False):
+ id: Required[str]
+ """The ID of the tool call."""
+
+ function: Required[Function]
+ """The function that the model called."""
+
+ type: Required[Literal["function"]]
+ """The type of the tool. Currently, only `function` is supported."""
+
+
+class Audio(TypedDict, total=False):
+ id: Required[str]
+ """Unique identifier for a previous audio response from the model."""
+
+
+class ChatCompletionContentPartRefusalParam(TypedDict, total=False):
+ refusal: Required[str]
+ """The refusal message generated by the model."""
+
+ type: Required[Literal["refusal"]]
+ """The type of the content part."""
+
+
+ChatCompletionContentPartParam: TypeAlias = Union[
+ ChatCompletionContentPartTextParam,
+ ChatCompletionContentPartImageParam,
+ ChatCompletionContentPartInputAudioParam,
+]
+ContentArrayOfContentPart: TypeAlias = Union[
+ ChatCompletionContentPartTextParam, ChatCompletionContentPartRefusalParam
+]
+
+
+class ChatCompletionSystemMessageParam(TypedDict, total=False):
+ content: Required[Union[str, Iterable[ChatCompletionContentPartTextParam]]]
+ """The contents of the system message."""
+
+ role: Required[Literal["system"]]
+ """The role of the messages author, in this case `system`."""
+
+ name: str
+ """An optional name for the participant.
+
+ Provides the model information to differentiate between participants of the same
+ role.
+ """
+
+
+class ChatCompletionUserMessageParam(TypedDict, total=False):
+ content: Required[Union[str, Iterable[ChatCompletionContentPartParam]]]
+ """The contents of the user message."""
+
+ role: Required[Literal["user"]]
+ """The role of the messages author, in this case `user`."""
+
+ name: str
+ """An optional name for the participant.
+
+ Provides the model information to differentiate between participants of the same
+ role.
+ """
+
+
+class ChatCompletionAssistantMessageParam(TypedDict, total=False):
+ role: Required[Literal["assistant"]]
+ """The role of the messages author, in this case `assistant`."""
+
+ audio: Optional[Audio]
+ """Data about a previous audio response from the model.
+
+ [Learn more](https://platform.openai.com/docs/guides/audio).
+ """
+
+ content: Union[str, Iterable[ContentArrayOfContentPart], None]
+ """The contents of the assistant message.
+
+ Required unless `tool_calls` or `function_call` is specified.
+ """
+
+ function_call: Optional[FunctionCall]
+ """Deprecated and replaced by `tool_calls`.
+
+ The name and arguments of a function that should be called, as generated by the
+ model.
+ """
+
+ name: str
+ """An optional name for the participant.
+
+ Provides the model information to differentiate between participants of the same
+ role.
+ """
+
+ refusal: Optional[str]
+ """The refusal message by the assistant."""
+
+ tool_calls: Iterable[ChatCompletionMessageToolCallParam]
+ """The tool calls generated by the model, such as function calls."""
+
+
+class ChatCompletionToolMessageParam(TypedDict, total=False):
+ content: Required[Union[str, Iterable[ChatCompletionContentPartTextParam]]]
+ """The contents of the tool message."""
+
+ role: Required[Literal["tool"]]
+ """The role of the messages author, in this case `tool`."""
+
+ tool_call_id: Required[str]
+ """Tool call that this message is responding to."""
+
+
+class ChatCompletionFunctionMessageParam(TypedDict, total=False):
+ content: Required[Optional[str]]
+ """The contents of the function message."""
+
+ name: Required[str]
+ """The name of the function to call."""
+
+ role: Required[Literal["function"]]
+ """The role of the messages author, in this case `function`."""
+
+
+# from openai.types.chat import ChatCompletionMessageParam
+OpenAIChatCompletionMessageParam: TypeAlias = Union[
+ ChatCompletionSystemMessageParam,
+ ChatCompletionUserMessageParam,
+ ChatCompletionAssistantMessageParam,
+ ChatCompletionToolMessageParam,
+ ChatCompletionFunctionMessageParam,
+]
+
+ChatCompletionMessageParam = OpenAIChatCompletionMessageParam
diff --git a/packages/dbgpt-core/src/dbgpt/model/cluster/apiserver/api.py b/packages/dbgpt-core/src/dbgpt/model/cluster/apiserver/api.py
index 78e768b66..735fd84c2 100644
--- a/packages/dbgpt-core/src/dbgpt/model/cluster/apiserver/api.py
+++ b/packages/dbgpt-core/src/dbgpt/model/cluster/apiserver/api.py
@@ -5,6 +5,7 @@ Adapted from https://github.com/lm-sys/FastChat/blob/main/fastchat/serve/openai_
"""
import asyncio
+import json
import logging
import os
from typing import Any, Dict, Generator, List, Optional
@@ -50,9 +51,13 @@ from dbgpt.model.cluster.registry import ModelRegistry
from dbgpt.model.parameter import ModelAPIServerParameters, WorkerType
from dbgpt.util.chat_util import transform_to_sse
from dbgpt.util.fastapi import create_app
-from dbgpt.util.tracer import initialize_tracer, root_tracer
+from dbgpt.util.tracer import initialize_tracer, root_tracer, trace
from dbgpt.util.tracer.tracer_impl import TracerParameters
-from dbgpt.util.utils import LoggingParameters, setup_logging
+from dbgpt.util.utils import (
+ LoggingParameters,
+ logging_str_to_uvicorn_level,
+ setup_logging,
+)
logger = logging.getLogger(__name__)
@@ -319,28 +324,49 @@ class APIServer(BaseComponent):
)
yield transform_to_sse(chunk)
+ delta_text = ""
previous_text = ""
+ thinking_text = ""
+ previous_thinking_text = ""
+ full_text = ""
+
+ span = root_tracer.start_span(
+ "API.chat_completion_stream_generator",
+ metadata={
+ "model": model_name,
+ "params": json.dumps(params, ensure_ascii=False),
+ },
+ )
+
async for model_output in worker_manager.generate_stream(params):
model_output: ModelOutput = model_output
if model_output.error_code != 0:
yield transform_to_sse(model_output.to_dict())
yield transform_to_sse("[DONE]")
return
- decoded_unicode = model_output.text.replace("\ufffd", "")
- delta_text = decoded_unicode[len(previous_text) :]
- previous_text = (
- decoded_unicode
- if len(decoded_unicode) > len(previous_text)
- else previous_text
- )
+ if model_output.has_text:
+ full_text = model_output.text
+ decoded_unicode = model_output.text.replace("\ufffd", "")
+ delta_text = decoded_unicode[len(previous_text) :]
+ previous_text = (
+ decoded_unicode
+ if len(decoded_unicode) > len(previous_text)
+ else previous_text
+ )
+ if model_output.has_thinking:
+ decoded_unicode = model_output.thinking_text.replace("\ufffd", "")
+ thinking_text = decoded_unicode[len(previous_thinking_text) :]
+ previous_thinking_text = (
+ decoded_unicode
+ if len(decoded_unicode) > len(previous_thinking_text)
+ else previous_thinking_text
+ )
- if len(delta_text) == 0:
+ if not delta_text:
delta_text = None
- choice_data = ChatCompletionResponseStreamChoice(
- index=i,
- delta=DeltaMessage(content=delta_text),
- finish_reason=model_output.finish_reason,
- )
+ if not thinking_text:
+ thinking_text = None
+
has_usage = False
if model_output.usage:
curr_usage = UsageInfo.model_validate(model_output.usage)
@@ -353,17 +379,29 @@ class APIServer(BaseComponent):
+ curr_usage.completion_tokens,
)
else:
- has_usage = False
usage = UsageInfo()
- chunk = ChatCompletionStreamResponse(
- id=id, choices=[choice_data], model=model_name, usage=usage
+ choice_data = ChatCompletionResponseStreamChoice(
+ index=i,
+ delta=DeltaMessage(
+ content=delta_text, reasoning_content=thinking_text
+ ),
+ finish_reason=model_output.finish_reason,
)
- if delta_text is None:
+ chunk = ChatCompletionStreamResponse(
+ id=id, choices=[choice_data], model=model_name or "", usage=usage
+ )
+ if delta_text is None and thinking_text is None:
if model_output.finish_reason is not None:
finish_stream_events.append(chunk)
if not has_usage:
continue
+
yield transform_to_sse(chunk)
+ span.end(
+ metadata={
+ "full_text": full_text,
+ }
+ )
# There is not "content" field in the last delta message, so exclude_none to
# exclude field "content".
@@ -371,6 +409,7 @@ class APIServer(BaseComponent):
yield transform_to_sse(finish_chunk)
yield transform_to_sse("[DONE]")
+ @trace()
async def chat_completion_generate(
self, model_name: str, params: Dict[str, Any], n: int
) -> ChatCompletionResponse:
@@ -398,7 +437,11 @@ class APIServer(BaseComponent):
choices.append(
ChatCompletionResponseChoice(
index=i,
- message=ChatMessage(role="assistant", content=model_output.text),
+ message=ChatMessage(
+ role="assistant",
+ content=model_output.text,
+ reasoning_content=model_output.thinking_text,
+ ),
finish_reason=model_output.finish_reason or "stop",
)
)
@@ -837,7 +880,12 @@ def initialize_apiserver(
@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request, exc):
- return create_error_response(ErrorCode.VALIDATION_TYPE_ERROR, str(exc))
+ message = ""
+ for error in exc.errors():
+ loc = ".".join(list(map(str, error.get("loc"))))
+ message += loc + ":" + error.get("msg") + ";"
+ logger.warning(message)
+ return create_error_response(ErrorCode.VALIDATION_TYPE_ERROR, message)
_initialize_all(apiserver_params.controller_addr, system_app)
@@ -852,11 +900,14 @@ def initialize_apiserver(
allow_methods=["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"],
allow_headers=["*"],
)
+ log_level = "info"
+ if log_config:
+ log_level = logging_str_to_uvicorn_level(log_config.level)
uvicorn.run(
cors_app,
host=apiserver_params.host,
port=apiserver_params.port,
- log_level="info",
+ log_level=log_level,
)
diff --git a/packages/dbgpt-core/src/dbgpt/util/tracer/tracer_cli.py b/packages/dbgpt-core/src/dbgpt/util/tracer/tracer_cli.py
index 999fcfdd2..023803ba7 100644
--- a/packages/dbgpt-core/src/dbgpt/util/tracer/tracer_cli.py
+++ b/packages/dbgpt-core/src/dbgpt/util/tracer/tracer_cli.py
@@ -94,6 +94,44 @@ def trace_cli_group():
default="text",
help="The output format",
)
+@click.option(
+ "-j",
+ "--json_path",
+ required=False,
+ type=str,
+ default=None,
+ help=(
+ "Extract specific JSON path from spans using JSONPath syntax. Example: "
+ "'$.metadata.messages[0].content'"
+ ),
+)
+@click.option(
+ "-sj",
+ "search_json_path",
+ required=False,
+ type=str,
+ default=None,
+ help=(
+ "Extract specific JSON path from spans using JSONPath syntax. Example: "
+ "'$.metadata.messages[0].content'"
+ ),
+)
+@click.option(
+ "-jm",
+ "--json_path_match",
+ required=False,
+ type=str,
+ default=None,
+ help=("To filter the data after extracting the JSON path"),
+)
+@click.option(
+ "--value",
+ required=False,
+ type=bool,
+ default=False,
+ is_flag=True,
+ help="Just show the value after extracting the JSON path",
+)
@click.argument("files", nargs=-1, type=click.Path(exists=True, readable=True))
def list(
trace_id: str,
@@ -106,6 +144,10 @@ def list(
end_time: str,
desc: bool,
output: str,
+ json_path: str,
+ search_json_path: str,
+ json_path_match: str,
+ value: bool = False,
files=None,
):
"""List your trace spans"""
@@ -141,8 +183,84 @@ def list(
# Sort spans based on the start time
spans = sorted(
spans, key=lambda span: _parse_datetime(span["start_time"]), reverse=desc
- )[:limit]
+ )
+ # Handle JSON path extraction if specified
+ if json_path:
+ try:
+ # Try to import python-jsonpath
+ try:
+ import jsonpath
+ except ImportError:
+ print("'python-jsonpath' library is required for --json_path option.")
+ print("Please install it with: pip install python-jsonpath")
+ return
+
+ # Add root prefix $ if not present
+ if not json_path.startswith("$"):
+ json_path = "$." + json_path
+ if search_json_path and not search_json_path.startswith("$"):
+ search_json_path = "$." + search_json_path
+
+ # Process all spans
+ extracted_data = []
+
+ for span in spans:
+ try:
+ # Find all matches using python-jsonpath
+ results = jsonpath.findall(json_path, span)
+ if results and search_json_path and json_path_match:
+ search_results = jsonpath.findall(search_json_path, span)
+ if not search_results or json_path_match not in search_results:
+ results = []
+
+ if results:
+ extracted_data.append(
+ {
+ "trace_id": span.get("trace_id"),
+ "span_id": span.get("span_id"),
+ "extracted_values": results,
+ }
+ )
+ except Exception as e:
+ # Skip spans that cause errors
+ logger.debug(
+ f"Error extracting from span {span.get('trace_id')}: {e}"
+ )
+ continue
+ extracted_data = extracted_data[:limit]
+ if value:
+ extracted_data = [
+ item["extracted_values"]
+ for item in extracted_data
+ if item["extracted_values"]
+ ]
+
+ if output == "json" and extracted_data:
+ print(json.dumps(extracted_data, ensure_ascii=False, indent=2))
+ elif extracted_data:
+ for item in extracted_data:
+ if not value:
+ for it in item["extracted_values"]:
+ show_value = json.dumps(it, ensure_ascii=False, indent=2)
+ print(
+ f"Trace ID: {item['trace_id']}, Span ID: "
+ f"{item['span_id']}, \nValue: {show_value}"
+ )
+ print("=" * 80)
+ else:
+ for it in item:
+ if isinstance(it, dict):
+ print(json.dumps(it, ensure_ascii=False, indent=2))
+ else:
+ print(it)
+ print("=" * 80)
+ return
+ except Exception as e:
+ print(f"Error while processing JSONPath: {e}")
+ return
+
+ spans = spans[:limit]
table = PrettyTable(
["Trace ID", "Span ID", "Operation Name", "Conversation UID"],
)
@@ -423,6 +541,8 @@ def read_spans_from_files(files=None) -> Iterable[Dict]:
for filename in glob.glob(filepath):
with open(filename, "r") as file:
for line in file:
+ if not line.strip():
+ continue
yield json.loads(line)
diff --git a/packages/dbgpt-core/src/dbgpt/util/tracer/tracer_impl.py b/packages/dbgpt-core/src/dbgpt/util/tracer/tracer_impl.py
index 397da2253..17e81304e 100644
--- a/packages/dbgpt-core/src/dbgpt/util/tracer/tracer_impl.py
+++ b/packages/dbgpt-core/src/dbgpt/util/tracer/tracer_impl.py
@@ -204,13 +204,39 @@ class TracerManager:
root_tracer: TracerManager = TracerManager()
-def trace(operation_name: Optional[str] = None, **trace_kwargs):
+def trace(
+ operation_name: Optional[str] = None, exclude_params: list = None, **trace_kwargs
+):
+ """Decorator for tracing function calls.
+
+ Args:
+ operation_name: Optional name of the operation. If not provided, it will be
+ derived from the function name.
+ exclude_params: List of parameter names to exclude from metadata extraction.
+ **trace_kwargs: Additional keyword arguments for the tracer.
+
+ Returns:
+ Decorated function with tracing functionality.
+ """
+ if exclude_params is None:
+ exclude_params = []
+
+ # Always exclude 'self' and 'cls' by default
+ default_exclude = ["self", "cls"]
+ exclude_params = default_exclude + exclude_params
+
def decorator(func):
@wraps(func)
def sync_wrapper(*args, **kwargs):
name = (
operation_name if operation_name else _parse_operation_name(func, *args)
)
+
+ # Extract function parameters as metadata if not provided in trace_kwargs
+ if "metadata" not in trace_kwargs:
+ metadata = _extract_function_params(func, args, kwargs, exclude_params)
+ trace_kwargs["metadata"] = metadata
+
with root_tracer.start_span(name, **trace_kwargs):
return func(*args, **kwargs)
@@ -219,6 +245,12 @@ def trace(operation_name: Optional[str] = None, **trace_kwargs):
name = (
operation_name if operation_name else _parse_operation_name(func, *args)
)
+
+ # Extract function parameters as metadata if not provided in trace_kwargs
+ if "metadata" not in trace_kwargs:
+ metadata = _extract_function_params(func, args, kwargs, exclude_params)
+ trace_kwargs["metadata"] = metadata
+
with root_tracer.start_span(name, **trace_kwargs):
return await func(*args, **kwargs)
@@ -230,6 +262,58 @@ def trace(operation_name: Optional[str] = None, **trace_kwargs):
return decorator
+def _extract_function_params(func, args, kwargs, exclude_params):
+ """Extract function parameters as metadata.
+
+ Args:
+ func: The function being traced.
+ args: Positional arguments passed to the function.
+ kwargs: Keyword arguments passed to the function.
+ exclude_params: List of parameter names to exclude.
+
+ Returns:
+ Dict containing parameter names and their values.
+ """
+ metadata = {}
+
+ # Get function signature
+ sig = inspect.signature(func)
+ parameters = list(sig.parameters.items())
+
+ # Process positional arguments
+ for i, arg in enumerate(args):
+ if i < len(parameters):
+ param_name = parameters[i][0]
+ if param_name not in exclude_params:
+ try:
+ # Try to make the value JSON serializable by converting to str if
+ # needed
+ metadata[param_name] = (
+ str(arg)
+ if not isinstance(arg, (str, int, float, bool, type(None)))
+ else arg
+ )
+ except Exception:
+ metadata[param_name] = f""
+
+ # Process keyword arguments
+ for param_name, param_value in kwargs.items():
+ if param_name not in exclude_params:
+ try:
+ # Try to make the value JSON serializable by converting to str if needed
+ metadata[param_name] = (
+ str(param_value)
+ if not isinstance(param_value, (str, int, float, bool, type(None)))
+ else param_value
+ )
+ except Exception:
+ metadata[param_name] = (
+ f""
+ )
+
+ return metadata
+
+
def _parse_operation_name(func, *args):
self_name = None
if inspect.signature(func).parameters.get("self"):
diff --git a/packages/dbgpt-ext/pyproject.toml b/packages/dbgpt-ext/pyproject.toml
index 2469da751..7890e5ca0 100644
--- a/packages/dbgpt-ext/pyproject.toml
+++ b/packages/dbgpt-ext/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "dbgpt-ext"
-version = "0.7.0"
+version = "0.7.1"
description = "Add your description here"
authors = [
{ name = "csunny", email = "cfqcsunny@gmail.com" }
diff --git a/packages/dbgpt-ext/src/dbgpt_ext/_version.py b/packages/dbgpt-ext/src/dbgpt_ext/_version.py
index 7a0c9fe2d..691a48ccc 100644
--- a/packages/dbgpt-ext/src/dbgpt_ext/_version.py
+++ b/packages/dbgpt-ext/src/dbgpt_ext/_version.py
@@ -1 +1 @@
-version = "0.7.0"
+version = "0.7.1"
diff --git a/packages/dbgpt-serve/pyproject.toml b/packages/dbgpt-serve/pyproject.toml
index c3cc259e4..a48b11e78 100644
--- a/packages/dbgpt-serve/pyproject.toml
+++ b/packages/dbgpt-serve/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "dbgpt-serve"
-version = "0.7.0"
+version = "0.7.1"
description = "Add your description here"
authors = [
{ name = "csunny", email = "cfqcsunny@gmail.com" }
diff --git a/packages/dbgpt-serve/src/dbgpt_serve/_version.py b/packages/dbgpt-serve/src/dbgpt_serve/_version.py
index 7a0c9fe2d..691a48ccc 100644
--- a/packages/dbgpt-serve/src/dbgpt_serve/_version.py
+++ b/packages/dbgpt-serve/src/dbgpt_serve/_version.py
@@ -1 +1 @@
-version = "0.7.0"
+version = "0.7.1"
diff --git a/pyproject.toml b/pyproject.toml
index 736c4e4c7..2da7ddcc3 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "dbgpt-mono"
-version = "0.7.0"
+version = "0.7.1"
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.\
diff --git a/uv.lock b/uv.lock
index 9bd7ec570..e863314bb 100644
--- a/uv.lock
+++ b/uv.lock
@@ -1676,7 +1676,7 @@ wheels = [
[[package]]
name = "dbgpt"
-version = "0.7.0"
+version = "0.7.1"
source = { editable = "packages/dbgpt-core" }
dependencies = [
{ name = "aiohttp" },
@@ -1732,6 +1732,7 @@ framework = [
{ name = "jsonschema" },
{ name = "openpyxl" },
{ name = "pymysql" },
+ { name = "python-jsonpath" },
{ name = "pyzmq" },
{ name = "seaborn" },
{ name = "tokenizers" },
@@ -1835,6 +1836,7 @@ requires-dist = [
{ name = "pympler", marker = "extra == 'simple-framework'" },
{ name = "pymysql", marker = "extra == 'framework'" },
{ name = "python-dotenv", specifier = "==1.0.0" },
+ { name = "python-jsonpath", marker = "extra == 'framework'" },
{ name = "python-multipart", marker = "extra == 'simple-framework'" },
{ name = "pyzmq", marker = "extra == 'framework'" },
{ name = "qianfan", marker = "extra == 'proxy-qianfan'" },
@@ -1867,7 +1869,7 @@ dev = []
[[package]]
name = "dbgpt-acc-auto"
-version = "0.7.0"
+version = "0.7.1"
source = { editable = "packages/dbgpt-accelerator/dbgpt-acc-auto" }
[package.optional-dependencies]
@@ -2010,7 +2012,7 @@ dev = []
[[package]]
name = "dbgpt-acc-flash-attn"
-version = "0.7.0"
+version = "0.7.1"
source = { editable = "packages/dbgpt-accelerator/dbgpt-acc-flash-attn" }
[package.dev-dependencies]
@@ -2038,7 +2040,7 @@ main = [{ name = "flash-attn", specifier = ">=2.5.8" }]
[[package]]
name = "dbgpt-app"
-version = "0.7.0"
+version = "0.7.1"
source = { editable = "packages/dbgpt-app" }
dependencies = [
{ name = "aiofiles" },
@@ -2091,21 +2093,21 @@ dev = []
[[package]]
name = "dbgpt-client"
-version = "0.7.0"
+version = "0.7.1"
source = { editable = "packages/dbgpt-client" }
dependencies = [
- { name = "dbgpt-serve" },
+ { name = "dbgpt", extra = ["cli", "client"] },
]
[package.metadata]
-requires-dist = [{ name = "dbgpt-serve", editable = "packages/dbgpt-serve" }]
+requires-dist = [{ name = "dbgpt", extras = ["client", "cli"], editable = "packages/dbgpt-core" }]
[package.metadata.requires-dev]
dev = []
[[package]]
name = "dbgpt-ext"
-version = "0.7.0"
+version = "0.7.1"
source = { editable = "packages/dbgpt-ext" }
dependencies = [
{ name = "dbgpt" },
@@ -2225,7 +2227,7 @@ dev = [{ name = "pytest", specifier = ">=8.3.4" }]
[[package]]
name = "dbgpt-mono"
-version = "0.7.0"
+version = "0.7.1"
source = { virtual = "." }
[package.dev-dependencies]
@@ -2270,7 +2272,7 @@ dev = [
[[package]]
name = "dbgpt-serve"
-version = "0.7.0"
+version = "0.7.1"
source = { editable = "packages/dbgpt-serve" }
dependencies = [
{ name = "dbgpt-ext" },
@@ -7712,6 +7714,15 @@ wheels = [
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/4b/72/2f30cf26664fcfa0bd8ec5ee62ec90c03bd485e4a294d92aabc76c5203a5/python_json_logger-3.2.1-py3-none-any.whl", hash = "sha256:cdc17047eb5374bd311e748b42f99d71223f3b0e186f4206cc5d52aefe85b090", size = 14924 },
]
+[[package]]
+name = "python-jsonpath"
+version = "1.3.0"
+source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" }
+sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/86/45/0ae98e958fc53cfdc544bb45262d9e8786f415aac7eb35f94a79af740773/python_jsonpath-1.3.0.tar.gz", hash = "sha256:ea5eb4d9b1296c8c19cc53538eb0f20fc54128f84571559ee63539e57875fefe", size = 43050 }
+wheels = [
+ { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b9/9d/5eed195961588f930db3008199b8023063ebd0253b9de9f0f13f3763b819/python_jsonpath-1.3.0-py3-none-any.whl", hash = "sha256:ce586ec5bd934ce97bc2f06600b00437d9684138b77273ced5b70694a8ef3a76", size = 54354 },
+]
+
[[package]]
name = "python-multipart"
version = "0.0.20"