Commit 396700dd authored by chenzk's avatar chenzk
Browse files

v1.0

parents
Pipeline #2603 failed with stages
in 0 seconds
"""Some UI components for the AWEL flow."""
import json
import logging
from typing import Any, Dict, List, Optional
from dbgpt.core.awel import JoinOperator, MapOperator
from dbgpt.core.awel.flow import (
FunctionDynamicOptions,
IOField,
OperatorCategory,
OptionValue,
Parameter,
VariablesDynamicOptions,
ViewMetadata,
ui,
)
from dbgpt.core.interface.file import FileStorageClient
from dbgpt.core.interface.variables import (
BUILTIN_VARIABLES_CORE_EMBEDDINGS,
BUILTIN_VARIABLES_CORE_FLOW_NODES,
BUILTIN_VARIABLES_CORE_FLOWS,
BUILTIN_VARIABLES_CORE_LLMS,
BUILTIN_VARIABLES_CORE_SECRETS,
BUILTIN_VARIABLES_CORE_VARIABLES,
)
logger = logging.getLogger(__name__)
class ExampleFlowSelectOperator(MapOperator[str, str]):
"""An example flow operator that includes a select as parameter."""
metadata = ViewMetadata(
label="Example Flow Select",
name="example_flow_select",
category=OperatorCategory.EXAMPLE,
description="An example flow operator that includes a select as parameter.",
parameters=[
Parameter.build_from(
"Fruits Selector",
"fruits",
type=str,
optional=True,
default=None,
placeholder="Select the fruits",
description="The fruits you like.",
options=[
OptionValue(label="Apple", name="apple", value="apple"),
OptionValue(label="Banana", name="banana", value="banana"),
OptionValue(label="Orange", name="orange", value="orange"),
OptionValue(label="Pear", name="pear", value="pear"),
],
ui=ui.UISelect(attr=ui.UISelect.UIAttribute(show_search=True)),
)
],
inputs=[
IOField.build_from(
"User Name",
"user_name",
str,
description="The name of the user.",
)
],
outputs=[
IOField.build_from(
"Fruits",
"fruits",
str,
description="User's favorite fruits.",
)
],
)
def __init__(self, fruits: Optional[str] = None, **kwargs):
super().__init__(**kwargs)
self.fruits = fruits
async def map(self, user_name: str) -> str:
"""Map the user name to the fruits."""
return "Your name is %s, and you like %s." % (user_name, self.fruits)
class ExampleFlowCascaderOperator(MapOperator[str, str]):
"""An example flow operator that includes a cascader as parameter."""
metadata = ViewMetadata(
label="Example Flow Cascader",
name="example_flow_cascader",
category=OperatorCategory.EXAMPLE,
description="An example flow operator that includes a cascader as parameter.",
parameters=[
Parameter.build_from(
"Address Selector",
"address",
type=str,
is_list=True,
optional=True,
default=None,
placeholder="Select the address",
description="The address of the location.",
options=[
OptionValue(
label="Zhejiang",
name="zhejiang",
value="zhejiang",
children=[
OptionValue(
label="Hangzhou",
name="hangzhou",
value="hangzhou",
children=[
OptionValue(
label="Xihu",
name="xihu",
value="xihu",
),
OptionValue(
label="Feilaifeng",
name="feilaifeng",
value="feilaifeng",
),
],
),
],
),
OptionValue(
label="Jiangsu",
name="jiangsu",
value="jiangsu",
children=[
OptionValue(
label="Nanjing",
name="nanjing",
value="nanjing",
children=[
OptionValue(
label="Zhonghua Gate",
name="zhonghuamen",
value="zhonghuamen",
),
OptionValue(
label="Zhongshanling",
name="zhongshanling",
value="zhongshanling",
),
],
),
],
),
],
ui=ui.UICascader(attr=ui.UICascader.UIAttribute(show_search=True)),
)
],
inputs=[
IOField.build_from(
"User Name",
"user_name",
str,
description="The name of the user.",
)
],
outputs=[
IOField.build_from(
"Address",
"address",
str,
description="User's address.",
)
],
)
def __int__(self, address: Optional[List[str]] = None, **kwargs):
super().__init__(**kwargs)
self.address = address or []
async def map(self, user_name: str) -> str:
"""Map the user name to the address."""
full_address_str = " ".join(self.address)
return "Your name is %s, and your address is %s." % (
user_name,
full_address_str,
)
class ExampleFlowCheckboxOperator(MapOperator[str, str]):
"""An example flow operator that includes a checkbox as parameter."""
metadata = ViewMetadata(
label="Example Flow Checkbox",
name="example_flow_checkbox",
category=OperatorCategory.EXAMPLE,
description="An example flow operator that includes a checkbox as parameter.",
parameters=[
Parameter.build_from(
"Fruits Selector",
"fruits",
type=str,
is_list=True,
optional=True,
default=None,
placeholder="Select the fruits",
description="The fruits you like.",
options=[
OptionValue(label="Apple", name="apple", value="apple"),
OptionValue(label="Banana", name="banana", value="banana"),
OptionValue(label="Orange", name="orange", value="orange"),
OptionValue(label="Pear", name="pear", value="pear"),
],
ui=ui.UICheckbox(),
)
],
inputs=[
IOField.build_from(
"User Name",
"user_name",
str,
description="The name of the user.",
)
],
outputs=[
IOField.build_from(
"Fruits",
"fruits",
str,
description="User's favorite fruits.",
)
],
)
def __init__(self, fruits: Optional[List[str]] = None, **kwargs):
super().__init__(**kwargs)
self.fruits = fruits or []
async def map(self, user_name: str) -> str:
"""Map the user name to the fruits."""
return "Your name is %s, and you like %s." % (user_name, ", ".join(self.fruits))
class ExampleFlowRadioOperator(MapOperator[str, str]):
"""An example flow operator that includes a radio as parameter."""
metadata = ViewMetadata(
label="Example Flow Radio",
name="example_flow_radio",
category=OperatorCategory.EXAMPLE,
description="An example flow operator that includes a radio as parameter.",
parameters=[
Parameter.build_from(
"Fruits Selector",
"fruits",
type=str,
optional=True,
default=None,
placeholder="Select the fruits",
description="The fruits you like.",
options=[
OptionValue(label="Apple", name="apple", value="apple"),
OptionValue(label="Banana", name="banana", value="banana"),
OptionValue(label="Orange", name="orange", value="orange"),
OptionValue(label="Pear", name="pear", value="pear"),
],
ui=ui.UIRadio(),
)
],
inputs=[
IOField.build_from(
"User Name",
"user_name",
str,
description="The name of the user.",
)
],
outputs=[
IOField.build_from(
"Fruits",
"fruits",
str,
description="User's favorite fruits.",
)
],
)
def __init__(self, fruits: Optional[str] = None, **kwargs):
super().__init__(**kwargs)
self.fruits = fruits
async def map(self, user_name: str) -> str:
"""Map the user name to the fruits."""
return "Your name is %s, and you like %s." % (user_name, self.fruits)
class ExampleFlowDatePickerOperator(MapOperator[str, str]):
"""An example flow operator that includes a date picker as parameter."""
metadata = ViewMetadata(
label="Example Flow Date Picker",
name="example_flow_date_picker",
category=OperatorCategory.EXAMPLE,
description="An example flow operator that includes a date picker as parameter.",
parameters=[
Parameter.build_from(
"Date Selector",
"date",
type=str,
placeholder="Select the date",
description="The date you choose.",
ui=ui.UIDatePicker(
attr=ui.UIDatePicker.UIAttribute(placement="bottomLeft")
),
)
],
inputs=[
IOField.build_from(
"User Name",
"user_name",
str,
description="The name of the user.",
)
],
outputs=[
IOField.build_from(
"Date",
"date",
str,
description="User's selected date.",
)
],
)
def __init__(self, date: str, **kwargs):
super().__init__(**kwargs)
self.date = date
async def map(self, user_name: str) -> str:
"""Map the user name to the date."""
return "Your name is %s, and you choose the date %s." % (user_name, self.date)
class ExampleFlowInputOperator(MapOperator[str, str]):
"""An example flow operator that includes an input as parameter."""
metadata = ViewMetadata(
label="Example Flow Input",
name="example_flow_input",
category=OperatorCategory.EXAMPLE,
description="An example flow operator that includes a input as parameter.",
parameters=[
Parameter.build_from(
"Your hobby",
"hobby",
type=str,
placeholder="Please input your hobby",
description="The hobby you like.",
ui=ui.UIInput(
attr=ui.UIInput.UIAttribute(
prefix="icon:UserOutlined", show_count=True, maxlength=200
)
),
)
],
inputs=[
IOField.build_from(
"User Name",
"user_name",
str,
description="The name of the user.",
)
],
outputs=[
IOField.build_from(
"User Hobby",
"hobby",
str,
description="User's hobby.",
)
],
)
def __init__(self, hobby: str, **kwargs):
super().__init__(**kwargs)
self.hobby = hobby
async def map(self, user_name: str) -> str:
"""Map the user name to the input."""
return "Your name is %s, and your hobby is %s." % (user_name, self.hobby)
class ExampleFlowTextAreaOperator(MapOperator[str, str]):
"""An example flow operator that includes a text area as parameter."""
metadata = ViewMetadata(
label="Example Flow Text Area",
name="example_flow_text_area",
category=OperatorCategory.EXAMPLE,
description="An example flow operator that includes a text area as parameter.",
parameters=[
Parameter.build_from(
"Your comment",
"comment",
type=str,
placeholder="Please input your comment",
description="The comment you want to say.",
ui=ui.UITextArea(
attr=ui.UITextArea.UIAttribute(
show_count=True,
maxlength=1000,
auto_size=ui.UITextArea.UIAttribute.AutoSize(
min_rows=2, max_rows=6
),
),
),
)
],
inputs=[
IOField.build_from(
"User Name",
"user_name",
str,
description="The name of the user.",
)
],
outputs=[
IOField.build_from(
"User Comment",
"comment",
str,
description="User's comment.",
)
],
)
def __init__(self, comment: str, **kwargs):
super().__init__(**kwargs)
self.comment = comment
async def map(self, user_name: str) -> str:
"""Map the user name to the text area."""
return "Your name is %s, and your comment is %s." % (user_name, self.comment)
class ExampleFlowSliderOperator(MapOperator[float, float]):
metadata = ViewMetadata(
label="Example Flow Slider",
name="example_flow_slider",
category=OperatorCategory.EXAMPLE,
description="An example flow operator that includes a slider as parameter.",
parameters=[
Parameter.build_from(
"Default Temperature",
"default_temperature",
type=float,
optional=True,
default=0.7,
placeholder="Set the default temperature, e.g., 0.7",
description="The default temperature to pass to the LLM.",
ui=ui.UISlider(
show_input=True,
attr=ui.UISlider.UIAttribute(min=0.0, max=2.0, step=0.1),
),
)
],
inputs=[
IOField.build_from(
"Temperature",
"temperature",
float,
description="The temperature.",
)
],
outputs=[
IOField.build_from(
"Temperature",
"temperature",
float,
description="The temperature to pass to the LLM.",
)
],
)
def __init__(self, default_temperature: float = 0.7, **kwargs):
super().__init__(**kwargs)
self.default_temperature = default_temperature
async def map(self, temperature: float) -> float:
"""Map the temperature to the result."""
if temperature < 0.0 or temperature > 2.0:
logger.warning("Temperature out of range: %s", temperature)
return self.default_temperature
else:
return temperature
class ExampleFlowSliderListOperator(MapOperator[float, float]):
"""An example flow operator that includes a slider list as parameter."""
metadata = ViewMetadata(
label="Example Flow Slider List",
name="example_flow_slider_list",
category=OperatorCategory.EXAMPLE,
description="An example flow operator that includes a slider list as parameter.",
parameters=[
Parameter.build_from(
"Temperature Selector",
"temperature_range",
type=float,
is_list=True,
optional=True,
default=None,
placeholder="Set the temperature, e.g., [0.1, 0.9]",
description="The temperature range to pass to the LLM.",
ui=ui.UISlider(
show_input=True,
attr=ui.UISlider.UIAttribute(min=0.0, max=2.0, step=0.1),
),
)
],
inputs=[
IOField.build_from(
"Temperature",
"temperature",
float,
description="The temperature.",
)
],
outputs=[
IOField.build_from(
"Temperature",
"temperature",
float,
description="The temperature to pass to the LLM.",
)
],
)
def __init__(self, temperature_range: Optional[List[float]] = None, **kwargs):
super().__init__(**kwargs)
temperature_range = temperature_range or [0.1, 0.9]
if temperature_range and len(temperature_range) != 2:
raise ValueError("The length of temperature range must be 2.")
self.temperature_range = temperature_range
async def map(self, temperature: float) -> float:
"""Map the temperature to the result."""
min_temperature, max_temperature = self.temperature_range
if temperature < min_temperature or temperature > max_temperature:
logger.warning(
"Temperature out of range: %s, min: %s, max: %s",
temperature,
min_temperature,
max_temperature,
)
return min_temperature
return temperature
class ExampleFlowTimePickerOperator(MapOperator[str, str]):
"""An example flow operator that includes a time picker as parameter."""
metadata = ViewMetadata(
label="Example Flow Time Picker",
name="example_flow_time_picker",
category=OperatorCategory.EXAMPLE,
description="An example flow operator that includes a time picker as parameter.",
parameters=[
Parameter.build_from(
"Time Selector",
"time",
type=str,
placeholder="Select the time",
description="The time you choose.",
ui=ui.UITimePicker(
attr=ui.UITimePicker.UIAttribute(
format="HH:mm:ss", hour_step=2, minute_step=10, second_step=10
),
),
)
],
inputs=[
IOField.build_from(
"User Name",
"user_name",
str,
description="The name of the user.",
)
],
outputs=[
IOField.build_from(
"Time",
"time",
str,
description="User's selected time.",
)
],
)
def __init__(self, time: str, **kwargs):
super().__init__(**kwargs)
self.time = time
async def map(self, user_name: str) -> str:
"""Map the user name to the time."""
return "Your name is %s, and you choose the time %s." % (user_name, self.time)
class ExampleFlowTreeSelectOperator(MapOperator[str, str]):
"""An example flow operator that includes a tree select as parameter."""
metadata = ViewMetadata(
label="Example Flow Tree Select",
name="example_flow_tree_select",
category=OperatorCategory.EXAMPLE,
description="An example flow operator that includes a tree select as parameter.",
parameters=[
Parameter.build_from(
"Address Selector",
"address",
type=str,
is_list=True,
optional=True,
default=None,
placeholder="Select the address",
description="The address of the location.",
options=[
OptionValue(
label="Zhejiang",
name="zhejiang",
value="zhejiang",
children=[
OptionValue(
label="Hangzhou",
name="hangzhou",
value="hangzhou",
children=[
OptionValue(
label="Xihu",
name="xihu",
value="xihu",
),
OptionValue(
label="Feilaifeng",
name="feilaifeng",
value="feilaifeng",
),
],
),
],
),
OptionValue(
label="Jiangsu",
name="jiangsu",
value="jiangsu",
children=[
OptionValue(
label="Nanjing",
name="nanjing",
value="nanjing",
children=[
OptionValue(
label="Zhonghua Gate",
name="zhonghuamen",
value="zhonghuamen",
),
OptionValue(
label="Zhongshanling",
name="zhongshanling",
value="zhongshanling",
),
],
),
],
),
],
ui=ui.UITreeSelect(attr=ui.UITreeSelect.UIAttribute(show_search=True)),
)
],
inputs=[
IOField.build_from(
"User Name",
"user_name",
str,
description="The name of the user.",
)
],
outputs=[
IOField.build_from(
"Address",
"address",
str,
description="User's address.",
)
],
)
def __int__(self, address: Optional[List[str]] = None, **kwargs):
super().__init__(**kwargs)
self.address = address or []
async def map(self, user_name: str) -> str:
"""Map the user name to the address."""
full_address_str = " ".join(self.address)
return "Your name is %s, and your address is %s." % (
user_name,
full_address_str,
)
def get_recent_3_times(time_interval: int = 1) -> List[OptionValue]:
"""Get the recent times."""
from datetime import datetime, timedelta
now = datetime.now()
recent_times = [now - timedelta(hours=time_interval * i) for i in range(3)]
formatted_times = [time.strftime("%Y-%m-%d %H:%M:%S") for time in recent_times]
option_values = [
OptionValue(label=formatted_time, name=f"time_{i + 1}", value=formatted_time)
for i, formatted_time in enumerate(formatted_times)
]
return option_values
class ExampleFlowRefreshOperator(MapOperator[str, str]):
"""An example flow operator that includes a refresh option."""
metadata = ViewMetadata(
label="Example Refresh Operator",
name="example_refresh_operator",
category=OperatorCategory.EXAMPLE,
description="An example flow operator that includes a refresh option.",
parameters=[
Parameter.build_from(
"Time Interval",
"time_interval",
type=int,
optional=True,
default=1,
placeholder="Set the time interval",
description="The time interval to fetch the times",
),
Parameter.build_from(
"Recent Time",
"recent_time",
type=str,
optional=True,
default=None,
placeholder="Select the recent time",
description="The recent time to choose.",
options=FunctionDynamicOptions(func=get_recent_3_times),
ui=ui.UISelect(
refresh=True,
refresh_depends=["time_interval"],
attr=ui.UISelect.UIAttribute(show_search=True),
),
),
],
inputs=[
IOField.build_from(
"User Name",
"user_name",
str,
description="The name of the user.",
)
],
outputs=[
IOField.build_from(
"Time",
"time",
str,
description="User's selected time.",
)
],
)
def __init__(
self, time_interval: int = 1, recent_time: Optional[str] = None, **kwargs
):
super().__init__(**kwargs)
self.time_interval = time_interval
self.recent_time = recent_time
async def map(self, user_name: str) -> str:
"""Map the user name to the time."""
return "Your name is %s, and you choose the time %s." % (
user_name,
self.recent_time,
)
class ExampleFlowUploadOperator(MapOperator[str, str]):
"""An example flow operator that includes an upload as parameter."""
metadata = ViewMetadata(
label="Example Flow Upload",
name="example_flow_upload",
category=OperatorCategory.EXAMPLE,
description="An example flow operator that includes a upload as parameter.",
parameters=[
Parameter.build_from(
"Single File Selector",
"file",
type=str,
optional=True,
default=None,
placeholder="Select the file",
description="The file you want to upload.",
ui=ui.UIUpload(
max_file_size=1024 * 1024 * 100,
up_event="after_select",
attr=ui.UIUpload.UIAttribute(max_count=1),
),
),
Parameter.build_from(
"Multiple Files Selector",
"multiple_files",
type=str,
is_list=True,
optional=True,
default=None,
placeholder="Select the multiple files",
description="The multiple files you want to upload.",
ui=ui.UIUpload(
max_file_size=1024 * 1024 * 100,
up_event="button_click",
attr=ui.UIUpload.UIAttribute(max_count=5),
),
),
Parameter.build_from(
"CSV File Selector",
"csv_file",
type=str,
optional=True,
default=None,
placeholder="Select the CSV file",
description="The CSV file you want to upload.",
ui=ui.UIUpload(
max_file_size=1024 * 1024 * 100,
up_event="after_select",
file_types=[".csv"],
attr=ui.UIUpload.UIAttribute(max_count=1),
),
),
Parameter.build_from(
"Images Selector",
"images",
type=str,
is_list=True,
optional=True,
default=None,
placeholder="Select the images",
description="The images you want to upload.",
ui=ui.UIUpload(
max_file_size=1024 * 1024 * 100,
up_event="button_click",
file_types=["image/*", ".pdf"],
drag=True,
attr=ui.UIUpload.UIAttribute(max_count=5),
),
),
],
inputs=[
IOField.build_from(
"User Name",
"user_name",
str,
description="The name of the user.",
)
],
outputs=[
IOField.build_from(
"File",
"file",
str,
description="User's uploaded file.",
)
],
)
def __init__(
self,
file: Optional[str] = None,
multiple_files: Optional[List[str]] = None,
csv_file: Optional[str] = None,
images: Optional[List[str]] = None,
**kwargs,
):
super().__init__(**kwargs)
self.file = file
self.multiple_files = multiple_files or []
self.csv_file = csv_file
self.images = images or []
async def map(self, user_name: str) -> str:
"""Map the user name to the file."""
fsc = FileStorageClient.get_instance(self.system_app)
files_metadata = await self.blocking_func_to_async(
self._parse_files_metadata, fsc
)
files_metadata_str = json.dumps(files_metadata, ensure_ascii=False, indent=4)
return "Your name is %s, and you files are %s." % (
user_name,
files_metadata_str,
)
def _parse_files_metadata(self, fsc: FileStorageClient) -> List[Dict[str, Any]]:
"""Parse the files metadata."""
if not self.file:
raise ValueError("The file is not uploaded.")
if not self.multiple_files:
raise ValueError("The multiple files are not uploaded.")
files = [self.file] + self.multiple_files + [self.csv_file] + self.images
results = []
for file in files:
_, metadata = fsc.get_file(file)
results.append(
{
"bucket": metadata.bucket,
"file_id": metadata.file_id,
"file_size": metadata.file_size,
"storage_type": metadata.storage_type,
"uri": metadata.uri,
"file_hash": metadata.file_hash,
}
)
return results
class ExampleFlowVariablesOperator(MapOperator[str, str]):
"""An example flow operator that includes a variables option."""
metadata = ViewMetadata(
label="Example Variables Operator",
name="example_variables_operator",
category=OperatorCategory.EXAMPLE,
description="An example flow operator that includes a variables option.",
parameters=[
Parameter.build_from(
"OpenAI API Key",
"openai_api_key",
type=str,
placeholder="Please select the OpenAI API key",
description="The OpenAI API key to use.",
options=VariablesDynamicOptions(),
ui=ui.UIPasswordInput(
key="dbgpt.model.openai.api_key",
),
),
Parameter.build_from(
"Model",
"model",
type=str,
placeholder="Please select the model",
description="The model to use.",
options=VariablesDynamicOptions(),
ui=ui.UIVariablesInput(
key="dbgpt.model.openai.model",
),
),
Parameter.build_from(
"Builtin Flows",
"builtin_flow",
type=str,
placeholder="Please select the builtin flows",
description="The builtin flows to use.",
options=VariablesDynamicOptions(),
ui=ui.UIVariablesInput(
key=BUILTIN_VARIABLES_CORE_FLOWS,
),
),
Parameter.build_from(
"Builtin Flow Nodes",
"builtin_flow_node",
type=str,
placeholder="Please select the builtin flow nodes",
description="The builtin flow nodes to use.",
options=VariablesDynamicOptions(),
ui=ui.UIVariablesInput(
key=BUILTIN_VARIABLES_CORE_FLOW_NODES,
),
),
Parameter.build_from(
"Builtin Variables",
"builtin_variable",
type=str,
placeholder="Please select the builtin variables",
description="The builtin variables to use.",
options=VariablesDynamicOptions(),
ui=ui.UIVariablesInput(
key=BUILTIN_VARIABLES_CORE_VARIABLES,
),
),
Parameter.build_from(
"Builtin Secrets",
"builtin_secret",
type=str,
placeholder="Please select the builtin secrets",
description="The builtin secrets to use.",
options=VariablesDynamicOptions(),
ui=ui.UIVariablesInput(
key=BUILTIN_VARIABLES_CORE_SECRETS,
),
),
Parameter.build_from(
"Builtin LLMs",
"builtin_llm",
type=str,
placeholder="Please select the builtin LLMs",
description="The builtin LLMs to use.",
options=VariablesDynamicOptions(),
ui=ui.UIVariablesInput(
key=BUILTIN_VARIABLES_CORE_LLMS,
),
),
Parameter.build_from(
"Builtin Embeddings",
"builtin_embedding",
type=str,
placeholder="Please select the builtin embeddings",
description="The builtin embeddings to use.",
options=VariablesDynamicOptions(),
ui=ui.UIVariablesInput(
key=BUILTIN_VARIABLES_CORE_EMBEDDINGS,
),
),
],
inputs=[
IOField.build_from(
"User Name",
"user_name",
str,
description="The name of the user.",
),
],
outputs=[
IOField.build_from(
"Model info",
"model",
str,
description="The model info.",
),
],
)
def __init__(
self,
openai_api_key: str,
model: str,
builtin_flow: str,
builtin_flow_node: str,
builtin_variable: str,
builtin_secret: str,
builtin_llm: str,
builtin_embedding: str,
**kwargs,
):
super().__init__(**kwargs)
self.openai_api_key = openai_api_key
self.model = model
self.builtin_flow = builtin_flow
self.builtin_flow_node = builtin_flow_node
self.builtin_variable = builtin_variable
self.builtin_secret = builtin_secret
self.builtin_llm = builtin_llm
self.builtin_embedding = builtin_embedding
async def map(self, user_name: str) -> str:
"""Map the user name to the model."""
dict_dict = {
"openai_api_key": self.openai_api_key,
"model": self.model,
"builtin_flow": self.builtin_flow,
"builtin_flow_node": self.builtin_flow_node,
"builtin_variable": self.builtin_variable,
"builtin_secret": self.builtin_secret,
"builtin_llm": self.builtin_llm,
"builtin_embedding": self.builtin_embedding,
}
json_data = json.dumps(dict_dict, ensure_ascii=False)
return "Your name is %s, and your model info is %s." % (user_name, json_data)
class ExampleFlowTagsOperator(MapOperator[str, str]):
"""An example flow operator that includes a tags option."""
metadata = ViewMetadata(
label="Example Tags Operator",
name="example_tags_operator",
category=OperatorCategory.EXAMPLE,
description="An example flow operator that includes a tags",
parameters=[],
inputs=[
IOField.build_from(
"User Name",
"user_name",
str,
description="The name of the user.",
),
],
outputs=[
IOField.build_from(
"Tags",
"tags",
str,
description="The tags to use.",
),
],
tags={"order": "higher-order", "type": "example"},
)
def __init__(self, **kwargs):
super().__init__(**kwargs)
async def map(self, user_name: str) -> str:
"""Map the user name to the tags."""
return "Your name is %s, and your tags are %s." % (user_name, "higher-order")
class ExampleFlowCodeEditorOperator(MapOperator[str, str]):
"""An example flow operator that includes a code editor as parameter."""
metadata = ViewMetadata(
label="Example Flow Code Editor",
name="example_flow_code_editor",
category=OperatorCategory.EXAMPLE,
description="An example flow operator that includes a code editor as parameter.",
parameters=[
Parameter.build_from(
"Code Editor",
"code",
type=str,
placeholder="Please input your code",
description="The code you want to edit.",
ui=ui.UICodeEditor(
language="python",
),
),
Parameter.build_from(
"Language",
"lang",
type=str,
optional=True,
default="python",
placeholder="Please select the language",
description="The language of the code.",
options=[
OptionValue(label="Python", name="python", value="python"),
OptionValue(
label="JavaScript", name="javascript", value="javascript"
),
],
ui=ui.UISelect(),
),
],
inputs=[
IOField.build_from(
"User Name",
"user_name",
str,
description="The name of the user.",
)
],
outputs=[
IOField.build_from(
"Code",
"code",
str,
description="Result of the code.",
)
],
)
def __init__(self, code: str, lang: str = "python", **kwargs):
super().__init__(**kwargs)
self.code = code
self.lang = lang
async def map(self, user_name: str) -> str:
"""Map the user name to the code."""
code = self.code
exit_code = -1
try:
exit_code, logs = await self.execute_code_blocks(code, self.lang)
except Exception as e:
logger.error(f"Failed to execute code: {e}")
logs = f"Failed to execute code: {e}"
return (
f"Your name is {user_name}, and your code is \n\n```python\n{code}"
f"\n\n```\n\nThe execution result is \n\n```\n{logs}\n\n```\n\n"
f"Exit code: {exit_code}."
)
async def execute_code_blocks(self, code_blocks: str, lang: str):
"""Execute the code blocks and return the result."""
from dbgpt.util.code.server import CodeResult, get_code_server
code_server = await get_code_server(self.system_app)
result: CodeResult = await code_server.exec(code_blocks, lang)
return result.exit_code, result.logs
class ExampleFlowDynamicParametersOperator(MapOperator[str, str]):
"""An example flow operator that includes dynamic parameters."""
metadata = ViewMetadata(
label="Example Dynamic Parameters Operator",
name="example_dynamic_parameters_operator",
category=OperatorCategory.EXAMPLE,
description="An example flow operator that includes dynamic parameters.",
parameters=[
Parameter.build_from(
"Dynamic String",
"dynamic_1",
type=str,
is_list=True,
placeholder="Please input the dynamic parameter",
description="The dynamic parameter you want to use, you can add more, "
"at least 1 parameter.",
dynamic=True,
dynamic_minimum=1,
ui=ui.UIInput(),
),
Parameter.build_from(
"Dynamic Integer",
"dynamic_2",
type=int,
is_list=True,
placeholder="Please input the dynamic parameter",
description="The dynamic parameter you want to use, you can add more, "
"at least 0 parameter.",
dynamic=True,
dynamic_minimum=0,
),
],
inputs=[
IOField.build_from(
"User Name",
"user_name",
str,
description="The name of the user.",
),
],
outputs=[
IOField.build_from(
"Dynamic",
"dynamic",
str,
description="User's selected dynamic.",
),
],
)
def __init__(self, dynamic_1: List[str], dynamic_2: List[int], **kwargs):
super().__init__(**kwargs)
if not dynamic_1:
raise ValueError("The dynamic string is empty.")
self.dynamic_1 = dynamic_1
self.dynamic_2 = dynamic_2
async def map(self, user_name: str) -> str:
"""Map the user name to the dynamic."""
return "Your name is %s, and your dynamic is %s." % (
user_name,
f"dynamic_1: {self.dynamic_1}, dynamic_2: {self.dynamic_2}",
)
class ExampleFlowDynamicOutputsOperator(MapOperator[str, str]):
"""An example flow operator that includes dynamic outputs."""
metadata = ViewMetadata(
label="Example Dynamic Outputs Operator",
name="example_dynamic_outputs_operator",
category=OperatorCategory.EXAMPLE,
description="An example flow operator that includes dynamic outputs.",
parameters=[],
inputs=[
IOField.build_from(
"User Name",
"user_name",
str,
description="The name of the user.",
),
],
outputs=[
IOField.build_from(
"Dynamic",
"dynamic",
str,
description="User's selected dynamic.",
dynamic=True,
dynamic_minimum=1,
),
],
)
async def map(self, user_name: str) -> str:
"""Map the user name to the dynamic."""
return "Your name is %s, this operator has dynamic outputs." % user_name
class ExampleFlowDynamicInputsOperator(JoinOperator[str]):
"""An example flow operator that includes dynamic inputs."""
metadata = ViewMetadata(
label="Example Dynamic Inputs Operator",
name="example_dynamic_inputs_operator",
category=OperatorCategory.EXAMPLE,
description="An example flow operator that includes dynamic inputs.",
parameters=[],
inputs=[
IOField.build_from(
"User Name",
"user_name",
str,
description="The name of the user.",
),
IOField.build_from(
"Other Inputs",
"other_inputs",
str,
description="Other inputs.",
dynamic=True,
dynamic_minimum=0,
),
],
outputs=[
IOField.build_from(
"Dynamic",
"dynamic",
str,
description="User's selected dynamic.",
),
],
)
def __init__(self, **kwargs):
super().__init__(combine_function=self.join, **kwargs)
async def join(self, user_name: str, *other_inputs: str) -> str:
"""Map the user name to the dynamic."""
if not other_inputs:
dyn_inputs = ["You have no other inputs."]
else:
dyn_inputs = [
f"Input {i}: {input_data}" for i, input_data in enumerate(other_inputs)
]
dyn_str = "\n".join(dyn_inputs)
return "Your name is %s, and your dynamic is %s." % (
user_name,
f"other_inputs:\n{dyn_str}",
)
"""AWEL: Data analyst assistant.
DB-GPT will automatically load and execute the current file after startup.
Examples:
.. code-block:: shell
# Run this file in your terminal with dev mode.
# First terminal
export OPENAI_API_KEY=xxx
export OPENAI_API_BASE=https://api.openai.com/v1
python examples/awel/simple_chat_history_example.py
Code fix command, return no streaming response
.. code-block:: shell
# Open a new terminal
# Second terminal
DBGPT_SERVER="http://127.0.0.1:5555"
MODEL="gpt-3.5-turbo"
# Fist round
curl -X POST $DBGPT_SERVER/api/v1/awel/trigger/examples/data_analyst/copilot \
-H "Content-Type: application/json" -d '{
"command": "dbgpt_awel_data_analyst_code_fix",
"model": "'"$MODEL"'",
"stream": false,
"context": {
"conv_uid": "uuid_conv_copilot_1234",
"chat_mode": "chat_with_code"
},
"messages": "SELECT * FRM orders WHERE order_amount > 500;"
}'
"""
import logging
import os
from functools import cache
from typing import Any, Dict, List, Optional
from dbgpt._private.pydantic import BaseModel, Field
from dbgpt.core import (
ChatPromptTemplate,
HumanPromptTemplate,
MessagesPlaceholder,
ModelMessage,
ModelRequest,
ModelRequestContext,
PromptManager,
PromptTemplate,
SystemPromptTemplate,
)
from dbgpt.core.awel import (
DAG,
BranchJoinOperator,
HttpTrigger,
JoinOperator,
MapOperator,
)
from dbgpt.core.operators import (
BufferedConversationMapperOperator,
HistoryDynamicPromptBuilderOperator,
LLMBranchOperator,
)
from dbgpt.model.operators import (
LLMOperator,
OpenAIStreamingOutputOperator,
StreamingLLMOperator,
)
from dbgpt_serve.conversation.operators import ServePreChatHistoryLoadOperator
logger = logging.getLogger(__name__)
PROMPT_LANG_ZH = "zh"
PROMPT_LANG_EN = "en"
CODE_DEFAULT = "dbgpt_awel_data_analyst_code_default"
CODE_FIX = "dbgpt_awel_data_analyst_code_fix"
CODE_PERF = "dbgpt_awel_data_analyst_code_perf"
CODE_EXPLAIN = "dbgpt_awel_data_analyst_code_explain"
CODE_COMMENT = "dbgpt_awel_data_analyst_code_comment"
CODE_TRANSLATE = "dbgpt_awel_data_analyst_code_translate"
CODE_DEFAULT_TEMPLATE_ZH = """作为一名经验丰富的数据仓库开发者和数据分析师。
你可以根据最佳实践来优化代码, 也可以对代码进行修复, 解释, 添加注释, 以及将代码翻译成其他语言。"""
CODE_DEFAULT_TEMPLATE_EN = """As an experienced data warehouse developer and data analyst.
You can optimize the code according to best practices, or fix, explain, add comments to the code,
and you can also translate the code into other languages.
"""
CODE_FIX_TEMPLATE_ZH = """作为一名经验丰富的数据仓库开发者和数据分析师,
这里有一段 {language} 代码。请按照最佳实践检查代码,找出并修复所有错误。请给出修复后的代码,并且提供对您所做的每一行更正的逐行解释,请使用和用户相同的语言进行回答。"""
CODE_FIX_TEMPLATE_EN = """As an experienced data warehouse developer and data analyst,
here is a snippet of code of {language}. Please review the code following best practices to identify and fix all errors.
Provide the corrected code and include a line-by-line explanation of all the fixes you've made, please use the same language as the user."""
CODE_PERF_TEMPLATE_ZH = """作为一名经验丰富的数据仓库开发者和数据分析师,这里有一段 {language} 代码。
请你按照最佳实践来优化这段代码。请在代码中加入注释点明所做的更改,并解释每项优化的原因,以便提高代码的维护性和性能,请使用和用户相同的语言进行回答。"""
CODE_PERF_TEMPLATE_EN = """As an experienced data warehouse developer and data analyst,
you are provided with a snippet of code of {language}. Please optimize the code according to best practices.
Include comments to highlight the changes made and explain the reasons for each optimization for better maintenance and performance,
please use the same language as the user."""
CODE_EXPLAIN_TEMPLATE_ZH = """作为一名经验丰富的数据仓库开发者和数据分析师,
现在给你的是一份 {language} 代码。请你逐行解释代码的含义,请使用和用户相同的语言进行回答。"""
CODE_EXPLAIN_TEMPLATE_EN = """As an experienced data warehouse developer and data analyst,
you are provided with a snippet of code of {language}. Please explain the meaning of the code line by line,
please use the same language as the user."""
CODE_COMMENT_TEMPLATE_ZH = """作为一名经验丰富的数据仓库开发者和数据分析师,现在给你的是一份 {language} 代码。
请你为每一行代码添加注释,解释每个部分的作用,请使用和用户相同的语言进行回答。"""
CODE_COMMENT_TEMPLATE_EN = """As an experienced Data Warehouse Developer and Data Analyst.
Below is a snippet of code written in {language}.
Please provide line-by-line comments explaining what each section of the code does, please use the same language as the user."""
CODE_TRANSLATE_TEMPLATE_ZH = """作为一名经验丰富的数据仓库开发者和数据分析师,现在手头有一份用{source_language}语言编写的代码片段。
请你将这段代码准确无误地翻译成{target_language}语言,确保语法和功能在翻译后的代码中得到正确体现,请使用和用户相同的语言进行回答。"""
CODE_TRANSLATE_TEMPLATE_EN = """As an experienced data warehouse developer and data analyst,
you're presented with a snippet of code written in {source_language}.
Please translate this code into {target_language} ensuring that the syntax and functionalities are accurately reflected in the translated code,
please use the same language as the user."""
class ReqContext(BaseModel):
user_name: Optional[str] = Field(
None, description="The user name of the model request."
)
sys_code: Optional[str] = Field(
None, description="The system code of the model request."
)
conv_uid: Optional[str] = Field(
None, description="The conversation uid of the model request."
)
chat_mode: Optional[str] = Field(
"chat_with_code", description="The chat mode of the model request."
)
class TriggerReqBody(BaseModel):
messages: str = Field(..., description="User input messages")
command: Optional[str] = Field(
default=None, description="Command name, None if common chat"
)
model: Optional[str] = Field(default="gpt-3.5-turbo", description="Model name")
stream: Optional[bool] = Field(default=False, description="Whether return stream")
language: Optional[str] = Field(default="hive", description="Language")
target_language: Optional[str] = Field(
default="hive", description="Target language, use in translate"
)
context: Optional[ReqContext] = Field(
default=None, description="The context of the model request."
)
@cache
def load_or_save_prompt_template(pm: PromptManager):
zh_ext_params = {
"chat_scene": "chat_with_code",
"sub_chat_scene": "data_analyst",
"prompt_type": "common",
"prompt_language": PROMPT_LANG_ZH,
}
en_ext_params = {
"chat_scene": "chat_with_code",
"sub_chat_scene": "data_analyst",
"prompt_type": "common",
"prompt_language": PROMPT_LANG_EN,
}
pm.query_or_save(
PromptTemplate.from_template(CODE_DEFAULT_TEMPLATE_ZH),
prompt_name=CODE_DEFAULT,
**zh_ext_params,
)
pm.query_or_save(
PromptTemplate.from_template(CODE_DEFAULT_TEMPLATE_EN),
prompt_name=CODE_DEFAULT,
**en_ext_params,
)
pm.query_or_save(
PromptTemplate.from_template(CODE_FIX_TEMPLATE_ZH),
prompt_name=CODE_FIX,
**zh_ext_params,
)
pm.query_or_save(
PromptTemplate.from_template(CODE_FIX_TEMPLATE_EN),
prompt_name=CODE_FIX,
**en_ext_params,
)
pm.query_or_save(
PromptTemplate.from_template(CODE_PERF_TEMPLATE_ZH),
prompt_name=CODE_PERF,
**zh_ext_params,
)
pm.query_or_save(
PromptTemplate.from_template(CODE_PERF_TEMPLATE_EN),
prompt_name=CODE_PERF,
**en_ext_params,
)
pm.query_or_save(
PromptTemplate.from_template(CODE_EXPLAIN_TEMPLATE_ZH),
prompt_name=CODE_EXPLAIN,
**zh_ext_params,
)
pm.query_or_save(
PromptTemplate.from_template(CODE_EXPLAIN_TEMPLATE_EN),
prompt_name=CODE_EXPLAIN,
**en_ext_params,
)
pm.query_or_save(
PromptTemplate.from_template(CODE_COMMENT_TEMPLATE_ZH),
prompt_name=CODE_COMMENT,
**zh_ext_params,
)
pm.query_or_save(
PromptTemplate.from_template(CODE_COMMENT_TEMPLATE_EN),
prompt_name=CODE_COMMENT,
**en_ext_params,
)
pm.query_or_save(
PromptTemplate.from_template(CODE_TRANSLATE_TEMPLATE_ZH),
prompt_name=CODE_TRANSLATE,
**zh_ext_params,
)
pm.query_or_save(
PromptTemplate.from_template(CODE_TRANSLATE_TEMPLATE_EN),
prompt_name=CODE_TRANSLATE,
**en_ext_params,
)
class PromptTemplateBuilderOperator(MapOperator[TriggerReqBody, ChatPromptTemplate]):
"""Build prompt template for chat with code."""
def __init__(self, **kwargs):
super().__init__(**kwargs)
self._default_prompt_manager = PromptManager()
async def map(self, input_value: TriggerReqBody) -> ChatPromptTemplate:
from dbgpt_serve.prompt.serve import SERVE_APP_NAME as PROMPT_SERVE_APP_NAME
from dbgpt_serve.prompt.serve import Serve as PromptServe
prompt_serve = self.system_app.get_component(
PROMPT_SERVE_APP_NAME, PromptServe, default_component=None
)
if prompt_serve:
pm = prompt_serve.prompt_manager
else:
pm = self._default_prompt_manager
load_or_save_prompt_template(pm)
user_language = self.system_app.config.get_current_lang(default="en")
if not input_value.command:
# No command, just chat, not include system prompt.
default_prompt_list = pm.prefer_query(
CODE_DEFAULT, prefer_prompt_language=user_language
)
default_prompt_template = (
default_prompt_list[0].to_prompt_template().template
)
prompt = ChatPromptTemplate(
messages=[
SystemPromptTemplate.from_template(default_prompt_template),
MessagesPlaceholder(variable_name="chat_history"),
HumanPromptTemplate.from_template("{user_input}"),
]
)
return prompt
# Query prompt template from prompt manager by command name
prompt_list = pm.prefer_query(
input_value.command, prefer_prompt_language=user_language
)
if not prompt_list:
error_msg = f"Prompt not found for command {input_value.command}, user_language: {user_language}"
logger.error(error_msg)
raise ValueError(error_msg)
prompt_template = prompt_list[0].to_prompt_template()
return ChatPromptTemplate(
messages=[
SystemPromptTemplate.from_template(prompt_template.template),
MessagesPlaceholder(variable_name="chat_history"),
HumanPromptTemplate.from_template("{user_input}"),
]
)
def parse_prompt_args(req: TriggerReqBody) -> Dict[str, Any]:
prompt_args = {"user_input": req.messages}
if not req.command:
return prompt_args
if req.command == CODE_TRANSLATE:
prompt_args["source_language"] = req.language
prompt_args["target_language"] = req.target_language
else:
prompt_args["language"] = req.language
return prompt_args
async def build_model_request(
messages: List[ModelMessage], req_body: TriggerReqBody
) -> ModelRequest:
return ModelRequest.build_request(
model=req_body.model,
messages=messages,
context=req_body.context,
stream=req_body.stream,
)
with DAG("dbgpt_awel_data_analyst_assistant") as dag:
trigger = HttpTrigger(
"/examples/data_analyst/copilot",
request_body=TriggerReqBody,
methods="POST",
streaming_predict_func=lambda x: x.stream,
)
prompt_template_load_task = PromptTemplateBuilderOperator()
# Load and store chat history
chat_history_load_task = ServePreChatHistoryLoadOperator()
keep_start_rounds = int(os.getenv("DBGPT_AWEL_DATA_ANALYST_KEEP_START_ROUNDS", 0))
keep_end_rounds = int(os.getenv("DBGPT_AWEL_DATA_ANALYST_KEEP_END_ROUNDS", 5))
# History transform task, here we keep `keep_start_rounds` round messages of history,
# and keep `keep_end_rounds` round messages of history.
history_transform_task = BufferedConversationMapperOperator(
keep_start_rounds=keep_start_rounds, keep_end_rounds=keep_end_rounds
)
history_prompt_build_task = HistoryDynamicPromptBuilderOperator(
history_key="chat_history"
)
model_request_build_task = JoinOperator(build_model_request)
# Use BaseLLMOperator to generate response.
llm_task = LLMOperator(task_name="llm_task")
streaming_llm_task = StreamingLLMOperator(task_name="streaming_llm_task")
branch_task = LLMBranchOperator(
stream_task_name="streaming_llm_task", no_stream_task_name="llm_task"
)
model_parse_task = MapOperator(lambda out: out.to_dict())
openai_format_stream_task = OpenAIStreamingOutputOperator()
result_join_task = BranchJoinOperator()
trigger >> prompt_template_load_task >> history_prompt_build_task
(
trigger
>> MapOperator(
lambda req: ModelRequestContext(
conv_uid=req.context.conv_uid,
stream=req.stream,
user_name=req.context.user_name,
sys_code=req.context.sys_code,
chat_mode=req.context.chat_mode,
)
)
>> chat_history_load_task
>> history_transform_task
>> history_prompt_build_task
)
trigger >> MapOperator(parse_prompt_args) >> history_prompt_build_task
history_prompt_build_task >> model_request_build_task
trigger >> model_request_build_task
model_request_build_task >> branch_task
# The branch of no streaming response.
(branch_task >> llm_task >> model_parse_task >> result_join_task)
# The branch of streaming response.
(branch_task >> streaming_llm_task >> openai_format_stream_task >> result_join_task)
if __name__ == "__main__":
if dag.leaf_nodes[0].dev_mode:
from dbgpt.core.awel import setup_dev_environment
setup_dev_environment([dag])
else:
pass
"""AWEL: Simple chat dag example
DB-GPT will automatically load and execute the current file after startup.
Example:
.. code-block:: shell
DBGPT_SERVER="http://127.0.0.1:5555"
MODEL="gpt-3.5-turbo"
curl -X POST $DBGPT_SERVER/api/v1/awel/trigger/examples/simple_chat \
-H "Content-Type: application/json" -d '{
"model": "'"$MODEL"'",
"user_input": "hello"
}'
"""
from dbgpt._private.pydantic import BaseModel, Field
from dbgpt.core import ModelMessage, ModelRequest
from dbgpt.core.awel import DAG, HttpTrigger, MapOperator
from dbgpt.model.operators import LLMOperator
class TriggerReqBody(BaseModel):
model: str = Field(..., description="Model name")
user_input: str = Field(..., description="User input")
class RequestHandleOperator(MapOperator[TriggerReqBody, ModelRequest]):
def __init__(self, **kwargs):
super().__init__(**kwargs)
async def map(self, input_value: TriggerReqBody) -> ModelRequest:
messages = [ModelMessage.build_human_message(input_value.user_input)]
print(f"Receive input value: {input_value}")
return ModelRequest.build_request(input_value.model, messages)
with DAG("dbgpt_awel_simple_dag_example", tags={"label": "example"}) as dag:
# Receive http request and trigger dag to run.
trigger = HttpTrigger(
"/examples/simple_chat", methods="POST", request_body=TriggerReqBody
)
request_handle_task = RequestHandleOperator()
llm_task = LLMOperator(task_name="llm_task")
model_parse_task = MapOperator(lambda out: out.to_dict())
trigger >> request_handle_task >> llm_task >> model_parse_task
if __name__ == "__main__":
if dag.leaf_nodes[0].dev_mode:
# Development mode, you can run the dag locally for debugging.
from dbgpt.core.awel import setup_dev_environment
setup_dev_environment([dag], port=5555)
else:
# Production mode, DB-GPT will automatically load and execute the current file after startup.
pass
"""AWEL: Simple chat with history example
DB-GPT will automatically load and execute the current file after startup.
Examples:
Call with non-streaming response.
.. code-block:: shell
DBGPT_SERVER="http://127.0.0.1:5555"
MODEL="gpt-3.5-turbo"
# Fist round
curl -X POST $DBGPT_SERVER/api/v1/awel/trigger/examples/simple_history/multi_round/chat/completions \
-H "Content-Type: application/json" -d '{
"model": "'"$MODEL"'",
"context": {
"conv_uid": "uuid_conv_1234"
},
"messages": "Who is elon musk?"
}'
# Second round
curl -X POST $DBGPT_SERVER/api/v1/awel/trigger/examples/simple_history/multi_round/chat/completions \
-H "Content-Type: application/json" -d '{
"model": "'"$MODEL"'",
"context": {
"conv_uid": "uuid_conv_1234"
},
"messages": "Is he rich?"
}'
Call with streaming response.
.. code-block:: shell
curl -X POST $DBGPT_SERVER/api/v1/awel/trigger/examples/simple_history/multi_round/chat/completions \
-H "Content-Type: application/json" -d '{
"model": "'"$MODEL"'",
"context": {
"conv_uid": "uuid_conv_stream_1234"
},
"stream": true,
"messages": "Who is elon musk?"
}'
# Second round
curl -X POST $DBGPT_SERVER/api/v1/awel/trigger/examples/simple_history/multi_round/chat/completions \
-H "Content-Type: application/json" -d '{
"model": "'"$MODEL"'",
"context": {
"conv_uid": "uuid_conv_stream_1234"
},
"stream": true,
"messages": "Is he rich?"
}'
"""
import logging
from typing import Dict, List, Optional, Union
from dbgpt._private.pydantic import BaseModel, Field
from dbgpt.core import (
ChatPromptTemplate,
HumanPromptTemplate,
InMemoryStorage,
MessagesPlaceholder,
ModelMessage,
ModelRequest,
ModelRequestContext,
SystemPromptTemplate,
)
from dbgpt.core.awel import DAG, BranchJoinOperator, HttpTrigger, MapOperator
from dbgpt.core.operators import (
ChatComposerInput,
ChatHistoryPromptComposerOperator,
LLMBranchOperator,
)
from dbgpt.model.operators import (
LLMOperator,
OpenAIStreamingOutputOperator,
StreamingLLMOperator,
)
logger = logging.getLogger(__name__)
class ReqContext(BaseModel):
user_name: Optional[str] = Field(
None, description="The user name of the model request."
)
sys_code: Optional[str] = Field(
None, description="The system code of the model request."
)
conv_uid: Optional[str] = Field(
None, description="The conversation uid of the model request."
)
class TriggerReqBody(BaseModel):
messages: Union[str, List[Dict[str, str]]] = Field(
..., description="User input messages"
)
model: str = Field(..., description="Model name")
stream: Optional[bool] = Field(default=False, description="Whether return stream")
context: Optional[ReqContext] = Field(
default=None, description="The context of the model request."
)
async def build_model_request(
messages: List[ModelMessage], req_body: TriggerReqBody
) -> ModelRequest:
return ModelRequest.build_request(
model=req_body.model,
messages=messages,
context=req_body.context,
stream=req_body.stream,
)
with DAG("dbgpt_awel_simple_chat_history") as multi_round_dag:
# Receive http request and trigger dag to run.
trigger = HttpTrigger(
"/examples/simple_history/multi_round/chat/completions",
methods="POST",
request_body=TriggerReqBody,
streaming_predict_func=lambda req: req.stream,
)
prompt = ChatPromptTemplate(
messages=[
SystemPromptTemplate.from_template("You are a helpful chatbot."),
MessagesPlaceholder(variable_name="chat_history"),
HumanPromptTemplate.from_template("{user_input}"),
]
)
composer_operator = ChatHistoryPromptComposerOperator(
prompt_template=prompt,
keep_end_rounds=5,
storage=InMemoryStorage(),
message_storage=InMemoryStorage(),
)
# Use BaseLLMOperator to generate response.
llm_task = LLMOperator(task_name="llm_task")
streaming_llm_task = StreamingLLMOperator(task_name="streaming_llm_task")
branch_task = LLMBranchOperator(
stream_task_name="streaming_llm_task", no_stream_task_name="llm_task"
)
model_parse_task = MapOperator(lambda out: out.to_dict())
openai_format_stream_task = OpenAIStreamingOutputOperator()
result_join_task = BranchJoinOperator()
req_handle_task = MapOperator(
lambda req: ChatComposerInput(
context=ModelRequestContext(
conv_uid=req.context.conv_uid, stream=req.stream
),
prompt_dict={"user_input": req.messages},
model_dict={
"model": req.model,
"context": req.context,
"stream": req.stream,
},
)
)
trigger >> req_handle_task >> composer_operator >> branch_task
# The branch of no streaming response.
branch_task >> llm_task >> model_parse_task >> result_join_task
# The branch of streaming response.
branch_task >> streaming_llm_task >> openai_format_stream_task >> result_join_task
if __name__ == "__main__":
if multi_round_dag.leaf_nodes[0].dev_mode:
# Development mode, you can run the dag locally for debugging.
from dbgpt.core.awel import setup_dev_environment
setup_dev_environment([multi_round_dag], port=5555)
else:
# Production mode, DB-GPT will automatically load and execute the current file after startup.
pass
"""AWEL: Simple dag example
DB-GPT will automatically load and execute the current file after startup.
Example:
.. code-block:: shell
DBGPT_SERVER="http://127.0.0.1:5555"
curl -X GET $DBGPT_SERVER/api/v1/awel/trigger/examples/hello\?name\=zhangsan
"""
from dbgpt._private.pydantic import BaseModel, Field
from dbgpt.core.awel import DAG, HttpTrigger, MapOperator
class TriggerReqBody(BaseModel):
name: str = Field(..., description="User name")
age: int = Field(18, description="User age")
class RequestHandleOperator(MapOperator[TriggerReqBody, str]):
def __init__(self, **kwargs):
super().__init__(**kwargs)
async def map(self, input_value: TriggerReqBody) -> str:
print(f"Receive input value: {input_value}")
return f"Hello, {input_value.name}, your age is {input_value.age}"
with DAG("simple_dag_example") as dag:
trigger = HttpTrigger("/examples/hello", request_body=TriggerReqBody)
map_node = RequestHandleOperator()
trigger >> map_node
if __name__ == "__main__":
if dag.leaf_nodes[0].dev_mode:
from dbgpt.core.awel import setup_dev_environment
setup_dev_environment([dag])
else:
pass
"""AWEL: Simple llm client example
DB-GPT will automatically load and execute the current file after startup.
Examples:
Call with non-streaming response.
.. code-block:: shell
DBGPT_SERVER="http://127.0.0.1:5555"
MODEL="gpt-3.5-turbo"
curl -X POST $DBGPT_SERVER/api/v1/awel/trigger/examples/simple_client/chat/completions \
-H "Content-Type: application/json" -d '{
"model": "'"$MODEL"'",
"messages": "hello"
}'
Call with streaming response.
.. code-block:: shell
curl -X POST $DBGPT_SERVER/api/v1/awel/trigger/examples/simple_client/chat/completions \
-H "Content-Type: application/json" -d '{
"model": "'"$MODEL"'",
"messages": "hello",
"stream": true
}'
Call model and count token.
.. code-block:: shell
curl -X POST $DBGPT_SERVER/api/v1/awel/trigger/examples/simple_client/count_token \
-H "Content-Type: application/json" -d '{
"model": "'"$MODEL"'",
"messages": "hello"
}'
"""
import logging
from typing import Any, Dict, List, Optional, Union
from dbgpt._private.pydantic import BaseModel, Field
from dbgpt.core import LLMClient
from dbgpt.core.awel import DAG, BranchJoinOperator, HttpTrigger, MapOperator
from dbgpt.core.operators import LLMBranchOperator, RequestBuilderOperator
from dbgpt.model.operators import (
LLMOperator,
MixinLLMOperator,
OpenAIStreamingOutputOperator,
StreamingLLMOperator,
)
logger = logging.getLogger(__name__)
class TriggerReqBody(BaseModel):
messages: Union[str, List[Dict[str, str]]] = Field(
..., description="User input messages"
)
model: str = Field(..., description="Model name")
stream: Optional[bool] = Field(default=False, description="Whether return stream")
class MyModelToolOperator(
MixinLLMOperator, MapOperator[TriggerReqBody, Dict[str, Any]]
):
def __init__(self, llm_client: Optional[LLMClient] = None, **kwargs):
super().__init__(llm_client)
MapOperator.__init__(self, llm_client, **kwargs)
async def map(self, input_value: TriggerReqBody) -> Dict[str, Any]:
prompt_tokens = await self.llm_client.count_token(
input_value.model, input_value.messages
)
available_models = await self.llm_client.models()
return {
"prompt_tokens": prompt_tokens,
"available_models": available_models,
}
with DAG("dbgpt_awel_simple_llm_client_generate") as client_generate_dag:
# Receive http request and trigger dag to run.
trigger = HttpTrigger(
"/examples/simple_client/chat/completions",
methods="POST",
request_body=TriggerReqBody,
streaming_predict_func=lambda req: req.stream,
)
request_handle_task = RequestBuilderOperator()
llm_task = LLMOperator(task_name="llm_task")
streaming_llm_task = StreamingLLMOperator(task_name="streaming_llm_task")
branch_task = LLMBranchOperator(
stream_task_name="streaming_llm_task", no_stream_task_name="llm_task"
)
model_parse_task = MapOperator(lambda out: out.to_dict())
openai_format_stream_task = OpenAIStreamingOutputOperator()
result_join_task = BranchJoinOperator()
trigger >> request_handle_task >> branch_task
branch_task >> llm_task >> model_parse_task >> result_join_task
branch_task >> streaming_llm_task >> openai_format_stream_task >> result_join_task
with DAG("dbgpt_awel_simple_llm_client_count_token") as client_count_token_dag:
# Receive http request and trigger dag to run.
trigger = HttpTrigger(
"/examples/simple_client/count_token",
methods="POST",
request_body=TriggerReqBody,
)
model_task = MyModelToolOperator()
trigger >> model_task
if __name__ == "__main__":
if client_generate_dag.leaf_nodes[0].dev_mode:
# Development mode, you can run the dag locally for debugging.
from dbgpt.core.awel import setup_dev_environment
dags = [client_generate_dag, client_count_token_dag]
setup_dev_environment(dags, port=5555)
else:
# Production mode, DB-GPT will automatically load and execute the current file after startup.
pass
import os
from typing import Any, Dict, Optional
from pandas import DataFrame
from dbgpt._private.pydantic import BaseModel, Field
from dbgpt.configs.model_config import MODEL_PATH, PILOT_PATH
from dbgpt.core import LLMClient, ModelMessage, ModelMessageRoleType, ModelRequest
from dbgpt.core.awel import DAG, HttpTrigger, JoinOperator, MapOperator
from dbgpt.datasource.rdbms.base import RDBMSConnector
from dbgpt.model.proxy import OpenAILLMClient
from dbgpt.rag.embedding import DefaultEmbeddingFactory
from dbgpt.util.chat_util import run_async_tasks
from dbgpt_ext.datasource.rdbms.conn_sqlite import SQLiteTempConnector
from dbgpt_ext.rag.operators.schema_linking import SchemaLinkingOperator
from dbgpt_ext.storage.vector_store.chroma_store import ChromaStore, ChromaVectorConfig
"""AWEL: Simple nl-schemalinking-sql-chart operator example
pre-requirements:
1. install openai python sdk
```
pip install "db-gpt[openai]"
```
2. set openai key and base
```
export OPENAI_API_KEY={your_openai_key}
export OPENAI_API_BASE={your_openai_base}
```
or
```
import os
os.environ["OPENAI_API_KEY"] = {your_openai_key}
os.environ["OPENAI_API_BASE"] = {your_openai_base}
```
python examples/awel/simple_nl_schema_sql_chart_example.py
Examples:
..code-block:: shell
curl --location 'http://127.0.0.1:5555/api/v1/awel/trigger/examples/rag/schema_linking' \
--header 'Content-Type: application/json' \
--data '{"query": "Statistics of user age in the user table are based on three categories: age is less than 10, age is greater than or equal to 10 and less than or equal to 20, and age is greater than 20. The first column of the statistical results is different ages, and the second column is count."}'
"""
INSTRUCTION = (
"I want you to act as a SQL terminal in front of an example database, you need only to return the sql "
"command to me.Below is an instruction that describes a task, Write a response that appropriately "
"completes the request.\n###Instruction:\n{}"
)
INPUT_PROMPT = "\n###Input:\n{}\n###Response:"
def _create_vector_connector():
"""Create vector connector."""
config = ChromaVectorConfig(
persist_path=PILOT_PATH,
name="embedding_rag_test",
embedding_fn=DefaultEmbeddingFactory(
default_model_name=os.path.join(MODEL_PATH, "text2vec-large-chinese"),
).create(),
)
return ChromaStore(config)
def _create_temporary_connection():
"""Create a temporary database connection for testing."""
connect = SQLiteTempConnector.create_temporary_db()
connect.create_temp_tables(
{
"user": {
"columns": {
"id": "INTEGER PRIMARY KEY",
"name": "TEXT",
"age": "INTEGER",
},
"data": [
(1, "Tom", 8),
(2, "Jerry", 16),
(3, "Jack", 18),
(4, "Alice", 20),
(5, "Bob", 22),
],
}
}
)
connect.create_temp_tables(
{
"job": {
"columns": {
"id": "INTEGER PRIMARY KEY",
"name": "TEXT",
"age": "INTEGER",
},
"data": [
(1, "student", 8),
(2, "student", 16),
(3, "student", 18),
(4, "teacher", 20),
(5, "teacher", 22),
],
}
}
)
connect.create_temp_tables(
{
"student": {
"columns": {
"id": "INTEGER PRIMARY KEY",
"name": "TEXT",
"age": "INTEGER",
"info": "TEXT",
},
"data": [
(1, "Andy", 8, "good"),
(2, "Jerry", 16, "bad"),
(3, "Wendy", 18, "good"),
(4, "Spider", 20, "bad"),
(5, "David", 22, "bad"),
],
}
}
)
return connect
def _prompt_join_fn(query: str, chunks: str) -> str:
prompt = INSTRUCTION.format(chunks + INPUT_PROMPT.format(query))
return prompt
class TriggerReqBody(BaseModel):
query: str = Field(..., description="User query")
class RequestHandleOperator(MapOperator[TriggerReqBody, Dict]):
def __init__(self, **kwargs):
super().__init__(**kwargs)
async def map(self, input_value: TriggerReqBody) -> Dict:
params = {
"query": input_value.query,
}
print(f"Receive input value: {input_value.query}")
return params
class SqlGenOperator(MapOperator[Any, Any]):
"""The Sql Generation Operator."""
def __init__(self, llm: Optional[LLMClient], model_name: str, **kwargs):
"""Init the sql generation operator
Args:
llm (Optional[LLMClient]): base llm
"""
super().__init__(**kwargs)
self._llm = llm
self._model_name = model_name
async def map(self, prompt_with_query_and_schema: str) -> str:
"""generate sql by llm.
Args:
prompt_with_query_and_schema (str): prompt
Return:
str: sql
"""
messages = [
ModelMessage(
role=ModelMessageRoleType.SYSTEM, content=prompt_with_query_and_schema
)
]
request = ModelRequest(model=self._model_name, messages=messages)
tasks = [self._llm.generate(request)]
output = await run_async_tasks(tasks=tasks, concurrency_limit=1)
sql = output[0].text
return sql
class SqlExecOperator(MapOperator[Any, Any]):
"""The Sql Execution Operator."""
def __init__(self, connector: Optional[RDBMSConnector] = None, **kwargs):
"""
Args:
connection (Optional[RDBMSConnector]): RDBMSConnector connection
"""
super().__init__(**kwargs)
self._connector = connector
def map(self, sql: str) -> DataFrame:
"""retrieve table schemas.
Args:
sql (str): query.
Return:
str: sql execution
"""
dataframe = self._connector.run_to_df(command=sql, fetch="all")
print(f"sql data is \n{dataframe}")
return dataframe
class ChartDrawOperator(MapOperator[Any, Any]):
"""The Chart Draw Operator."""
def __init__(self, **kwargs):
"""
Args:
connection (RDBMSConnector): The connection.
"""
super().__init__(**kwargs)
def map(self, df: DataFrame) -> str:
"""get sql result in db and draw.
Args:
sql (str): str.
"""
import matplotlib.pyplot as plt
category_column = df.columns[0]
count_column = df.columns[1]
plt.figure(figsize=(8, 4))
plt.bar(df[category_column], df[count_column])
plt.xlabel(category_column)
plt.ylabel(count_column)
plt.show()
return str(df)
with DAG("simple_nl_schema_sql_chart_example") as dag:
trigger = HttpTrigger(
"/examples/rag/schema_linking", methods="POST", request_body=TriggerReqBody
)
request_handle_task = RequestHandleOperator()
query_operator = MapOperator(lambda request: request["query"])
llm = (OpenAILLMClient(api_key=os.getenv("OPENAI_API_KEY", "your api key")),)
model_name = "gpt-3.5-turbo"
retriever_task = SchemaLinkingOperator(
connector=_create_temporary_connection(), llm=llm, model_name=model_name
)
prompt_join_operator = JoinOperator(combine_function=_prompt_join_fn)
sql_gen_operator = SqlGenOperator(llm=llm, model_name=model_name)
sql_exec_operator = SqlExecOperator(connector=_create_temporary_connection())
draw_chart_operator = ChartDrawOperator(connector=_create_temporary_connection())
trigger >> request_handle_task >> query_operator >> prompt_join_operator
(
trigger
>> request_handle_task
>> query_operator
>> retriever_task
>> prompt_join_operator
)
prompt_join_operator >> sql_gen_operator >> sql_exec_operator >> draw_chart_operator
if __name__ == "__main__":
if dag.leaf_nodes[0].dev_mode:
# Development mode, you can run the dag locally for debugging.
from dbgpt.core.awel import setup_dev_environment
setup_dev_environment([dag], port=5555)
else:
pass
"""AWEL: Simple rag rewrite example
pre-requirements:
1. install openai python sdk
```
pip install openai
```
2. set openai key and base
```
export OPENAI_API_KEY={your_openai_key}
export OPENAI_API_BASE={your_openai_base}
```
or
```
import os
os.environ["OPENAI_API_KEY"] = {your_openai_key}
os.environ["OPENAI_API_BASE"] = {your_openai_base}
```
python examples/awel/simple_rag_rewrite_example.py
Example:
.. code-block:: shell
DBGPT_SERVER="http://127.0.0.1:5555"
curl -X POST $DBGPT_SERVER/api/v1/awel/trigger/examples/rag/rewrite \
-H "Content-Type: application/json" -d '{
"query": "compare curry and james",
"context":"steve curry and lebron james are nba all-stars"
}'
"""
import os
from typing import Dict
from dbgpt._private.pydantic import BaseModel, Field
from dbgpt.core.awel import DAG, HttpTrigger, MapOperator
from dbgpt.model.proxy import OpenAILLMClient
from dbgpt.rag.operators import QueryRewriteOperator
class TriggerReqBody(BaseModel):
query: str = Field(..., description="User query")
context: str = Field(..., description="context")
class RequestHandleOperator(MapOperator[TriggerReqBody, Dict]):
def __init__(self, **kwargs):
super().__init__(**kwargs)
async def map(self, input_value: TriggerReqBody) -> Dict:
params = {
"query": input_value.query,
"context": input_value.context,
}
print(f"Receive input value: {input_value}")
return params
with DAG("dbgpt_awel_simple_rag_rewrite_example") as dag:
trigger = HttpTrigger(
"/examples/rag/rewrite", methods="POST", request_body=TriggerReqBody
)
request_handle_task = RequestHandleOperator()
# build query rewrite operator
rewrite_task = QueryRewriteOperator(
llm_client=OpenAILLMClient(api_key=os.getenv("OPENAI_API_KEY", "your api key")),
nums=2,
)
trigger >> request_handle_task >> rewrite_task
if __name__ == "__main__":
if dag.leaf_nodes[0].dev_mode:
# Development mode, you can run the dag locally for debugging.
from dbgpt.core.awel import setup_dev_environment
setup_dev_environment([dag], port=5555)
else:
pass
"""AWEL:
This example shows how to use AWEL to build a simple rag summary example.
pre-requirements:
1. install openai python sdk
```
pip install openai
```
2. set openai key and base
```
export OPENAI_API_KEY={your_openai_key}
export OPENAI_API_BASE={your_openai_base}
```
or
```
import os
os.environ["OPENAI_API_KEY"] = {your_openai_key}
os.environ["OPENAI_API_BASE"] = {your_openai_base}
```
python examples/awel/simple_rag_summary_example.py
Example:
.. code-block:: shell
curl -X POST http://127.0.0.1:5555/api/v1/awel/trigger/examples/rag/summary \
-H "Content-Type: application/json" -d '{
"url": "https://docs.dbgpt.site/docs/awel"
}'
"""
import os
from typing import Dict
from dbgpt._private.pydantic import BaseModel, Field
from dbgpt.core.awel import DAG, HttpTrigger, MapOperator
from dbgpt.model.proxy import OpenAILLMClient
from dbgpt.rag.knowledge.base import KnowledgeType
from dbgpt_ext.rag.operators import KnowledgeOperator, SummaryAssemblerOperator
class TriggerReqBody(BaseModel):
url: str = Field(..., description="url")
class RequestHandleOperator(MapOperator[TriggerReqBody, Dict]):
def __init__(self, **kwargs):
super().__init__(**kwargs)
async def map(self, input_value: TriggerReqBody) -> Dict:
params = {
"url": input_value.url,
}
print(f"Receive input value: {input_value}")
return params
with DAG("dbgpt_awel_simple_rag_summary_example") as dag:
trigger = HttpTrigger(
"/examples/rag/summary", methods="POST", request_body=TriggerReqBody
)
request_handle_task = RequestHandleOperator()
path_operator = MapOperator(lambda request: request["url"])
# build knowledge operator
knowledge_operator = KnowledgeOperator(knowledge_type=KnowledgeType.URL.name)
# build summary assembler operator
summary_operator = SummaryAssemblerOperator(
llm_client=OpenAILLMClient(api_key=os.getenv("OPENAI_API_KEY", "your api key")),
language="en",
)
(
trigger
>> request_handle_task
>> path_operator
>> knowledge_operator
>> summary_operator
)
if __name__ == "__main__":
if dag.leaf_nodes[0].dev_mode:
# Development mode, you can run the dag locally for debugging.
from dbgpt.core.awel import setup_dev_environment
setup_dev_environment([dag], port=5555)
else:
pass
"""Client: Simple App CRUD example.
This example demonstrates how to use the dbgpt client to get, list apps.
Example:
.. code-block:: python
DBGPT_API_KEY = "dbgpt"
client = Client(api_key=DBGPT_API_KEY)
# 1. List all apps
res = await list_app(client)
# 2. Get an app
res = await get_app(client, app_id="bf1c7561-13fc-4fe0-bf5d-c22e724766a8")
"""
import asyncio
from dbgpt_client import Client
from dbgpt_client.app import list_app
async def main():
# initialize client
DBGPT_API_KEY = "dbgpt"
client = Client(api_key=DBGPT_API_KEY)
res = await list_app(client)
print(res)
if __name__ == "__main__":
asyncio.run(main())
"""Client: Simple Chat example.
This example demonstrates how to use the dbgpt client to chat with the chatgpt model.
Example:
.. code-block:: python
DBGPT_API_KEY = "dbgpt"
# chat with stream
client = Client(api_key=DBGPT_API_KEY)
# 1. chat normal
async for data in client.chat_stream(
model="chatgpt_proxyllm",
messages="hello",
):
print(data.dict())
# chat with no stream
res = await client.chat(model="chatgpt_proxyllm", messages="Hello?")
print(res.json())
# 2. chat with app
async for data in client.chat_stream(
model="chatgpt_proxyllm",
chat_mode="chat_app",
chat_param="${app_code}",
messages="hello",
):
print(data.dict())
# 3. chat with knowledge
async for data in client.chat_stream(
model="chatgpt_proxyllm",
chat_mode="chat_knowledge",
chat_param="${space_name}",
messages="hello",
):
print(data.dict())
# 4. chat with flow
async for data in client.chat_stream(
model="chatgpt_proxyllm",
chat_mode="chat_flow",
chat_param="${flow_id}",
messages="hello",
):
print(data.dict())
"""
import asyncio
from dbgpt_client import Client
async def main():
# initialize client
DBGPT_API_KEY = "dbgpt"
client = Client(api_key=DBGPT_API_KEY)
data = await client.chat(model="Qwen2.5-72B-Instruct", messages="hello")
# async for data in client.chat_stream(
# model="chatgpt_proxyllm",
# messages="hello",
# ):
print(data)
# res = await client.chat(model="chatgpt_proxyllm" ,messages="hello")
# print(res)
if __name__ == "__main__":
asyncio.run(main())
"""Client: run evaluation example.
This example demonstrates how to use the dbgpt client to evaluate with the rag recall
and app answer.
Example:
.. code-block:: python
DBGPT_API_KEY = "dbgpt"
client = Client(api_key=DBGPT_API_KEY)
# 1. evaluate with rag recall
request = EvaluateServeRequest(
# The scene type of the evaluation, e.g. support app, recall
scene_key="recall",
# e.g. app id(when scene_key is app), space id(when scene_key is recall)
scene_value="147",
context={"top_k": 5},
evaluate_metrics=[
"RetrieverHitRateMetric",
"RetrieverMRRMetric",
"RetrieverSimilarityMetric",
],
datasets=[
{
"query": "what awel talked about",
"doc_name": "awel.md",
}
],
)
# 2. evaluate with app answer
request = EvaluateServeRequest(
# The scene type of the evaluation, e.g. support app, recall
scene_key="app",
# e.g. app id(when scene_key is app), space id(when scene_key is recall)
scene_value="2c76eea2-83b6-11ef-b482-acde48001122",
"context"={
"top_k": 5,
"prompt": "942acd7e33b54ce28565f89f9b278044",
"model": "zhipu_proxyllm",
},
evaluate_metrics=[
"AnswerRelevancyMetric",
],
datasets=[
{
"query": "what awel talked about",
"doc_name": "awel.md",
}
],
)
data = await run_evaluation(client, request=request)
print(data)
"""
import asyncio
from dbgpt_client import Client
from dbgpt_client.evaluation import run_evaluation
from dbgpt_serve.evaluate.api.schemas import EvaluateServeRequest
async def main():
# initialize client
DBGPT_API_KEY = "dbgpt"
SPACE_ID = "147"
client = Client(api_key=DBGPT_API_KEY)
request = EvaluateServeRequest(
# The scene type of the evaluation, e.g. support app, recall
scene_key="recall",
# e.g. app id(when scene_key is app), space id(when scene_key is recall)
scene_value=SPACE_ID,
context={"top_k": 5},
evaluate_metrics=[
"RetrieverHitRateMetric",
"RetrieverMRRMetric",
"RetrieverSimilarityMetric",
],
datasets=[
{
"query": "what awel talked about",
"doc_name": "awel.md",
}
],
)
data = await run_evaluation(client, request=request)
print(data)
if __name__ == "__main__":
asyncio.run(main())
# /// script
# dependencies = [
# "openai",
# ]
# [tool.uv]
# exclude-newer = "2025-03-07T00:00:00Z"
# ///
"""Chat With Your DB-GPT's API by OpenAI Client
Sample Usage:
```bash
uv run examples/client/client_openai_chat.py -m Qwen/QwQ-32B --input "Hello"
```
More examples:
1. Chat Normal Mode:
```bash
uv run examples/client/client_openai_chat.py -m Qwen/QwQ-32B \
--input "Which is bigger, 9.8 or 9.11?"
```
2. Chat Database Mode(chat_with_db_qa):
```bash
uv run examples/client/client_openai_chat.py -m Qwen/QwQ-32B \
--chat-mode chat_with_db_qa \
--param "sqlite_dbgpt" \
--input "Which table stores database connection information?"
```
3. Chat With Your Data(chat_data):
```bash
uv run examples/client/client_openai_chat.py -m Qwen/QwQ-32B \
--chat-mode chat_data \
--param "sqlite_dbgpt" \
--input "Which database can I currently connect to? What is its name and type?"
```
4. Chat With Knowledge(chat_knowledge):
```bash
uv run examples/client/client_openai_chat.py -m Qwen/QwQ-32B \
--chat-mode chat_knowledge \
--param "awel" \
--input "What is AWEL?"
```
5. Chat With Third-party API(chat_third_party):
```bash
uv run examples/client/client_openai_chat.py -m deepseek-chat \
--input "Which is bigger, 9.8 or 9.11?" \
--chat-mode none \
--api-key $DEEPSEEK_API_KEY \
--api-base https://api.deepseek.com/v1
```
""" # noqa
import argparse
from openai import OpenAI
DBGPT_API_KEY = "dbgpt"
def handle_output(response):
has_thinking = False
print("=" * 80)
reasoning_content = ""
for chunk in response:
delta_content = chunk.choices[0].delta.content
if hasattr(chunk.choices[0].delta, "reasoning_content"):
reasoning_content = chunk.choices[0].delta.reasoning_content
if reasoning_content:
if not has_thinking:
print("<thinking>", flush=True)
print(reasoning_content, end="", flush=True)
has_thinking = True
if delta_content:
if has_thinking:
print("</thinking>", flush=True)
print(delta_content, end="", flush=True)
has_thinking = False
def main():
parser = argparse.ArgumentParser(description="OpenAI Chat Client")
parser.add_argument(
"-m",
"--model",
type=str,
default="deepseek-chat",
help="Model name",
)
parser.add_argument(
"-c",
"--chat-mode",
type=str,
default="chat_normal",
help="Chat mode. Default is chat_normal",
)
parser.add_argument(
"-p",
"--param",
type=str,
default=None,
help="Chat param",
)
parser.add_argument(
"--input",
type=str,
default="Hello, how are you?",
help="User input",
)
parser.add_argument(
"--api-key",
type=str,
default=DBGPT_API_KEY,
help="API key",
)
parser.add_argument(
"--api-base",
type=str,
default="http://localhost:5670/api/v2",
help="Base URL",
)
parser.add_argument(
"--max-tokens",
type=int,
default=4096,
help="Max tokens",
)
args = parser.parse_args()
client = OpenAI(
api_key=args.api_key,
base_url=args.api_base,
)
messages = [
{
"role": "user",
"content": args.input,
},
]
extra_body = {}
if args.chat_mode != "none":
extra_body["chat_mode"] = args.chat_mode
if args.param:
extra_body["chat_param"] = args.param
response = client.chat.completions.create(
model=args.model,
messages=messages,
extra_body=extra_body,
stream=True,
max_tokens=args.max_tokens,
)
handle_output(response)
if __name__ == "__main__":
main()
"""Client: Simple Flow CRUD example
This example demonstrates how to use the dbgpt client to create, get, update, and
delete datasource.
Example:
.. code-block:: python
DBGPT_API_KEY = "dbgpt"
client = Client(api_key=DBGPT_API_KEY)
# 1. Create a flow
res = await create_datasource(
client,
DatasourceModel(
db_name="dbgpt",
desc="for client datasource",
db_type="mysql",
db_type="mysql",
db_host="127.0.0.1",
db_user="root",
db_pwd="xxxx",
db_port=3306,
),
)
# 2. Update a flow
res = await update_datasource(
client,
DatasourceModel(
db_name="dbgpt",
desc="for client datasource",
db_type="mysql",
db_type="mysql",
db_host="127.0.0.1",
db_user="root",
db_pwd="xxxx",
db_port=3306,
),
)
# 3. Delete a flow
res = await delete_datasource(client, datasource_id="10")
# 4. Get a flow
res = await get_datasource(client, datasource_id="10")
# 5. List all datasource
res = await list_datasource(client)
"""
import asyncio
from dbgpt_client import Client
from dbgpt_client.datasource import list_datasource
async def main():
# initialize client
DBGPT_API_KEY = "dbgpt"
client = Client(api_key=DBGPT_API_KEY)
res = await list_datasource(client)
print(res)
if __name__ == "__main__":
asyncio.run(main())
"""Client: Simple Flow CRUD example
This example demonstrates how to use the dbgpt client to create, get, update, and
delete flows.
Example:
.. code-block:: python
DBGPT_API_KEY = "dbgpt"
client = Client(api_key=DBGPT_API_KEY)
# 1. Create a flow
res = await create_flow(
client,
FlowPanel(name="test_flow", desc="for client flow", owner="dbgpt"),
)
# 2. Update a flow
res = await update_flow(
client,
FlowPanel(name="test_flow", desc="for client flow333", owner="dbgpt"),
)
# 3. Delete a flow
res = await delete_flow(client, flow_id="bf1c7561-13fc-4fe0-bf5d-c22e724766a8")
# 4. Get a flow
res = await get_flow(client, flow_id="bf1c7561-13fc-4fe0-bf5d-c22e724766a8")
# 5. List all flows
res = await list_flow(client)
"""
import asyncio
from dbgpt_client import Client
from dbgpt_client.flow import list_flow
async def main():
# initialize client
DBGPT_API_KEY = "dbgpt"
client = Client(api_key=DBGPT_API_KEY)
res = await list_flow(client)
print(res)
if __name__ == "__main__":
asyncio.run(main())
"""Client: Simple Knowledge CRUD example.
This example demonstrates how to use the dbgpt client to create, get, update, and
delete knowledge spaces and documents.
Example:
.. code-block:: python
DBGPT_API_KEY = "dbgpt"
client = Client(api_key=DBGPT_API_KEY)
# 1. Create a space
res = await create_space(
client,
SpaceModel(
name="test_space",
vector_type="Chroma",
desc="for client space",
owner="dbgpt",
),
)
# 2. Update a space
res = await update_space(
client,
SpaceModel(
name="test_space",
vector_type="Chroma",
desc="for client space333",
owner="dbgpt",
),
)
# 3. Delete a space
res = await delete_space(client, space_id="37")
# 4. Get a space
res = await get_space(client, space_id="5")
# 5. List all spaces
res = await list_space(client)
# 6. Create a document
res = await create_document(
client,
DocumentModel(
space_id="5",
doc_name="test_doc",
doc_type="TEXT",
doc_content="test content",
doc_source="",
),
)
# 7. Sync a document
res = await sync_document(
client,
sync_model=SyncModel(
doc_id="153",
space_id="40",
model_name="text2vec",
chunk_parameters=ChunkParameters(chunk_strategy="Automatic"),
),
)
# 8. Get a document
res = await get_document(client, "52")
# 9. List all documents
res = await list_document(client)
# 10. Delete a document
res = await delete_document(client, "150")
"""
import asyncio
from dbgpt_client import Client
from dbgpt_client.knowledge import create_space
from dbgpt_client.schema import SpaceModel
async def main():
# initialize client
DBGPT_API_KEY = "dbgpt"
client = Client(api_key=DBGPT_API_KEY)
res = await create_space(
client,
SpaceModel(
name="test_space_1",
vector_type="Chroma",
desc="for client space desc",
owner="dbgpt",
),
)
print(res)
# list all spaces
# res = await list_space(client)
# print(res)
# get space
# res = await get_space(client, space_id='5')
# create space
# res = await create_space(client, SpaceModel(name="test_space", vector_type="Chroma", desc="for client space", owner="dbgpt"))
# update space
# res = await update_space(client, SpaceModel(name="test_space", vector_type="Chroma", desc="for client space333", owner="dbgpt"))
# delete space
# res = await delete_space(client, space_id='31')
# print(res)
# list all documents
# res = await list_document(client)
# get document
# res = await get_document(client, "52")
# delete document
# res = await delete_document(client, "150")
# create document
# res = await create_document(client, DocumentModel(space_id="5", doc_name="test_doc", doc_type="test", doc_content="test content"
# , doc_file=('your_file_name', open('{your_file_path}', 'rb'))))
# sync document
# res = await sync_document(client, sync_model=SyncModel(doc_id="157", space_id="49", model_name="text2vec", chunk_parameters=ChunkParameters(chunk_strategy="Automatic")))
if __name__ == "__main__":
asyncio.run(main())
import asyncio
import os
from dbgpt.configs.model_config import ROOT_PATH
from dbgpt_ext.rag import ChunkParameters
from dbgpt_ext.rag.assembler.bm25 import BM25Assembler
from dbgpt_ext.rag.knowledge import KnowledgeFactory
from dbgpt_ext.storage.vector_store.elastic_store import ElasticsearchStoreConfig
"""Embedding rag example.
pre-requirements:
set your elasticsearch config in your example code.
Examples:
..code-block:: shell
python examples/rag/bm25_retriever_example.py
"""
def _create_es_config():
"""Create vector connector."""
return ElasticsearchStoreConfig(
uri="localhost",
port="9200",
user="elastic",
password="dbgpt",
)
async def main():
file_path = os.path.join(ROOT_PATH, "docs/docs/awel/awel.md")
knowledge = KnowledgeFactory.from_file_path(file_path)
es_config = _create_es_config()
chunk_parameters = ChunkParameters(chunk_strategy="CHUNK_BY_SIZE")
# create bm25 assembler
assembler = BM25Assembler.load_from_knowledge(
knowledge=knowledge,
es_config=es_config,
chunk_parameters=chunk_parameters,
)
assembler.persist()
# get bm25 retriever
retriever = assembler.as_retriever(3)
chunks = retriever.retrieve_with_scores("what is awel talk about", 0.3)
print(f"bm25 rag example results:{chunks}")
if __name__ == "__main__":
asyncio.run(main())
"""This example demonstrates how to use the cross-encoder reranker
to rerank the retrieved chunks.
The cross-encoder reranker is a neural network model that takes a query
and a chunk as input and outputs a score that represents the relevance of the chunk
to the query.
Download pretrained cross-encoder models can be found at https://huggingface.co/models.
Example:
python examples/rag/cross_encoder_rerank_example.py
"""
import asyncio
import os
from dbgpt.configs.model_config import MODEL_PATH, PILOT_PATH, ROOT_PATH
from dbgpt.rag.embedding import DefaultEmbeddingFactory
from dbgpt.rag.retriever.rerank import CrossEncoderRanker
from dbgpt_ext.rag import ChunkParameters
from dbgpt_ext.rag.assembler import EmbeddingAssembler
from dbgpt_ext.rag.knowledge import KnowledgeFactory
from dbgpt_ext.storage.vector_store.chroma_store import ChromaStore, ChromaVectorConfig
def _create_vector_connector():
"""Create vector connector."""
config = ChromaVectorConfig(
persist_path=PILOT_PATH,
)
return ChromaStore(
config,
name="embedding_rag_test",
embedding_fn=DefaultEmbeddingFactory(
default_model_name=os.path.join(MODEL_PATH, "text2vec-large-chinese"),
).create(),
)
async def main():
file_path = os.path.join(ROOT_PATH, "docs/docs/awel/awel.md")
knowledge = KnowledgeFactory.from_file_path(file_path)
vector_connector = _create_vector_connector()
chunk_parameters = ChunkParameters(chunk_strategy="CHUNK_BY_MARKDOWN_HEADER")
# get embedding assembler
assembler = EmbeddingAssembler.load_from_knowledge(
knowledge=knowledge,
chunk_parameters=chunk_parameters,
index_store=vector_connector,
)
assembler.persist()
# get embeddings retriever
retriever = assembler.as_retriever(3)
# create metadata filter
query = "what is awel talk about"
chunks = await retriever.aretrieve_with_scores(query, 0.3)
print("before rerank results:\n")
for i, chunk in enumerate(chunks):
print(f"----{i + 1}.chunk content:{chunk.content}\n score:{chunk.score}")
# cross-encoder rerankpython
cross_encoder_model = os.path.join(MODEL_PATH, "bge-reranker-base")
rerank = CrossEncoderRanker(topk=3, model=cross_encoder_model)
new_chunks = rerank.rank(chunks, query=query)
print("after cross-encoder rerank results:\n")
for i, chunk in enumerate(new_chunks):
print(f"----{i + 1}.chunk content:{chunk.content}\n score:{chunk.score}")
if __name__ == "__main__":
asyncio.run(main())
import os
from dbgpt.configs.model_config import MODEL_PATH, PILOT_PATH
from dbgpt.rag.embedding import DefaultEmbeddingFactory
from dbgpt_ext.datasource.rdbms.conn_sqlite import SQLiteTempConnector
from dbgpt_ext.rag.assembler import DBSchemaAssembler
from dbgpt_ext.storage.vector_store.chroma_store import ChromaStore, ChromaVectorConfig
"""DB struct rag example.
pre-requirements:
set your embedding model path in your example code.
```
embedding_model_path = "{your_embedding_model_path}"
```
Examples:
..code-block:: shell
python examples/rag/db_schema_rag_example.py
"""
def _create_temporary_connection():
"""Create a temporary database connection for testing."""
connect = SQLiteTempConnector.create_temporary_db()
connect.create_temp_tables(
{
"user": {
"columns": {
"id": "INTEGER PRIMARY KEY",
"name": "TEXT",
"age": "INTEGER",
},
"data": [
(1, "Tom", 10),
(2, "Jerry", 16),
(3, "Jack", 18),
(4, "Alice", 20),
(5, "Bob", 22),
],
}
}
)
return connect
def _create_vector_connector():
"""Create vector connector."""
config = ChromaVectorConfig(
persist_path=PILOT_PATH,
)
return ChromaStore(
config,
name="embedding_rag_test",
embedding_fn=DefaultEmbeddingFactory(
default_model_name=os.path.join(MODEL_PATH, "text2vec-large-chinese"),
).create(),
)
if __name__ == "__main__":
connection = _create_temporary_connection()
vector_connector = _create_vector_connector()
assembler = DBSchemaAssembler.load_from_connection(
connector=connection, table_vector_store_connector=vector_connector
)
assembler.persist()
# get db schema retriever
retriever = assembler.as_retriever(top_k=1)
chunks = retriever.retrieve("show columns from user")
print(f"db schema rag example results:{[chunk.content for chunk in chunks]}")
import asyncio
import os
from dbgpt.configs.model_config import MODEL_PATH, PILOT_PATH, ROOT_PATH
from dbgpt.rag.embedding import DefaultEmbeddingFactory
from dbgpt_ext.rag import ChunkParameters
from dbgpt_ext.rag.assembler import EmbeddingAssembler
from dbgpt_ext.rag.knowledge import KnowledgeFactory
from dbgpt_ext.storage.vector_store.chroma_store import ChromaStore, ChromaVectorConfig
"""Embedding rag example.
pre-requirements:
set your embedding model path in your example code.
```
embedding_model_path = "{your_embedding_model_path}"
```
Examples:
..code-block:: shell
python examples/rag/embedding_rag_example.py
"""
def _create_vector_connector():
"""Create vector connector."""
config = ChromaVectorConfig(
persist_path=PILOT_PATH,
)
return ChromaStore(
config,
name="embedding_rag_test",
embedding_fn=DefaultEmbeddingFactory(
default_model_name=os.path.join(MODEL_PATH, "text2vec-large-chinese"),
).create(),
)
async def main():
file_path = os.path.join(ROOT_PATH, "docs/docs/awel/awel.md")
knowledge = KnowledgeFactory.from_file_path(file_path)
vector_store = _create_vector_connector()
chunk_parameters = ChunkParameters(chunk_strategy="CHUNK_BY_SIZE")
# get embedding assembler
assembler = EmbeddingAssembler.load_from_knowledge(
knowledge=knowledge,
chunk_parameters=chunk_parameters,
index_store=vector_store,
)
assembler.persist()
# get embeddings retriever
retriever = assembler.as_retriever(3)
chunks = await retriever.aretrieve_with_scores("what is awel talk about", 0.3)
print(f"embedding rag example results:{chunks}")
if __name__ == "__main__":
asyncio.run(main())
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment