Add mssql support (#3985)

some thing
-  execsql  add connection mssql
- fix bug duckduckgo-search rate limit
- update typo vi res

---------

Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com>
This commit is contained in:
so95 2024-12-12 18:26:44 +07:00 committed by GitHub
parent e8d74108a5
commit d6c74ff131
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 440 additions and 319 deletions

View File

@ -85,6 +85,15 @@ RUN --mount=type=cache,id=ragflow_apt,target=/var/cache/apt,sharing=locked \
apt update && \ apt update && \
apt install -y nodejs cargo apt install -y nodejs cargo
# Add msssql17
RUN --mount=type=cache,id=ragflow_apt,target=/var/cache/apt,sharing=locked \
curl https://packages.microsoft.com/keys/microsoft.asc | tee /etc/apt/trusted.gpg.d/microsoft.asc && \
curl https://packages.microsoft.com/config/ubuntu/22.04/prod.list | tee /etc/apt/sources.list.d/mssql-release.list && \
apt update && \
ACCEPT_EULA=Y apt install -y unixodbc-dev msodbcsql17
# Add dependencies of selenium # Add dependencies of selenium
RUN --mount=type=bind,from=infiniflow/ragflow_deps:latest,source=/chrome-linux64-121-0-6167-85,target=/chrome-linux64.zip \ RUN --mount=type=bind,from=infiniflow/ragflow_deps:latest,source=/chrome-linux64-121-0-6167-85,target=/chrome-linux64.zip \
unzip /chrome-linux64.zip && \ unzip /chrome-linux64.zip && \
@ -170,5 +179,4 @@ RUN chmod +x ./entrypoint.sh
COPY --from=builder /ragflow/web/dist /ragflow/web/dist COPY --from=builder /ragflow/web/dist /ragflow/web/dist
COPY --from=builder /ragflow/VERSION /ragflow/VERSION COPY --from=builder /ragflow/VERSION /ragflow/VERSION
ENTRYPOINT ["./entrypoint.sh"] ENTRYPOINT ["./entrypoint.sh"]

View File

@ -19,6 +19,7 @@ import pandas as pd
import pymysql import pymysql
import psycopg2 import psycopg2
from agent.component.base import ComponentBase, ComponentParamBase from agent.component.base import ComponentBase, ComponentParamBase
import pyodbc
class ExeSQLParam(ComponentParamBase): class ExeSQLParam(ComponentParamBase):
@ -38,7 +39,7 @@ class ExeSQLParam(ComponentParamBase):
self.top_n = 30 self.top_n = 30
def check(self): def check(self):
self.check_valid_value(self.db_type, "Choose DB type", ['mysql', 'postgresql', 'mariadb']) self.check_valid_value(self.db_type, "Choose DB type", ['mysql', 'postgresql', 'mariadb', 'mssql'])
self.check_empty(self.database, "Database name") self.check_empty(self.database, "Database name")
self.check_empty(self.username, "database username") self.check_empty(self.username, "database username")
self.check_empty(self.host, "IP Address") self.check_empty(self.host, "IP Address")
@ -77,7 +78,15 @@ class ExeSQL(ComponentBase, ABC):
elif self._param.db_type == 'postgresql': elif self._param.db_type == 'postgresql':
db = psycopg2.connect(dbname=self._param.database, user=self._param.username, host=self._param.host, db = psycopg2.connect(dbname=self._param.database, user=self._param.username, host=self._param.host,
port=self._param.port, password=self._param.password) port=self._param.port, password=self._param.password)
elif self._param.db_type == 'mssql':
conn_str = (
r'DRIVER={ODBC Driver 17 for SQL Server};'
r'SERVER=' + self._param.host + ',' + str(self._param.port) + ';'
r'DATABASE=' + self._param.database + ';'
r'UID=' + self._param.username + ';'
r'PWD=' + self._param.password
)
db = pyodbc.connect(conn_str)
try: try:
cursor = db.cursor() cursor = db.cursor()
except Exception as e: except Exception as e:

View File

@ -242,8 +242,26 @@ def test_db_connect():
elif req["db_type"] == 'postgresql': elif req["db_type"] == 'postgresql':
db = PostgresqlDatabase(req["database"], user=req["username"], host=req["host"], port=req["port"], db = PostgresqlDatabase(req["database"], user=req["username"], host=req["host"], port=req["port"],
password=req["password"]) password=req["password"])
elif req["db_type"] == 'mssql':
import pyodbc
connection_string = (
f"DRIVER={{ODBC Driver 17 for SQL Server}};"
f"SERVER={req['host']},{req['port']};"
f"DATABASE={req['database']};"
f"UID={req['username']};"
f"PWD={req['password']};"
)
db = pyodbc.connect(connection_string)
cursor = db.cursor()
cursor.execute("SELECT 1")
cursor.close()
else:
return server_error_response("Unsupported database type.")
if req["db_type"] != 'mssql':
db.connect() db.connect()
db.close() db.close()
return get_json_result(data="Database Connection Successful!") return get_json_result(data="Database Connection Successful!")
except Exception as e: except Exception as e:
return server_error_response(e) return server_error_response(e)

667
poetry.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -31,7 +31,7 @@ dashscope = "1.20.11"
deepl = "1.18.0" deepl = "1.18.0"
demjson3 = "3.0.6" demjson3 = "3.0.6"
discord-py = "2.3.2" discord-py = "2.3.2"
duckduckgo-search = "6.1.9" duckduckgo-search = "6.4.1"
editdistance = "0.8.1" editdistance = "0.8.1"
elastic-transport = "8.12.0" elastic-transport = "8.12.0"
elasticsearch = "8.12.1" elasticsearch = "8.12.1"
@ -117,6 +117,7 @@ pypdf2 = "^3.0.1"
graspologic = "^3.4.1" graspologic = "^3.4.1"
pymysql = "^1.1.1" pymysql = "^1.1.1"
mini-racer = "^0.12.4" mini-racer = "^0.12.4"
pyodbc = "^5.2.0"
pyicu = "^2.13.1" pyicu = "^2.13.1"
flasgger = "^0.9.7.1" flasgger = "^0.9.7.1"
polars = { version = "^1.9.0", markers = "platform_machine == 'x86_64'" } polars = { version = "^1.9.0", markers = "platform_machine == 'x86_64'" }

View File

@ -24,10 +24,18 @@ const enFlattened = flattenObject(translation_en);
const viFlattened = flattenObject(translation_vi); const viFlattened = flattenObject(translation_vi);
const esFlattened = flattenObject(translation_es); const esFlattened = flattenObject(translation_es);
const zhFlattened = flattenObject(translation_zh); const zhFlattened = flattenObject(translation_zh);
const jaFlattened = flattenObject(translation_ja);
const zh_traditionalFlattened = flattenObject(translation_zh_traditional); const zh_traditionalFlattened = flattenObject(translation_zh_traditional);
export const translationTable = createTranslationTable( export const translationTable = createTranslationTable(
[enFlattened, viFlattened, esFlattened, zhFlattened, zh_traditionalFlattened], [
['English', 'Vietnamese', 'Spanish', 'zh', 'zh-TRADITIONAL'], enFlattened,
viFlattened,
esFlattened,
zhFlattened,
zh_traditionalFlattened,
jaFlattened,
],
['English', 'Vietnamese', 'Spanish', 'zh', 'zh-TRADITIONAL', 'ja'],
); );
i18n i18n
.use(initReactI18next) .use(initReactI18next)

View File

@ -353,7 +353,8 @@ The above is the content you need to summarize.`,
setAnOpenerTip: 'Set an opening greeting for users.', setAnOpenerTip: 'Set an opening greeting for users.',
knowledgeBases: 'Knowledge bases', knowledgeBases: 'Knowledge bases',
knowledgeBasesMessage: 'Please select', knowledgeBasesMessage: 'Please select',
knowledgeBasesTip: 'Select the knowledge bases to associate with this chat assistant.', knowledgeBasesTip:
'Select the knowledge bases to associate with this chat assistant.',
system: 'System', system: 'System',
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. 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.
Here is the knowledge base: Here is the knowledge base:
@ -455,8 +456,7 @@ The above is the content you need to summarize.`,
profileDescription: 'Update your photo and personal details here.', profileDescription: 'Update your photo and personal details here.',
maxTokens: 'Max Tokens', maxTokens: 'Max Tokens',
maxTokensMessage: 'Max Tokens is required', maxTokensMessage: 'Max Tokens is required',
maxTokensTip: maxTokensTip: `This sets the maximum length of the model's output, measured in the number of tokens (words or pieces of words).`,
`This sets the maximum length of the model's output, measured in the number of tokens (words or pieces of words).`,
maxTokensInvalidMessage: 'Please enter a valid number for Max Tokens.', maxTokensInvalidMessage: 'Please enter a valid number for Max Tokens.',
maxTokensMinMessage: 'Max Tokens cannot be less than 0.', maxTokensMinMessage: 'Max Tokens cannot be less than 0.',
password: 'Password', password: 'Password',

View File

@ -35,6 +35,7 @@ export default {
submit: 'Gửi', submit: 'Gửi',
vietnamese: 'Tiếng việt', vietnamese: 'Tiếng việt',
spanish: 'Tiếng Tây Ban Nha', spanish: 'Tiếng Tây Ban Nha',
japanese: 'Tiếng Nhật',
}, },
login: { login: {
login: 'Đăng nhập', login: 'Đăng nhập',
@ -447,6 +448,7 @@ export default {
'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.', '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.',
howUseId: 'Làm thế nào để sử dụng ID cuộc trò chuyện?', howUseId: 'Làm thế nào để sử dụng ID cuộc trò chuyện?',
description: 'Mô tả về trợ lý', description: 'Mô tả về trợ lý',
betaError: `"Beta API Token" không được để trống!`,
}, },
setting: { setting: {
profile: 'Hồ sơ', profile: 'Hồ sơ',
@ -841,7 +843,7 @@ export default {
timePeriod: 'Kỳ hạn', timePeriod: 'Kỳ hạn',
qWeatherLangOptions: { qWeatherLangOptions: {
zh: 'Giản thể Trung Quốc', zh: 'Giản thể Trung Quốc',
'zh-hant': '繁體中文', 'zh-hant': 'Phồn thể Trung Quốc',
en: 'Tiếng Anh', en: 'Tiếng Anh',
de: 'Tiếng Đức', de: 'Tiếng Đức',
es: 'Tiếng Tây Ban Nha', es: 'Tiếng Tây Ban Nha',
@ -1079,6 +1081,9 @@ export default {
jsonUploadTypeErrorMessage: 'Vui lòng tải lên tệp json', jsonUploadTypeErrorMessage: 'Vui lòng tải lên tệp json',
dynamicParameters: 'Tham số động', dynamicParameters: 'Tham số động',
emailSubject: 'Tiêu đề email', emailSubject: 'Tiêu đề email',
ccEmail: 'Email CC',
toEmailTip: 'to_email: Email người nhận (Bắt buộc)',
ccEmailTip: 'cc_email: Email CC (Tùy chọn)',
}, },
footer: { footer: {
profile: 'All rights reserved @ React', profile: 'All rights reserved @ React',

View File

@ -2855,10 +2855,12 @@ export const QWeatherTimePeriodOptions = [
'30d', '30d',
]; ];
export const ExeSQLOptions = ['mysql', 'postgresql', 'mariadb'].map((x) => ({ export const ExeSQLOptions = ['mysql', 'postgresql', 'mariadb', 'mssql'].map(
(x) => ({
label: upperFirst(x), label: upperFirst(x),
value: x, value: x,
})); }),
);
export const SwitchElseTo = 'end_cpn_id'; export const SwitchElseTo = 'end_cpn_id';

View File

@ -5,7 +5,14 @@ function UserSettingLocale() {
return ( return (
<TranslationTable <TranslationTable
data={translationTable} data={translationTable}
languages={['English', 'Vietnamese', 'Spanish', 'zh', 'zh-TRADITIONAL']} languages={[
'English',
'Vietnamese',
'Spanish',
'zh',
'zh-TRADITIONAL',
'ja',
]}
/> />
); );
} }