diff --git a/.env.example b/.env.example
index aa73850c..e312b838 100644
--- a/.env.example
+++ b/.env.example
@@ -1,16 +1,7 @@
-
-# Before running, please copy .env.example to .env
-DOMAIN=localhost
-FRONTEND_HOST=http://localhost:5173
-ENVIRONMENT=local
PROJECT_NAME="SQLBot"
-STACK_NAME=SQLBot
-
# Backend
BACKEND_CORS_ORIGINS="http://localhost,http://localhost:5173,https://localhost,https://localhost:5173"
SECRET_KEY=y5txe1mRmS_JpOrUzFzHEu-kIQn3lf7ll0AOv9DQh0s
-FIRST_SUPERUSER=admin@example.com
-FIRST_SUPERUSER_PASSWORD=123456 # Change this to your pwd
TOKEN_KEY="X-SQLBOT-TOKEN"
DEFAULT_PWD="SQLBot@123456"
@@ -22,7 +13,6 @@ LOG_FORMAT="%(asctime)s - %(name)s - %(levelname)s:%(lineno)d - %(message)s"
SQL_DEBUG=False
CACHE_TYPE="memory"
-CACHE_REDIS_URL="redis://127.0.0.1:6379"
# Postgres
POSTGRES_SERVER=localhost
@@ -31,12 +21,6 @@ POSTGRES_DB=sqlbot
POSTGRES_USER=root
POSTGRES_PASSWORD=132456 # Change this to your pwd
-SENTRY_DSN=
-
-# Configure these with your own Docker registry images
-DOCKER_IMAGE_BACKEND=backend
-DOCKER_IMAGE_FRONTEND=frontend
-
MCP_IMAGE_PATH=/opt/sqlbot/images
MCP_IMAGE_HOST=http://localhost:3000
SERVER_IMAGE_HOST=https://sqlbot.fit2cloud.cn/images/
diff --git a/backend/apps/chat/task/llm.py b/backend/apps/chat/task/llm.py
index e758fa93..895aea5e 100644
--- a/backend/apps/chat/task/llm.py
+++ b/backend/apps/chat/task/llm.py
@@ -439,6 +439,7 @@ class LLMService:
_ds = self.out_ds_instance.get_ds(data['id'])
self.ds = _ds
self.chat_question.engine = _ds.type
+ self.chat_question.db_schema = self.out_ds_instance.get_db_schema(self.ds.id)
_engine_type = self.chat_question.engine
_chat.engine_type = _ds.type
else:
@@ -448,6 +449,7 @@ class LLMService:
raise Exception(f"Datasource configuration with id {_datasource} not found")
self.ds = CoreDatasource(**_ds.model_dump())
self.chat_question.engine = _ds.type_name if _ds.type != 'excel' else 'PostgreSQL'
+ self.chat_question.db_schema = get_table_schema(session=self.session, current_user=self.current_user, ds=self.ds)
_engine_type = self.chat_question.engine
_chat.engine_type = _ds.type_name
# save chat
@@ -834,7 +836,8 @@ class LLMService:
self.ds.id) if self.out_ds_instance else get_table_schema(session=self.session,
current_user=self.current_user,
ds=self.ds)
-
+ else:
+ self.validate_history_ds()
# generate sql
sql_res = self.generate_sql()
full_sql_text = ''
@@ -1023,7 +1026,13 @@ class LLMService:
finally:
# end
pass
-
+
+ def validate_history_ds(self):
+ _invalid_ds = False
+ _ds = self.ds
+ _assistant = self.current_assistant
+ if _invalid_ds:
+ yield orjson.dumps({'content': 'ds is invalid', 'type': 'error'}).decode() + '\n\n'
def execute_sql_with_db(db: SQLDatabase, sql: str) -> str:
"""Execute SQL query using SQLDatabase
diff --git a/backend/common/core/config.py b/backend/common/core/config.py
index 482f4d61..9de1279b 100644
--- a/backend/common/core/config.py
+++ b/backend/common/core/config.py
@@ -1,19 +1,14 @@
import secrets
-import warnings
from typing import Annotated, Any, Literal
from pydantic import (
AnyUrl,
BeforeValidator,
- EmailStr,
- HttpUrl,
PostgresDsn,
computed_field,
- model_validator,
)
from pydantic_core import MultiHostUrl
from pydantic_settings import BaseSettings, SettingsConfigDict
-from typing_extensions import Self
def parse_cors(v: Any) -> list[str] | str:
@@ -31,12 +26,12 @@ class Settings(BaseSettings):
env_ignore_empty=True,
extra="ignore",
)
+ PROJECT_NAME: str = "SQLBot"
API_V1_STR: str = "/api/v1"
SECRET_KEY: str = secrets.token_urlsafe(32)
# 60 minutes * 24 hours * 8 days = 8 days
ACCESS_TOKEN_EXPIRE_MINUTES: int = 60 * 24 * 8
FRONTEND_HOST: str = "http://localhost:5173"
- ENVIRONMENT: Literal["local", "staging", "production"] = "local"
BACKEND_CORS_ORIGINS: Annotated[
list[AnyUrl] | str, BeforeValidator(parse_cors)
@@ -49,8 +44,6 @@ class Settings(BaseSettings):
self.FRONTEND_HOST
]
- PROJECT_NAME: str
- SENTRY_DSN: HttpUrl | None = None
POSTGRES_SERVER: str
POSTGRES_PORT: int = 5432
POSTGRES_USER: str
@@ -81,55 +74,8 @@ class Settings(BaseSettings):
path=self.POSTGRES_DB,
)
- SMTP_TLS: bool = True
- SMTP_SSL: bool = False
- SMTP_PORT: int = 587
- SMTP_HOST: str | None = None
- SMTP_USER: str | None = None
- SMTP_PASSWORD: str | None = None
- EMAILS_FROM_EMAIL: EmailStr | None = None
- EMAILS_FROM_NAME: EmailStr | None = None
MCP_IMAGE_PATH: str
MCP_IMAGE_HOST: str
SERVER_IMAGE_HOST: str
- @model_validator(mode="after")
- def _set_default_emails_from(self) -> Self:
- if not self.EMAILS_FROM_NAME:
- self.EMAILS_FROM_NAME = self.PROJECT_NAME
- return self
-
- EMAIL_RESET_TOKEN_EXPIRE_HOURS: int = 48
-
- @computed_field # type: ignore[prop-decorator]
- @property
- def emails_enabled(self) -> bool:
- return bool(self.SMTP_HOST and self.EMAILS_FROM_EMAIL)
-
- EMAIL_TEST_USER: EmailStr = "test@example.com"
- FIRST_SUPERUSER: EmailStr
- FIRST_SUPERUSER_PASSWORD: str
-
- def _check_default_secret(self, var_name: str, value: str | None) -> None:
- if value == "changethis":
- message = (
- f'The value of {var_name} is "changethis", '
- "for security, please change it, at least for deployments."
- )
- if self.ENVIRONMENT == "local":
- warnings.warn(message, stacklevel=1)
- else:
- raise ValueError(message)
-
- @model_validator(mode="after")
- def _enforce_non_default_secrets(self) -> Self:
- self._check_default_secret("SECRET_KEY", self.SECRET_KEY)
- self._check_default_secret("POSTGRES_PASSWORD", self.POSTGRES_PASSWORD)
- self._check_default_secret(
- "FIRST_SUPERUSER_PASSWORD", self.FIRST_SUPERUSER_PASSWORD
- )
-
- return self
-
-
settings = Settings() # type: ignore
diff --git a/backend/main.py b/backend/main.py
index 9024658c..2a41133e 100644
--- a/backend/main.py
+++ b/backend/main.py
@@ -1,5 +1,4 @@
from fastapi.concurrency import asynccontextmanager
-import sentry_sdk
from fastapi import FastAPI
from fastapi.routing import APIRoute
from starlette.middleware.cors import CORSMiddleware
@@ -38,9 +37,6 @@ def custom_generate_unique_id(route: APIRoute) -> str:
return f"{tag}-{route.name}"
-if settings.SENTRY_DSN and settings.ENVIRONMENT != "local":
- sentry_sdk.init(dsn=str(settings.SENTRY_DSN), enable_tracing=True)
-
app = FastAPI(
title=settings.PROJECT_NAME,
openapi_url=f"{settings.API_V1_STR}/openapi.json",
diff --git a/backend/template.yaml b/backend/template.yaml
index 8163b2fd..0c86b1ce 100644
--- a/backend/template.yaml
+++ b/backend/template.yaml
@@ -6,6 +6,7 @@ template:
任务:
根据给定的表结构(M-Schema)和用户问题生成符合{engine}数据库引擎规范的sql语句,以及sql中所用到的表名(不要包含schema和database,用数组返回)。
你必须遵守以下规则:
+ - 不要编造没有提供给你的表结构
- 生成的SQL必须符合{engine}的规范。
- 你的回答必须使用如下JSON格式返回:
{{"success":true,"sql":"生成的SQL语句","tables":["表名1","表名2",...]}}
diff --git a/frontend/public/assistant.js b/frontend/public/assistant.js
index cc0d7b2b..fd60c620 100644
--- a/frontend/public/assistant.js
+++ b/frontend/public/assistant.js
@@ -22,7 +22,7 @@
-
+
🌟 遇见问题,不再有障碍!
你好,我是你的智能小助手。
点我,开启高效解答模式,让问题变成过去式。
@@ -217,9 +217,9 @@
bottom: 0!important;
}
}
-
+
/* 引导 */
-
+
#sqlbot-assistant .sqlbot-assistant-mask {
position: fixed;
z-index: 10001;
@@ -289,7 +289,7 @@
right: 20px;
top: 20px;
cursor: pointer;
-
+
}
#sqlbot-assistant-chat-container {
width: 460px;
@@ -303,7 +303,7 @@
right: 0 !important;
}
}
-
+
#sqlbot-assistant .sqlbot-assistant-chat-button{
position: fixed;
${data.x_type}: ${data.x_value}px;
@@ -362,7 +362,7 @@
from {
height: 0;;
}
-
+
to {
height: 600px;
}
@@ -433,7 +433,6 @@
}
if (event.data?.busi == 'ready' && event.data?.ready) {
const certificate = parsrCertificate(data)
- console.log(certificate)
params = {
busi: 'certificate',
certificate,
diff --git a/frontend/src/components/filter-text/index.ts b/frontend/src/components/filter-text/index.ts
index 343a0af8..7f250759 100644
--- a/frontend/src/components/filter-text/index.ts
+++ b/frontend/src/components/filter-text/index.ts
@@ -58,8 +58,6 @@ const valueText = (field: string, val: string, options: any[]) => {
return val
}
export const convertFilterText = (conditions: any[], options: any[]) => {
- console.log('conditions', conditions, options)
-
const result: any[] = []
conditions.forEach((condition) => {
const field = condition.field
diff --git a/frontend/src/i18n/zh-CN.json b/frontend/src/i18n/zh-CN.json
index 750e9e8a..660c65f8 100644
--- a/frontend/src/i18n/zh-CN.json
+++ b/frontend/src/i18n/zh-CN.json
@@ -44,7 +44,7 @@
"add_dashboard_name_tips": "请输入仪表板名称",
"existing_dashboard": "存量仪表板",
"add_success": "添加成功",
- "no_data": "没找到相关内容",
+ "no_data": "没有找到相关内容",
"new_tab": "新建Tab",
"length_limit64": "字段长度需要在1-64之间",
"sort_column": "排序字段",
diff --git a/frontend/src/router/watch.ts b/frontend/src/router/watch.ts
index a5fc9c41..5ec611e0 100644
--- a/frontend/src/router/watch.ts
+++ b/frontend/src/router/watch.ts
@@ -31,7 +31,7 @@ export const watchRouter = (router: any) => {
return
}
if (to.path === '/login') {
- console.log(from)
+ console.info(from)
next('/chat')
} else {
next()
diff --git a/frontend/src/views/chat/answer/AnalysisAnswer.vue b/frontend/src/views/chat/answer/AnalysisAnswer.vue
index 764c8622..34358d5d 100644
--- a/frontend/src/views/chat/answer/AnalysisAnswer.vue
+++ b/frontend/src/views/chat/answer/AnalysisAnswer.vue
@@ -133,9 +133,6 @@ const sendMessage = async () => {
_list.push(line)
}
}
-
- // console.log(_list)
-
for (const str of _list) {
let data
try {
@@ -161,7 +158,7 @@ const sendMessage = async () => {
_currentChat.value.records[index.value].id = data.id
break
case 'info':
- console.log(data.msg)
+ console.info(data.msg)
break
case 'error':
currentRecord.error = data.content
diff --git a/frontend/src/views/chat/answer/ChartAnswer.vue b/frontend/src/views/chat/answer/ChartAnswer.vue
index 805a05f6..d87569fb 100644
--- a/frontend/src/views/chat/answer/ChartAnswer.vue
+++ b/frontend/src/views/chat/answer/ChartAnswer.vue
@@ -137,9 +137,6 @@ const sendMessage = async () => {
_list.push(line)
}
}
-
- // console.log(_list)
-
for (const str of _list) {
let data
try {
@@ -165,7 +162,7 @@ const sendMessage = async () => {
_currentChat.value.records[index.value].id = data.id
break
case 'info':
- console.log(data.msg)
+ console.info(data.msg)
break
case 'brief':
_currentChat.value.brief = data.brief
diff --git a/frontend/src/views/chat/answer/PredictAnswer.vue b/frontend/src/views/chat/answer/PredictAnswer.vue
index c2a4aaca..1bb339f8 100644
--- a/frontend/src/views/chat/answer/PredictAnswer.vue
+++ b/frontend/src/views/chat/answer/PredictAnswer.vue
@@ -133,9 +133,6 @@ const sendMessage = async () => {
_list.push(line)
}
}
-
- // console.log(_list)
-
for (const str of _list) {
let data
try {
@@ -160,7 +157,7 @@ const sendMessage = async () => {
_currentChat.value.records[index.value].id = data.id
break
case 'info':
- console.log(data.msg)
+ console.info(data.msg)
break
case 'error':
currentRecord.error = data.content
diff --git a/frontend/src/views/chat/chat-block/UserChat.vue b/frontend/src/views/chat/chat-block/UserChat.vue
index 13422d32..d360b948 100644
--- a/frontend/src/views/chat/chat-block/UserChat.vue
+++ b/frontend/src/views/chat/chat-block/UserChat.vue
@@ -8,10 +8,10 @@ const props = defineProps<{
const { t } = useI18n()
function clickAnalysis() {
- console.log('analysis_record_id: ' + props.message?.record?.analysis_record_id)
+ console.info('analysis_record_id: ' + props.message?.record?.analysis_record_id)
}
function clickPredict() {
- console.log('predict_record_id: ' + props.message?.record?.predict_record_id)
+ console.info('predict_record_id: ' + props.message?.record?.predict_record_id)
}
diff --git a/frontend/src/views/chat/index.vue b/frontend/src/views/chat/index.vue
index 7e1e78e3..ecd89429 100644
--- a/frontend/src/views/chat/index.vue
+++ b/frontend/src/views/chat/index.vue
@@ -461,11 +461,11 @@ const currentChatEngineType = computed(() => {
})
function onChatDeleted(id: number) {
- console.log('deleted', id)
+ console.info('deleted', id)
}
function onChatRenamed(chat: Chat) {
- console.log('renamed', chat)
+ console.info('renamed', chat)
}
const chatListSideBarShow = ref(true)
diff --git a/frontend/src/views/dashboard/components/sq-text-t7/index.vue b/frontend/src/views/dashboard/components/sq-text-t7/index.vue
index b2070122..bf22fede 100644
--- a/frontend/src/views/dashboard/components/sq-text-t7/index.vue
+++ b/frontend/src/views/dashboard/components/sq-text-t7/index.vue
@@ -52,7 +52,7 @@ const initOptions = {
}
const handleInit = (editor: any) => {
editorRef.value = editor
- console.log('TinyMCE 初始化完成', editor)
+ console.info('TinyMCE 初始化完成', editor)
}
diff --git a/frontend/src/views/ds/Datasource.vue b/frontend/src/views/ds/Datasource.vue
index b6fbebd8..4273d211 100644
--- a/frontend/src/views/ds/Datasource.vue
+++ b/frontend/src/views/ds/Datasource.vue
@@ -126,11 +126,11 @@ const refreshData = () => {
}
const panelClick = () => {
- console.log('panelClick')
+ console.info('panelClick')
}
const smartClick = () => {
- console.log('smartClick')
+ console.info('smartClick')
}
const deleteHandler = (item: any) => {
diff --git a/frontend/src/views/setting/Professional.vue b/frontend/src/views/setting/Professional.vue
index bd19b976..4ab19613 100644
--- a/frontend/src/views/setting/Professional.vue
+++ b/frontend/src/views/setting/Professional.vue
@@ -114,11 +114,10 @@ const state = reactive({
},
})
const handleSearch = (e: any) => {
- console.log('search', e)
+ console.info('search', e)
}
const editHandler = (id: any) => {
termApi.query(id).then((res: any) => {
- console.log('term detail', res)
state.form = res
dialogFormVisible.value = true
})
@@ -181,7 +180,7 @@ const addTerm = () => {
}
const editTerm = () => {
termApi.edit(state.form).then((res: any) => {
- console.log('edit term', res)
+ console.info('edit term', res)
dialogFormVisible.value = false
search()
ElMessage({
diff --git a/frontend/src/views/setting/index.vue b/frontend/src/views/setting/index.vue
index 99496857..7ea3cbfa 100644
--- a/frontend/src/views/setting/index.vue
+++ b/frontend/src/views/setting/index.vue
@@ -31,7 +31,7 @@ import Professional from './Professional.vue'
const activeName = ref('0')
const handleClick = (tab: any, event: MouseEvent) => {
- console.log(tab, event)
+ console.info(tab, event)
}
diff --git a/frontend/src/views/system/embedded/index.vue b/frontend/src/views/system/embedded/index.vue
index 38bf6afd..dc357d4e 100644
--- a/frontend/src/views/system/embedded/index.vue
+++ b/frontend/src/views/system/embedded/index.vue
@@ -164,7 +164,7 @@ const beforeClose = () => {
}
const handleActive = (row: any) => {
- console.log('row', row)
+ console.info('row', row)
}
const handlePrivate = (row: any) => {
diff --git a/frontend/src/views/system/model/Model.vue b/frontend/src/views/system/model/Model.vue
index a7b11cae..11415864 100644
--- a/frontend/src/views/system/model/Model.vue
+++ b/frontend/src/views/system/model/Model.vue
@@ -35,7 +35,7 @@ const activeName = ref('')
const activeType = ref('')
const modelFormRef = ref()
const cardRefs = ref([])
-const showCardError = ref(true) // if you don`t want card mask error, just change this to false
+// const showCardError = ref(true) // if you don`t want card mask error, just change this to false
reactive({
form: {
id: '',
@@ -71,6 +71,8 @@ const defaultModelListWithSearch = computed(() => {
})
const modelCheckHandler = async (item: any) => {
+ console.log(item)
+ /**
const response = await modelApi.check(item)
const reader = response.body.getReader()
const decoder = new TextDecoder()
@@ -110,6 +112,7 @@ const modelCheckHandler = async (item: any) => {
currentRef?.showErrorMask(checkMsg)
}
})
+ */
}
const duplicateName = async (item: any) => {
const res = await modelApi.queryAll()
@@ -201,7 +204,7 @@ const deleteHandler = (item: any) => {
customClass: 'confirm-no_icon',
autofocus: false,
callback: (val: string) => {
- console.log(val)
+ console.info(val)
},
})
return
diff --git a/frontend/src/views/system/permission/auth-tree/FilterFiled.vue b/frontend/src/views/system/permission/auth-tree/FilterFiled.vue
index 68b00675..c1068677 100644
--- a/frontend/src/views/system/permission/auth-tree/FilterFiled.vue
+++ b/frontend/src/views/system/permission/auth-tree/FilterFiled.vue
@@ -93,7 +93,7 @@ const filterTypeChange = () => {
initEnumOptions()
}
const initEnumOptions = () => {
- console.log('initEnumOptions')
+ console.info('initEnumOptions')
}
const selectItem = ({ field_name, id }: any) => {
diff --git a/frontend/src/views/system/user/User.vue b/frontend/src/views/system/user/User.vue
index 9c140a70..add0e20e 100644
--- a/frontend/src/views/system/user/User.vue
+++ b/frontend/src/views/system/user/User.vue
@@ -552,7 +552,7 @@ const handleEditPassword = (id: any) => {
const handleConfirmPassword = () => {
passwordRef.value.validate((val: any) => {
if (val) {
- console.log(val)
+ console.info(val)
}
})
dialogVisiblePassword.value = false
diff --git a/frontend/src/views/system/user/index.vue b/frontend/src/views/system/user/index.vue
index 801fd1c2..d9e9e4e2 100644
--- a/frontend/src/views/system/user/index.vue
+++ b/frontend/src/views/system/user/index.vue
@@ -152,10 +152,10 @@ const state = reactive({
},
})
const handleSearch = (e: any) => {
- console.log('search', e)
+ console.info('search', e)
}
const editHandler = (id: any) => {
- console.log('editHandler', id)
+ console.info('editHandler', id)
/* userApi.query(id).then((res: any) => {
console.log('term detail', res)
state.form = res
@@ -163,7 +163,7 @@ const editHandler = (id: any) => {
}) */
}
const deleteHandler = (id: any) => {
- console.log('deleteHandler', id)
+ console.info('deleteHandler', id)
ElMessageBox.confirm('Are you sure to delete?', 'Warning', {
confirmButtonText: 'OK',
cancelButtonText: 'Cancel',
@@ -222,7 +222,7 @@ const addTerm = () => {
}
const editTerm = () => {
userApi.edit(state.form).then((res: any) => {
- console.log('edit term', res)
+ console.info('edit term', res)
dialogFormVisible.value = false
search()
ElMessage({
diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts
index 4749a7e2..c63a7c3a 100644
--- a/frontend/vite.config.ts
+++ b/frontend/vite.config.ts
@@ -7,8 +7,8 @@ import path from 'path'
import svgLoader from 'vite-svg-loader'
export default defineConfig(({ mode }) => {
const env = loadEnv(mode, process.cwd())
- console.log(mode)
- console.log(env)
+ console.info(mode)
+ console.info(env)
return {
base: './',
plugins: [
diff --git a/g2-ssr/app.js b/g2-ssr/app.js
index 425419e3..9589e9b6 100644
--- a/g2-ssr/app.js
+++ b/g2-ssr/app.js
@@ -17,7 +17,7 @@ http.createServer((req, res) => {
toPost(req, res);
}
}).listen(port, () => {
- console.log(`Server listening on: http://localhost:${port}`);
+ console.info(`Server listening on: http://localhost:${port}`);
});
function getOptions(type, axis, data) {
@@ -50,9 +50,7 @@ function getOptions(type, axis, data) {
// 创建 Chart 和配置
async function GenerateCharts(obj) {
- console.log(obj)
const options = getOptions(obj.type, JSON.parse(obj.axis), JSON.parse(obj.data));
- console.log(options);
const chart = await createChart(options);
// 导出
@@ -69,7 +67,6 @@ async function GenerateCharts(obj) {
function toGet(req, res) {
let data = 'GET请求内容:\n' + util.inspect(url.parse(req.url));
res.end(data);
- console.log(data);
}
//获取POST请求内容、cookie