Add mssql support (#3985)
Browse filessome thing
- execsql add connection mssql
- fix bug duckduckgo-search rate limit
- update typo vi res
---------
Co-authored-by: Kevin Hu <[email protected]>
- Dockerfile +10 -2
- agent/component/exesql.py +11 -2
- api/apps/canvas_app.py +19 -1
- poetry.lock +0 -0
- pyproject.toml +2 -1
- web/src/locales/config.ts +10 -2
- web/src/locales/en.ts +3 -3
- web/src/locales/vi.ts +6 -1
- web/src/pages/flow/constant.tsx +6 -4
- web/src/pages/user-setting/setting-locale/index.tsx +8 -1
Dockerfile
CHANGED
@@ -83,7 +83,16 @@ RUN --mount=type=cache,id=ragflow_apt,target=/var/cache/apt,sharing=locked \
|
|
83 |
apt purge -y nodejs npm && \
|
84 |
apt autoremove && \
|
85 |
apt update && \
|
86 |
-
apt install -y nodejs cargo
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
87 |
|
88 |
# Add dependencies of selenium
|
89 |
RUN --mount=type=bind,from=infiniflow/ragflow_deps:latest,source=/chrome-linux64-121-0-6167-85,target=/chrome-linux64.zip \
|
@@ -170,5 +179,4 @@ RUN chmod +x ./entrypoint.sh
|
|
170 |
COPY --from=builder /ragflow/web/dist /ragflow/web/dist
|
171 |
|
172 |
COPY --from=builder /ragflow/VERSION /ragflow/VERSION
|
173 |
-
|
174 |
ENTRYPOINT ["./entrypoint.sh"]
|
|
|
83 |
apt purge -y nodejs npm && \
|
84 |
apt autoremove && \
|
85 |
apt update && \
|
86 |
+
apt install -y nodejs cargo
|
87 |
+
|
88 |
+
# Add msssql17
|
89 |
+
RUN --mount=type=cache,id=ragflow_apt,target=/var/cache/apt,sharing=locked \
|
90 |
+
curl https://packages.microsoft.com/keys/microsoft.asc | tee /etc/apt/trusted.gpg.d/microsoft.asc && \
|
91 |
+
curl https://packages.microsoft.com/config/ubuntu/22.04/prod.list | tee /etc/apt/sources.list.d/mssql-release.list && \
|
92 |
+
apt update && \
|
93 |
+
ACCEPT_EULA=Y apt install -y unixodbc-dev msodbcsql17
|
94 |
+
|
95 |
+
|
96 |
|
97 |
# Add dependencies of selenium
|
98 |
RUN --mount=type=bind,from=infiniflow/ragflow_deps:latest,source=/chrome-linux64-121-0-6167-85,target=/chrome-linux64.zip \
|
|
|
179 |
COPY --from=builder /ragflow/web/dist /ragflow/web/dist
|
180 |
|
181 |
COPY --from=builder /ragflow/VERSION /ragflow/VERSION
|
|
|
182 |
ENTRYPOINT ["./entrypoint.sh"]
|
agent/component/exesql.py
CHANGED
@@ -19,6 +19,7 @@ import pandas as pd
|
|
19 |
import pymysql
|
20 |
import psycopg2
|
21 |
from agent.component.base import ComponentBase, ComponentParamBase
|
|
|
22 |
|
23 |
|
24 |
class ExeSQLParam(ComponentParamBase):
|
@@ -38,7 +39,7 @@ class ExeSQLParam(ComponentParamBase):
|
|
38 |
self.top_n = 30
|
39 |
|
40 |
def check(self):
|
41 |
-
self.check_valid_value(self.db_type, "Choose DB type", ['mysql', 'postgresql', 'mariadb'])
|
42 |
self.check_empty(self.database, "Database name")
|
43 |
self.check_empty(self.username, "database username")
|
44 |
self.check_empty(self.host, "IP Address")
|
@@ -77,7 +78,15 @@ class ExeSQL(ComponentBase, ABC):
|
|
77 |
elif self._param.db_type == 'postgresql':
|
78 |
db = psycopg2.connect(dbname=self._param.database, user=self._param.username, host=self._param.host,
|
79 |
port=self._param.port, password=self._param.password)
|
80 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
81 |
try:
|
82 |
cursor = db.cursor()
|
83 |
except Exception as e:
|
|
|
19 |
import pymysql
|
20 |
import psycopg2
|
21 |
from agent.component.base import ComponentBase, ComponentParamBase
|
22 |
+
import pyodbc
|
23 |
|
24 |
|
25 |
class ExeSQLParam(ComponentParamBase):
|
|
|
39 |
self.top_n = 30
|
40 |
|
41 |
def check(self):
|
42 |
+
self.check_valid_value(self.db_type, "Choose DB type", ['mysql', 'postgresql', 'mariadb', 'mssql'])
|
43 |
self.check_empty(self.database, "Database name")
|
44 |
self.check_empty(self.username, "database username")
|
45 |
self.check_empty(self.host, "IP Address")
|
|
|
78 |
elif self._param.db_type == 'postgresql':
|
79 |
db = psycopg2.connect(dbname=self._param.database, user=self._param.username, host=self._param.host,
|
80 |
port=self._param.port, password=self._param.password)
|
81 |
+
elif self._param.db_type == 'mssql':
|
82 |
+
conn_str = (
|
83 |
+
r'DRIVER={ODBC Driver 17 for SQL Server};'
|
84 |
+
r'SERVER=' + self._param.host + ',' + str(self._param.port) + ';'
|
85 |
+
r'DATABASE=' + self._param.database + ';'
|
86 |
+
r'UID=' + self._param.username + ';'
|
87 |
+
r'PWD=' + self._param.password
|
88 |
+
)
|
89 |
+
db = pyodbc.connect(conn_str)
|
90 |
try:
|
91 |
cursor = db.cursor()
|
92 |
except Exception as e:
|
api/apps/canvas_app.py
CHANGED
@@ -242,8 +242,26 @@ def test_db_connect():
|
|
242 |
elif req["db_type"] == 'postgresql':
|
243 |
db = PostgresqlDatabase(req["database"], user=req["username"], host=req["host"], port=req["port"],
|
244 |
password=req["password"])
|
245 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
246 |
db.close()
|
|
|
247 |
return get_json_result(data="Database Connection Successful!")
|
248 |
except Exception as e:
|
249 |
return server_error_response(e)
|
|
|
|
242 |
elif req["db_type"] == 'postgresql':
|
243 |
db = PostgresqlDatabase(req["database"], user=req["username"], host=req["host"], port=req["port"],
|
244 |
password=req["password"])
|
245 |
+
elif req["db_type"] == 'mssql':
|
246 |
+
import pyodbc
|
247 |
+
connection_string = (
|
248 |
+
f"DRIVER={{ODBC Driver 17 for SQL Server}};"
|
249 |
+
f"SERVER={req['host']},{req['port']};"
|
250 |
+
f"DATABASE={req['database']};"
|
251 |
+
f"UID={req['username']};"
|
252 |
+
f"PWD={req['password']};"
|
253 |
+
)
|
254 |
+
db = pyodbc.connect(connection_string)
|
255 |
+
cursor = db.cursor()
|
256 |
+
cursor.execute("SELECT 1")
|
257 |
+
cursor.close()
|
258 |
+
else:
|
259 |
+
return server_error_response("Unsupported database type.")
|
260 |
+
if req["db_type"] != 'mssql':
|
261 |
+
db.connect()
|
262 |
db.close()
|
263 |
+
|
264 |
return get_json_result(data="Database Connection Successful!")
|
265 |
except Exception as e:
|
266 |
return server_error_response(e)
|
267 |
+
|
poetry.lock
CHANGED
The diff for this file is too large to render.
See raw diff
|
|
pyproject.toml
CHANGED
@@ -31,7 +31,7 @@ dashscope = "1.20.11"
|
|
31 |
deepl = "1.18.0"
|
32 |
demjson3 = "3.0.6"
|
33 |
discord-py = "2.3.2"
|
34 |
-
duckduckgo-search = "6.1
|
35 |
editdistance = "0.8.1"
|
36 |
elastic-transport = "8.12.0"
|
37 |
elasticsearch = "8.12.1"
|
@@ -117,6 +117,7 @@ pypdf2 = "^3.0.1"
|
|
117 |
graspologic = "^3.4.1"
|
118 |
pymysql = "^1.1.1"
|
119 |
mini-racer = "^0.12.4"
|
|
|
120 |
pyicu = "^2.13.1"
|
121 |
flasgger = "^0.9.7.1"
|
122 |
polars = { version = "^1.9.0", markers = "platform_machine == 'x86_64'" }
|
|
|
31 |
deepl = "1.18.0"
|
32 |
demjson3 = "3.0.6"
|
33 |
discord-py = "2.3.2"
|
34 |
+
duckduckgo-search = "6.4.1"
|
35 |
editdistance = "0.8.1"
|
36 |
elastic-transport = "8.12.0"
|
37 |
elasticsearch = "8.12.1"
|
|
|
117 |
graspologic = "^3.4.1"
|
118 |
pymysql = "^1.1.1"
|
119 |
mini-racer = "^0.12.4"
|
120 |
+
pyodbc = "^5.2.0"
|
121 |
pyicu = "^2.13.1"
|
122 |
flasgger = "^0.9.7.1"
|
123 |
polars = { version = "^1.9.0", markers = "platform_machine == 'x86_64'" }
|
web/src/locales/config.ts
CHANGED
@@ -24,10 +24,18 @@ const enFlattened = flattenObject(translation_en);
|
|
24 |
const viFlattened = flattenObject(translation_vi);
|
25 |
const esFlattened = flattenObject(translation_es);
|
26 |
const zhFlattened = flattenObject(translation_zh);
|
|
|
27 |
const zh_traditionalFlattened = flattenObject(translation_zh_traditional);
|
28 |
export const translationTable = createTranslationTable(
|
29 |
-
[
|
30 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
31 |
);
|
32 |
i18n
|
33 |
.use(initReactI18next)
|
|
|
24 |
const viFlattened = flattenObject(translation_vi);
|
25 |
const esFlattened = flattenObject(translation_es);
|
26 |
const zhFlattened = flattenObject(translation_zh);
|
27 |
+
const jaFlattened = flattenObject(translation_ja);
|
28 |
const zh_traditionalFlattened = flattenObject(translation_zh_traditional);
|
29 |
export const translationTable = createTranslationTable(
|
30 |
+
[
|
31 |
+
enFlattened,
|
32 |
+
viFlattened,
|
33 |
+
esFlattened,
|
34 |
+
zhFlattened,
|
35 |
+
zh_traditionalFlattened,
|
36 |
+
jaFlattened,
|
37 |
+
],
|
38 |
+
['English', 'Vietnamese', 'Spanish', 'zh', 'zh-TRADITIONAL', 'ja'],
|
39 |
);
|
40 |
i18n
|
41 |
.use(initReactI18next)
|
web/src/locales/en.ts
CHANGED
@@ -353,7 +353,8 @@ The above is the content you need to summarize.`,
|
|
353 |
setAnOpenerTip: 'Set an opening greeting for users.',
|
354 |
knowledgeBases: 'Knowledge bases',
|
355 |
knowledgeBasesMessage: 'Please select',
|
356 |
-
knowledgeBasesTip:
|
|
|
357 |
system: 'System',
|
358 |
systemInitialValue: `You are an intelligent assistant. Please summarize the content of the knowledge base to answer the question. Please list the data in the knowledge base and answer in detail. When all knowledge base content is irrelevant to the question, your answer must include the sentence "The answer you are looking for is not found in the knowledge base!" Answers need to consider chat history.
|
359 |
Here is the knowledge base:
|
@@ -455,8 +456,7 @@ The above is the content you need to summarize.`,
|
|
455 |
profileDescription: 'Update your photo and personal details here.',
|
456 |
maxTokens: 'Max Tokens',
|
457 |
maxTokensMessage: 'Max Tokens is required',
|
458 |
-
maxTokensTip:
|
459 |
-
`This sets the maximum length of the model's output, measured in the number of tokens (words or pieces of words).`,
|
460 |
maxTokensInvalidMessage: 'Please enter a valid number for Max Tokens.',
|
461 |
maxTokensMinMessage: 'Max Tokens cannot be less than 0.',
|
462 |
password: 'Password',
|
|
|
353 |
setAnOpenerTip: 'Set an opening greeting for users.',
|
354 |
knowledgeBases: 'Knowledge bases',
|
355 |
knowledgeBasesMessage: 'Please select',
|
356 |
+
knowledgeBasesTip:
|
357 |
+
'Select the knowledge bases to associate with this chat assistant.',
|
358 |
system: 'System',
|
359 |
systemInitialValue: `You are an intelligent assistant. Please summarize the content of the knowledge base to answer the question. Please list the data in the knowledge base and answer in detail. When all knowledge base content is irrelevant to the question, your answer must include the sentence "The answer you are looking for is not found in the knowledge base!" Answers need to consider chat history.
|
360 |
Here is the knowledge base:
|
|
|
456 |
profileDescription: 'Update your photo and personal details here.',
|
457 |
maxTokens: 'Max Tokens',
|
458 |
maxTokensMessage: 'Max Tokens is required',
|
459 |
+
maxTokensTip: `This sets the maximum length of the model's output, measured in the number of tokens (words or pieces of words).`,
|
|
|
460 |
maxTokensInvalidMessage: 'Please enter a valid number for Max Tokens.',
|
461 |
maxTokensMinMessage: 'Max Tokens cannot be less than 0.',
|
462 |
password: 'Password',
|
web/src/locales/vi.ts
CHANGED
@@ -35,6 +35,7 @@ export default {
|
|
35 |
submit: 'Gửi',
|
36 |
vietnamese: 'Tiếng việt',
|
37 |
spanish: 'Tiếng Tây Ban Nha',
|
|
|
38 |
},
|
39 |
login: {
|
40 |
login: 'Đăng nhập',
|
@@ -447,6 +448,7 @@ export default {
|
|
447 |
'Trong các cuộc trò chuyện nhiều vòng, truy vấn vào cơ sở kiến thức được tối ưu hóa. Mô hình lớn sẽ được gọi để sử dụng thêm các token.',
|
448 |
howUseId: 'Làm thế nào để sử dụng ID cuộc trò chuyện?',
|
449 |
description: 'Mô tả về trợ lý',
|
|
|
450 |
},
|
451 |
setting: {
|
452 |
profile: 'Hồ sơ',
|
@@ -841,7 +843,7 @@ export default {
|
|
841 |
timePeriod: 'Kỳ hạn',
|
842 |
qWeatherLangOptions: {
|
843 |
zh: 'Giản thể Trung Quốc',
|
844 |
-
'zh-hant': '
|
845 |
en: 'Tiếng Anh',
|
846 |
de: 'Tiếng Đức',
|
847 |
es: 'Tiếng Tây Ban Nha',
|
@@ -1079,6 +1081,9 @@ export default {
|
|
1079 |
jsonUploadTypeErrorMessage: 'Vui lòng tải lên tệp json',
|
1080 |
dynamicParameters: 'Tham số động',
|
1081 |
emailSubject: 'Tiêu đề email',
|
|
|
|
|
|
|
1082 |
},
|
1083 |
footer: {
|
1084 |
profile: 'All rights reserved @ React',
|
|
|
35 |
submit: 'Gửi',
|
36 |
vietnamese: 'Tiếng việt',
|
37 |
spanish: 'Tiếng Tây Ban Nha',
|
38 |
+
japanese: 'Tiếng Nhật',
|
39 |
},
|
40 |
login: {
|
41 |
login: 'Đăng nhập',
|
|
|
448 |
'Trong các cuộc trò chuyện nhiều vòng, truy vấn vào cơ sở kiến thức được tối ưu hóa. Mô hình lớn sẽ được gọi để sử dụng thêm các token.',
|
449 |
howUseId: 'Làm thế nào để sử dụng ID cuộc trò chuyện?',
|
450 |
description: 'Mô tả về trợ lý',
|
451 |
+
betaError: `"Beta API Token" không được để trống!`,
|
452 |
},
|
453 |
setting: {
|
454 |
profile: 'Hồ sơ',
|
|
|
843 |
timePeriod: 'Kỳ hạn',
|
844 |
qWeatherLangOptions: {
|
845 |
zh: 'Giản thể Trung Quốc',
|
846 |
+
'zh-hant': 'Phồn thể Trung Quốc',
|
847 |
en: 'Tiếng Anh',
|
848 |
de: 'Tiếng Đức',
|
849 |
es: 'Tiếng Tây Ban Nha',
|
|
|
1081 |
jsonUploadTypeErrorMessage: 'Vui lòng tải lên tệp json',
|
1082 |
dynamicParameters: 'Tham số động',
|
1083 |
emailSubject: 'Tiêu đề email',
|
1084 |
+
ccEmail: 'Email CC',
|
1085 |
+
toEmailTip: 'to_email: Email người nhận (Bắt buộc)',
|
1086 |
+
ccEmailTip: 'cc_email: Email CC (Tùy chọn)',
|
1087 |
},
|
1088 |
footer: {
|
1089 |
profile: 'All rights reserved @ React',
|
web/src/pages/flow/constant.tsx
CHANGED
@@ -2855,10 +2855,12 @@ export const QWeatherTimePeriodOptions = [
|
|
2855 |
'30d',
|
2856 |
];
|
2857 |
|
2858 |
-
export const ExeSQLOptions = ['mysql', 'postgresql', 'mariadb'].map(
|
2859 |
-
|
2860 |
-
|
2861 |
-
|
|
|
|
|
2862 |
|
2863 |
export const SwitchElseTo = 'end_cpn_id';
|
2864 |
|
|
|
2855 |
'30d',
|
2856 |
];
|
2857 |
|
2858 |
+
export const ExeSQLOptions = ['mysql', 'postgresql', 'mariadb', 'mssql'].map(
|
2859 |
+
(x) => ({
|
2860 |
+
label: upperFirst(x),
|
2861 |
+
value: x,
|
2862 |
+
}),
|
2863 |
+
);
|
2864 |
|
2865 |
export const SwitchElseTo = 'end_cpn_id';
|
2866 |
|
web/src/pages/user-setting/setting-locale/index.tsx
CHANGED
@@ -5,7 +5,14 @@ function UserSettingLocale() {
|
|
5 |
return (
|
6 |
<TranslationTable
|
7 |
data={translationTable}
|
8 |
-
languages={[
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
/>
|
10 |
);
|
11 |
}
|
|
|
5 |
return (
|
6 |
<TranslationTable
|
7 |
data={translationTable}
|
8 |
+
languages={[
|
9 |
+
'English',
|
10 |
+
'Vietnamese',
|
11 |
+
'Spanish',
|
12 |
+
'zh',
|
13 |
+
'zh-TRADITIONAL',
|
14 |
+
'ja',
|
15 |
+
]}
|
16 |
/>
|
17 |
);
|
18 |
}
|