### What problem does this PR solve? feat: Add component ExecSQL #1739 ### Type of change - [x] New Feature (non-breaking change which adds functionality)tags/v0.10.0
| @@ -0,0 +1,6 @@ | |||
| <svg t="1723794486485" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7111" | |||
| width="200" height="200"> | |||
| <path | |||
| d="M776.533333 755.456H598.903467c-14.421333 0-26.112 12.475733-26.112 27.869867v168.618666h28.433066L776.533333 760.439467v-4.983467zM776.533333 699.733333v-88.183466c0-15.189333 11.4688-27.477333 25.6-27.477334s25.6 12.288 25.6 27.477334v160.136533c0 7.2192-2.645333 14.1312-7.338666 19.285333L630.2208 998.7072a24.746667 24.746667 0 0 1-18.261333 8.226133H228.693333C163.669333 1006.933333 110.933333 950.306133 110.933333 880.452267V143.530667C110.933333 73.693867 163.669333 17.066667 228.693333 17.066667h481.28C774.997333 17.066667 827.733333 73.693867 827.733333 143.547733v48.930134c0 15.189333-11.4688 27.477333-25.6 27.477333s-25.6-12.288-25.6-27.477333V143.530667c0-39.4752-29.7984-71.492267-66.56-71.492267H228.693333c-36.7616 0-66.56 32.017067-66.56 71.509333v736.887467c0 39.4752 29.7984 71.492267 66.56 71.492267H520.533333v-168.618667C520.533333 737.160533 555.6224 699.733333 598.903467 699.733333H776.533333zM367.7696 280.576c27.272533 0 47.530667 5.512533 60.416 16.896 13.687467 11.997867 19.1488 30.8224 16.093867 56.149333h-37.666134c-0.238933-14.2848-4.215467-24.6784-11.3664-30.839466-7.0656-6.485333-19.456-9.4208-36.317866-9.4208-14.609067 0-26.0608 1.9456-34.747734 6.178133-10.752 4.864-17.015467 12.970667-19.336533 24.0128-2.048 9.745067 1.4336 17.8688 11.246933 23.722667 4.317867 2.577067 16.605867 7.458133 36.608 14.267733 29.44 9.728 47.9232 17.527467 55.927467 22.7328 17.578667 12.014933 24.1664 28.5696 19.6608 50.005333-4.369067 20.770133-15.9744 37.3248-34.730667 49.322667-18.688 11.690667-43.042133 17.8688-72.584533 17.8688-28.5696 0-49.8176-5.5296-63.402667-16.554667-16.605867-13.653333-22.801067-35.072-18.210133-64.6144h37.666133c-1.092267 17.527467 2.389333 30.208 10.888534 37.666134 7.7312 6.485333 20.9408 10.069333 40.106666 10.069333 16.878933 0 31.112533-2.935467 42.018134-8.448 10.973867-5.8368 17.749333-13.312 19.797333-23.04 2.594133-12.356267-2.833067-22.084267-15.616-29.2352-4.061867-2.269867-17.902933-7.458133-41.915733-15.2576-26.658133-9.079467-43.144533-15.581867-49.152-19.473067-15.581867-10.717867-21.077333-26.299733-16.776534-46.762666 4.3008-20.445867 16.162133-36.676267 36.164267-48.366934 18.602667-11.3664 40.226133-16.878933 65.2288-16.878933z m249.122133 0c35.3792 0 60.910933 11.3664 76.509867 34.4064 14.8992 21.76 18.568533 50.653867 11.042133 86.357333-7.304533 34.747733-22.664533 62.976-45.346133 84.411734 6.109867 11.042133 12.424533 22.7328 18.261333 35.072l-29.184 21.418666a712.5504 712.5504 0 0 0-18.1248-35.703466c-18.944 9.728-40.482133 14.933333-63.863466 14.933333-35.703467 0-61.166933-11.690667-76.509867-34.423467-14.848-22.0672-18.244267-50.6368-10.8544-85.7088 7.441067-35.3792 22.869333-63.9488 47.0016-86.016 25.0368-23.381333 55.3472-34.747733 91.067733-34.747733z m-7.048533 33.450667c-24.0128 0-44.2368 8.106667-60.962133 24.337066-15.940267 15.581867-26.4704 36.352-32.085334 62.976-5.5296 26.299733-3.7376 47.086933 5.649067 62.6688 9.642667 15.906133 26.760533 24.029867 50.7904 24.029867a90.794667 90.794667 0 0 0 41.2672-9.4208c-8.704-14.2848-17.066667-26.948267-25.378133-38.314667l26.5728-21.418666a704.085333 704.085333 0 0 1 25.838933 37.649066c11.451733-14.2848 19.899733-32.785067 24.610133-55.1936 5.7344-27.255467 3.754667-48.6912-5.632-64.273066-9.710933-15.581867-26.624-23.04-50.670933-23.04z m171.434667-28.910934h37.666133l-41.949867 199.338667h125.320534l-6.826667 32.477867h-162.986667l48.776534-231.816534z" | |||
| fill="#2c2c2c" p-id="7112"></path> | |||
| </svg> | |||
| @@ -7,9 +7,10 @@ type FieldType = { | |||
| interface IProps { | |||
| initialValue?: number; | |||
| max?: number; | |||
| } | |||
| const TopNItem = ({ initialValue = 8 }: IProps) => { | |||
| const TopNItem = ({ initialValue = 8, max = 30 }: IProps) => { | |||
| const { t } = useTranslate('chat'); | |||
| return ( | |||
| @@ -19,7 +20,7 @@ const TopNItem = ({ initialValue = 8 }: IProps) => { | |||
| initialValue={initialValue} | |||
| tooltip={t('topNTip')} | |||
| > | |||
| <Slider max={30} /> | |||
| <Slider max={max} /> | |||
| </Form.Item> | |||
| ); | |||
| }; | |||
| @@ -795,6 +795,15 @@ The above is the content you need to summarize.`, | |||
| '30d': '30 days', | |||
| }, | |||
| publish: 'API', | |||
| exeSQL: 'ExeSQL', | |||
| exeSQLDescription: | |||
| 'The component queries the results from the corresponding relational database via SQL statements. Supports MySQL, PostgreSQL, MariaDB. ', | |||
| dbType: 'Database Type', | |||
| database: 'Database', | |||
| username: 'Username', | |||
| host: 'Host', | |||
| port: 'Port', | |||
| password: 'Password', | |||
| }, | |||
| footer: { | |||
| profile: 'All rights reserved @ React', | |||
| @@ -753,6 +753,15 @@ export default { | |||
| '30d': '30天', | |||
| }, | |||
| publish: 'API', | |||
| exeSQL: 'ExeSQL', | |||
| exeSQLDescription: | |||
| '此元件透過SQL語句從對應的關聯式資料庫中查詢結果。支援 MySQL、PostgreSQL、MariaDB。 ', | |||
| dbType: '資料庫類型', | |||
| database: '資料庫', | |||
| username: '使用者名稱', | |||
| host: '主機', | |||
| port: '端口', | |||
| password: '密碼', | |||
| }, | |||
| footer: { | |||
| profile: '“保留所有權利 @ react”', | |||
| @@ -771,6 +771,15 @@ export default { | |||
| '30d': '30天', | |||
| }, | |||
| publish: 'API', | |||
| exeSQL: 'ExeSQL', | |||
| exeSQLDescription: | |||
| '该组件通过SQL语句从相应的关系数据库中查询结果。支持MySQL,PostgreSQL,MariaDB。', | |||
| dbType: '数据库类型', | |||
| database: '数据库', | |||
| username: '用户名', | |||
| host: '主机', | |||
| port: '端口', | |||
| password: '密码', | |||
| }, | |||
| footer: { | |||
| profile: 'All rights reserved @ React', | |||
| @@ -4,6 +4,7 @@ import { ReactComponent as BaiduIcon } from '@/assets/svg/baidu.svg'; | |||
| import { ReactComponent as BingIcon } from '@/assets/svg/bing.svg'; | |||
| import { ReactComponent as DeepLIcon } from '@/assets/svg/deepl.svg'; | |||
| import { ReactComponent as DuckIcon } from '@/assets/svg/duck.svg'; | |||
| import { ReactComponent as ExeSqlIcon } from '@/assets/svg/exesql.svg'; | |||
| import { ReactComponent as GithubIcon } from '@/assets/svg/github.svg'; | |||
| import { ReactComponent as GoogleScholarIcon } from '@/assets/svg/google-scholar.svg'; | |||
| import { ReactComponent as GoogleIcon } from '@/assets/svg/google.svg'; | |||
| @@ -31,6 +32,7 @@ import { | |||
| SendOutlined, | |||
| SlidersOutlined, | |||
| } from '@ant-design/icons'; | |||
| import upperFirst from 'lodash/upperFirst'; | |||
| export enum Operator { | |||
| Begin = 'Begin', | |||
| @@ -54,6 +56,7 @@ export enum Operator { | |||
| GitHub = 'GitHub', | |||
| BaiduFanyi = 'BaiduFanyi', | |||
| QWeather = 'QWeather', | |||
| ExeSQL = 'ExeSQL', | |||
| } | |||
| export const operatorIconMap = { | |||
| @@ -78,6 +81,7 @@ export const operatorIconMap = { | |||
| [Operator.GitHub]: GithubIcon, | |||
| [Operator.BaiduFanyi]: baiduFanyiIcon, | |||
| [Operator.QWeather]: QWeatherIcon, | |||
| [Operator.ExeSQL]: ExeSqlIcon, | |||
| }; | |||
| export const operatorMap = { | |||
| @@ -165,6 +169,7 @@ export const operatorMap = { | |||
| [Operator.GitHub]: {}, | |||
| [Operator.BaiduFanyi]: {}, | |||
| [Operator.QWeather]: {}, | |||
| [Operator.ExeSQL]: {}, | |||
| }; | |||
| export const componentMenuList = [ | |||
| @@ -228,6 +233,9 @@ export const componentMenuList = [ | |||
| { | |||
| name: Operator.QWeather, | |||
| }, | |||
| { | |||
| name: Operator.ExeSQL, | |||
| }, | |||
| ]; | |||
| export const initialRetrievalValues = { | |||
| @@ -354,6 +362,17 @@ export const initialQWeatherValues = { | |||
| time_period: 'now', | |||
| }; | |||
| export const initialExeSqlValues = { | |||
| db_type: 'mysql', | |||
| database: '', | |||
| username: '', | |||
| host: '', | |||
| port: 3306, | |||
| password: '', | |||
| loop: 3, | |||
| top_n: 30, | |||
| }; | |||
| export const CategorizeAnchorPointPositions = [ | |||
| { top: 1, right: 34 }, | |||
| { top: 8, right: 18 }, | |||
| @@ -422,6 +441,7 @@ export const RestrictedUpstreamMap = { | |||
| [Operator.GitHub]: [Operator.Begin, Operator.Retrieval], | |||
| [Operator.BaiduFanyi]: [Operator.Begin, Operator.Retrieval], | |||
| [Operator.QWeather]: [Operator.Begin, Operator.Retrieval], | |||
| [Operator.ExeSQL]: [Operator.Begin], | |||
| }; | |||
| export const NodeMap = { | |||
| @@ -446,6 +466,7 @@ export const NodeMap = { | |||
| [Operator.GitHub]: 'ragNode', | |||
| [Operator.BaiduFanyi]: 'ragNode', | |||
| [Operator.QWeather]: 'ragNode', | |||
| [Operator.ExeSQL]: 'ragNode', | |||
| }; | |||
| export const LanguageOptions = [ | |||
| @@ -2576,3 +2597,8 @@ export const QWeatherTimePeriodOptions = [ | |||
| '15d', | |||
| '30d', | |||
| ]; | |||
| export const ExeSQLOptions = ['mysql', 'postgresql', 'mariadb'].map((x) => ({ | |||
| label: upperFirst(x), | |||
| value: x, | |||
| })); | |||
| @@ -0,0 +1,61 @@ | |||
| import TopNItem from '@/components/top-n-item'; | |||
| import { useTranslate } from '@/hooks/common-hooks'; | |||
| import { Form, Input, InputNumber, Select } from 'antd'; | |||
| import { ExeSQLOptions } from '../constant'; | |||
| import { IOperatorForm } from '../interface'; | |||
| const ExeSQLForm = ({ onValuesChange, form }: IOperatorForm) => { | |||
| const { t } = useTranslate('flow'); | |||
| return ( | |||
| <Form | |||
| name="basic" | |||
| labelCol={{ span: 7 }} | |||
| wrapperCol={{ span: 17 }} | |||
| autoComplete="off" | |||
| form={form} | |||
| onValuesChange={onValuesChange} | |||
| > | |||
| <Form.Item | |||
| label={t('dbType')} | |||
| name={'db_type'} | |||
| rules={[{ required: true }]} | |||
| > | |||
| <Select options={ExeSQLOptions}></Select> | |||
| </Form.Item> | |||
| <Form.Item | |||
| label={t('database')} | |||
| name={'database'} | |||
| rules={[{ required: true }]} | |||
| > | |||
| <Input></Input> | |||
| </Form.Item> | |||
| <Form.Item | |||
| label={t('username')} | |||
| name={'username'} | |||
| rules={[{ required: true }]} | |||
| > | |||
| <Input></Input> | |||
| </Form.Item> | |||
| <Form.Item label={t('host')} name={'host'} rules={[{ required: true }]}> | |||
| <Input></Input> | |||
| </Form.Item> | |||
| <Form.Item label={t('port')} name={'port'} rules={[{ required: true }]}> | |||
| <InputNumber></InputNumber> | |||
| </Form.Item> | |||
| <Form.Item | |||
| label={t('password')} | |||
| name={'password'} | |||
| rules={[{ required: true }]} | |||
| > | |||
| <Input.Password></Input.Password> | |||
| </Form.Item> | |||
| <Form.Item label={t('loop')} name={'loop'} rules={[{ required: true }]}> | |||
| <InputNumber></InputNumber> | |||
| </Form.Item> | |||
| <TopNItem initialValue={30} max={100000}></TopNItem> | |||
| </Form> | |||
| ); | |||
| }; | |||
| export default ExeSQLForm; | |||
| @@ -11,7 +11,9 @@ import BeginForm from '../begin-form'; | |||
| import BingForm from '../bing-form'; | |||
| import CategorizeForm from '../categorize-form'; | |||
| import { Operator } from '../constant'; | |||
| import DeepLForm from '../deepl-form'; | |||
| import DuckDuckGoForm from '../duckduckgo-form'; | |||
| import ExeSQLForm from '../exesql-form'; | |||
| import GenerateForm from '../generate-form'; | |||
| import GithubForm from '../github-form'; | |||
| import GoogleForm from '../google-form'; | |||
| @@ -26,8 +28,6 @@ import RelevantForm from '../relevant-form'; | |||
| import RetrievalForm from '../retrieval-form'; | |||
| import RewriteQuestionForm from '../rewrite-question-form'; | |||
| import WikipediaForm from '../wikipedia-form'; | |||
| import DeepLForm from '../deepl-form'; | |||
| import styles from './index.less'; | |||
| interface IProps { | |||
| @@ -56,6 +56,7 @@ const FormMap = { | |||
| [Operator.GitHub]: GithubForm, | |||
| [Operator.BaiduFanyi]: BaiduFanyiForm, | |||
| [Operator.QWeather]: QWeatherForm, | |||
| [Operator.ExeSQL]: ExeSQLForm, | |||
| }; | |||
| const EmptyContent = () => <div>empty</div>; | |||
| @@ -6,7 +6,12 @@ import { IGenerateParameter } from '../interface'; | |||
| import useGraphStore from '../store'; | |||
| // exclude nodes with branches | |||
| const ExcludedNodes = [Operator.Categorize, Operator.Relevant]; | |||
| const ExcludedNodes = [ | |||
| Operator.Categorize, | |||
| Operator.Relevant, | |||
| Operator.Begin, | |||
| Operator.Answer, | |||
| ]; | |||
| export const useBuildComponentIdSelectOptions = (nodeId?: string) => { | |||
| const nodes = useGraphStore((state) => state.nodes); | |||
| @@ -38,6 +38,7 @@ import { | |||
| initialCategorizeValues, | |||
| initialDeepLValues, | |||
| initialDuckValues, | |||
| initialExeSqlValues, | |||
| initialGenerateValues, | |||
| initialGithubValues, | |||
| initialGoogleScholarValues, | |||
| @@ -107,6 +108,7 @@ export const useInitializeOperatorParams = () => { | |||
| [Operator.GitHub]: initialGithubValues, | |||
| [Operator.BaiduFanyi]: initialBaiduFanyiValues, | |||
| [Operator.QWeather]: initialQWeatherValues, | |||
| [Operator.ExeSQL]: initialExeSqlValues, | |||
| }; | |||
| }, [llmId]); | |||
| @@ -47,7 +47,7 @@ const OllamaModal = ({ | |||
| return ( | |||
| <Flex justify={'space-between'}> | |||
| <a | |||
| href={`https://github.com/infiniflow/ragflow/blob/main/docs/guides/deploy_local_llm.md`} | |||
| href={`https://github.com/infiniflow/ragflow/blob/main/docs/guides/deploy_local_llm.mdx`} | |||
| target="_blank" | |||
| rel="noreferrer" | |||
| > | |||