feat(Agent): ChatAgent And AgentHub
1.Merge main conflicts resolution
@ -230,22 +230,31 @@ class ApiCall:
|
||||
return False
|
||||
|
||||
def api_view_context(self, all_context: str, display_mode: bool = False):
|
||||
error_mk_tags = ["```", "```python", "```xml"]
|
||||
call_context_map = extract_content_open_ending(all_context, self.agent_prefix, self.agent_end, True)
|
||||
for api_index, api_context in call_context_map.items():
|
||||
api_status = self.plugin_status_map.get(api_context)
|
||||
if api_status is not None:
|
||||
if display_mode:
|
||||
if api_status.api_result:
|
||||
for tag in error_mk_tags:
|
||||
all_context = all_context.replace(tag + api_context + "```", api_context)
|
||||
all_context = all_context.replace(api_context, api_status.api_result)
|
||||
|
||||
else:
|
||||
if api_status.status == Status.FAILED.value:
|
||||
all_context = all_context.replace(api_context, f"""\n<span style=\"color:red\">ERROR!</span>{api_status.err_msg}\n """)
|
||||
else:
|
||||
cost = (api_status.end_time - self.start_time) / 1000
|
||||
cost_str = "{:.2f}".format(cost)
|
||||
for tag in error_mk_tags:
|
||||
all_context = all_context.replace(tag + api_context + "```", api_context)
|
||||
all_context = all_context.replace(api_context, f'\n<span style=\"color:green\">Waiting...{cost_str}S</span>\n')
|
||||
else:
|
||||
for tag in error_mk_tags:
|
||||
all_context = all_context.replace(tag + api_context + "```", api_context)
|
||||
all_context = all_context.replace(api_context, self.to_view_text(api_status))
|
||||
|
||||
else:
|
||||
# not ready api call view change
|
||||
now_time = datetime.now().timestamp() * 1000
|
||||
@ -263,6 +272,8 @@ class ApiCall:
|
||||
api_context = api_context.replace("\\n", "").replace("\n", "")
|
||||
api_call_element = ET.fromstring(api_context)
|
||||
api_name = api_call_element.find('name').text
|
||||
if api_name.find("[")>=0 or api_name.find("]")>=0:
|
||||
api_name = api_name.replace("[", "").replace("]", "")
|
||||
api_args = {}
|
||||
args_elements = api_call_element.find('args')
|
||||
for child_element in args_elements.iter():
|
||||
|
@ -14,7 +14,9 @@ import matplotlib.ticker as mtick
|
||||
from matplotlib.font_manager import FontManager
|
||||
|
||||
|
||||
CFG = Config()
|
||||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
static_message_img_path = os.path.join(os.getcwd(), "message/img")
|
||||
|
||||
|
@ -1,11 +1,9 @@
|
||||
from pandas import DataFrame
|
||||
|
||||
from pilot.base_modules.agent.commands.command_mange import command
|
||||
from pilot.configs.config import Config
|
||||
|
||||
|
||||
CFG = Config()
|
||||
|
||||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@command(
|
||||
"response_table",
|
||||
|
@ -1,12 +1,9 @@
|
||||
from pandas import DataFrame
|
||||
|
||||
from pilot.base_modules.agent.commands.command_mange import command
|
||||
from pilot.configs.config import Config
|
||||
from pilot.configs.model_config import LOGDIR
|
||||
from pilot.utils import build_logger
|
||||
|
||||
CFG = Config()
|
||||
logger = build_logger("show_table_gen", LOGDIR + "show_table_gen.log")
|
||||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@command(
|
||||
|
@ -1,5 +1,6 @@
|
||||
import json
|
||||
import time
|
||||
import logging
|
||||
from fastapi import (
|
||||
APIRouter,
|
||||
Body,
|
||||
@ -9,7 +10,7 @@ from fastapi import (
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import List
|
||||
from pilot.configs.model_config import LOGDIR
|
||||
from pilot.utils import build_logger
|
||||
|
||||
|
||||
from pilot.openapi.api_view_model import (
|
||||
Result,
|
||||
@ -22,14 +23,14 @@ from .plugins_util import scan_plugins
|
||||
from .commands.generator import PluginPromptGenerator
|
||||
|
||||
from pilot.configs.model_config import PLUGINS_DIR
|
||||
from pilot.componet import BaseComponet, ComponetType, SystemApp
|
||||
from pilot.component import BaseComponent, ComponentType, SystemApp
|
||||
|
||||
router = APIRouter()
|
||||
logger = build_logger("agent_mange", LOGDIR + "agent_mange.log")
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ModuleAgent(BaseComponet, ABC):
|
||||
name = ComponetType.AGENT_HUB
|
||||
class ModuleAgent(BaseComponent, ABC):
|
||||
name = ComponentType.AGENT_HUB
|
||||
|
||||
def __init__(self):
|
||||
#load plugins
|
||||
|
@ -1,4 +1,23 @@
|
||||
import re
|
||||
|
||||
def is_all_chinese(text):
|
||||
### Determine whether the string is pure Chinese
|
||||
pattern = re.compile(r'^[一-龥]+$')
|
||||
match = re.match(pattern, text)
|
||||
return match is not None
|
||||
|
||||
|
||||
def is_number_chinese(text):
|
||||
### Determine whether the string is numbers and Chinese
|
||||
pattern = re.compile(r'^[\d一-龥]+$')
|
||||
match = re.match(pattern, text)
|
||||
return match is not None
|
||||
|
||||
def is_chinese_include_number(text):
|
||||
### Determine whether the string is pure Chinese or Chinese containing numbers
|
||||
pattern = re.compile(r'^[一-龥]+[\d一-龥]*$')
|
||||
match = re.match(pattern, text)
|
||||
return match is not None
|
||||
|
||||
def extract_content(long_string, s1, s2, is_include: bool = False):
|
||||
# extract text
|
||||
|
@ -3,24 +3,32 @@ import uuid
|
||||
import asyncio
|
||||
import os
|
||||
import shutil
|
||||
import logging
|
||||
from fastapi import (
|
||||
APIRouter,
|
||||
Request,
|
||||
File,
|
||||
UploadFile,
|
||||
Form,
|
||||
Body,
|
||||
BackgroundTasks,
|
||||
Depends,
|
||||
)
|
||||
|
||||
from fastapi.responses import StreamingResponse
|
||||
from fastapi.exceptions import RequestValidationError
|
||||
from typing import List
|
||||
import tempfile
|
||||
|
||||
from pilot.componet import ComponetType
|
||||
from pilot.component import ComponentType
|
||||
from pilot.openapi.api_view_model import (
|
||||
Result,
|
||||
ConversationVo,
|
||||
MessageVo,
|
||||
ChatSceneVo,
|
||||
ChatCompletionResponseStreamChoice,
|
||||
DeltaMessage,
|
||||
ChatCompletionStreamResponse,
|
||||
)
|
||||
from pilot.connections.db_conn_info import DBConfig, DbTypeInfo
|
||||
from pilot.configs.config import Config
|
||||
@ -30,17 +38,19 @@ from pilot.server.knowledge.request.request import KnowledgeSpaceRequest
|
||||
from pilot.scene.base_chat import BaseChat
|
||||
from pilot.scene.base import ChatScene
|
||||
from pilot.scene.chat_factory import ChatFactory
|
||||
from pilot.configs.model_config import LOGDIR
|
||||
from pilot.utils import build_logger
|
||||
from pilot.common.schema import DBType
|
||||
|
||||
from pilot.scene.message import OnceConversation
|
||||
from pilot.configs.model_config import KNOWLEDGE_UPLOAD_ROOT_PATH
|
||||
from pilot.configs.model_config import LLM_MODEL_CONFIG, KNOWLEDGE_UPLOAD_ROOT_PATH
|
||||
from pilot.summary.db_summary_client import DBSummaryClient
|
||||
from pilot.memory.chat_history.chat_hisotry_factory import ChatHistory
|
||||
from pilot.model.cluster import BaseModelController, WorkerManager, WorkerManagerFactory
|
||||
from pilot.model.base import FlatSupportedModel
|
||||
|
||||
router = APIRouter()
|
||||
CFG = Config()
|
||||
CHAT_FACTORY = ChatFactory()
|
||||
logger = build_logger("api_v1", LOGDIR + "api_v1.log")
|
||||
logger = logging.getLogger(__name__)
|
||||
knowledge_service = KnowledgeService()
|
||||
|
||||
model_semaphore = None
|
||||
@ -75,6 +85,26 @@ def plugins_select_info():
|
||||
return plugins_infos
|
||||
|
||||
|
||||
def get_db_list_info():
|
||||
dbs = CFG.LOCAL_DB_MANAGE.get_db_list()
|
||||
params: dict = {}
|
||||
for item in dbs:
|
||||
comment = item["comment"]
|
||||
if comment is not None and len(comment) > 0:
|
||||
params.update({item["db_name"]: comment})
|
||||
return params
|
||||
|
||||
|
||||
def knowledge_list_info():
|
||||
"""return knowledge space list"""
|
||||
params: dict = {}
|
||||
request = KnowledgeSpaceRequest()
|
||||
spaces = knowledge_service.get_knowledge_space(request)
|
||||
for space in spaces:
|
||||
params.update({space.name: space.desc})
|
||||
return params
|
||||
|
||||
|
||||
def knowledge_list():
|
||||
"""return knowledge space list"""
|
||||
params: dict = {}
|
||||
@ -85,6 +115,20 @@ def knowledge_list():
|
||||
return params
|
||||
|
||||
|
||||
def get_model_controller() -> BaseModelController:
|
||||
controller = CFG.SYSTEM_APP.get_component(
|
||||
ComponentType.MODEL_CONTROLLER, BaseModelController
|
||||
)
|
||||
return controller
|
||||
|
||||
|
||||
def get_worker_manager() -> WorkerManager:
|
||||
worker_manager = CFG.SYSTEM_APP.get_component(
|
||||
ComponentType.WORKER_MANAGER_FACTORY, WorkerManagerFactory
|
||||
).create()
|
||||
return worker_manager
|
||||
|
||||
|
||||
@router.get("/v1/chat/db/list", response_model=Result[DBConfig])
|
||||
async def db_connect_list():
|
||||
return Result.succ(CFG.LOCAL_DB_MANAGE.get_db_list())
|
||||
@ -344,22 +388,17 @@ async def chat_completions(dialogue: ConversationVo = Body()):
|
||||
)
|
||||
else:
|
||||
return StreamingResponse(
|
||||
stream_generator(chat),
|
||||
stream_generator(chat, dialogue.incremental, dialogue.model_name),
|
||||
headers=headers,
|
||||
media_type="text/plain",
|
||||
)
|
||||
|
||||
|
||||
@router.get("/v1/model/types")
|
||||
async def model_types(request: Request):
|
||||
print(f"/controller/model/types")
|
||||
async def model_types(controller: BaseModelController = Depends(get_model_controller)):
|
||||
logger.info(f"/controller/model/types")
|
||||
try:
|
||||
types = set()
|
||||
from pilot.model.cluster.controller.controller import BaseModelController
|
||||
|
||||
controller = CFG.SYSTEM_APP.get_componet(
|
||||
ComponetType.MODEL_CONTROLLER, BaseModelController
|
||||
)
|
||||
models = await controller.get_all_instances(healthy_only=True)
|
||||
for model in models:
|
||||
worker_name, worker_type = model.model_name.split("@")
|
||||
@ -371,18 +410,60 @@ async def model_types(request: Request):
|
||||
return Result.faild(code="E000X", msg=f"controller model types error {e}")
|
||||
|
||||
|
||||
@router.get("/v1/model/supports")
|
||||
async def model_supports(worker_manager: WorkerManager = Depends(get_worker_manager)):
|
||||
logger.info(f"/controller/model/supports")
|
||||
try:
|
||||
models = await worker_manager.supported_models()
|
||||
return Result.succ(FlatSupportedModel.from_supports(models))
|
||||
except Exception as e:
|
||||
return Result.faild(code="E000X", msg=f"Fetch supportd models error {e}")
|
||||
|
||||
|
||||
async def no_stream_generator(chat):
|
||||
msg = await chat.nostream_call()
|
||||
yield f"data: {msg}\n\n"
|
||||
|
||||
|
||||
async def stream_generator(chat):
|
||||
async def stream_generator(chat, incremental: bool, model_name: str):
|
||||
"""Generate streaming responses
|
||||
|
||||
Our goal is to generate an openai-compatible streaming responses.
|
||||
Currently, the incremental response is compatible, and the full response will be transformed in the future.
|
||||
|
||||
Args:
|
||||
chat (BaseChat): Chat instance.
|
||||
incremental (bool): Used to control whether the content is returned incrementally or in full each time.
|
||||
model_name (str): The model name
|
||||
|
||||
Yields:
|
||||
_type_: streaming responses
|
||||
"""
|
||||
msg = "[LLM_ERROR]: llm server has no output, maybe your prompt template is wrong."
|
||||
|
||||
stream_id = f"chatcmpl-{str(uuid.uuid1())}"
|
||||
previous_response = ""
|
||||
async for chunk in chat.stream_call():
|
||||
if chunk:
|
||||
yield f"data:{chunk}\n\n"
|
||||
msg = chunk.replace("\ufffd", "")
|
||||
if incremental:
|
||||
incremental_output = msg[len(previous_response) :]
|
||||
choice_data = ChatCompletionResponseStreamChoice(
|
||||
index=0,
|
||||
delta=DeltaMessage(role="assistant", content=incremental_output),
|
||||
)
|
||||
chunk = ChatCompletionStreamResponse(
|
||||
id=stream_id, choices=[choice_data], model=model_name
|
||||
)
|
||||
yield f"data: {chunk.json(exclude_unset=True, ensure_ascii=False)}\n\n"
|
||||
else:
|
||||
# TODO generate an openai-compatible streaming responses
|
||||
msg = msg.replace("\n", "\\n")
|
||||
yield f"data:{msg}\n\n"
|
||||
previous_response = msg
|
||||
await asyncio.sleep(0.02)
|
||||
|
||||
|
||||
if incremental:
|
||||
yield "data: [DONE]\n\n"
|
||||
|
||||
|
||||
def message2Vo(message: dict, order, model_name) -> MessageVo:
|
||||
|
@ -173,7 +173,7 @@ class BaseChat(ABC):
|
||||
f"""<span style=\"color:red\">ERROR!</span>{str(e)}\n {ai_response_text} """
|
||||
)
|
||||
### store current conversation
|
||||
self.memory.append(self.current_message)
|
||||
self.memory.append(self.current_message)
|
||||
|
||||
async def nostream_call(self):
|
||||
payload = self.__call_base()
|
||||
|
@ -9,7 +9,7 @@ from pilot.base_modules.agent.commands.command_mange import ApiCall
|
||||
from pilot.base_modules.agent import PluginPromptGenerator
|
||||
from pilot.common.string_utils import extract_content
|
||||
from .prompt import prompt
|
||||
from pilot.componet import ComponetType
|
||||
from pilot.component import ComponentType
|
||||
from pilot.base_modules.agent.controller import ModuleAgent
|
||||
|
||||
CFG = Config()
|
||||
@ -31,7 +31,7 @@ class ChatAgent(BaseChat):
|
||||
self.plugins_prompt_generator.command_registry = CFG.command_registry
|
||||
|
||||
# load select plugin
|
||||
agent_module = CFG.SYSTEM_APP.get_componet(ComponetType.AGENT_HUB, ModuleAgent)
|
||||
agent_module = CFG.SYSTEM_APP.get_componet(ComponentType.AGENT_HUB, ModuleAgent)
|
||||
self.plugins_prompt_generator = agent_module.load_select_plugin(self.plugins_prompt_generator, self.select_plugins)
|
||||
|
||||
self.api_call = ApiCall(plugin_generator=self.plugins_prompt_generator)
|
||||
|
@ -76,22 +76,4 @@ class ChatExcel(BaseChat):
|
||||
def stream_plugin_call(self, text):
|
||||
text = text.replace("\n", " ")
|
||||
print(f"stream_plugin_call:{text}")
|
||||
return self.api_call.run_display_sql(text, self.excel_reader.get_df_by_sql_ex)
|
||||
|
||||
|
||||
|
||||
# def do_action(self, prompt_response):
|
||||
# print(f"do_action:{prompt_response}")
|
||||
#
|
||||
# # colunms, datas = self.excel_reader.run(prompt_response.sql)
|
||||
#
|
||||
#
|
||||
# param = {
|
||||
# "speak": prompt_response.thoughts,
|
||||
# "df": self.excel_reader.get_df_by_sql_ex(prompt_response.sql),
|
||||
# }
|
||||
#
|
||||
# if CFG.command_disply.get_command(prompt_response.display):
|
||||
# return CFG.command_disply.call(prompt_response.display, **param)
|
||||
# else:
|
||||
# return CFG.command_disply.call("response_table", **param)
|
||||
return self.api_call.run_display_sql(text, self.excel_reader.get_df_by_sql_ex)
|
@ -32,9 +32,9 @@ _DEFAULT_TEMPLATE_ZH = """
|
||||
1.请先输出你的分析思路内容,再输出具体的数据分析结果,其中数据分析结果部分确保用如下格式输出:<api-call><name>[数据展示方式]</name><args><sql>[正确的duckdb数据分析sql]</sql></args></api-call>
|
||||
2.请确保数据分析结果格式的内容在整个回答中只出现一次,确保上述结构稳定,把[]部分内容替换为对应的值
|
||||
3.数据分析结果可用的展示方式请在下面的展示方式中选择最合适的一种,放入数据分析结果的name字段内如果无法确定,则使用'Text'作为显示,可用显示类型如下: {disply_type}
|
||||
4.SQL中需要使用的表名是: {table_name},请确保不要使用不在数据结构中的列名。
|
||||
4.SQL中需要使用的表名是: {table_name},请不要使用没在数据结构中的列名。
|
||||
5.优先使用数据分析的方式回答,如果用户问题不涉及数据分析内容,你可以按你的理解进行回答
|
||||
6.请确保你的输出内容有良好排版,输出内容均为普通markdown文本,没有特殊的格式
|
||||
6.请确保你的输出内容有良好排版,输出内容均为普通markdown文本,不要用```或者```python这种标签来包围<api-call>的输出内容
|
||||
|
||||
用户问题:{user_input}
|
||||
请确保你的输出格式如下:
|
||||
|
@ -1,11 +1,16 @@
|
||||
import logging
|
||||
|
||||
import duckdb
|
||||
import os
|
||||
import re
|
||||
import sqlparse
|
||||
import pandas as pd
|
||||
import numpy as np
|
||||
from pyparsing import CaselessKeyword, Word, alphas, alphanums, delimitedList, Forward, Group, Optional,\
|
||||
Literal, infixNotation, opAssoc, unicodeString,Regex
|
||||
|
||||
from pilot.common.pd_utils import csv_colunm_foramt
|
||||
from pilot.common.string_utils import is_chinese_include_number
|
||||
|
||||
|
||||
def excel_colunm_format(old_name: str) -> str:
|
||||
@ -21,9 +26,69 @@ def add_quotes_ex(sql: str, column_names):
|
||||
sql = sql.replace(column_name, f'"{column_name}"')
|
||||
return sql
|
||||
|
||||
def parse_sql(sql):
|
||||
# 定义关键字和标识符
|
||||
select_stmt = Forward()
|
||||
column = Regex(r'[\w一-龥]*')
|
||||
table = Word(alphanums)
|
||||
join_expr = Forward()
|
||||
where_expr = Forward()
|
||||
group_by_expr = Forward()
|
||||
order_by_expr = Forward()
|
||||
|
||||
select_keyword = CaselessKeyword("SELECT")
|
||||
from_keyword = CaselessKeyword("FROM")
|
||||
join_keyword = CaselessKeyword("JOIN")
|
||||
on_keyword = CaselessKeyword("ON")
|
||||
where_keyword = CaselessKeyword("WHERE")
|
||||
group_by_keyword = CaselessKeyword("GROUP BY")
|
||||
order_by_keyword = CaselessKeyword("ORDER BY")
|
||||
and_keyword = CaselessKeyword("AND")
|
||||
or_keyword = CaselessKeyword("OR")
|
||||
in_keyword = CaselessKeyword("IN")
|
||||
not_in_keyword = CaselessKeyword("NOT IN")
|
||||
|
||||
# 定义语法规则
|
||||
select_stmt <<= (select_keyword + delimitedList(column) +
|
||||
from_keyword + delimitedList(table) +
|
||||
Optional(join_expr) +
|
||||
Optional(where_keyword + where_expr) +
|
||||
Optional(group_by_keyword + group_by_expr) +
|
||||
Optional(order_by_keyword + order_by_expr))
|
||||
|
||||
join_expr <<= join_keyword + table + on_keyword + column + Literal("=") + column
|
||||
|
||||
where_expr <<= column + Literal("=") + Word(alphanums) + \
|
||||
Optional(and_keyword + where_expr) | \
|
||||
column + Literal(">") + Word(alphanums) + \
|
||||
Optional(and_keyword + where_expr) | \
|
||||
column + Literal("<") + Word(alphanums) + \
|
||||
Optional(and_keyword + where_expr)
|
||||
|
||||
group_by_expr <<= delimitedList(column)
|
||||
|
||||
order_by_expr <<= column + Optional(Literal("ASC") | Literal("DESC"))
|
||||
|
||||
# 解析 SQL 语句
|
||||
parsed_result = select_stmt.parseString(sql)
|
||||
|
||||
return parsed_result.asList()
|
||||
|
||||
|
||||
|
||||
def add_quotes_v2(sql: str, column_names):
|
||||
pass
|
||||
|
||||
def add_quotes_v3(sql):
|
||||
pattern = r'[一-鿿]+'
|
||||
matches = re.findall(pattern, sql)
|
||||
for match in matches:
|
||||
sql = sql.replace(match, f'[{match}]')
|
||||
return sql
|
||||
|
||||
def add_quotes(sql, column_names=[]):
|
||||
sql = sql.replace("`", "")
|
||||
sql = sql.replace("'", "")
|
||||
parsed = sqlparse.parse(sql)
|
||||
for stmt in parsed:
|
||||
for token in stmt.tokens:
|
||||
@ -36,31 +101,122 @@ def deep_quotes(token, column_names=[]):
|
||||
for token_child in token.tokens:
|
||||
deep_quotes(token_child, column_names)
|
||||
else:
|
||||
if token.value in column_names:
|
||||
token.value = f'"{token.value.replace("`", "")}"'
|
||||
elif token.ttype == sqlparse.tokens.Name:
|
||||
token.value = f'"{token.value.replace("`", "")}"'
|
||||
if is_chinese_include_number(token.value):
|
||||
new_value = token.value.replace("`", "").replace("'", "")
|
||||
token.value = f'"{new_value}"'
|
||||
|
||||
def get_select_clause(sql):
|
||||
parsed = sqlparse.parse(sql)[0] # 解析 SQL 语句,获取第一个语句块
|
||||
|
||||
select_tokens = []
|
||||
is_select = False
|
||||
|
||||
for token in parsed.tokens:
|
||||
if token.is_keyword and token.value.upper() == "SELECT":
|
||||
is_select = True
|
||||
elif is_select:
|
||||
if token.is_keyword and token.value.upper() == "FROM":
|
||||
break
|
||||
select_tokens.append(token)
|
||||
return "".join(str(token) for token in select_tokens)
|
||||
|
||||
def parse_select_fields(sql):
|
||||
parsed = sqlparse.parse(sql)[0] # 解析 SQL 语句,获取第一个语句块
|
||||
fields = []
|
||||
|
||||
for token in parsed.tokens:
|
||||
# 使用 flatten() 方法合并 '2022' 和 '年' 为一个 token
|
||||
if token.match(sqlparse.tokens.Literal.String.Single):
|
||||
token.flatten()
|
||||
if isinstance(token, sqlparse.sql.Identifier):
|
||||
fields.append(token.get_real_name())
|
||||
|
||||
# 处理中文
|
||||
fields = [field.replace(f"field", f'"{field}"') for field in fields]
|
||||
|
||||
return fields
|
||||
|
||||
def add_quotes_to_chinese_columns(sql, column_names=[]):
|
||||
parsed = sqlparse.parse(sql)
|
||||
for stmt in parsed:
|
||||
process_statement(stmt, column_names)
|
||||
return str(parsed[0])
|
||||
|
||||
def process_statement(statement, column_names=[]):
|
||||
if isinstance(statement, sqlparse.sql.IdentifierList):
|
||||
for identifier in statement.get_identifiers():
|
||||
process_identifier(identifier)
|
||||
elif isinstance(statement, sqlparse.sql.Identifier):
|
||||
process_identifier(statement, column_names)
|
||||
elif isinstance(statement, sqlparse.sql.TokenList):
|
||||
for item in statement.tokens:
|
||||
process_statement(item)
|
||||
|
||||
def process_identifier(identifier, column_names=[]):
|
||||
# if identifier.has_alias():
|
||||
# alias = identifier.get_alias()
|
||||
# identifier.tokens[-1].value = '[' + alias + ']'
|
||||
if identifier.tokens and identifier.value in column_names:
|
||||
if is_chinese(identifier.value):
|
||||
new_value = get_new_value(identifier.value)
|
||||
identifier.value = new_value
|
||||
identifier.normalized = new_value
|
||||
identifier.tokens = [sqlparse.sql.Token(sqlparse.tokens.Name, new_value)]
|
||||
else:
|
||||
for token in identifier.tokens:
|
||||
if isinstance(token, sqlparse.sql.Function):
|
||||
process_function(token)
|
||||
elif token.ttype in sqlparse.tokens.Name and is_chinese(token.value):
|
||||
new_value = get_new_value(token.value)
|
||||
token.value = new_value
|
||||
token.normalized = new_value
|
||||
elif token.value in column_names and is_chinese(token.value):
|
||||
new_value = get_new_value(token.value)
|
||||
token.value = new_value
|
||||
token.normalized = new_value
|
||||
token.tokens = [sqlparse.sql.Token(sqlparse.tokens.Name, new_value)]
|
||||
def get_new_value(value):
|
||||
return f""" "{value.replace("`", "").replace("'", "").replace('"', "")}" """
|
||||
|
||||
def process_function(function):
|
||||
function_params = list(function.get_parameters())
|
||||
# for param in function_params:
|
||||
for i in range(len(function_params)):
|
||||
param = function_params[i]
|
||||
# 如果参数部分是一个标识符(字段名)
|
||||
if isinstance(param, sqlparse.sql.Identifier):
|
||||
# 判断是否需要替换字段值
|
||||
if is_chinese(param.value):
|
||||
# 替换字段值
|
||||
new_value = get_new_value(param.value)
|
||||
# new_parameter = sqlparse.sql.Identifier(f'[{param.value}]')
|
||||
function_params[i].tokens = [sqlparse.sql.Token(sqlparse.tokens.Name, new_value)]
|
||||
print(str(function))
|
||||
|
||||
def is_chinese(text):
|
||||
for char in text:
|
||||
if '一' <= char <= '鿿':
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sql = "SELECT `地区`, (`2021年人口` - `2001年人口`) / `2001年人口` * 100 AS `Population_Growth_Rate` FROM Generated_by_ChatExcel_table1 (2)"
|
||||
if f'"Generated_by_ChatExcel_table1 (2)"' not in sql:
|
||||
sql = sql.replace(
|
||||
"Generated_by_ChatExcel_table1 (2)", f'"Generated_by_ChatExcel_table1 (2)"'
|
||||
)
|
||||
sql = add_quotes_ex(
|
||||
sql, ["地区", "地区代码", "2001年人口", "2006年人口", "2011年人口", "2016年人口", "2021年人口"]
|
||||
)
|
||||
# sql = "SELECT 姓名, 年龄 FROM table1 JOIN table2 ON table1.id = table2.id WHERE 字段 = '值' AND 字段2 > 10 GROUP BY 姓名 ORDER BY 年龄 DESC"
|
||||
#
|
||||
# parsed_result = parse_sql(sql)
|
||||
# print(parsed_result)
|
||||
# sql_2 = 'SELECT "省份", "2022年" AS "GDP", ROUND(("2022年" / (SELECT SUM("2022年") FROM excel_data)) * 100, 2) AS "占比" FROM excel_data ORDER BY "占比" DESC'
|
||||
# print(add_quotes_to_chinese_columns(sql_2))
|
||||
|
||||
# sql = """ SELECT 省份, 2021年, 2022年 as GDP FROM excel_data """
|
||||
sql = """ SELECT 省份, 2022年, 2021年 FROM excel_data """
|
||||
sql_2 = """ SELECT "省份", "2022年" as "2022年实际GDP增速", "2021年" as "2021年实际GDP增速" FROM excel_data """
|
||||
sql_3 = """ SELECT "省份", ("2022年" / ("2022年" + "2021年")) * 100 as "2022年实际GDP增速占比", ("2021年" / ("2022年" + "2021年")) * 100 as "2021年实际GDP增速占比" FROM excel_data """
|
||||
|
||||
sql = add_quotes_to_chinese_columns(sql_3)
|
||||
print(f"excute sql:{sql}")
|
||||
|
||||
|
||||
def is_chinese(string):
|
||||
# 使用正则表达式匹配中文字符
|
||||
pattern = re.compile(r"[一-龥]")
|
||||
match = re.search(pattern, string)
|
||||
return match is not None
|
||||
|
||||
|
||||
class ExcelReader:
|
||||
def __init__(self, file_path):
|
||||
file_name = os.path.basename(file_path)
|
||||
@ -104,15 +260,20 @@ class ExcelReader:
|
||||
self.db.register(self.table_name, self.df)
|
||||
|
||||
def run(self, sql):
|
||||
if f'"{self.table_name}"' not in sql:
|
||||
sql = sql.replace(self.table_name, f'"{self.table_name}"')
|
||||
sql = add_quotes_ex(sql, self.columns_map.values())
|
||||
print(f"excute sql:{sql}")
|
||||
results = self.db.execute(sql)
|
||||
colunms = []
|
||||
for descrip in results.description:
|
||||
colunms.append(descrip[0])
|
||||
return colunms, results.fetchall()
|
||||
try:
|
||||
if f'"{self.table_name}"' in sql:
|
||||
sql = sql.replace(f'"{self.table_name}"', self.table_name)
|
||||
sql = add_quotes_to_chinese_columns(sql)
|
||||
print(f"excute sql:{sql}")
|
||||
results = self.db.execute(sql)
|
||||
colunms = []
|
||||
for descrip in results.description:
|
||||
colunms.append(descrip[0])
|
||||
return colunms, results.fetchall()
|
||||
except Exception as e:
|
||||
logging.error("excel sql run error!", e)
|
||||
raise ValueError(f"Data Query Exception!{sql}")
|
||||
|
||||
|
||||
def get_df_by_sql_ex(self, sql):
|
||||
colunms, values = self.run(sql)
|
||||
|
@ -30,9 +30,8 @@ from pilot.server.llm_manage.api import router as llm_manage_api
|
||||
from pilot.openapi.api_v1.api_v1 import router as api_v1
|
||||
from pilot.openapi.base import validation_exception_handler
|
||||
from pilot.openapi.api_v1.editor.api_editor_v1 import router as api_editor_route_v1
|
||||
from pilot.base_modules.agent import static_message_img_path
|
||||
from pilot.openapi.api_v1.feedback.api_fb_v1 import router as api_fb_v1
|
||||
from pilot.commands.disply_type.show_chart_gen import static_message_img_path
|
||||
from pilot.base_modules.agent.commands.disply_type.show_chart_gen import static_message_img_path
|
||||
from pilot.model.cluster import initialize_worker_manager_in_client
|
||||
from pilot.utils.utils import (
|
||||
setup_logging,
|
||||
|
1
pilot/server/static/404.html
Normal file
1
pilot/server/static/404/index.html
Normal file
BIN
pilot/server/static/LOGO.png
Normal file
After Width: | Height: | Size: 130 KiB |
BIN
pilot/server/static/LOGO_1.png
Normal file
After Width: | Height: | Size: 9.7 KiB |
BIN
pilot/server/static/LOGO_SMALL.png
Normal file
After Width: | Height: | Size: 28 KiB |
BIN
pilot/server/static/WHITE_LOGO.png
Normal file
After Width: | Height: | Size: 58 KiB |
@ -0,0 +1 @@
|
||||
self.__BUILD_MANIFEST=function(s,c,t,a,e,d,f,n,i,u,b,h,k,j,r,o,p){return{__rewrites:{beforeFiles:[],afterFiles:[],fallback:[]},"/":[c,s,a,e,d,i,u,"static/chunks/539-dcd22f1f6b99ebee.js","static/chunks/pages/index-2c0208b595e11faa.js"],"/_error":["static/chunks/pages/_error-dee72aff9b2e2c12.js"],"/chat/[scene]/[id]":["static/chunks/pages/chat/[scene]/[id]-77b9b752e70a7a79.js"],"/database":[s,a,e,b,i,h,"static/chunks/785-46a0e236e0942766.js","static/chunks/pages/database-bb293d5b5d222235.js"],"/datastores":[c,t,f,n,k,j,r,"static/chunks/pages/datastores-8df26f90e1717040.js"],"/datastores/documents":[c,o,s,t,f,d,n,k,b,j,r,p,"static/chunks/749-fac3e13c5ab7cff1.js","static/chunks/pages/datastores/documents-2de93a9719baa975.js"],"/datastores/documents/chunklist":[c,s,t,d,n,p,"static/chunks/pages/datastores/documents/chunklist-143fff9263facb49.js"],"/models":[o,s,t,a,f,e,h,"static/chunks/991-0cfc6e4020e4d683.js","static/chunks/pages/models-8a1710c86a0ad664.js"],"/prompt":[c,s,t,a,f,e,d,"static/chunks/45-b98c4238ff6e0cc1.js",u,"static/chunks/61-4b1a896c7810d559.js","static/chunks/367-88244d673d2fa27b.js","static/chunks/pages/prompt-9f44fc677830f134.js"],sortedPages:["/","/_app","/_error","/chat/[scene]/[id]","/database","/datastores","/datastores/documents","/datastores/documents/chunklist","/models","/prompt"]}}("static/chunks/996-e5792cec1f2b1f49.js","static/chunks/29107295-90b90cb30c825230.js","static/chunks/262-301259b7bd25a2f2.js","static/chunks/566-074186f7bac9291d.js","static/chunks/479-68b22ee2b7a47fb3.js","static/chunks/647-f9d834aad2c525c1.js","static/chunks/737-8b1fcf8b6e843f49.js","static/chunks/995-2f502d60cecceeb6.js","static/chunks/411-d9eba2657c72f766.js","static/chunks/615-2e05a69bfa343278.js","static/chunks/442-197e6cbc1e54109a.js","static/chunks/928-74244889bd7f2699.js","static/chunks/294-1f84c8cb4f01db65.js","static/chunks/655-1c948938dfd927ff.js","static/chunks/387-03259b62c3d128f7.js","static/chunks/75fc9c18-a784766a129ec5fb.js","static/chunks/963-0ad205f64dc9848d.js"),self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB();
|
@ -0,0 +1 @@
|
||||
self.__SSG_MANIFEST=new Set([]);self.__SSG_MANIFEST_CB&&self.__SSG_MANIFEST_CB()
|
500
pilot/server/static/_next/static/chunks/414.62c17210217493bc.js
Normal file
@ -0,0 +1 @@
|
||||
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[820],{81981:function(n,_,u){(window.__NEXT_P=window.__NEXT_P||[]).push(["/_error",function(){return u(14600)}])}},function(n){n.O(0,[774,888,179],function(){return n(n.s=81981)}),_N_E=n.O()}]);
|
@ -0,0 +1 @@
|
||||
.model-tab:before{content:"";position:absolute;left:.4rem;width:45%;height:80%;background-color:#ffc800;border-radius:2rem;transition:all .4s}.editor-tab:before{left:calc(50%)}
|
1
pilot/server/static/chat/[scene]/[id]/index.html
Normal file
1
pilot/server/static/database/index.html
Normal file
1
pilot/server/static/datastores/documents/index.html
Normal file
1
pilot/server/static/datastores/index.html
Normal file
BIN
pilot/server/static/empty.png
Normal file
After Width: | Height: | Size: 78 KiB |
BIN
pilot/server/static/favicon.ico
Normal file
After Width: | Height: | Size: 264 KiB |
73
pilot/server/static/huggingface_logo.svg
Normal file
@ -0,0 +1,73 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg
|
||||
width="95"
|
||||
height="88"
|
||||
viewBox="0 0 95 88"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M47.2119 76.5C66.4037 76.5 81.9619 60.9419 81.9619 41.75C81.9619 22.5581 66.4037 7 47.2119 7C28.02 7 12.4619 22.5581 12.4619 41.75C12.4619 60.9419 28.02 76.5 47.2119 76.5Z"
|
||||
fill="#FFD21E"
|
||||
/>
|
||||
<path
|
||||
d="M81.9619 41.75C81.9619 22.5581 66.4037 7 47.2119 7C28.02 7 12.4619 22.5581 12.4619 41.75C12.4619 60.9419 28.02 76.5 47.2119 76.5C66.4037 76.5 81.9619 60.9419 81.9619 41.75ZM8.46185 41.75C8.46185 20.349 25.8108 3 47.2119 3C68.6129 3 85.9619 20.349 85.9619 41.75C85.9619 63.151 68.6129 80.5 47.2119 80.5C25.8108 80.5 8.46185 63.151 8.46185 41.75Z"
|
||||
fill="#FF9D0B"
|
||||
/>
|
||||
<path
|
||||
d="M58.5024 32.2915C59.7768 32.7415 60.2839 35.3615 61.5713 34.6769C64.0095 33.3805 64.9351 30.353 63.6387 27.9148C62.3423 25.4767 59.3148 24.5511 56.8766 25.8475C54.4384 27.1439 53.5128 30.1714 54.8092 32.6096C55.4211 33.7604 57.3632 31.8892 58.5024 32.2915Z"
|
||||
fill="#3A3B45"
|
||||
/>
|
||||
<path
|
||||
d="M34.9454 32.2915C33.671 32.7415 33.164 35.3615 31.8766 34.6769C29.4384 33.3805 28.5128 30.353 29.8092 27.9148C31.1056 25.4767 34.1331 24.5511 36.5713 25.8475C39.0095 27.1439 39.9351 30.1714 38.6387 32.6096C38.0268 33.7604 36.0846 31.8892 34.9454 32.2915Z"
|
||||
fill="#3A3B45"
|
||||
/>
|
||||
<path
|
||||
d="M46.9619 56.289C56.7903 56.289 59.9619 47.5261 59.9619 43.0262C59.9619 40.6875 58.3898 41.4236 55.8718 42.6702C53.5449 43.8222 50.4102 45.4101 46.9619 45.4101C39.7822 45.4101 33.9619 38.5263 33.9619 43.0262C33.9619 47.5261 37.1334 56.289 46.9619 56.289Z"
|
||||
fill="#3A3B45"
|
||||
/>
|
||||
<mask
|
||||
id="mask0"
|
||||
mask-type="alpha"
|
||||
maskUnits="userSpaceOnUse"
|
||||
x="33"
|
||||
y="41"
|
||||
width="27"
|
||||
height="16"
|
||||
>
|
||||
<path
|
||||
d="M46.9619 56.289C56.7903 56.289 59.9619 47.5261 59.9619 43.0262C59.9619 40.6875 58.3898 41.4236 55.8718 42.6702C53.5449 43.8222 50.4102 45.4101 46.9619 45.4101C39.7822 45.4101 33.9619 38.5263 33.9619 43.0262C33.9619 47.5261 37.1334 56.289 46.9619 56.289Z"
|
||||
fill="white"
|
||||
/>
|
||||
</mask>
|
||||
<g mask="url(#mask0)">
|
||||
<path
|
||||
d="M47.2119 66.5C52.0018 66.5 55.8848 62.617 55.8848 57.8271C55.8848 54.0962 53.5291 50.9156 50.224 49.6915C50.1023 49.6464 49.9794 49.604 49.8553 49.5643C49.0219 49.2979 48.1337 52.1623 47.2119 52.1623C46.3506 52.1623 45.5186 49.2797 44.7332 49.5135C41.151 50.5799 38.5389 53.8984 38.5389 57.8271C38.5389 62.617 42.4219 66.5 47.2119 66.5Z"
|
||||
fill="#F94040"
|
||||
/>
|
||||
</g>
|
||||
<path
|
||||
d="M70.7119 37C72.5068 37 73.9619 35.5449 73.9619 33.75C73.9619 31.9551 72.5068 30.5 70.7119 30.5C68.9169 30.5 67.4619 31.9551 67.4619 33.75C67.4619 35.5449 68.9169 37 70.7119 37Z"
|
||||
fill="#FF9D0B"
|
||||
/>
|
||||
<path
|
||||
d="M24.2119 37C26.0068 37 27.4619 35.5449 27.4619 33.75C27.4619 31.9551 26.0068 30.5 24.2119 30.5C22.4169 30.5 20.9619 31.9551 20.9619 33.75C20.9619 35.5449 22.4169 37 24.2119 37Z"
|
||||
fill="#FF9D0B"
|
||||
/>
|
||||
<path
|
||||
d="M17.5238 48C15.9048 48 14.4578 48.665 13.4488 49.871C12.8248 50.618 12.1728 51.822 12.1198 53.625C11.4408 53.43 10.7878 53.321 10.1778 53.321C8.6278 53.321 7.2278 53.915 6.2378 54.994C4.9658 56.379 4.4008 58.081 4.6468 59.784C4.7638 60.595 5.0348 61.322 5.4398 61.995C4.5858 62.686 3.9568 63.648 3.6528 64.805C3.4148 65.712 3.1708 67.601 4.4448 69.547C4.3638 69.674 4.2878 69.806 4.2168 69.941C3.4508 71.395 3.4018 73.038 4.0778 74.568C5.1028 76.887 7.6498 78.714 12.5958 80.675C15.6728 81.895 18.4878 82.675 18.5128 82.682C22.5808 83.737 26.2598 84.273 29.4448 84.273C35.2988 84.273 39.4898 82.48 41.9018 78.944C45.7838 73.25 45.2288 68.042 40.2058 63.022C37.4258 60.244 35.5778 56.148 35.1928 55.249C34.4168 52.587 32.3648 49.628 28.9538 49.628H28.9528C28.6658 49.628 28.3758 49.651 28.0898 49.696C26.5958 49.931 25.2898 50.791 24.3568 52.085C23.3498 50.833 22.3718 49.837 21.4868 49.275C20.1528 48.429 18.8198 48 17.5238 48ZM17.5238 52C18.0338 52 18.6568 52.217 19.3438 52.653C21.4768 54.006 25.5928 61.081 27.0998 63.833C27.6048 64.755 28.4678 65.145 29.2448 65.145C30.7868 65.145 31.9908 63.612 29.3858 61.664C25.4688 58.733 26.8428 53.942 28.7128 53.647C28.7948 53.634 28.8758 53.628 28.9538 53.628C30.6538 53.628 31.4038 56.558 31.4038 56.558C31.4038 56.558 33.6018 62.078 37.3778 65.851C41.1538 69.625 41.3488 72.654 38.5968 76.69C36.7198 79.442 33.1268 80.273 29.4448 80.273C25.6258 80.273 21.7108 79.379 19.5168 78.81C19.4088 78.782 6.0658 75.013 7.7558 71.805C8.0398 71.266 8.5078 71.05 9.0968 71.05C11.4768 71.05 15.8058 74.592 17.6668 74.592C18.0828 74.592 18.3758 74.415 18.4958 73.983C19.2888 71.138 6.4388 69.942 7.5218 65.821C7.7128 65.092 8.2308 64.796 8.9588 64.797C12.1038 64.797 19.1598 70.328 20.6388 70.328C20.7518 70.328 20.8328 70.295 20.8768 70.225C21.6178 69.029 21.2118 68.194 15.9888 65.033C10.7658 61.871 7.0998 59.969 9.1848 57.699C9.4248 57.437 9.7648 57.321 10.1778 57.321C13.3488 57.322 20.8408 64.14 20.8408 64.14C20.8408 64.14 22.8628 66.243 24.0858 66.243C24.3668 66.243 24.6058 66.132 24.7678 65.858C25.6348 64.396 16.7148 57.636 16.2118 54.847C15.8708 52.957 16.4508 52 17.5238 52Z"
|
||||
fill="#FF9D0B"
|
||||
/>
|
||||
<path
|
||||
d="M38.5967 76.6898C41.3487 72.6538 41.1537 69.6248 37.3777 65.8508C33.6017 62.0778 31.4037 56.5578 31.4037 56.5578C31.4037 56.5578 30.5827 53.3518 28.7127 53.6468C26.8427 53.9418 25.4697 58.7328 29.3867 61.6638C33.3037 64.5938 28.6067 66.5848 27.0997 63.8328C25.5927 61.0808 21.4777 54.0058 19.3437 52.6528C17.2107 51.2998 15.7087 52.0578 16.2117 54.8468C16.7147 57.6358 25.6357 64.3958 24.7677 65.8588C23.8997 67.3208 20.8407 64.1398 20.8407 64.1398C20.8407 64.1398 11.2687 55.4288 9.18465 57.6988C7.10065 59.9688 10.7657 61.8708 15.9887 65.0328C21.2127 68.1938 21.6177 69.0288 20.8767 70.2248C20.1347 71.4208 8.60465 61.6998 7.52165 65.8208C6.43965 69.9418 19.2887 71.1378 18.4957 73.9828C17.7027 76.8288 9.44465 68.5978 7.75565 71.8048C6.06565 75.0128 19.4087 78.7818 19.5167 78.8098C23.8267 79.9278 34.7727 82.2968 38.5967 76.6898Z"
|
||||
fill="#FFD21E"
|
||||
/>
|
||||
<path
|
||||
d="M77.3999 48C79.0189 48 80.4659 48.665 81.4749 49.871C82.0989 50.618 82.7509 51.822 82.8039 53.625C83.4829 53.43 84.1359 53.321 84.7459 53.321C86.2959 53.321 87.6959 53.915 88.6859 54.994C89.9579 56.379 90.5229 58.081 90.2769 59.784C90.1599 60.595 89.8889 61.322 89.4839 61.995C90.3379 62.686 90.9669 63.648 91.2709 64.805C91.5089 65.712 91.7529 67.601 90.4789 69.547C90.5599 69.674 90.6359 69.806 90.7069 69.941C91.4729 71.395 91.5219 73.038 90.8459 74.568C89.8209 76.887 87.2739 78.714 82.3279 80.675C79.2509 81.895 76.4359 82.675 76.4109 82.682C72.3429 83.737 68.6639 84.273 65.4789 84.273C59.6249 84.273 55.4339 82.48 53.0219 78.944C49.1399 73.25 49.6949 68.042 54.7179 63.022C57.4979 60.244 59.3459 56.148 59.7309 55.249C60.5069 52.587 62.5589 49.628 65.9699 49.628H65.9709C66.2579 49.628 66.5479 49.651 66.8339 49.696C68.3279 49.931 69.6339 50.791 70.5669 52.085C71.5739 50.833 72.5519 49.837 73.4369 49.275C74.7709 48.429 76.1039 48 77.3999 48ZM77.3999 52C76.8899 52 76.2669 52.217 75.5799 52.653C73.4469 54.006 69.3309 61.081 67.8239 63.833C67.3189 64.755 66.4559 65.145 65.6789 65.145C64.1369 65.145 62.9329 63.612 65.5379 61.664C69.4549 58.733 68.0809 53.942 66.2109 53.647C66.1289 53.634 66.0479 53.628 65.9699 53.628C64.2699 53.628 63.5199 56.558 63.5199 56.558C63.5199 56.558 61.3219 62.078 57.5459 65.851C53.7699 69.625 53.5749 72.654 56.3269 76.69C58.2039 79.442 61.7969 80.273 65.4789 80.273C69.2979 80.273 73.2129 79.379 75.4069 78.81C75.5149 78.782 88.8579 75.013 87.1679 71.805C86.8839 71.266 86.4159 71.05 85.8269 71.05C83.4469 71.05 79.1179 74.592 77.2569 74.592C76.8409 74.592 76.5479 74.415 76.4279 73.983C75.6349 71.138 88.4849 69.942 87.4019 65.821C87.2109 65.092 86.6929 64.796 85.9649 64.797C82.8199 64.797 75.7639 70.328 74.2849 70.328C74.1719 70.328 74.0909 70.295 74.0469 70.225C73.3059 69.029 73.7119 68.194 78.9349 65.033C84.1579 61.871 87.8239 59.969 85.7389 57.699C85.4989 57.437 85.1589 57.321 84.7459 57.321C81.5749 57.322 74.0829 64.14 74.0829 64.14C74.0829 64.14 72.0609 66.243 70.8379 66.243C70.5569 66.243 70.3179 66.132 70.1559 65.858C69.2889 64.396 78.2089 57.636 78.7119 54.847C79.0529 52.957 78.4729 52 77.3999 52Z"
|
||||
fill="#FF9D0B"
|
||||
/>
|
||||
<path
|
||||
d="M56.3271 76.6898C53.5751 72.6538 53.7701 69.6248 57.5461 65.8508C61.3221 62.0778 63.5201 56.5578 63.5201 56.5578C63.5201 56.5578 64.3411 53.3518 66.2111 53.6468C68.0811 53.9418 69.4541 58.7328 65.5371 61.6638C61.6201 64.5938 66.3171 66.5848 67.8241 63.8328C69.3311 61.0808 73.4461 54.0058 75.5801 52.6528C77.7131 51.2998 79.2151 52.0578 78.7121 54.8468C78.2091 57.6358 69.2881 64.3958 70.1561 65.8588C71.0241 67.3208 74.0831 64.1398 74.0831 64.1398C74.0831 64.1398 83.6551 55.4288 85.7391 57.6988C87.8231 59.9688 84.1581 61.8708 78.9351 65.0328C73.7111 68.1938 73.3061 69.0288 74.0471 70.2248C74.7891 71.4208 86.3191 61.6998 87.4021 65.8208C88.4841 69.9418 75.6351 71.1378 76.4281 73.9828C77.2211 76.8288 85.4791 68.5978 87.1681 71.8048C88.8581 75.0128 75.5151 78.7818 75.4071 78.8098C71.0971 79.9278 60.1511 82.2968 56.3271 76.6898Z"
|
||||
fill="#FFD21E"
|
||||
/>
|
||||
</svg>
|
After Width: | Height: | Size: 8.7 KiB |
BIN
pilot/server/static/icons/access.png
Normal file
After Width: | Height: | Size: 6.8 KiB |
BIN
pilot/server/static/icons/cassandra.png
Normal file
After Width: | Height: | Size: 4.9 KiB |
BIN
pilot/server/static/icons/clickhouse.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
pilot/server/static/icons/couchbase.png
Normal file
After Width: | Height: | Size: 3.8 KiB |
BIN
pilot/server/static/icons/db.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
pilot/server/static/icons/db2.png
Normal file
After Width: | Height: | Size: 768 B |
BIN
pilot/server/static/icons/duckdb.png
Normal file
After Width: | Height: | Size: 2.7 KiB |
BIN
pilot/server/static/icons/hbase.png
Normal file
After Width: | Height: | Size: 4.3 KiB |
BIN
pilot/server/static/icons/mongodb.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
pilot/server/static/icons/mssql.png
Normal file
After Width: | Height: | Size: 3.5 KiB |
BIN
pilot/server/static/icons/mysql.png
Normal file
After Width: | Height: | Size: 5.7 KiB |
BIN
pilot/server/static/icons/oracle.png
Normal file
After Width: | Height: | Size: 3.9 KiB |
BIN
pilot/server/static/icons/postgresql.png
Normal file
After Width: | Height: | Size: 9.4 KiB |
BIN
pilot/server/static/icons/redis.png
Normal file
After Width: | Height: | Size: 5.1 KiB |
BIN
pilot/server/static/icons/spark.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
pilot/server/static/icons/sqlite.png
Normal file
After Width: | Height: | Size: 4.5 KiB |
BIN
pilot/server/static/images/fallback.png
Normal file
After Width: | Height: | Size: 2.3 KiB |