├── .gitattributes ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.yml │ ├── feature_request.yml │ ├── question.yml │ └── subtask.yml ├── pull_request_template.md └── workflows │ ├── release.yml │ └── tests.yml ├── .gitignore ├── .pre-commit-config.yaml ├── Dockerfile ├── Dockerfile.deps ├── Dockerfile.scratch.oc9 ├── LICENSE ├── README.md ├── README_id.md ├── README_ja.md ├── README_ko.md ├── README_pt_br.md ├── README_tzh.md ├── README_zh.md ├── SECURITY.md ├── agent ├── README.md ├── README_zh.md ├── __init__.py ├── canvas.py ├── component │ ├── __init__.py │ ├── akshare.py │ ├── answer.py │ ├── arxiv.py │ ├── baidu.py │ ├── baidufanyi.py │ ├── base.py │ ├── begin.py │ ├── bing.py │ ├── categorize.py │ ├── code.py │ ├── concentrator.py │ ├── crawler.py │ ├── deepl.py │ ├── duckduckgo.py │ ├── email.py │ ├── exesql.py │ ├── generate.py │ ├── github.py │ ├── google.py │ ├── googlescholar.py │ ├── invoke.py │ ├── iteration.py │ ├── iterationitem.py │ ├── jin10.py │ ├── keyword.py │ ├── message.py │ ├── pubmed.py │ ├── qweather.py │ ├── relevant.py │ ├── retrieval.py │ ├── rewrite.py │ ├── switch.py │ ├── template.py │ ├── tushare.py │ ├── wencai.py │ ├── wikipedia.py │ └── yahoofinance.py ├── settings.py ├── templates │ ├── DB Assistant.json │ ├── HR_callout_zh.json │ ├── customer_service.json │ ├── general_chat_bot.json │ ├── interpreter.json │ ├── investment_advisor.json │ ├── medical_consultation.json │ ├── research_report.json │ ├── seo_blog.json │ ├── text2sql.json │ └── websearch_assistant.json └── test │ ├── client.py │ └── dsl_examples │ ├── baidu_generate_and_switch.json │ ├── categorize.json │ ├── concentrator_message.json │ ├── customer_service.json │ ├── exesql.json │ ├── headhunter_zh.json │ ├── intergreper.json │ ├── interpreter.json │ ├── keyword_wikipedia_and_generate.json │ ├── retrieval_and_generate.json │ ├── retrieval_categorize_and_generate.json │ ├── retrieval_relevant_and_generate.json │ ├── retrieval_relevant_keyword_baidu_and_generate.json │ └── retrieval_relevant_rewrite_and_generate.json ├── agentic_reasoning ├── __init__.py ├── deep_research.py └── prompts.py ├── api ├── __init__.py ├── apps │ ├── __init__.py │ ├── api_app.py │ ├── auth │ │ ├── README.md │ │ ├── __init__.py │ │ ├── github.py │ │ ├── oauth.py │ │ └── oidc.py │ ├── canvas_app.py │ ├── chunk_app.py │ ├── conversation_app.py │ ├── dialog_app.py │ ├── document_app.py │ ├── file2document_app.py │ ├── file_app.py │ ├── kb_app.py │ ├── langfuse_app.py │ ├── llm_app.py │ ├── mcp_server_app.py │ ├── plugin_app.py │ ├── sdk │ │ ├── agent.py │ │ ├── chat.py │ │ ├── dataset.py │ │ ├── dify_retrieval.py │ │ ├── doc.py │ │ ├── files.py │ │ └── session.py │ ├── search_app.py │ ├── system_app.py │ ├── tenant_app.py │ └── user_app.py ├── constants.py ├── db │ ├── __init__.py │ ├── db_models.py │ ├── db_utils.py │ ├── init_data.py │ ├── reload_config_base.py │ ├── runtime_config.py │ └── services │ │ ├── __init__.py │ │ ├── api_service.py │ │ ├── canvas_service.py │ │ ├── common_service.py │ │ ├── conversation_service.py │ │ ├── dialog_service.py │ │ ├── document_service.py │ │ ├── file2document_service.py │ │ ├── file_service.py │ │ ├── knowledgebase_service.py │ │ ├── langfuse_service.py │ │ ├── llm_service.py │ │ ├── mcp_server_service.py │ │ ├── search_service.py │ │ ├── task_service.py │ │ ├── user_canvas_version.py │ │ └── user_service.py ├── ragflow_server.py ├── settings.py ├── utils │ ├── __init__.py │ ├── api_utils.py │ ├── commands.py │ ├── file_utils.py │ ├── log_utils.py │ ├── t_crypt.py │ ├── validation_utils.py │ └── web_utils.py ├── validation.py └── versions.py ├── conf ├── infinity_mapping.json ├── llm_factories.json ├── mapping.json ├── os_mapping.json ├── private.pem ├── public.pem └── service_conf.yaml ├── deepdoc ├── README.md ├── README_zh.md ├── __init__.py ├── parser │ ├── __init__.py │ ├── docx_parser.py │ ├── excel_parser.py │ ├── figure_parser.py │ ├── html_parser.py │ ├── json_parser.py │ ├── markdown_parser.py │ ├── pdf_parser.py │ ├── ppt_parser.py │ ├── resume │ │ ├── __init__.py │ │ ├── entities │ │ │ ├── __init__.py │ │ │ ├── corporations.py │ │ │ ├── degrees.py │ │ │ ├── industries.py │ │ │ ├── regions.py │ │ │ ├── res │ │ │ │ ├── corp.tks.freq.json │ │ │ │ ├── corp_baike_len.csv │ │ │ │ ├── corp_tag.json │ │ │ │ ├── good_corp.json │ │ │ │ ├── good_sch.json │ │ │ │ ├── school.rank.csv │ │ │ │ └── schools.csv │ │ │ └── schools.py │ │ ├── step_one.py │ │ └── step_two.py │ ├── txt_parser.py │ └── utils.py └── vision │ ├── __init__.py │ ├── layout_recognizer.py │ ├── ocr.py │ ├── operators.py │ ├── postprocess.py │ ├── recognizer.py │ ├── seeit.py │ ├── t_ocr.py │ ├── t_recognizer.py │ └── table_structure_recognizer.py ├── docker ├── .env ├── README.md ├── docker-compose-CN-oc9.yml ├── docker-compose-base.yml ├── docker-compose-gpu-CN-oc9.yml ├── docker-compose-gpu.yml ├── docker-compose-macos.yml ├── docker-compose.yml ├── entrypoint.sh ├── infinity_conf.toml ├── init.sql ├── launch_backend_service.sh ├── nginx │ ├── nginx.conf │ ├── proxy.conf │ ├── ragflow.conf │ └── ragflow.https.conf └── service_conf.yaml.template ├── docs ├── _category_.json ├── configurations.md ├── contribution │ ├── _category_.json │ └── contributing.md ├── develop │ ├── _category_.json │ ├── acquire_ragflow_api_key.md │ ├── build_docker_image.mdx │ ├── launch_ragflow_from_source.md │ ├── mcp │ │ ├── _category_.json │ │ ├── launch_mcp_server.md │ │ ├── mcp_client_example.md │ │ └── mcp_tools.md │ └── switch_doc_engine.md ├── faq.mdx ├── guides │ ├── _category_.json │ ├── agent │ │ ├── _category_.json │ │ ├── agent_component_reference │ │ │ ├── _category_.json │ │ │ ├── begin.mdx │ │ │ ├── categorize.mdx │ │ │ ├── code.mdx │ │ │ ├── concentrator.mdx │ │ │ ├── generate.mdx │ │ │ ├── interact.mdx │ │ │ ├── iteration.mdx │ │ │ ├── keyword.mdx │ │ │ ├── message.mdx │ │ │ ├── note.mdx │ │ │ ├── retrieval.mdx │ │ │ ├── rewrite.mdx │ │ │ ├── switch.mdx │ │ │ └── template.mdx │ │ ├── agent_introduction.md │ │ ├── embed_agent_into_webpage.md │ │ ├── general_purpose_chatbot.md │ │ ├── sandbox_quickstart.md │ │ └── text2sql_agent.md │ ├── ai_search.md │ ├── chat │ │ ├── _category_.json │ │ ├── best_practices │ │ │ ├── _category_.json │ │ │ └── accelerate_question_answering.mdx │ │ ├── implement_deep_research.md │ │ ├── set_chat_variables.md │ │ └── start_chat.md │ ├── dataset │ │ ├── _category_.json │ │ ├── autokeyword_autoquestion.mdx │ │ ├── best_practices │ │ │ ├── _category_.json │ │ │ └── accelerate_doc_indexing.mdx │ │ ├── configure_knowledge_base.md │ │ ├── construct_knowledge_graph.md │ │ ├── enable_excel2html.md │ │ ├── enable_raptor.md │ │ ├── run_retrieval_test.md │ │ ├── select_pdf_parser.md │ │ ├── set_metadata.md │ │ ├── set_page_rank.md │ │ └── use_tag_sets.md │ ├── manage_files.md │ ├── models │ │ ├── _category_.json │ │ ├── deploy_local_llm.mdx │ │ └── llm_api_key_setup.md │ ├── run_health_check.md │ ├── team │ │ ├── _category_.json │ │ ├── join_or_leave_team.md │ │ ├── manage_team_members.md │ │ ├── share_agents.md │ │ ├── share_chat_assistant.md │ │ ├── share_knowledge_bases.md │ │ └── share_model.md │ ├── tracing.mdx │ └── upgrade_ragflow.mdx ├── quickstart.mdx ├── references │ ├── _category_.json │ ├── glossary.mdx │ ├── http_api_reference.md │ ├── python_api_reference.md │ └── supported_models.mdx └── release_notes.md ├── download_deps.py ├── example ├── http │ └── dataset_example.sh └── sdk │ └── dataset_example.py ├── graphrag ├── __init__.py ├── entity_resolution.py ├── entity_resolution_prompt.py ├── general │ ├── __init__.py │ ├── community_report_prompt.py │ ├── community_reports_extractor.py │ ├── entity_embedding.py │ ├── extractor.py │ ├── graph_extractor.py │ ├── graph_prompt.py │ ├── index.py │ ├── leiden.py │ ├── mind_map_extractor.py │ ├── mind_map_prompt.py │ └── smoke.py ├── light │ ├── __init__.py │ ├── graph_extractor.py │ ├── graph_prompt.py │ └── smoke.py ├── query_analyze_prompt.py ├── search.py └── utils.py ├── helm ├── .helmignore ├── Chart.yaml ├── templates │ ├── _helpers.tpl │ ├── elasticsearch-config.yaml │ ├── elasticsearch.yaml │ ├── env.yaml │ ├── infinity.yaml │ ├── ingress.yaml │ ├── minio.yaml │ ├── mysql-config.yaml │ ├── mysql.yaml │ ├── ragflow.yaml │ ├── ragflow_config.yaml │ ├── redis.yaml │ └── tests │ │ └── test-connection.yaml └── values.yaml ├── intergrations ├── chatgpt-on-wechat │ └── plugins │ │ ├── README.md │ │ ├── __init__.py │ │ ├── config.json │ │ ├── ragflow_chat.py │ │ └── requirements.txt └── extension_chrome │ ├── README.md │ ├── assets │ ├── logo-with-text.png │ ├── logo.png │ └── logo.svg │ ├── background.js │ ├── content.js │ ├── icons │ ├── icon-128x128.png │ ├── icon-16x16.png │ └── icon-48x48.png │ ├── manifest.json │ ├── options.html │ ├── options.js │ ├── popup.html │ ├── popup.js │ └── styles │ ├── options.css │ └── popup.css ├── mcp ├── client │ ├── client.py │ └── streamable_http_client.py └── server │ └── server.py ├── plugin ├── README.md ├── README_zh.md ├── __init__.py ├── common.py ├── embedded_plugins │ └── llm_tools │ │ └── bad_calculator.py ├── llm_tool_plugin.py └── plugin_manager.py ├── pyproject.toml ├── rag ├── __init__.py ├── app │ ├── __init__.py │ ├── audio.py │ ├── book.py │ ├── email.py │ ├── laws.py │ ├── manual.py │ ├── naive.py │ ├── one.py │ ├── paper.py │ ├── picture.py │ ├── presentation.py │ ├── qa.py │ ├── resume.py │ ├── table.py │ └── tag.py ├── benchmark.py ├── llm │ ├── __init__.py │ ├── chat_model.py │ ├── cv_model.py │ ├── embedding_model.py │ ├── rerank_model.py │ ├── sequence2txt_model.py │ └── tts_model.py ├── nlp │ ├── __init__.py │ ├── query.py │ ├── rag_tokenizer.py │ ├── search.py │ ├── surname.py │ ├── synonym.py │ └── term_weight.py ├── prompt_template.py ├── prompts.py ├── prompts │ ├── citation_prompt.md │ ├── content_tagging_prompt.md │ ├── cross_languages_sys_prompt.md │ ├── cross_languages_user_prompt.md │ ├── full_question_prompt.md │ ├── keyword_prompt.md │ ├── question_prompt.md │ ├── vision_llm_describe_prompt.md │ └── vision_llm_figure_describe_prompt.md ├── raptor.py ├── res │ ├── huqie.txt │ ├── ner.json │ └── synonym.json ├── settings.py ├── svr │ ├── cache_file_svr.py │ ├── discord_svr.py │ ├── jina_server.py │ └── task_executor.py └── utils │ ├── __init__.py │ ├── azure_sas_conn.py │ ├── azure_spn_conn.py │ ├── doc_store_conn.py │ ├── es_conn.py │ ├── infinity_conn.py │ ├── mcp_tool_call_conn.py │ ├── minio_conn.py │ ├── opendal_conn.py │ ├── opensearch_conn.py │ ├── oss_conn.py │ ├── redis_conn.py │ ├── s3_conn.py │ ├── storage_factory.py │ └── tavily_conn.py ├── sandbox ├── .env.example ├── Makefile ├── README.md ├── asserts │ └── code_executor_manager.svg ├── docker-compose.yml ├── executor_manager │ ├── Dockerfile │ ├── api │ │ ├── __init__.py │ │ ├── handlers.py │ │ └── routes.py │ ├── core │ │ ├── __init__.py │ │ ├── config.py │ │ ├── container.py │ │ └── logger.py │ ├── main.py │ ├── models │ │ ├── __init__.py │ │ ├── enums.py │ │ └── schemas.py │ ├── requirements.txt │ ├── seccomp-profile-default.json │ ├── services │ │ ├── __init__.py │ │ ├── execution.py │ │ ├── limiter.py │ │ └── security.py │ ├── util.py │ └── utils │ │ ├── __init__.py │ │ └── common.py ├── pyproject.toml ├── sandbox_base_image │ ├── nodejs │ │ ├── Dockerfile │ │ ├── package-lock.json │ │ └── package.json │ └── python │ │ ├── Dockerfile │ │ └── requirements.txt ├── scripts │ ├── restart.sh │ ├── start.sh │ ├── stop.sh │ ├── wait-for-it-http.sh │ └── wait-for-it.sh ├── tests │ └── sandbox_security_tests_full.py └── uv.lock ├── sdk └── python │ ├── README.md │ ├── hello_ragflow.py │ ├── pyproject.toml │ ├── ragflow_sdk │ ├── __init__.py │ ├── modules │ │ ├── __init__.py │ │ ├── agent.py │ │ ├── base.py │ │ ├── chat.py │ │ ├── chunk.py │ │ ├── dataset.py │ │ ├── document.py │ │ └── session.py │ └── ragflow.py │ ├── test │ ├── conftest.py │ ├── libs │ │ ├── __init__.py │ │ ├── auth.py │ │ └── utils │ │ │ ├── __init__.py │ │ │ ├── file_utils.py │ │ │ └── hypothesis_utils.py │ ├── test_frontend_api │ │ ├── common.py │ │ ├── get_email.py │ │ ├── test_chunk.py │ │ └── test_dataset.py │ ├── test_http_api │ │ ├── common.py │ │ ├── conftest.py │ │ ├── test_chat_assistant_management │ │ │ ├── conftest.py │ │ │ ├── test_create_chat_assistant.py │ │ │ ├── test_delete_chat_assistants.py │ │ │ ├── test_list_chat_assistants.py │ │ │ └── test_update_chat_assistant.py │ │ ├── test_chunk_management_within_dataset │ │ │ ├── conftest.py │ │ │ ├── test_add_chunk.py │ │ │ ├── test_delete_chunks.py │ │ │ ├── test_list_chunks.py │ │ │ ├── test_retrieval_chunks.py │ │ │ └── test_update_chunk.py │ │ ├── test_dataset_mangement │ │ │ ├── conftest.py │ │ │ ├── test_create_dataset.py │ │ │ ├── test_delete_datasets.py │ │ │ ├── test_list_datasets.py │ │ │ └── test_update_dataset.py │ │ ├── test_file_management_within_dataset │ │ │ ├── conftest.py │ │ │ ├── test_delete_documents.py │ │ │ ├── test_download_document.py │ │ │ ├── test_list_documents.py │ │ │ ├── test_parse_documents.py │ │ │ ├── test_stop_parse_documents.py │ │ │ ├── test_update_document.py │ │ │ └── test_upload_documents.py │ │ └── test_session_management │ │ │ ├── conftest.py │ │ │ ├── test_create_session_with_chat_assistant.py │ │ │ ├── test_delete_sessions_with_chat_assistant.py │ │ │ ├── test_list_sessions_with_chat_assistant.py │ │ │ └── test_update_session_with_chat_assistant.py │ └── test_sdk_api │ │ ├── common.py │ │ ├── get_email.py │ │ ├── t_agent.py │ │ ├── t_chat.py │ │ ├── t_chunk.py │ │ ├── t_dataset.py │ │ ├── t_document.py │ │ ├── t_session.py │ │ └── test_data │ │ ├── ragflow.txt │ │ ├── ragflow_test.txt │ │ ├── test.docx │ │ ├── test.html │ │ ├── test.jpg │ │ ├── test.json │ │ ├── test.md │ │ ├── test.pdf │ │ ├── test.ppt │ │ ├── test.txt │ │ └── test.xlsx │ └── uv.lock ├── show_env.sh ├── test ├── configs.py ├── conftest.py ├── libs │ ├── __init__.py │ └── auth.py ├── testcases │ ├── test_http_api │ │ ├── common.py │ │ ├── conftest.py │ │ ├── test_chat_assistant_management │ │ │ ├── conftest.py │ │ │ ├── test_create_chat_assistant.py │ │ │ ├── test_delete_chat_assistants.py │ │ │ ├── test_list_chat_assistants.py │ │ │ └── test_update_chat_assistant.py │ │ ├── test_chunk_management_within_dataset │ │ │ ├── conftest.py │ │ │ ├── test_add_chunk.py │ │ │ ├── test_delete_chunks.py │ │ │ ├── test_list_chunks.py │ │ │ ├── test_retrieval_chunks.py │ │ │ └── test_update_chunk.py │ │ ├── test_dataset_mangement │ │ │ ├── conftest.py │ │ │ ├── test_create_dataset.py │ │ │ ├── test_delete_datasets.py │ │ │ ├── test_list_datasets.py │ │ │ └── test_update_dataset.py │ │ ├── test_file_management_within_dataset │ │ │ ├── conftest.py │ │ │ ├── test_delete_documents.py │ │ │ ├── test_download_document.py │ │ │ ├── test_list_documents.py │ │ │ ├── test_parse_documents.py │ │ │ ├── test_stop_parse_documents.py │ │ │ ├── test_update_document.py │ │ │ └── test_upload_documents.py │ │ └── test_session_management │ │ │ ├── conftest.py │ │ │ ├── test_create_session_with_chat_assistant.py │ │ │ ├── test_delete_sessions_with_chat_assistant.py │ │ │ ├── test_list_sessions_with_chat_assistant.py │ │ │ └── test_update_session_with_chat_assistant.py │ ├── test_sdk_api │ │ ├── common.py │ │ ├── conftest.py │ │ ├── test_chat_assistant_management │ │ │ ├── conftest.py │ │ │ ├── test_create_chat_assistant.py │ │ │ ├── test_delete_chat_assistants.py │ │ │ ├── test_list_chat_assistants.py │ │ │ └── test_update_chat_assistant.py │ │ ├── test_chunk_management_within_dataset │ │ │ ├── conftest.py │ │ │ ├── test_add_chunk.py │ │ │ ├── test_delete_chunks.py │ │ │ ├── test_list_chunks.py │ │ │ ├── test_retrieval_chunks.py │ │ │ └── test_update_chunk.py │ │ ├── test_dataset_mangement │ │ │ ├── conftest.py │ │ │ ├── test_create_dataset.py │ │ │ ├── test_delete_datasets.py │ │ │ ├── test_list_datasets.py │ │ │ └── test_update_dataset.py │ │ ├── test_file_management_within_dataset │ │ │ ├── conftest.py │ │ │ ├── test_delete_documents.py │ │ │ ├── test_download_document.py │ │ │ ├── test_list_documents.py │ │ │ ├── test_parse_documents.py │ │ │ ├── test_stop_parse_documents.py │ │ │ ├── test_update_document.py │ │ │ └── test_upload_documents.py │ │ └── test_session_management │ │ │ ├── conftest.py │ │ │ ├── test_create_session_with_chat_assistant.py │ │ │ ├── test_delete_sessions_with_chat_assistant.py │ │ │ ├── test_list_sessions_with_chat_assistant.py │ │ │ └── test_update_session_with_chat_assistant.py │ └── test_web_api │ │ ├── common.py │ │ ├── conftest.py │ │ ├── test_chunk_app │ │ ├── conftest.py │ │ ├── test_create_chunk.py │ │ ├── test_list_chunks.py │ │ ├── test_retrieval_chunks.py │ │ ├── test_rm_chunks.py │ │ └── test_update_chunk.py │ │ ├── test_dialog_app │ │ ├── conftest.py │ │ ├── test_create_dialog.py │ │ ├── test_delete_dialogs.py │ │ ├── test_dialog_edge_cases.py │ │ ├── test_get_dialog.py │ │ ├── test_list_dialogs.py │ │ └── test_update_dialog.py │ │ ├── test_document_app │ │ ├── conftest.py │ │ ├── test_create_document.py │ │ ├── test_list_documents.py │ │ ├── test_paser_documents.py │ │ ├── test_rm_documents.py │ │ └── test_upload_documents.py │ │ └── test_kb_app │ │ ├── conftest.py │ │ ├── test_create_kb.py │ │ ├── test_detail_kb.py │ │ ├── test_list_kbs.py │ │ ├── test_rm_kb.py │ │ └── test_update_kb.py └── utils │ ├── __init__.py │ ├── file_utils.py │ └── hypothesis_utils.py ├── uv.lock └── web ├── .env ├── .eslintrc.js ├── .gitignore ├── .husky └── pre-commit ├── .npmrc ├── .prettierignore ├── .prettierrc ├── .umirc.ts ├── externals.d.ts ├── jest-setup.ts ├── jest.config.ts ├── package-lock.json ├── package.json ├── public ├── iconfont.js ├── logo.svg └── pdfjs-dist │ └── pdf.worker.min.js ├── src ├── app.tsx ├── assets │ ├── banner.png │ ├── filter.svg │ ├── icon │ │ └── Icon.tsx │ ├── inter │ │ ├── Inter-Black.woff2 │ │ ├── Inter-BlackItalic.woff2 │ │ ├── Inter-Bold.woff2 │ │ ├── Inter-BoldItalic.woff2 │ │ ├── Inter-ExtraBold.woff2 │ │ ├── Inter-ExtraBoldItalic.woff2 │ │ ├── Inter-ExtraLight.woff2 │ │ ├── Inter-ExtraLightItalic.woff2 │ │ ├── Inter-Italic.woff2 │ │ ├── Inter-Light.woff2 │ │ ├── Inter-LightItalic.woff2 │ │ ├── Inter-Medium.woff2 │ │ ├── Inter-MediumItalic.woff2 │ │ ├── Inter-Regular.woff2 │ │ ├── Inter-SemiBold.woff2 │ │ ├── Inter-SemiBoldItalic.woff2 │ │ ├── Inter-Thin.woff2 │ │ ├── Inter-ThinItalic.woff2 │ │ ├── InterDisplay-Black.woff2 │ │ ├── InterDisplay-BlackItalic.woff2 │ │ ├── InterDisplay-Bold.woff2 │ │ ├── InterDisplay-BoldItalic.woff2 │ │ ├── InterDisplay-ExtraBold.woff2 │ │ ├── InterDisplay-ExtraBoldItalic.woff2 │ │ ├── InterDisplay-ExtraLight.woff2 │ │ ├── InterDisplay-ExtraLightItalic.woff2 │ │ ├── InterDisplay-Italic.woff2 │ │ ├── InterDisplay-Light.woff2 │ │ ├── InterDisplay-LightItalic.woff2 │ │ ├── InterDisplay-Medium.woff2 │ │ ├── InterDisplay-MediumItalic.woff2 │ │ ├── InterDisplay-Regular.woff2 │ │ ├── InterDisplay-SemiBold.woff2 │ │ ├── InterDisplay-SemiBoldItalic.woff2 │ │ ├── InterDisplay-Thin.woff2 │ │ ├── InterDisplay-ThinItalic.woff2 │ │ ├── InterVariable-Italic.woff2 │ │ └── InterVariable.woff2 │ ├── logo-with-text.png │ ├── svg │ │ ├── akshare.svg │ │ ├── api.svg │ │ ├── arxiv.svg │ │ ├── assistant.svg │ │ ├── baidu-fanyi.svg │ │ ├── baidu.svg │ │ ├── begin.svg │ │ ├── bing.svg │ │ ├── cancel.svg │ │ ├── chat-app-cube.svg │ │ ├── chat-configuration-atom.svg │ │ ├── chat-star.svg │ │ ├── chunk-method │ │ │ ├── book-01.svg │ │ │ ├── book-02.svg │ │ │ ├── book-03.svg │ │ │ ├── book-04.svg │ │ │ ├── chunk-empty.svg │ │ │ ├── knowledge-graph-01.svg │ │ │ ├── knowledge-graph-02.svg │ │ │ ├── law-01.svg │ │ │ ├── law-02.svg │ │ │ ├── manual-01.svg │ │ │ ├── manual-02.svg │ │ │ ├── manual-03.svg │ │ │ ├── manual-04.svg │ │ │ ├── media-01.svg │ │ │ ├── media-02.svg │ │ │ ├── naive-01.svg │ │ │ ├── naive-02.svg │ │ │ ├── one-01.svg │ │ │ ├── one-02.svg │ │ │ ├── one-03.svg │ │ │ ├── one-04.svg │ │ │ ├── paper-01.svg │ │ │ ├── paper-02.svg │ │ │ ├── presentation-01.svg │ │ │ ├── presentation-02.svg │ │ │ ├── qa-01.svg │ │ │ ├── qa-02.svg │ │ │ ├── resume-01.svg │ │ │ ├── resume-02.svg │ │ │ ├── table-01.svg │ │ │ ├── table-02.svg │ │ │ ├── tag-01.svg │ │ │ └── tag-02.svg │ │ ├── concentrator.svg │ │ ├── crawler.svg │ │ ├── database.svg │ │ ├── deepl.svg │ │ ├── delete.svg │ │ ├── disable.svg │ │ ├── duck.svg │ │ ├── email.svg │ │ ├── enable.svg │ │ ├── es.svg │ │ ├── exesql.svg │ │ ├── file-icon │ │ │ ├── aep.svg │ │ │ ├── ai.svg │ │ │ ├── avi.svg │ │ │ ├── css.svg │ │ │ ├── csv.svg │ │ │ ├── dmg.svg │ │ │ ├── doc.svg │ │ │ ├── docx.svg │ │ │ ├── eps.svg │ │ │ ├── exe.svg │ │ │ ├── fig.svg │ │ │ ├── folder.svg │ │ │ ├── gif.svg │ │ │ ├── html.svg │ │ │ ├── indd.svg │ │ │ ├── java.svg │ │ │ ├── jpeg.svg │ │ │ ├── jpg.svg │ │ │ ├── js.svg │ │ │ ├── json.svg │ │ │ ├── md.svg │ │ │ ├── mkv.svg │ │ │ ├── mp3.svg │ │ │ ├── mp4.svg │ │ │ ├── mpeg.svg │ │ │ ├── pdf.svg │ │ │ ├── png.svg │ │ │ ├── ppt.svg │ │ │ ├── pptx.svg │ │ │ ├── psd.svg │ │ │ ├── rss.svg │ │ │ ├── sql.svg │ │ │ ├── svg.svg │ │ │ ├── tiff.svg │ │ │ ├── txt.svg │ │ │ ├── wav.svg │ │ │ ├── webp.svg │ │ │ ├── xls.svg │ │ │ ├── xlsx.svg │ │ │ └── xml.svg │ │ ├── file-management.svg │ │ ├── github.svg │ │ ├── google-scholar.svg │ │ ├── google.svg │ │ ├── graph.svg │ │ ├── invoke-ai.svg │ │ ├── jin10.svg │ │ ├── keyword.svg │ │ ├── knowledge-base.svg │ │ ├── knowledge-configration.svg │ │ ├── knowledge-dataset.svg │ │ ├── knowledge-testing.svg │ │ ├── langfuse.svg │ │ ├── llm │ │ │ ├── anthropic.svg │ │ │ ├── azure.svg │ │ │ ├── baai.svg │ │ │ ├── baichuan.svg │ │ │ ├── bedrock.svg │ │ │ ├── chat-minimax.svg │ │ │ ├── cohere.svg │ │ │ ├── deepseek.svg │ │ │ ├── fish-audio.svg │ │ │ ├── gemini.svg │ │ │ ├── gitee-ai.svg │ │ │ ├── github.svg │ │ │ ├── google-cloud.svg │ │ │ ├── google.svg │ │ │ ├── gpustack.svg │ │ │ ├── groq-next.svg │ │ │ ├── huggingface.svg │ │ │ ├── hunyuan.svg │ │ │ ├── jina.svg │ │ │ ├── lepton-ai.svg │ │ │ ├── lm-studio.svg │ │ │ ├── local-ai.svg │ │ │ ├── mistral.svg │ │ │ ├── modelscope.svg │ │ │ ├── moonshot.svg │ │ │ ├── nomic-ai.svg │ │ │ ├── novita-ai.svg │ │ │ ├── nvidia.svg │ │ │ ├── ollama.svg │ │ │ ├── open-router.svg │ │ │ ├── openai-api.svg │ │ │ ├── openai.svg │ │ │ ├── perfx-cloud.svg │ │ │ ├── ppio.svg │ │ │ ├── replicate.svg │ │ │ ├── sentence-transformers.svg │ │ │ ├── siliconflow.svg │ │ │ ├── spark.svg │ │ │ ├── stepfun.svg │ │ │ ├── tencent-cloud.svg │ │ │ ├── together-ai.svg │ │ │ ├── tongyi.svg │ │ │ ├── upstage.svg │ │ │ ├── vllm.svg │ │ │ ├── volc_engine.svg │ │ │ ├── voyage.svg │ │ │ ├── wenxin.svg │ │ │ ├── xinference.svg │ │ │ ├── yi.svg │ │ │ ├── yiyan.svg │ │ │ ├── youdao.svg │ │ │ └── zhipu.svg │ │ ├── login-avatars.svg │ │ ├── login-background.svg │ │ ├── login-star.svg │ │ ├── logo-with-text-white.svg │ │ ├── logout.svg │ │ ├── minio.svg │ │ ├── model-providers.svg │ │ ├── moon.svg │ │ ├── more-model.svg │ │ ├── more.svg │ │ ├── move.svg │ │ ├── mysql.svg │ │ ├── navigation-pointer.svg │ │ ├── next-login-bg.svg │ │ ├── note.svg │ │ ├── nothing.svg │ │ ├── paper-clip.svg │ │ ├── password.svg │ │ ├── plus-circle-fill.svg │ │ ├── plus.svg │ │ ├── profile.svg │ │ ├── prompt.svg │ │ ├── pubmed.svg │ │ ├── qweather.svg │ │ ├── redis.svg │ │ ├── refresh.svg │ │ ├── resize.svg │ │ ├── run.svg │ │ ├── select-files-end.svg │ │ ├── select-files-start.svg │ │ ├── selected-files-collapse.svg │ │ ├── sso.svg │ │ ├── storage.svg │ │ ├── switch.svg │ │ ├── team.svg │ │ ├── template.svg │ │ ├── translation.svg │ │ ├── tushare.svg │ │ ├── wencai.svg │ │ ├── wikipedia.svg │ │ └── yahoo-finance.svg │ └── yay.jpg ├── base.ts ├── components │ ├── api-service │ │ ├── chat-api-key-modal │ │ │ └── index.tsx │ │ ├── chat-overview-modal │ │ │ ├── api-content.tsx │ │ │ ├── backend-service-api.tsx │ │ │ ├── index.less │ │ │ ├── index.tsx │ │ │ ├── markdown-toc.tsx │ │ │ └── stats-chart.tsx │ │ ├── embed-modal │ │ │ ├── index.less │ │ │ └── index.tsx │ │ └── hooks.ts │ ├── auto-keywords-form-field.tsx │ ├── auto-keywords-item.tsx │ ├── bulk-operate-bar.tsx │ ├── chat-input.tsx │ ├── chunk-method-dialog │ │ ├── dynamic-page-range.tsx │ │ ├── hooks.ts │ │ ├── index.tsx │ │ └── use-default-parser-values.ts │ ├── chunk-method-modal │ │ ├── hooks.ts │ │ ├── index.less │ │ └── index.tsx │ ├── collapse.tsx │ ├── confirm-delete-dialog.tsx │ ├── copy-to-clipboard.tsx │ ├── cross-language-item-ui.tsx │ ├── cross-language-item.tsx │ ├── dataset-configuration-container.tsx │ ├── delimiter-form-field.tsx │ ├── delimiter.tsx │ ├── edit-tag │ │ └── index.tsx │ ├── editable-cell.tsx │ ├── entity-types-form-field.tsx │ ├── entity-types-item.tsx │ ├── excel-to-html-form-field.tsx │ ├── excel-to-html.tsx │ ├── file-icon │ │ ├── index.less │ │ └── index.tsx │ ├── file-upload-dialog │ │ └── index.tsx │ ├── file-upload-modal │ │ ├── index.less │ │ └── index.tsx │ ├── file-upload.tsx │ ├── file-uploader.tsx │ ├── form-container.tsx │ ├── highlight-markdown │ │ ├── index.less │ │ └── index.tsx │ ├── hooks │ │ ├── use-mobile.tsx │ │ └── use-toast.tsx │ ├── icon-font.tsx │ ├── image │ │ └── index.tsx │ ├── indented-tree │ │ ├── indented-tree.tsx │ │ └── modal.tsx │ ├── knowledge-base-item.tsx │ ├── large-model-form-field.tsx │ ├── layout-recognize-form-field.tsx │ ├── layout-recognize.tsx │ ├── line-chart │ │ └── index.tsx │ ├── list-filter-bar │ │ ├── filter-popover.tsx │ │ ├── index.tsx │ │ ├── interface.ts │ │ └── use-handle-filter-submit.ts │ ├── llm-select │ │ ├── index.less │ │ ├── index.tsx │ │ ├── llm-label.tsx │ │ └── next.tsx │ ├── llm-setting-items │ │ ├── index.less │ │ ├── index.tsx │ │ ├── next.tsx │ │ ├── slider.tsx │ │ └── use-watch-change.ts │ ├── llm-tools-select.tsx │ ├── max-token-number-from-field.tsx │ ├── max-token-number.tsx │ ├── message-history-window-size-item.tsx │ ├── message-input │ │ ├── index.less │ │ └── index.tsx │ ├── message-item │ │ ├── feedback-modal.tsx │ │ ├── group-button.tsx │ │ ├── hooks.ts │ │ ├── index.less │ │ ├── index.tsx │ │ └── prompt-modal.tsx │ ├── modal-manager.tsx │ ├── more-button.tsx │ ├── new-document-link.tsx │ ├── next-markdown-content │ │ ├── index.less │ │ └── index.tsx │ ├── next-message-item │ │ ├── feedback-modal.tsx │ │ ├── group-button.tsx │ │ ├── hooks.ts │ │ ├── index.less │ │ ├── index.tsx │ │ ├── prompt-modal.tsx │ │ └── reference-document-list.tsx │ ├── operate-dropdown │ │ ├── index.less │ │ └── index.tsx │ ├── originui │ │ ├── input.tsx │ │ ├── select-with-search.tsx │ │ └── timeline.tsx │ ├── page-header.tsx │ ├── page-rank-form-field.tsx │ ├── page-rank.tsx │ ├── parse-configuration │ │ ├── graph-rag-form-fields.tsx │ │ ├── graph-rag-items.tsx │ │ ├── index.tsx │ │ ├── raptor-form-fields-old.tsx │ │ └── raptor-form-fields.tsx │ ├── password-input │ │ └── index.tsx │ ├── pdf-drawer │ │ ├── hooks.ts │ │ └── index.tsx │ ├── pdf-previewer │ │ ├── hooks.ts │ │ ├── index.less │ │ └── index.tsx │ ├── prompt-editor │ │ ├── constant.ts │ │ ├── index.css │ │ ├── index.tsx │ │ ├── theme.ts │ │ ├── variable-node.tsx │ │ ├── variable-on-change-plugin.tsx │ │ └── variable-picker-plugin.tsx │ ├── ragflow-avatar.tsx │ ├── rename-dialog │ │ ├── index.tsx │ │ └── rename-form.tsx │ ├── rename-modal │ │ └── index.tsx │ ├── rerank.tsx │ ├── retrieval-documents │ │ ├── index.less │ │ ├── index.tsx │ │ └── select-files.tsx │ ├── similarity-slider │ │ └── index.tsx │ ├── skeleton-card.tsx │ ├── slider-input-form-field.tsx │ ├── svg-icon.tsx │ ├── switch-fom-field.tsx │ ├── table-skeleton.tsx │ ├── tavily-item.tsx │ ├── theme-provider.tsx │ ├── top-n-item.tsx │ ├── ui │ │ ├── accordion.tsx │ │ ├── alert-dialog.tsx │ │ ├── aspect-ratio.tsx │ │ ├── async-tree-select.tsx │ │ ├── avatar.tsx │ │ ├── badge.tsx │ │ ├── breadcrumb.tsx │ │ ├── button.tsx │ │ ├── card.tsx │ │ ├── checkbox.tsx │ │ ├── collapsible.tsx │ │ ├── command.tsx │ │ ├── container.tsx │ │ ├── dialog.tsx │ │ ├── divider.tsx │ │ ├── dropdown-menu.tsx │ │ ├── dual-range-slider.tsx │ │ ├── form.tsx │ │ ├── hover-card.tsx │ │ ├── input-otp.tsx │ │ ├── input.tsx │ │ ├── label.tsx │ │ ├── loading-button.tsx │ │ ├── message.ts │ │ ├── modal.tsx │ │ ├── multi-select.tsx │ │ ├── navigation-menu.tsx │ │ ├── pagination.tsx │ │ ├── popover.tsx │ │ ├── progress.tsx │ │ ├── radio-group.tsx │ │ ├── radio.tsx │ │ ├── ragflow-pagination.tsx │ │ ├── scroll-area.tsx │ │ ├── segmented.tsx │ │ ├── select.tsx │ │ ├── separator.tsx │ │ ├── sheet.tsx │ │ ├── sidebar.tsx │ │ ├── skeleton.tsx │ │ ├── slider.tsx │ │ ├── sonner.tsx │ │ ├── space.tsx │ │ ├── spin.tsx │ │ ├── switch.tsx │ │ ├── table.tsx │ │ ├── tabs-underlined.tsx │ │ ├── tabs.tsx │ │ ├── textarea.tsx │ │ ├── toast.tsx │ │ ├── toaster.tsx │ │ ├── toggle-group.tsx │ │ ├── toggle.tsx │ │ ├── tooltip.tsx │ │ ├── transfer-list.tsx │ │ └── tree-view.tsx │ ├── use-knowledge-graph-item.tsx │ └── xyflow │ │ ├── base-node.tsx │ │ └── tooltip-node.tsx ├── conf.json ├── constants │ ├── agent.ts │ ├── authorization.ts │ ├── chat.ts │ ├── common.ts │ ├── file.ts │ ├── form.ts │ ├── knowledge.ts │ ├── llm.ts │ └── setting.ts ├── custom.d.ts ├── global.less ├── hooks │ ├── auth-hooks.ts │ ├── chat-hooks.ts │ ├── chunk-hooks.ts │ ├── common-hooks.tsx │ ├── document-hooks.ts │ ├── file-manager-hooks.ts │ ├── flow-hooks.ts │ ├── knowledge-hooks.ts │ ├── llm-hooks.tsx │ ├── logic-hooks.ts │ ├── logic-hooks │ │ ├── navigate-hooks.ts │ │ └── use-row-selection.ts │ ├── login-hooks.ts │ ├── plugin-hooks.tsx │ ├── route-hook.ts │ ├── system-hooks.ts │ ├── use-agent-request.ts │ ├── use-callback-ref.ts │ ├── use-chat-request.ts │ ├── use-chunk-request.ts │ ├── use-controllable-state.ts │ ├── use-document-request.ts │ ├── use-file-request.ts │ ├── use-knowledge-request.ts │ ├── use-mcp-request.ts │ ├── use-send-message.ts │ └── user-setting-hooks.tsx ├── icons │ ├── github.svg │ └── google.svg ├── inter.less ├── interfaces │ ├── common.ts │ ├── database │ │ ├── agent.ts │ │ ├── base.ts │ │ ├── chat.ts │ │ ├── document.ts │ │ ├── file-manager.ts │ │ ├── flow.ts │ │ ├── knowledge.ts │ │ ├── llm.ts │ │ ├── mcp-server.ts │ │ ├── mcp.ts │ │ ├── plugin.ts │ │ ├── system.ts │ │ └── user-setting.ts │ └── request │ │ ├── base.ts │ │ ├── chat.ts │ │ ├── document.ts │ │ ├── file-manager.ts │ │ ├── flow.ts │ │ ├── knowledge.ts │ │ ├── llm.ts │ │ ├── mcp.ts │ │ └── system.ts ├── layouts │ ├── components │ │ ├── header │ │ │ ├── index.less │ │ │ └── index.tsx │ │ ├── right-toolbar │ │ │ ├── index.less │ │ │ └── index.tsx │ │ └── user │ │ │ └── index.tsx │ ├── index.less │ ├── index.tsx │ ├── next-header.tsx │ └── next.tsx ├── less │ ├── index.less │ ├── mixins.less │ └── variable.less ├── lib │ └── utils.ts ├── locales │ ├── config.ts │ ├── de.ts │ ├── en.ts │ ├── es.ts │ ├── id.ts │ ├── ja.ts │ ├── pt-br.ts │ ├── until.ts │ ├── vi.ts │ ├── zh-traditional.ts │ └── zh.ts ├── pages │ ├── 404.jsx │ ├── add-knowledge │ │ ├── components │ │ │ ├── knowledge-chunk │ │ │ │ ├── components │ │ │ │ │ ├── chunk-card │ │ │ │ │ │ ├── index.less │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── chunk-creating-modal │ │ │ │ │ │ ├── index.tsx │ │ │ │ │ │ └── tag-feature-item.tsx │ │ │ │ │ ├── chunk-toolbar │ │ │ │ │ │ └── index.tsx │ │ │ │ │ └── document-preview │ │ │ │ │ │ ├── hooks.ts │ │ │ │ │ │ ├── index.less │ │ │ │ │ │ └── preview.tsx │ │ │ │ ├── constant.ts │ │ │ │ ├── hooks.ts │ │ │ │ ├── index.less │ │ │ │ ├── index.tsx │ │ │ │ └── utils.ts │ │ │ ├── knowledge-dataset │ │ │ │ ├── index.less │ │ │ │ └── index.tsx │ │ │ ├── knowledge-file │ │ │ │ ├── constant.ts │ │ │ │ ├── create-file-modal.tsx │ │ │ │ ├── document-toolbar.tsx │ │ │ │ ├── hooks.ts │ │ │ │ ├── index.less │ │ │ │ ├── index.tsx │ │ │ │ ├── parsing-action-cell │ │ │ │ │ ├── index.less │ │ │ │ │ └── index.tsx │ │ │ │ ├── parsing-status-cell │ │ │ │ │ ├── index.less │ │ │ │ │ └── index.tsx │ │ │ │ ├── rename-modal │ │ │ │ │ └── index.tsx │ │ │ │ ├── set-meta-modal │ │ │ │ │ └── index.tsx │ │ │ │ ├── utils.ts │ │ │ │ └── web-crawl-modal.tsx │ │ │ ├── knowledge-graph │ │ │ │ ├── constant.ts │ │ │ │ ├── force-graph.tsx │ │ │ │ ├── index.less │ │ │ │ ├── index.tsx │ │ │ │ ├── use-delete-graph.ts │ │ │ │ └── util.ts │ │ │ ├── knowledge-setting │ │ │ │ ├── category-panel.tsx │ │ │ │ ├── configuration │ │ │ │ │ ├── audio.tsx │ │ │ │ │ ├── book.tsx │ │ │ │ │ ├── common-item.tsx │ │ │ │ │ ├── email.tsx │ │ │ │ │ ├── index.tsx │ │ │ │ │ ├── knowledge-graph.tsx │ │ │ │ │ ├── laws.tsx │ │ │ │ │ ├── manual.tsx │ │ │ │ │ ├── naive.tsx │ │ │ │ │ ├── one.tsx │ │ │ │ │ ├── paper.tsx │ │ │ │ │ ├── picture.tsx │ │ │ │ │ ├── presentation.tsx │ │ │ │ │ ├── qa.tsx │ │ │ │ │ ├── resume.tsx │ │ │ │ │ ├── table.tsx │ │ │ │ │ └── tag.tsx │ │ │ │ ├── hooks.ts │ │ │ │ ├── index.less │ │ │ │ ├── index.tsx │ │ │ │ ├── tag-item.tsx │ │ │ │ ├── tag-table │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── rename-dialog │ │ │ │ │ │ ├── index.tsx │ │ │ │ │ │ └── rename-form.tsx │ │ │ │ ├── tag-tabs.tsx │ │ │ │ ├── tag-word-cloud.tsx │ │ │ │ └── utils.ts │ │ │ ├── knowledge-sidebar │ │ │ │ ├── index.less │ │ │ │ └── index.tsx │ │ │ └── knowledge-testing │ │ │ │ ├── index.less │ │ │ │ ├── index.tsx │ │ │ │ ├── testing-control │ │ │ │ ├── index.less │ │ │ │ ├── index.tsx │ │ │ │ └── label-word-cloud.tsx │ │ │ │ └── testing-result │ │ │ │ ├── index.less │ │ │ │ ├── index.tsx │ │ │ │ └── select-files.tsx │ │ ├── constant.ts │ │ ├── index.less │ │ └── index.tsx │ ├── agent │ │ ├── agent-sidebar.tsx │ │ ├── canvas │ │ │ ├── context-menu │ │ │ │ ├── index.less │ │ │ │ └── index.tsx │ │ │ ├── edge │ │ │ │ ├── index.less │ │ │ │ └── index.tsx │ │ │ ├── index.less │ │ │ ├── index.tsx │ │ │ └── node │ │ │ │ ├── agent-node.tsx │ │ │ │ ├── begin-node.tsx │ │ │ │ ├── card.tsx │ │ │ │ ├── categorize-handle.tsx │ │ │ │ ├── categorize-node.tsx │ │ │ │ ├── dropdown.tsx │ │ │ │ ├── dropdown │ │ │ │ └── next-step-dropdown.tsx │ │ │ │ ├── email-node.tsx │ │ │ │ ├── generate-node.tsx │ │ │ │ ├── handle-icon.tsx │ │ │ │ ├── handle.tsx │ │ │ │ ├── index.less │ │ │ │ ├── index.tsx │ │ │ │ ├── invoke-node.tsx │ │ │ │ ├── iteration-node.tsx │ │ │ │ ├── keyword-node.tsx │ │ │ │ ├── logic-node.tsx │ │ │ │ ├── message-node.tsx │ │ │ │ ├── node-header.tsx │ │ │ │ ├── node-wrapper.tsx │ │ │ │ ├── note-node │ │ │ │ ├── index.tsx │ │ │ │ └── use-watch-change.ts │ │ │ │ ├── popover.tsx │ │ │ │ ├── relevant-node.tsx │ │ │ │ ├── resize-icon.tsx │ │ │ │ ├── retrieval-node.tsx │ │ │ │ ├── rewrite-node.tsx │ │ │ │ ├── switch-node.tsx │ │ │ │ ├── template-node.tsx │ │ │ │ ├── tool-node.tsx │ │ │ │ ├── toolbar.tsx │ │ │ │ ├── use-build-categorize-handle-positions.ts │ │ │ │ └── use-build-switch-handle-positions.ts │ │ ├── chat │ │ │ ├── box.tsx │ │ │ ├── chat-sheet.tsx │ │ │ └── hooks.ts │ │ ├── constant.tsx │ │ ├── context.ts │ │ ├── debug-content │ │ │ ├── index.tsx │ │ │ ├── popover-form.tsx │ │ │ └── uploader.tsx │ │ ├── flow-tooltip.tsx │ │ ├── form-hooks.ts │ │ ├── form-sheet │ │ │ ├── index.less │ │ │ ├── next.tsx │ │ │ ├── single-debug-drawer │ │ │ │ └── index.tsx │ │ │ ├── use-form-config-map.tsx │ │ │ └── use-values.ts │ │ ├── form │ │ │ ├── agent-form │ │ │ │ ├── agent-tools.tsx │ │ │ │ ├── dynamic-prompt.tsx │ │ │ │ ├── dynamic-tool.tsx │ │ │ │ ├── index.tsx │ │ │ │ ├── tool-popover │ │ │ │ │ ├── index.tsx │ │ │ │ │ ├── tool-command.tsx │ │ │ │ │ ├── use-update-mcp.ts │ │ │ │ │ └── use-update-tools.ts │ │ │ │ ├── use-get-tools.ts │ │ │ │ ├── use-values.ts │ │ │ │ └── use-watch-change.ts │ │ │ ├── akshare-form │ │ │ │ └── index.tsx │ │ │ ├── answer-form │ │ │ │ └── index.tsx │ │ │ ├── arxiv-form │ │ │ │ └── index.tsx │ │ │ ├── baidu-fanyi-form │ │ │ │ └── index.tsx │ │ │ ├── baidu-form │ │ │ │ └── index.tsx │ │ │ ├── begin-form │ │ │ │ ├── begin-dynamic-options.tsx │ │ │ │ ├── index.tsx │ │ │ │ ├── parameter-dialog.tsx │ │ │ │ ├── query-table.tsx │ │ │ │ ├── use-edit-query.ts │ │ │ │ ├── use-values.ts │ │ │ │ ├── use-watch-change.ts │ │ │ │ └── utils.ts │ │ │ ├── bing-form │ │ │ │ └── index.tsx │ │ │ ├── categorize-form │ │ │ │ ├── dynamic-categorize.tsx │ │ │ │ ├── dynamic-example.tsx │ │ │ │ ├── index.tsx │ │ │ │ ├── use-values.ts │ │ │ │ └── use-watch-change.ts │ │ │ ├── code-form │ │ │ │ ├── index.tsx │ │ │ │ ├── next-variable.tsx │ │ │ │ ├── schema.ts │ │ │ │ ├── use-values.ts │ │ │ │ └── use-watch-change.ts │ │ │ ├── components │ │ │ │ ├── description-field.tsx │ │ │ │ ├── dynamic-input-variable.tsx │ │ │ │ ├── index.less │ │ │ │ ├── next-dynamic-input-variable.tsx │ │ │ │ ├── output.tsx │ │ │ │ ├── prompt-editor │ │ │ │ │ ├── constant.ts │ │ │ │ │ ├── index.css │ │ │ │ │ ├── index.tsx │ │ │ │ │ ├── theme.ts │ │ │ │ │ ├── variable-node.tsx │ │ │ │ │ ├── variable-on-change-plugin.tsx │ │ │ │ │ └── variable-picker-plugin.tsx │ │ │ │ └── query-variable.tsx │ │ │ ├── concentrator-form │ │ │ │ └── index.tsx │ │ │ ├── crawler-form │ │ │ │ └── index.tsx │ │ │ ├── deepl-form │ │ │ │ └── index.tsx │ │ │ ├── duckduckgo-form │ │ │ │ └── index.tsx │ │ │ ├── email-form │ │ │ │ └── index.tsx │ │ │ ├── exesql-form │ │ │ │ └── index.tsx │ │ │ ├── generate-form │ │ │ │ └── index.tsx │ │ │ ├── github-form │ │ │ │ └── index.tsx │ │ │ ├── google-form │ │ │ │ └── index.tsx │ │ │ ├── google-scholar-form │ │ │ │ └── index.tsx │ │ │ ├── invoke-form │ │ │ │ ├── dynamic-variables.tsx │ │ │ │ ├── hooks.ts │ │ │ │ ├── index.less │ │ │ │ └── index.tsx │ │ │ ├── iteration-form │ │ │ │ ├── dynamic-output.tsx │ │ │ │ ├── index.tsx │ │ │ │ ├── interface.ts │ │ │ │ ├── use-build-options.ts │ │ │ │ ├── use-values.ts │ │ │ │ └── use-watch-form-change.ts │ │ │ ├── iteration-start-from │ │ │ │ └── index.tsx │ │ │ ├── jin10-form │ │ │ │ └── index.tsx │ │ │ ├── keyword-extract-form │ │ │ │ └── index.tsx │ │ │ ├── message-form │ │ │ │ ├── index.tsx │ │ │ │ ├── use-values.ts │ │ │ │ └── use-watch-change.ts │ │ │ ├── pubmed-form │ │ │ │ └── index.tsx │ │ │ ├── qweather-form │ │ │ │ └── index.tsx │ │ │ ├── relevant-form │ │ │ │ ├── hooks.ts │ │ │ │ └── index.tsx │ │ │ ├── retrieval-form │ │ │ │ ├── next.tsx │ │ │ │ └── use-values.ts │ │ │ ├── rewrite-question-form │ │ │ │ └── index.tsx │ │ │ ├── string-transform-form │ │ │ │ ├── index.tsx │ │ │ │ ├── use-values.ts │ │ │ │ └── use-watch-form-change.ts │ │ │ ├── switch-form │ │ │ │ ├── index.tsx │ │ │ │ ├── use-values.ts │ │ │ │ └── use-watch-change.ts │ │ │ ├── tavily-form │ │ │ │ ├── dynamic-domain.tsx │ │ │ │ ├── index.tsx │ │ │ │ ├── use-values.ts │ │ │ │ └── use-watch-change.ts │ │ │ ├── template-form │ │ │ │ └── index.tsx │ │ │ ├── tool-form │ │ │ │ ├── constant.tsx │ │ │ │ ├── index.tsx │ │ │ │ ├── mcp-form │ │ │ │ │ ├── index.tsx │ │ │ │ │ ├── mcp-card.tsx │ │ │ │ │ ├── use-values.ts │ │ │ │ │ └── use-watch-change.ts │ │ │ │ ├── retrieval-form │ │ │ │ │ └── index.tsx │ │ │ │ ├── tavily-form │ │ │ │ │ └── index.tsx │ │ │ │ ├── use-values.ts │ │ │ │ └── use-watch-change.ts │ │ │ ├── tushare-form │ │ │ │ └── index.tsx │ │ │ ├── user-fill-up-form │ │ │ │ ├── index.tsx │ │ │ │ ├── use-values.ts │ │ │ │ └── use-watch-change.ts │ │ │ ├── wencai-form │ │ │ │ └── index.tsx │ │ │ ├── wikipedia-form │ │ │ │ └── index.tsx │ │ │ └── yahoo-finance-form │ │ │ │ └── index.tsx │ │ ├── hooks.tsx │ │ ├── hooks │ │ │ ├── use-add-node.ts │ │ │ ├── use-before-delete.tsx │ │ │ ├── use-build-dsl.ts │ │ │ ├── use-cache-chat-log.ts │ │ │ ├── use-change-node-name.ts │ │ │ ├── use-export-json.ts │ │ │ ├── use-fetch-data.ts │ │ │ ├── use-find-mcp-by-id.ts │ │ │ ├── use-form-values.ts │ │ │ ├── use-get-begin-query.tsx │ │ │ ├── use-iteration.ts │ │ │ ├── use-move-note.ts │ │ │ ├── use-open-document.ts │ │ │ ├── use-save-graph.ts │ │ │ ├── use-set-graph.ts │ │ │ ├── use-show-drawer.tsx │ │ │ └── use-watch-form-change.ts │ │ ├── index.tsx │ │ ├── interface.ts │ │ ├── log-sheet │ │ │ ├── data.ts │ │ │ └── index.tsx │ │ ├── operator-icon.tsx │ │ ├── options.ts │ │ ├── run-sheet │ │ │ └── index.tsx │ │ ├── store.ts │ │ ├── upload-agent-dialog │ │ │ ├── index.tsx │ │ │ └── upload-agent-form.tsx │ │ ├── utils.test.ts │ │ ├── utils.ts │ │ └── utils │ │ │ ├── build-output-list.ts │ │ │ ├── chat.ts │ │ │ ├── delete-node.ts │ │ │ └── filter-downstream-nodes.ts │ ├── agents │ │ ├── agent-card.tsx │ │ ├── agent-dropdown.tsx │ │ ├── agent-templates.tsx │ │ ├── create-agent-dialog.tsx │ │ ├── create-agent-form.tsx │ │ ├── index.tsx │ │ ├── template-card.tsx │ │ └── use-rename-agent.ts │ ├── chat │ │ ├── chat-configuration-modal │ │ │ ├── assistant-setting.tsx │ │ │ ├── editable-cell.tsx │ │ │ ├── index.less │ │ │ ├── index.tsx │ │ │ ├── model-setting.tsx │ │ │ └── prompt-engine.tsx │ │ ├── chat-container │ │ │ ├── index.less │ │ │ └── index.tsx │ │ ├── chat-id-modal │ │ │ ├── index.less │ │ │ └── index.tsx │ │ ├── constants.ts │ │ ├── context.ts │ │ ├── hooks.ts │ │ ├── index.less │ │ ├── index.tsx │ │ ├── interface.ts │ │ ├── markdown-content │ │ │ ├── index.less │ │ │ └── index.tsx │ │ ├── share │ │ │ ├── index.less │ │ │ ├── index.tsx │ │ │ └── large.tsx │ │ ├── shared-hooks.ts │ │ └── utils.ts │ ├── chunk │ │ ├── chunk-card.tsx │ │ ├── chunk-result │ │ │ └── index.tsx │ │ ├── chunk-toolbar.tsx │ │ ├── chunked-result-panel.tsx │ │ ├── index-old.tsx │ │ ├── index.tsx │ │ ├── parsed-result-panel.tsx │ │ ├── parsed-result │ │ │ ├── add-knowledge │ │ │ │ ├── components │ │ │ │ │ └── knowledge-chunk │ │ │ │ │ │ ├── components │ │ │ │ │ │ ├── chunk-card │ │ │ │ │ │ │ ├── index.less │ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ │ ├── chunk-creating-modal │ │ │ │ │ │ │ ├── index.tsx │ │ │ │ │ │ │ └── tag-feature-item.tsx │ │ │ │ │ │ ├── chunk-result-bar │ │ │ │ │ │ │ ├── checkbox-sets.tsx │ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ │ ├── chunk-toolbar │ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ │ └── document-preview │ │ │ │ │ │ │ ├── csv-preview.tsx │ │ │ │ │ │ │ ├── doc-preview.tsx │ │ │ │ │ │ │ ├── document-header.tsx │ │ │ │ │ │ │ ├── excel-preview.tsx │ │ │ │ │ │ │ ├── hooks.ts │ │ │ │ │ │ │ ├── image-preview.tsx │ │ │ │ │ │ │ ├── index.less │ │ │ │ │ │ │ ├── index.tsx │ │ │ │ │ │ │ ├── pdf-preview.tsx │ │ │ │ │ │ │ ├── ppt-preview.tsx │ │ │ │ │ │ │ └── txt-preview.tsx │ │ │ │ │ │ ├── constant.ts │ │ │ │ │ │ ├── hooks.ts │ │ │ │ │ │ ├── index.less │ │ │ │ │ │ ├── index.tsx │ │ │ │ │ │ └── utils.ts │ │ │ │ ├── constant.ts │ │ │ │ ├── index.less │ │ │ │ └── index.tsx │ │ │ ├── index-old.tsx │ │ │ ├── index.tsx │ │ │ └── knowledge-chunk │ │ │ │ ├── components │ │ │ │ ├── chunk-card │ │ │ │ │ ├── index.less │ │ │ │ │ └── index.tsx │ │ │ │ ├── chunk-creating-modal │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── tag-feature-item.tsx │ │ │ │ ├── chunk-toolbar │ │ │ │ │ └── index.tsx │ │ │ │ └── document-preview │ │ │ │ │ ├── hooks.ts │ │ │ │ │ ├── index.less │ │ │ │ │ └── preview.tsx │ │ │ │ ├── constant.ts │ │ │ │ ├── hooks.ts │ │ │ │ ├── index.less │ │ │ │ ├── index.tsx │ │ │ │ └── utils.ts │ │ └── result-view │ │ │ └── index.tsx │ ├── dataset │ │ ├── dataset-title.tsx │ │ ├── dataset │ │ │ ├── constant.ts │ │ │ ├── dataset-action-cell.tsx │ │ │ ├── dataset-table.tsx │ │ │ ├── hooks.ts │ │ │ ├── index.tsx │ │ │ ├── parsing-card.tsx │ │ │ ├── parsing-status-cell.tsx │ │ │ ├── set-meta-dialog.tsx │ │ │ ├── use-bulk-operate-dataset.tsx │ │ │ ├── use-change-document-parser.ts │ │ │ ├── use-create-empty-document.ts │ │ │ ├── use-dataset-table-columns.tsx │ │ │ ├── use-rename-document.ts │ │ │ ├── use-run-document.ts │ │ │ ├── use-save-meta.ts │ │ │ ├── use-select-filters.ts │ │ │ ├── use-upload-document.ts │ │ │ └── utils.ts │ │ ├── index.tsx │ │ ├── setting │ │ │ ├── advanced-setting-form.tsx │ │ │ ├── basic-setting-form.tsx │ │ │ ├── category-panel.tsx │ │ │ ├── chunk-method-card.tsx │ │ │ ├── chunk-method-form.tsx │ │ │ ├── chunk-method-learn-more.tsx │ │ │ ├── configuration-form-container.tsx │ │ │ ├── configuration │ │ │ │ ├── audio.tsx │ │ │ │ ├── book.tsx │ │ │ │ ├── common-item.tsx │ │ │ │ ├── email.tsx │ │ │ │ ├── knowledge-graph.tsx │ │ │ │ ├── laws.tsx │ │ │ │ ├── manual.tsx │ │ │ │ ├── naive.tsx │ │ │ │ ├── one.tsx │ │ │ │ ├── paper.tsx │ │ │ │ ├── picture.tsx │ │ │ │ ├── presentation.tsx │ │ │ │ ├── qa.tsx │ │ │ │ ├── resume.tsx │ │ │ │ ├── table.tsx │ │ │ │ └── tag.tsx │ │ │ ├── form-schema.ts │ │ │ ├── general-form.tsx │ │ │ ├── hooks.ts │ │ │ ├── index.less │ │ │ ├── index.tsx │ │ │ ├── tag-item.tsx │ │ │ ├── tag-table │ │ │ │ ├── index.tsx │ │ │ │ └── rename-dialog │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── rename-form.tsx │ │ │ ├── tag-tabs.tsx │ │ │ ├── tag-word-cloud.tsx │ │ │ └── utils.ts │ │ ├── sidebar │ │ │ ├── hooks.tsx │ │ │ └── index.tsx │ │ └── testing │ │ │ ├── index.tsx │ │ │ ├── testing-form.tsx │ │ │ └── testing-result.tsx │ ├── datasets │ │ ├── dataset-card.tsx │ │ ├── dataset-creating-dialog.tsx │ │ ├── dataset-dropdown.tsx │ │ ├── hooks.ts │ │ ├── index.tsx │ │ ├── use-display-owner.ts │ │ ├── use-rename-dataset.ts │ │ └── use-select-owners.ts │ ├── document-viewer │ │ ├── docx │ │ │ ├── index.less │ │ │ └── index.tsx │ │ ├── excel │ │ │ └── index.tsx │ │ ├── file-error │ │ │ ├── index.less │ │ │ └── index.tsx │ │ ├── hooks.ts │ │ ├── image │ │ │ └── index.tsx │ │ ├── index.less │ │ ├── index.tsx │ │ ├── md │ │ │ └── index.tsx │ │ ├── pdf │ │ │ └── index.tsx │ │ └── text │ │ │ └── index.tsx │ ├── file-manager │ │ ├── action-cell │ │ │ └── index.tsx │ │ ├── connect-to-knowledge-modal │ │ │ └── index.tsx │ │ ├── file-toolbar.tsx │ │ ├── folder-create-modal │ │ │ └── index.tsx │ │ ├── hooks.ts │ │ ├── index.less │ │ ├── index.tsx │ │ └── move-file-modal │ │ │ ├── async-tree-select.tsx │ │ │ └── index.tsx │ ├── files │ │ ├── action-cell.tsx │ │ ├── create-folder-dialog │ │ │ ├── create-folder-form.tsx │ │ │ └── index.tsx │ │ ├── file-breadcrumb.tsx │ │ ├── files-table.tsx │ │ ├── hooks.ts │ │ ├── index.tsx │ │ ├── knowledge-cell.tsx │ │ ├── link-to-dataset-dialog.tsx │ │ ├── move-dialog.tsx │ │ ├── use-bulk-operate-file.tsx │ │ ├── use-create-folder.ts │ │ ├── use-delete-file.ts │ │ ├── use-move-file.ts │ │ ├── use-navigate-to-folder.ts │ │ ├── use-upload-file.ts │ │ └── util.ts │ ├── flow │ │ ├── canvas │ │ │ ├── context-menu │ │ │ │ ├── index.less │ │ │ │ └── index.tsx │ │ │ ├── edge │ │ │ │ ├── index.less │ │ │ │ └── index.tsx │ │ │ ├── index.less │ │ │ ├── index.tsx │ │ │ └── node │ │ │ │ ├── begin-node.tsx │ │ │ │ ├── card.tsx │ │ │ │ ├── categorize-handle.tsx │ │ │ │ ├── categorize-node.tsx │ │ │ │ ├── dropdown.tsx │ │ │ │ ├── email-node.tsx │ │ │ │ ├── generate-node.tsx │ │ │ │ ├── handle-icon.tsx │ │ │ │ ├── hooks.ts │ │ │ │ ├── index.less │ │ │ │ ├── index.tsx │ │ │ │ ├── invoke-node.tsx │ │ │ │ ├── iteration-node.tsx │ │ │ │ ├── keyword-node.tsx │ │ │ │ ├── logic-node.tsx │ │ │ │ ├── message-node.tsx │ │ │ │ ├── node-header.tsx │ │ │ │ ├── note-node.tsx │ │ │ │ ├── popover.tsx │ │ │ │ ├── relevant-node.tsx │ │ │ │ ├── retrieval-node.tsx │ │ │ │ ├── rewrite-node.tsx │ │ │ │ ├── switch-node.tsx │ │ │ │ └── template-node.tsx │ │ ├── chat │ │ │ ├── box.tsx │ │ │ ├── drawer.tsx │ │ │ ├── hooks.ts │ │ │ └── index.less │ │ ├── constant.tsx │ │ ├── context.ts │ │ ├── customer_service.json │ │ ├── debug-content │ │ │ ├── index.less │ │ │ ├── index.tsx │ │ │ └── popover-form.tsx │ │ ├── flow-drawer │ │ │ ├── index.less │ │ │ ├── index.tsx │ │ │ └── single-debug-drawer │ │ │ │ └── index.tsx │ │ ├── flow-id-modal │ │ │ ├── index.less │ │ │ └── index.tsx │ │ ├── flow-setting │ │ │ ├── index.less │ │ │ └── index.tsx │ │ ├── flow-sider │ │ │ ├── index.less │ │ │ └── index.tsx │ │ ├── flow-tooltip.tsx │ │ ├── form-hooks.ts │ │ ├── form │ │ │ ├── akshare-form │ │ │ │ └── index.tsx │ │ │ ├── answer-form │ │ │ │ └── index.tsx │ │ │ ├── arxiv-form │ │ │ │ └── index.tsx │ │ │ ├── baidu-fanyi-form │ │ │ │ └── index.tsx │ │ │ ├── baidu-form │ │ │ │ └── index.tsx │ │ │ ├── begin-form │ │ │ │ ├── begin-dynamic-options.tsx │ │ │ │ ├── hooks.ts │ │ │ │ ├── index.less │ │ │ │ ├── index.tsx │ │ │ │ ├── paramater-modal.tsx │ │ │ │ └── query-table.tsx │ │ │ ├── bing-form │ │ │ │ └── index.tsx │ │ │ ├── categorize-form │ │ │ │ ├── dynamic-categorize.tsx │ │ │ │ ├── hooks.ts │ │ │ │ ├── index.less │ │ │ │ └── index.tsx │ │ │ ├── code-form │ │ │ │ ├── dynamic-input-variable.tsx │ │ │ │ ├── dynamic-output-variable.tsx │ │ │ │ ├── index.less │ │ │ │ └── index.tsx │ │ │ ├── components │ │ │ │ ├── dynamic-input-variable.tsx │ │ │ │ └── index.less │ │ │ ├── concentrator-form │ │ │ │ └── index.tsx │ │ │ ├── crawler-form │ │ │ │ └── index.tsx │ │ │ ├── deepl-form │ │ │ │ └── index.tsx │ │ │ ├── duckduckgo-form │ │ │ │ └── index.tsx │ │ │ ├── email-form │ │ │ │ └── index.tsx │ │ │ ├── exesql-form │ │ │ │ └── index.tsx │ │ │ ├── generate-form │ │ │ │ ├── dynamic-parameters.tsx │ │ │ │ ├── hooks.ts │ │ │ │ ├── index.less │ │ │ │ └── index.tsx │ │ │ ├── github-form │ │ │ │ └── index.tsx │ │ │ ├── google-form │ │ │ │ └── index.tsx │ │ │ ├── google-scholar-form │ │ │ │ └── index.tsx │ │ │ ├── invoke-form │ │ │ │ ├── dynamic-variables.tsx │ │ │ │ ├── hooks.ts │ │ │ │ ├── index.less │ │ │ │ └── index.tsx │ │ │ ├── iteration-from │ │ │ │ └── index.tsx │ │ │ ├── jin10-form │ │ │ │ └── index.tsx │ │ │ ├── keyword-extract-form │ │ │ │ └── index.tsx │ │ │ ├── message-form │ │ │ │ ├── index.less │ │ │ │ └── index.tsx │ │ │ ├── pubmed-form │ │ │ │ └── index.tsx │ │ │ ├── qweather-form │ │ │ │ └── index.tsx │ │ │ ├── relevant-form │ │ │ │ ├── hooks.ts │ │ │ │ └── index.tsx │ │ │ ├── retrieval-form │ │ │ │ └── index.tsx │ │ │ ├── rewrite-question-form │ │ │ │ └── index.tsx │ │ │ ├── switch-form │ │ │ │ ├── index.less │ │ │ │ └── index.tsx │ │ │ ├── template-form │ │ │ │ └── index.tsx │ │ │ ├── tushare-form │ │ │ │ └── index.tsx │ │ │ ├── wencai-form │ │ │ │ └── index.tsx │ │ │ ├── wikipedia-form │ │ │ │ └── index.tsx │ │ │ └── yahoo-finance-form │ │ │ │ └── index.tsx │ │ ├── header │ │ │ ├── index.less │ │ │ └── index.tsx │ │ ├── headhunter_zh.json │ │ ├── history-version-modal │ │ │ └── index.tsx │ │ ├── hooks.tsx │ │ ├── hooks │ │ │ ├── use-before-delete.tsx │ │ │ ├── use-build-dsl.ts │ │ │ ├── use-export-json.ts │ │ │ ├── use-fetch-data.ts │ │ │ ├── use-get-begin-query.tsx │ │ │ ├── use-iteration.ts │ │ │ ├── use-open-document.ts │ │ │ ├── use-save-graph.ts │ │ │ ├── use-set-graph.ts │ │ │ └── use-show-drawer.tsx │ │ ├── index.tsx │ │ ├── interface.ts │ │ ├── interpreter.json │ │ ├── json-upload-modal │ │ │ ├── index.less │ │ │ └── index.tsx │ │ ├── list │ │ │ ├── agent-template-modal.tsx │ │ │ ├── create-agent-modal.tsx │ │ │ ├── flow-card │ │ │ │ ├── index.less │ │ │ │ └── index.tsx │ │ │ ├── graph-avatar.tsx │ │ │ ├── hooks.ts │ │ │ ├── index.less │ │ │ └── index.tsx │ │ ├── mock.tsx │ │ ├── operator-icon │ │ │ ├── index.less │ │ │ └── index.tsx │ │ ├── retrieval_relevant_rewrite_and_generate.json │ │ ├── run-drawer │ │ │ ├── index.less │ │ │ ├── index.tsx │ │ │ └── popover-form.tsx │ │ ├── store.ts │ │ ├── utils.test.ts │ │ └── utils.ts │ ├── home │ │ ├── agent-list.tsx │ │ ├── application-card.tsx │ │ ├── applications.tsx │ │ ├── banner.tsx │ │ ├── chat-list.tsx │ │ ├── datasets.tsx │ │ ├── header.tsx │ │ └── index.tsx │ ├── knowledge │ │ ├── hooks.ts │ │ ├── index.less │ │ ├── index.tsx │ │ ├── knowledge-card │ │ │ ├── index.less │ │ │ └── index.tsx │ │ └── knowledge-creating-modal │ │ │ └── index.tsx │ ├── login-next │ │ ├── form.tsx │ │ ├── hooks.ts │ │ └── index.tsx │ ├── login │ │ ├── index.less │ │ ├── index.tsx │ │ └── right-panel.tsx │ ├── next-chats │ │ ├── chat-card.tsx │ │ ├── chat │ │ │ ├── app-settings │ │ │ │ ├── chat-basic-settings.tsx │ │ │ │ ├── chat-model-settings.tsx │ │ │ │ ├── chat-prompt-engine.tsx │ │ │ │ ├── index.tsx │ │ │ │ ├── subhead.tsx │ │ │ │ └── use-chat-setting-schema.tsx │ │ │ ├── chat-box.tsx │ │ │ ├── index.tsx │ │ │ └── sessions.tsx │ │ └── index.tsx │ ├── next-search │ │ └── index.tsx │ ├── next-searches │ │ ├── index.tsx │ │ └── search-card.tsx │ ├── profile-setting │ │ ├── components.tsx │ │ ├── hooks.tsx │ │ ├── index.tsx │ │ ├── mcp │ │ │ ├── edit-mcp-dialog.tsx │ │ │ ├── edit-mcp-form.tsx │ │ │ ├── import-mcp-dialog │ │ │ │ ├── import-mcp-form.tsx │ │ │ │ └── index.tsx │ │ │ ├── index.tsx │ │ │ ├── mcp-card.tsx │ │ │ ├── mcp-dropdown.tsx │ │ │ ├── tool-card.tsx │ │ │ ├── use-bulk-operate-mcp.tsx │ │ │ ├── use-edit-mcp.ts │ │ │ ├── use-export-mcp.ts │ │ │ └── use-import-mcp.ts │ │ ├── model │ │ │ ├── index.tsx │ │ │ └── model-card.tsx │ │ ├── plan │ │ │ ├── index.tsx │ │ │ └── pricing-card.tsx │ │ ├── profile │ │ │ └── index.tsx │ │ ├── prompt │ │ │ └── index.tsx │ │ ├── sidebar │ │ │ ├── hooks.tsx │ │ │ └── index.tsx │ │ └── team │ │ │ └── index.tsx │ ├── search │ │ ├── hooks.ts │ │ ├── index.less │ │ ├── index.tsx │ │ ├── mindmap-drawer.tsx │ │ └── sidebar.tsx │ └── user-setting │ │ ├── components │ │ └── setting-title │ │ │ └── index.tsx │ │ ├── constants.tsx │ │ ├── hooks.ts │ │ ├── index.less │ │ ├── index.tsx │ │ ├── interface.ts │ │ ├── setting-api │ │ ├── index.less │ │ └── index.tsx │ │ ├── setting-locale │ │ ├── TranslationTable.tsx │ │ └── index.tsx │ │ ├── setting-model │ │ ├── Tencent-modal │ │ │ └── index.tsx │ │ ├── api-key-modal │ │ │ └── index.tsx │ │ ├── azure-openai-modal │ │ │ └── index.tsx │ │ ├── bedrock-modal │ │ │ └── index.tsx │ │ ├── constant.ts │ │ ├── fish-audio-modal │ │ │ └── index.tsx │ │ ├── google-modal │ │ │ └── index.tsx │ │ ├── hooks.ts │ │ ├── hunyuan-modal │ │ │ └── index.tsx │ │ ├── index.less │ │ ├── index.tsx │ │ ├── langfuse │ │ │ ├── index.tsx │ │ │ ├── langfuse-configuration-dialog.tsx │ │ │ ├── langfuse-configuration-form.tsx │ │ │ └── use-save-langfuse-configuration.tsx │ │ ├── ollama-modal │ │ │ └── index.tsx │ │ ├── spark-modal │ │ │ └── index.tsx │ │ ├── system-model-setting-modal │ │ │ └── index.tsx │ │ ├── volcengine-modal │ │ │ └── index.tsx │ │ └── yiyan-modal │ │ │ └── index.tsx │ │ ├── setting-password │ │ ├── index.less │ │ └── index.tsx │ │ ├── setting-profile │ │ ├── index.less │ │ └── index.tsx │ │ ├── setting-system │ │ ├── index.less │ │ ├── index.tsx │ │ └── task-bar-chat.tsx │ │ ├── setting-team │ │ ├── add-user-modal.tsx │ │ ├── hooks.ts │ │ ├── index.less │ │ ├── index.tsx │ │ ├── tenant-table.tsx │ │ └── user-table.tsx │ │ ├── sidebar │ │ ├── index.less │ │ └── index.tsx │ │ └── utils.ts ├── routes.ts ├── services │ ├── chat-service.ts │ ├── file-manager-service.ts │ ├── flow-service.ts │ ├── knowledge-service.ts │ ├── mcp-server-service.ts │ ├── plugin-service.ts │ └── user-service.ts ├── theme │ ├── theme.ts │ └── vars.less ├── utils │ ├── api.ts │ ├── authorization-util.ts │ ├── chat.ts │ ├── common-util.ts │ ├── component-util.ts │ ├── dataset-util.ts │ ├── date.ts │ ├── document-util.ts │ ├── dom-util.ts │ ├── file-util.ts │ ├── form.ts │ ├── index.ts │ ├── llm-util.ts │ ├── register-server.ts │ ├── request.ts │ └── store-util.ts └── wrappers │ └── auth.tsx ├── tailwind.config.js ├── tailwind.css ├── tsconfig.json └── typings.d.ts /.gitattributes: -------------------------------------------------------------------------------- 1 | *.sh text eol=lf 2 | docker/entrypoint.sh text eol=lf executable 3 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | ### What problem does this PR solve? 2 | 3 | _Briefly describe what this PR aims to solve. Include background context that will help reviewers understand the purpose of the PR._ 4 | 5 | ### Type of change 6 | 7 | - [ ] Bug Fix (non-breaking change which fixes an issue) 8 | - [ ] New Feature (non-breaking change which adds functionality) 9 | - [ ] Documentation Update 10 | - [ ] Refactoring 11 | - [ ] Performance Improvement 12 | - [ ] Other (please describe): 13 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: https://github.com/pre-commit/pre-commit-hooks 3 | rev: v4.6.0 4 | hooks: 5 | - id: check-yaml 6 | - id: check-json 7 | - id: end-of-file-fixer 8 | - id: trailing-whitespace 9 | - id: check-case-conflict 10 | - id: check-merge-conflict 11 | - id: mixed-line-ending 12 | - id: check-symlinks 13 | 14 | - repo: https://github.com/astral-sh/ruff-pre-commit 15 | rev: v0.11.6 16 | hooks: 17 | - id: ruff 18 | args: [ --fix ] 19 | - id: ruff-format 20 | -------------------------------------------------------------------------------- /Dockerfile.deps: -------------------------------------------------------------------------------- 1 | # This builds an image that contains the resources needed by Dockerfile 2 | # 3 | FROM scratch 4 | 5 | # Copy resources downloaded via download_deps.py 6 | COPY chromedriver-linux64-121-0-6167-85 chrome-linux64-121-0-6167-85 cl100k_base.tiktoken libssl1.1_1.1.1f-1ubuntu2_amd64.deb libssl1.1_1.1.1f-1ubuntu2_arm64.deb tika-server-standard-3.0.0.jar tika-server-standard-3.0.0.jar.md5 libssl*.deb / 7 | 8 | COPY nltk_data /nltk_data 9 | 10 | COPY huggingface.co /huggingface.co 11 | -------------------------------------------------------------------------------- /agent/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2025 The InfiniFlow Authors. All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | from beartype.claw import beartype_this_package 18 | beartype_this_package() 19 | -------------------------------------------------------------------------------- /agent/settings.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2025 The InfiniFlow Authors. All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | FLOAT_ZERO = 1e-8 18 | PARAM_MAXDEPTH = 5 19 | -------------------------------------------------------------------------------- /agentic_reasoning/__init__.py: -------------------------------------------------------------------------------- 1 | from .deep_research import DeepResearcher as DeepResearcher -------------------------------------------------------------------------------- /api/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2025 The InfiniFlow Authors. All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | from beartype.claw import beartype_this_package 18 | beartype_this_package() 19 | -------------------------------------------------------------------------------- /api/apps/plugin_app.py: -------------------------------------------------------------------------------- 1 | from flask import Response 2 | from flask_login import login_required 3 | from api.utils.api_utils import get_json_result 4 | from plugin import GlobalPluginManager 5 | 6 | @manager.route('/llm_tools', methods=['GET']) # noqa: F821 7 | @login_required 8 | def llm_tools() -> Response: 9 | tools = GlobalPluginManager.get_llm_tools() 10 | tools_metadata = [t.get_metadata() for t in tools] 11 | 12 | return get_json_result(data=tools_metadata) 13 | -------------------------------------------------------------------------------- /conf/public.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArq9XTUSeYr2+N1h3Afl/ 3 | z8Dse/2yD0ZGrKwx+EEEcdsBLca9Ynmx3nIB5obmLlSfmskLpBo0UACBmB5rEjBp 4 | 2Q2f3AG3Hjd4B+gNCG6BDaawuDlgANIhGnaTLrIqWrrcm4EMzJOnAOI1fgzJRsOO 5 | UEfaS318Eq9OVO3apEyCCt0lOQK6PuksduOjVxtltDav+guVAA068NrPYmRNabVK 6 | RNLJpL8w4D44sfth5RvZ3q9t+6RTArpEtc5sh5ChzvqPOzKGMXW83C95TxmXqpbK 7 | 6olN4RevSfVjEAgCydH6HN6OhtOQEcnrU97r9H0iZOWwbw3pVrZiUkuRD1R56Wzs 8 | 2wIDAQAB 9 | -----END PUBLIC KEY----- 10 | -------------------------------------------------------------------------------- /deepdoc/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2025 The InfiniFlow Authors. All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | from beartype.claw import beartype_this_package 18 | beartype_this_package() 19 | -------------------------------------------------------------------------------- /deepdoc/parser/resume/entities/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2025 The InfiniFlow Authors. All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # -------------------------------------------------------------------------------- /docker/init.sql: -------------------------------------------------------------------------------- 1 | CREATE DATABASE IF NOT EXISTS rag_flow; 2 | USE rag_flow; -------------------------------------------------------------------------------- /docker/nginx/nginx.conf: -------------------------------------------------------------------------------- 1 | user root; 2 | worker_processes auto; 3 | 4 | error_log /var/log/nginx/error.log notice; 5 | pid /var/run/nginx.pid; 6 | 7 | 8 | events { 9 | worker_connections 1024; 10 | } 11 | 12 | 13 | http { 14 | include /etc/nginx/mime.types; 15 | default_type application/octet-stream; 16 | 17 | log_format main '$remote_addr - $remote_user [$time_local] "$request" ' 18 | '$status $body_bytes_sent "$http_referer" ' 19 | '"$http_user_agent" "$http_x_forwarded_for"'; 20 | 21 | access_log /var/log/nginx/access.log main; 22 | 23 | sendfile on; 24 | #tcp_nopush on; 25 | 26 | keepalive_timeout 65; 27 | 28 | #gzip on; 29 | client_max_body_size 1024M; 30 | 31 | include /etc/nginx/conf.d/ragflow.conf; 32 | } 33 | 34 | -------------------------------------------------------------------------------- /docker/nginx/proxy.conf: -------------------------------------------------------------------------------- 1 | proxy_set_header Host $host; 2 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 3 | proxy_set_header X-Forwarded-Proto $scheme; 4 | proxy_http_version 1.1; 5 | proxy_set_header Connection ""; 6 | proxy_buffering off; 7 | proxy_read_timeout 3600s; 8 | proxy_send_timeout 3600s; 9 | -------------------------------------------------------------------------------- /docker/nginx/ragflow.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80; 3 | server_name _; 4 | root /ragflow/web/dist; 5 | 6 | gzip on; 7 | gzip_min_length 1k; 8 | gzip_comp_level 9; 9 | gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png; 10 | gzip_vary on; 11 | gzip_disable "MSIE [1-6]\."; 12 | 13 | location ~ ^/(v1|api) { 14 | proxy_pass http://ragflow:9380; 15 | include proxy.conf; 16 | } 17 | 18 | 19 | location / { 20 | index index.html; 21 | try_files $uri $uri/ /index.html; 22 | } 23 | 24 | # Cache-Control: max-age~@~AExpires 25 | location ~ ^/static/(css|js|media)/ { 26 | expires 10y; 27 | access_log off; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /docs/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Get Started", 3 | "position": 1, 4 | "link": { 5 | "type": "generated-index", 6 | "description": "RAGFlow Quick Start" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /docs/contribution/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Contribution", 3 | "position": 8, 4 | "link": { 5 | "type": "generated-index", 6 | "description": "Miscellaneous contribution guides." 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /docs/develop/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Developers", 3 | "position": 4, 4 | "link": { 5 | "type": "generated-index", 6 | "description": "Guides for hardcore developers" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /docs/develop/mcp/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "MCP", 3 | "position": 40, 4 | "link": { 5 | "type": "generated-index", 6 | "description": "Guides and references on accessing RAGFlow's knowledge bases via MCP." 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /docs/develop/mcp/mcp_tools.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 2 3 | slug: /mcp_tools 4 | --- 5 | 6 | # RAGFlow MCP tools 7 | 8 | The MCP server currently offers a specialized tool to assist users in searching for relevant information powered by RAGFlow DeepDoc technology: 9 | 10 | - **retrieve**: Fetches relevant chunks from specified `dataset_ids` and optional `document_ids` using the RAGFlow retrieve interface, based on a given question. Details of all available datasets, namely, `id` and `description`, are provided within the tool description for each individual dataset. 11 | 12 | For more information, see our Python implementation of the [MCP server](https://github.com/infiniflow/ragflow/blob/main/mcp/server/server.py). -------------------------------------------------------------------------------- /docs/guides/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Guides", 3 | "position": 3, 4 | "link": { 5 | "type": "generated-index", 6 | "description": "Guides for RAGFlow users and developers." 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /docs/guides/agent/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Agents", 3 | "position": 3, 4 | "link": { 5 | "type": "generated-index", 6 | "description": "RAGFlow v0.8.0 introduces an agent mechanism, featuring a no-code workflow editor on the front end and a comprehensive graph-based task orchestration framework on the backend." 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /docs/guides/agent/agent_component_reference/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Agent Components", 3 | "position": 20, 4 | "link": { 5 | "type": "generated-index", 6 | "description": "A complete reference for RAGFlow's agent components." 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /docs/guides/chat/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Chat", 3 | "position": 1, 4 | "link": { 5 | "type": "generated-index", 6 | "description": "Chat-specific guides." 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /docs/guides/chat/best_practices/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Best practices", 3 | "position": 7, 4 | "link": { 5 | "type": "generated-index", 6 | "description": "Best practices on chat assistant configuration." 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /docs/guides/dataset/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Datasets", 3 | "position": 0, 4 | "link": { 5 | "type": "generated-index", 6 | "description": "Guides on configuring a knowledge base." 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /docs/guides/dataset/best_practices/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Best practices", 3 | "position": 11, 4 | "link": { 5 | "type": "generated-index", 6 | "description": "Best practices on configuring a knowledge base." 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /docs/guides/models/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Models", 3 | "position": -1, 4 | "link": { 5 | "type": "generated-index", 6 | "description": "Guides on model settings." 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /docs/guides/team/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Team", 3 | "position": 4, 4 | "link": { 5 | "type": "generated-index", 6 | "description": "Team-specific guides." 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /docs/guides/team/share_chat_assistant.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 5 3 | slug: /share_chat_assistant 4 | --- 5 | 6 | # Share chat assistant 7 | 8 | Sharing chat assistant is currently exclusive to RAGFlow Enterprise, but will be made available in due course. -------------------------------------------------------------------------------- /docs/guides/team/share_model.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 7 3 | slug: /share_model 4 | --- 5 | 6 | # Share models 7 | 8 | Sharing models is currently exclusive to RAGFlow Enterprise. -------------------------------------------------------------------------------- /docs/references/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "References", 3 | "position": 6, 4 | "link": { 5 | "type": "generated-index", 6 | "description": "Miscellaneous References" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /graphrag/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infiniflow/ragflow/f2909ea0c4d0d8739f487bb54851e508b39bee62/graphrag/__init__.py -------------------------------------------------------------------------------- /graphrag/general/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infiniflow/ragflow/f2909ea0c4d0d8739f487bb54851e508b39bee62/graphrag/general/__init__.py -------------------------------------------------------------------------------- /graphrag/light/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infiniflow/ragflow/f2909ea0c4d0d8739f487bb54851e508b39bee62/graphrag/light/__init__.py -------------------------------------------------------------------------------- /helm/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /helm/templates/elasticsearch-config.yaml: -------------------------------------------------------------------------------- 1 | {{- if eq .Values.env.DOC_ENGINE "elasticsearch" -}} 2 | apiVersion: v1 3 | kind: ConfigMap 4 | metadata: 5 | name: {{ include "ragflow.fullname" . }}-es-config 6 | data: 7 | node.name: "es01" 8 | bootstrap.memory_lock: "false" 9 | discovery.type: "single-node" 10 | xpack.security.enabled: "true" 11 | xpack.security.http.ssl.enabled: "false" 12 | xpack.security.transport.ssl.enabled: "false" 13 | {{- end -}} 14 | -------------------------------------------------------------------------------- /helm/templates/mysql-config.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: ConfigMap 4 | metadata: 5 | name: mysql-init-script 6 | data: 7 | init.sql: |- 8 | CREATE DATABASE IF NOT EXISTS rag_flow; 9 | USE rag_flow; 10 | -------------------------------------------------------------------------------- /helm/templates/tests/test-connection.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: "{{ include "ragflow.fullname" . }}-test-connection" 5 | labels: 6 | {{- include "ragflow.labels" . | nindent 4 }} 7 | annotations: 8 | "helm.sh/hook": test 9 | spec: 10 | containers: 11 | - name: wget 12 | image: busybox 13 | command: 14 | - 'wget' 15 | args: 16 | - {{ printf "%s.%s.svc" (include "ragflow.fullname" .) .Release.Namespace }} 17 | restartPolicy: Never 18 | -------------------------------------------------------------------------------- /intergrations/chatgpt-on-wechat/plugins/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "api_key": "ragflow-***", 3 | "host_address": "127.0.0.1:80" 4 | } 5 | -------------------------------------------------------------------------------- /intergrations/chatgpt-on-wechat/plugins/requirements.txt: -------------------------------------------------------------------------------- 1 | requests 2 | -------------------------------------------------------------------------------- /intergrations/extension_chrome/assets/logo-with-text.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infiniflow/ragflow/f2909ea0c4d0d8739f487bb54851e508b39bee62/intergrations/extension_chrome/assets/logo-with-text.png -------------------------------------------------------------------------------- /intergrations/extension_chrome/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infiniflow/ragflow/f2909ea0c4d0d8739f487bb54851e508b39bee62/intergrations/extension_chrome/assets/logo.png -------------------------------------------------------------------------------- /intergrations/extension_chrome/background.js: -------------------------------------------------------------------------------- 1 | chrome.runtime.onInstalled.addListener(() => { 2 | console.log("Tiện ích đã được cài đặt!"); 3 | }); 4 | 5 | chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { 6 | if (message.action === "PAGE_INFO") { 7 | console.log( message); 8 | 9 | 10 | chrome.storage.local.set({ pageInfo: message }, () => { 11 | console.log("Page info saved to local storage."); 12 | }); 13 | 14 | // Send a response to the content script 15 | sendResponse({ status: "success", message: "Page info received and processed." }); 16 | } 17 | }); -------------------------------------------------------------------------------- /intergrations/extension_chrome/icons/icon-128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infiniflow/ragflow/f2909ea0c4d0d8739f487bb54851e508b39bee62/intergrations/extension_chrome/icons/icon-128x128.png -------------------------------------------------------------------------------- /intergrations/extension_chrome/icons/icon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infiniflow/ragflow/f2909ea0c4d0d8739f487bb54851e508b39bee62/intergrations/extension_chrome/icons/icon-16x16.png -------------------------------------------------------------------------------- /intergrations/extension_chrome/icons/icon-48x48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infiniflow/ragflow/f2909ea0c4d0d8739f487bb54851e508b39bee62/intergrations/extension_chrome/icons/icon-48x48.png -------------------------------------------------------------------------------- /intergrations/extension_chrome/popup.html: -------------------------------------------------------------------------------- 1 | <!DOCTYPE html> 2 | <html> 3 | 4 | <head> 5 | <meta charset="utf-8" /> 6 | <meta name="viewport" 7 | content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0" /> 8 | <title>RAGFLOW</title> 9 | <link rel="stylesheet" href="styles/popup.css" /> 10 | </head> 11 | 12 | <body id="ragflow"> 13 | <div class="window"> 14 | <textarea id="getHtml"></textarea> 15 | <iframe src="" style="width: 100%; height: 100%; min-height: 600px" frameborder="0"></iframe> 16 | </div> 17 | <script src="popup.js"></script> 18 | </body> 19 | 20 | </html> -------------------------------------------------------------------------------- /intergrations/extension_chrome/styles/popup.css: -------------------------------------------------------------------------------- 1 | #ragflow { 2 | font-family: "Segoe UI", Arial, sans-serif; 3 | margin: 0; 4 | padding: 0; 5 | display: flex; 6 | justify-content: center; 7 | align-items: center; 8 | width: 320px; 9 | } 10 | 11 | #ragflow .window { 12 | display: flex; 13 | flex-direction: column; 14 | justify-content: space-between; 15 | flex: 1; 16 | overflow: hidden; 17 | } 18 | #ragflow #output { 19 | position: absolute; 20 | } -------------------------------------------------------------------------------- /plugin/__init__.py: -------------------------------------------------------------------------------- 1 | from .plugin_manager import PluginManager 2 | 3 | GlobalPluginManager = PluginManager() 4 | -------------------------------------------------------------------------------- /plugin/common.py: -------------------------------------------------------------------------------- 1 | PLUGIN_TYPE_LLM_TOOLS = "llm_tools" -------------------------------------------------------------------------------- /rag/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2025 The InfiniFlow Authors. All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | from beartype.claw import beartype_this_package 18 | beartype_this_package() 19 | -------------------------------------------------------------------------------- /rag/app/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2025 The InfiniFlow Authors. All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # -------------------------------------------------------------------------------- /rag/prompt_template.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | BASE_DIR = os.path.dirname(__file__) 4 | 5 | PROMPT_DIR = os.path.join(BASE_DIR, "prompts") 6 | 7 | _loaded_prompts = {} 8 | 9 | 10 | def load_prompt(name: str) -> str: 11 | if name in _loaded_prompts: 12 | return _loaded_prompts[name] 13 | 14 | path = os.path.join(PROMPT_DIR, f"{name}.md") 15 | if not os.path.isfile(path): 16 | raise FileNotFoundError(f"Prompt file '{name}.md' not found in prompts/ directory.") 17 | 18 | with open(path, "r", encoding="utf-8") as f: 19 | content = f.read().strip() 20 | _loaded_prompts[name] = content 21 | return content 22 | -------------------------------------------------------------------------------- /rag/prompts/cross_languages_sys_prompt.md: -------------------------------------------------------------------------------- 1 | ## Role 2 | A streamlined multilingual translator. 3 | 4 | ## Behavior Rules 5 | 1. Accept batch translation requests in the following format: 6 | **Input:** `[text]` 7 | **Target Languages:** comma-separated list 8 | 9 | 2. Maintain: 10 | - Original formatting (tables, lists, spacing) 11 | - Technical terminology accuracy 12 | - Cultural context appropriateness 13 | 14 | 3. Output translations in the following format: 15 | 16 | [Translation in language1] 17 | ### 18 | [Translation in language2] 19 | 20 | --- 21 | 22 | ## Example 23 | 24 | **Input:** 25 | Hello World! Let's discuss AI safety. 26 | === 27 | Chinese, French, Japanese 28 | 29 | **Output:** 30 | 你好世界!让我们讨论人工智能安全问题。 31 | ### 32 | Bonjour le monde ! Parlons de la sécurité de l'IA. 33 | ### 34 | こんにちは世界!AIの安全性について話し合いましょう。 35 | 36 | -------------------------------------------------------------------------------- /rag/prompts/cross_languages_user_prompt.md: -------------------------------------------------------------------------------- 1 | **Input:** 2 | {{ query }} 3 | === 4 | {{ languages | join(', ') }} 5 | 6 | **Output:** 7 | 8 | -------------------------------------------------------------------------------- /rag/prompts/keyword_prompt.md: -------------------------------------------------------------------------------- 1 | ## Role 2 | You are a text analyzer. 3 | 4 | ## Task 5 | Extract the most important keywords/phrases of a given piece of text content. 6 | 7 | ## Requirements 8 | - Summarize the text content, and give the top {{ topn }} important keywords/phrases. 9 | - The keywords MUST be in the same language as the given piece of text content. 10 | - The keywords are delimited by ENGLISH COMMA. 11 | - Output keywords ONLY. 12 | 13 | --- 14 | 15 | ## Text Content 16 | {{ content }} 17 | -------------------------------------------------------------------------------- /rag/prompts/question_prompt.md: -------------------------------------------------------------------------------- 1 | ## Role 2 | You are a text analyzer. 3 | 4 | ## Task 5 | Propose {{ topn }} questions about a given piece of text content. 6 | 7 | ## Requirements 8 | - Understand and summarize the text content, and propose the top {{ topn }} important questions. 9 | - The questions SHOULD NOT have overlapping meanings. 10 | - The questions SHOULD cover the main content of the text as much as possible. 11 | - The questions MUST be in the same language as the given piece of text content. 12 | - One question per line. 13 | - Output questions ONLY. 14 | 15 | --- 16 | 17 | ## Text Content 18 | {{ content }} 19 | 20 | -------------------------------------------------------------------------------- /sandbox/.env.example: -------------------------------------------------------------------------------- 1 | # Copy this file to `.env` and modify as needed 2 | 3 | SANDBOX_EXECUTOR_MANAGER_POOL_SIZE=5 4 | SANDBOX_BASE_PYTHON_IMAGE=sandbox-base-python:latest 5 | SANDBOX_BASE_NODEJS_IMAGE=sandbox-base-nodejs:latest 6 | SANDBOX_EXECUTOR_MANAGER_PORT=9385 7 | SANDBOX_ENABLE_SECCOMP=false 8 | SANDBOX_MAX_MEMORY=256m # b, k, m, g 9 | SANDBOX_TIMEOUT=10s # s, m, 1m30s 10 | -------------------------------------------------------------------------------- /sandbox/executor_manager/api/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2025 The InfiniFlow Authors. All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | -------------------------------------------------------------------------------- /sandbox/executor_manager/core/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2025 The InfiniFlow Authors. All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | -------------------------------------------------------------------------------- /sandbox/executor_manager/core/logger.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2025 The InfiniFlow Authors. All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | import logging 17 | 18 | logging.basicConfig(level=logging.INFO) 19 | logger = logging.getLogger("sandbox") 20 | -------------------------------------------------------------------------------- /sandbox/executor_manager/models/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2025 The InfiniFlow Authors. All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | -------------------------------------------------------------------------------- /sandbox/executor_manager/requirements.txt: -------------------------------------------------------------------------------- 1 | fastapi 2 | uvicorn 3 | slowapi -------------------------------------------------------------------------------- /sandbox/executor_manager/services/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2025 The InfiniFlow Authors. All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | -------------------------------------------------------------------------------- /sandbox/executor_manager/utils/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2025 The InfiniFlow Authors. All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | -------------------------------------------------------------------------------- /sandbox/pyproject.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name = "gvisor-sandbox" 3 | version = "0.1.0" 4 | description = "Add your description here" 5 | readme = "README.md" 6 | requires-python = ">=3.10" 7 | dependencies = [ 8 | "fastapi>=0.115.12", 9 | "httpx>=0.28.1", 10 | "pydantic>=2.11.4", 11 | "requests>=2.32.3", 12 | "slowapi>=0.1.9", 13 | "uvicorn>=0.34.2", 14 | ] 15 | 16 | [[tool.uv.index]] 17 | url = "https://pypi.tuna.tsinghua.edu.cn/simple" 18 | 19 | [dependency-groups] 20 | dev = [ 21 | "basedpyright>=1.29.1", 22 | ] 23 | 24 | [tool.ruff] 25 | line-length = 200 26 | 27 | [tool.ruff.lint] 28 | extend-select = ["C4", "SIM", "TCH"] 29 | -------------------------------------------------------------------------------- /sandbox/sandbox_base_image/nodejs/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:24-bookworm-slim 2 | 3 | RUN npm config set registry https://registry.npmmirror.com 4 | 5 | # RUN grep -rl 'deb.debian.org' /etc/apt/ | xargs sed -i 's|http[s]*://deb.debian.org|https://mirrors.ustc.edu.cn|g' && \ 6 | # apt-get update && \ 7 | # apt-get install -y curl gcc make 8 | 9 | 10 | WORKDIR /app 11 | 12 | COPY package.json package-lock.json . 13 | 14 | RUN npm install 15 | 16 | CMD ["sleep", "infinity"] 17 | 18 | -------------------------------------------------------------------------------- /sandbox/sandbox_base_image/nodejs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nodejs", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "scripts": { 6 | "test": "echo \"Error: no test specified\" && exit 1" 7 | }, 8 | "keywords": [], 9 | "author": "", 10 | "license": "ISC", 11 | "description": "", 12 | "dependencies": { 13 | "axios": "^1.9.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /sandbox/sandbox_base_image/python/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.11-slim-bookworm 2 | 3 | COPY --from=ghcr.io/astral-sh/uv:0.7.5 /uv /uvx /bin/ 4 | ENV UV_INDEX_URL=https://pypi.tuna.tsinghua.edu.cn/simple 5 | 6 | COPY requirements.txt . 7 | 8 | RUN grep -rl 'deb.debian.org' /etc/apt/ | xargs sed -i 's|http[s]*://deb.debian.org|https://mirrors.tuna.tsinghua.edu.cn|g' && \ 9 | apt-get update && \ 10 | apt-get install -y curl gcc && \ 11 | uv pip install --system -r requirements.txt 12 | 13 | WORKDIR /workspace 14 | 15 | CMD ["sleep", "infinity"] 16 | -------------------------------------------------------------------------------- /sandbox/sandbox_base_image/python/requirements.txt: -------------------------------------------------------------------------------- 1 | numpy 2 | pandas 3 | requests 4 | -------------------------------------------------------------------------------- /sandbox/scripts/restart.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Copyright 2025 The InfiniFlow Authors. All Rights Reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | # 17 | 18 | set -e 19 | 20 | bash "$(dirname "$0")/stop.sh" 21 | bash "$(dirname "$0")/start.sh" 22 | -------------------------------------------------------------------------------- /sdk/python/README.md: -------------------------------------------------------------------------------- 1 | # ragflow-sdk 2 | 3 | # build and publish python SDK to pypi.org 4 | 5 | ```shell 6 | uv build 7 | uv pip install twine 8 | export TWINE_USERNAME="__token__" 9 | export TWINE_PASSWORD=$YOUR_PYPI_API_TOKEN 10 | twine upload dist/*.whl 11 | ``` 12 | -------------------------------------------------------------------------------- /sdk/python/hello_ragflow.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2025 The InfiniFlow Authors. All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | import ragflow_sdk 18 | 19 | print(ragflow_sdk.__version__) 20 | -------------------------------------------------------------------------------- /sdk/python/ragflow_sdk/modules/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2025 The InfiniFlow Authors. All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # -------------------------------------------------------------------------------- /sdk/python/test/libs/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2025 The InfiniFlow Authors. All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | -------------------------------------------------------------------------------- /sdk/python/test/test_frontend_api/get_email.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2025 The InfiniFlow Authors. All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | def test_get_email(get_email): 18 | print("\nEmail account:",flush=True) 19 | print(f"{get_email}\n",flush=True) -------------------------------------------------------------------------------- /sdk/python/test/test_sdk_api/common.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2025 The InfiniFlow Authors. All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | import os 18 | 19 | HOST_ADDRESS = os.getenv('HOST_ADDRESS', 'http://127.0.0.1:9380') 20 | -------------------------------------------------------------------------------- /sdk/python/test/test_sdk_api/get_email.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2025 The InfiniFlow Authors. All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | def test_get_email(get_email): 18 | print("\nEmail account:", flush=True) 19 | print(f"{get_email}\n", flush=True) 20 | -------------------------------------------------------------------------------- /sdk/python/test/test_sdk_api/test_data/ragflow.txt: -------------------------------------------------------------------------------- 1 | {"data":null,"code":100,"message":"TypeError(\"download_document() got an unexpected keyword argument 'tenant_id'\")"} 2 | -------------------------------------------------------------------------------- /sdk/python/test/test_sdk_api/test_data/test.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infiniflow/ragflow/f2909ea0c4d0d8739f487bb54851e508b39bee62/sdk/python/test/test_sdk_api/test_data/test.docx -------------------------------------------------------------------------------- /sdk/python/test/test_sdk_api/test_data/test.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infiniflow/ragflow/f2909ea0c4d0d8739f487bb54851e508b39bee62/sdk/python/test/test_sdk_api/test_data/test.jpg -------------------------------------------------------------------------------- /sdk/python/test/test_sdk_api/test_data/test.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infiniflow/ragflow/f2909ea0c4d0d8739f487bb54851e508b39bee62/sdk/python/test/test_sdk_api/test_data/test.pdf -------------------------------------------------------------------------------- /sdk/python/test/test_sdk_api/test_data/test.ppt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infiniflow/ragflow/f2909ea0c4d0d8739f487bb54851e508b39bee62/sdk/python/test/test_sdk_api/test_data/test.ppt -------------------------------------------------------------------------------- /sdk/python/test/test_sdk_api/test_data/test.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infiniflow/ragflow/f2909ea0c4d0d8739f487bb54851e508b39bee62/sdk/python/test/test_sdk_api/test_data/test.xlsx -------------------------------------------------------------------------------- /test/libs/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2025 The InfiniFlow Authors. All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | -------------------------------------------------------------------------------- /web/.env: -------------------------------------------------------------------------------- 1 | PORT=9222 -------------------------------------------------------------------------------- /web/.eslintrc.js: -------------------------------------------------------------------------------- 1 | // .eslintrc.js 2 | module.exports = { 3 | // Umi 项目 4 | extends: [require.resolve('umi/eslint'), 'plugin:react-hooks/recommended'], 5 | }; 6 | -------------------------------------------------------------------------------- /web/.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | /.env.local 3 | /.umirc.local.ts 4 | /config/config.local.ts 5 | /src/.umi/* 6 | /src/.umi-production/* 7 | /src/.umi-test 8 | /dist 9 | .swc 10 | -------------------------------------------------------------------------------- /web/.husky/pre-commit: -------------------------------------------------------------------------------- 1 | cd web 2 | npx lint-staged -------------------------------------------------------------------------------- /web/.npmrc: -------------------------------------------------------------------------------- 1 | engine-strict=true 2 | registry=https://registry.npmmirror.com/ 3 | -------------------------------------------------------------------------------- /web/.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .umi 3 | .umi-production 4 | -------------------------------------------------------------------------------- /web/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 80, 3 | "singleQuote": true, 4 | "trailingComma": "all", 5 | "proseWrap": "never", 6 | "overrides": [{ "files": ".prettierrc", "options": { "parser": "json" } }], 7 | "plugins": [ 8 | "prettier-plugin-organize-imports", 9 | "prettier-plugin-packagejson" 10 | ], 11 | "endOfLine": "lf" 12 | } 13 | -------------------------------------------------------------------------------- /web/jest-setup.ts: -------------------------------------------------------------------------------- 1 | import '@testing-library/jest-dom'; 2 | import 'umi/test-setup'; 3 | -------------------------------------------------------------------------------- /web/src/assets/banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infiniflow/ragflow/f2909ea0c4d0d8739f487bb54851e508b39bee62/web/src/assets/banner.png -------------------------------------------------------------------------------- /web/src/assets/filter.svg: -------------------------------------------------------------------------------- 1 | <svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg"> 2 | <path d="M5 10H15M2.5 5H17.5M7.5 15H12.5" stroke="#344054" stroke-width="1.66667" stroke-linecap="round" stroke-linejoin="round"/> 3 | </svg> 4 | -------------------------------------------------------------------------------- /web/src/assets/inter/Inter-Black.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infiniflow/ragflow/f2909ea0c4d0d8739f487bb54851e508b39bee62/web/src/assets/inter/Inter-Black.woff2 -------------------------------------------------------------------------------- /web/src/assets/inter/Inter-BlackItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infiniflow/ragflow/f2909ea0c4d0d8739f487bb54851e508b39bee62/web/src/assets/inter/Inter-BlackItalic.woff2 -------------------------------------------------------------------------------- /web/src/assets/inter/Inter-Bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infiniflow/ragflow/f2909ea0c4d0d8739f487bb54851e508b39bee62/web/src/assets/inter/Inter-Bold.woff2 -------------------------------------------------------------------------------- /web/src/assets/inter/Inter-BoldItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infiniflow/ragflow/f2909ea0c4d0d8739f487bb54851e508b39bee62/web/src/assets/inter/Inter-BoldItalic.woff2 -------------------------------------------------------------------------------- /web/src/assets/inter/Inter-ExtraBold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infiniflow/ragflow/f2909ea0c4d0d8739f487bb54851e508b39bee62/web/src/assets/inter/Inter-ExtraBold.woff2 -------------------------------------------------------------------------------- /web/src/assets/inter/Inter-ExtraBoldItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infiniflow/ragflow/f2909ea0c4d0d8739f487bb54851e508b39bee62/web/src/assets/inter/Inter-ExtraBoldItalic.woff2 -------------------------------------------------------------------------------- /web/src/assets/inter/Inter-ExtraLight.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infiniflow/ragflow/f2909ea0c4d0d8739f487bb54851e508b39bee62/web/src/assets/inter/Inter-ExtraLight.woff2 -------------------------------------------------------------------------------- /web/src/assets/inter/Inter-ExtraLightItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infiniflow/ragflow/f2909ea0c4d0d8739f487bb54851e508b39bee62/web/src/assets/inter/Inter-ExtraLightItalic.woff2 -------------------------------------------------------------------------------- /web/src/assets/inter/Inter-Italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infiniflow/ragflow/f2909ea0c4d0d8739f487bb54851e508b39bee62/web/src/assets/inter/Inter-Italic.woff2 -------------------------------------------------------------------------------- /web/src/assets/inter/Inter-Light.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infiniflow/ragflow/f2909ea0c4d0d8739f487bb54851e508b39bee62/web/src/assets/inter/Inter-Light.woff2 -------------------------------------------------------------------------------- /web/src/assets/inter/Inter-LightItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infiniflow/ragflow/f2909ea0c4d0d8739f487bb54851e508b39bee62/web/src/assets/inter/Inter-LightItalic.woff2 -------------------------------------------------------------------------------- /web/src/assets/inter/Inter-Medium.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infiniflow/ragflow/f2909ea0c4d0d8739f487bb54851e508b39bee62/web/src/assets/inter/Inter-Medium.woff2 -------------------------------------------------------------------------------- /web/src/assets/inter/Inter-MediumItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infiniflow/ragflow/f2909ea0c4d0d8739f487bb54851e508b39bee62/web/src/assets/inter/Inter-MediumItalic.woff2 -------------------------------------------------------------------------------- /web/src/assets/inter/Inter-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infiniflow/ragflow/f2909ea0c4d0d8739f487bb54851e508b39bee62/web/src/assets/inter/Inter-Regular.woff2 -------------------------------------------------------------------------------- /web/src/assets/inter/Inter-SemiBold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infiniflow/ragflow/f2909ea0c4d0d8739f487bb54851e508b39bee62/web/src/assets/inter/Inter-SemiBold.woff2 -------------------------------------------------------------------------------- /web/src/assets/inter/Inter-SemiBoldItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infiniflow/ragflow/f2909ea0c4d0d8739f487bb54851e508b39bee62/web/src/assets/inter/Inter-SemiBoldItalic.woff2 -------------------------------------------------------------------------------- /web/src/assets/inter/Inter-Thin.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infiniflow/ragflow/f2909ea0c4d0d8739f487bb54851e508b39bee62/web/src/assets/inter/Inter-Thin.woff2 -------------------------------------------------------------------------------- /web/src/assets/inter/Inter-ThinItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infiniflow/ragflow/f2909ea0c4d0d8739f487bb54851e508b39bee62/web/src/assets/inter/Inter-ThinItalic.woff2 -------------------------------------------------------------------------------- /web/src/assets/inter/InterDisplay-Black.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infiniflow/ragflow/f2909ea0c4d0d8739f487bb54851e508b39bee62/web/src/assets/inter/InterDisplay-Black.woff2 -------------------------------------------------------------------------------- /web/src/assets/inter/InterDisplay-BlackItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infiniflow/ragflow/f2909ea0c4d0d8739f487bb54851e508b39bee62/web/src/assets/inter/InterDisplay-BlackItalic.woff2 -------------------------------------------------------------------------------- /web/src/assets/inter/InterDisplay-Bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infiniflow/ragflow/f2909ea0c4d0d8739f487bb54851e508b39bee62/web/src/assets/inter/InterDisplay-Bold.woff2 -------------------------------------------------------------------------------- /web/src/assets/inter/InterDisplay-BoldItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infiniflow/ragflow/f2909ea0c4d0d8739f487bb54851e508b39bee62/web/src/assets/inter/InterDisplay-BoldItalic.woff2 -------------------------------------------------------------------------------- /web/src/assets/inter/InterDisplay-ExtraBold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infiniflow/ragflow/f2909ea0c4d0d8739f487bb54851e508b39bee62/web/src/assets/inter/InterDisplay-ExtraBold.woff2 -------------------------------------------------------------------------------- /web/src/assets/inter/InterDisplay-ExtraBoldItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infiniflow/ragflow/f2909ea0c4d0d8739f487bb54851e508b39bee62/web/src/assets/inter/InterDisplay-ExtraBoldItalic.woff2 -------------------------------------------------------------------------------- /web/src/assets/inter/InterDisplay-ExtraLight.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infiniflow/ragflow/f2909ea0c4d0d8739f487bb54851e508b39bee62/web/src/assets/inter/InterDisplay-ExtraLight.woff2 -------------------------------------------------------------------------------- /web/src/assets/inter/InterDisplay-ExtraLightItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infiniflow/ragflow/f2909ea0c4d0d8739f487bb54851e508b39bee62/web/src/assets/inter/InterDisplay-ExtraLightItalic.woff2 -------------------------------------------------------------------------------- /web/src/assets/inter/InterDisplay-Italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infiniflow/ragflow/f2909ea0c4d0d8739f487bb54851e508b39bee62/web/src/assets/inter/InterDisplay-Italic.woff2 -------------------------------------------------------------------------------- /web/src/assets/inter/InterDisplay-Light.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infiniflow/ragflow/f2909ea0c4d0d8739f487bb54851e508b39bee62/web/src/assets/inter/InterDisplay-Light.woff2 -------------------------------------------------------------------------------- /web/src/assets/inter/InterDisplay-LightItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infiniflow/ragflow/f2909ea0c4d0d8739f487bb54851e508b39bee62/web/src/assets/inter/InterDisplay-LightItalic.woff2 -------------------------------------------------------------------------------- /web/src/assets/inter/InterDisplay-Medium.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infiniflow/ragflow/f2909ea0c4d0d8739f487bb54851e508b39bee62/web/src/assets/inter/InterDisplay-Medium.woff2 -------------------------------------------------------------------------------- /web/src/assets/inter/InterDisplay-MediumItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infiniflow/ragflow/f2909ea0c4d0d8739f487bb54851e508b39bee62/web/src/assets/inter/InterDisplay-MediumItalic.woff2 -------------------------------------------------------------------------------- /web/src/assets/inter/InterDisplay-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infiniflow/ragflow/f2909ea0c4d0d8739f487bb54851e508b39bee62/web/src/assets/inter/InterDisplay-Regular.woff2 -------------------------------------------------------------------------------- /web/src/assets/inter/InterDisplay-SemiBold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infiniflow/ragflow/f2909ea0c4d0d8739f487bb54851e508b39bee62/web/src/assets/inter/InterDisplay-SemiBold.woff2 -------------------------------------------------------------------------------- /web/src/assets/inter/InterDisplay-SemiBoldItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infiniflow/ragflow/f2909ea0c4d0d8739f487bb54851e508b39bee62/web/src/assets/inter/InterDisplay-SemiBoldItalic.woff2 -------------------------------------------------------------------------------- /web/src/assets/inter/InterDisplay-Thin.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infiniflow/ragflow/f2909ea0c4d0d8739f487bb54851e508b39bee62/web/src/assets/inter/InterDisplay-Thin.woff2 -------------------------------------------------------------------------------- /web/src/assets/inter/InterDisplay-ThinItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infiniflow/ragflow/f2909ea0c4d0d8739f487bb54851e508b39bee62/web/src/assets/inter/InterDisplay-ThinItalic.woff2 -------------------------------------------------------------------------------- /web/src/assets/inter/InterVariable-Italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infiniflow/ragflow/f2909ea0c4d0d8739f487bb54851e508b39bee62/web/src/assets/inter/InterVariable-Italic.woff2 -------------------------------------------------------------------------------- /web/src/assets/inter/InterVariable.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infiniflow/ragflow/f2909ea0c4d0d8739f487bb54851e508b39bee62/web/src/assets/inter/InterVariable.woff2 -------------------------------------------------------------------------------- /web/src/assets/logo-with-text.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infiniflow/ragflow/f2909ea0c4d0d8739f487bb54851e508b39bee62/web/src/assets/logo-with-text.png -------------------------------------------------------------------------------- /web/src/assets/svg/bing.svg: -------------------------------------------------------------------------------- 1 | <svg t="1722318934204" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" 2 | p-id="12570" width="200" height="200"> 3 | <path d="M99.555556 99.555556h391.964444v391.964444H99.555556V99.555556z" fill="#F25022" p-id="12571"></path> 4 | <path d="M532.48 99.555556H924.444444v391.964444H532.48V99.555556z" fill="#7FBA00" p-id="12572"></path> 5 | <path d="M99.555556 532.48h391.964444V924.444444H99.555556V532.48z" fill="#00A4EF" p-id="12573"></path> 6 | <path d="M532.48 532.48H924.444444V924.444444H532.48V532.48z" fill="#FFB900" p-id="12574"></path> 7 | </svg> -------------------------------------------------------------------------------- /web/src/assets/svg/cancel.svg: -------------------------------------------------------------------------------- 1 | <svg width="22" height="22" viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg"> 2 | <path 3 | d="M0.5 11C0.5 5.20101 5.20101 0.5 11 0.5C16.799 0.5 21.5 5.20101 21.5 11C21.5 16.799 16.799 21.5 11 21.5C5.20101 21.5 0.5 16.799 0.5 11Z" 4 | fill="#FEF3F2" /> 5 | <path 6 | d="M0.5 11C0.5 5.20101 5.20101 0.5 11 0.5C16.799 0.5 21.5 5.20101 21.5 11C21.5 16.799 16.799 21.5 11 21.5C5.20101 21.5 0.5 16.799 0.5 11Z" 7 | stroke="#FECDCA" /> 8 | <path d="M14 8L8 14M8 8L14 14" stroke="#F04438" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" /> 9 | </svg> -------------------------------------------------------------------------------- /web/src/assets/svg/disable.svg: -------------------------------------------------------------------------------- 1 | <svg t="1712735718884" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8042" 2 | id="mx_n_1712735718887" width="22" height="22"> 3 | <path 4 | d="M222.634667 272.298667A382.4 382.4 0 0 0 138.666667 512c0 212.117333 171.904 384 384 384 90.666667 0 174.016-31.424 239.701333-83.968l-539.733333-539.733333z m60.330666-60.330667l539.733334 539.733333A382.4 382.4 0 0 0 906.666667 512c0-212.117333-171.904-384-384-384-90.666667 0-174.016 31.424-239.701334 83.968zM53.333333 512c0-259.221333 210.090667-469.333333 469.333334-469.333333 259.221333 0 469.333333 210.090667 469.333333 469.333333 0 259.221333-210.090667 469.333333-469.333333 469.333333-259.221333 0-469.333333-210.090667-469.333334-469.333333z" 5 | fill="#F04438" p-id="8043"></path> 6 | </svg> -------------------------------------------------------------------------------- /web/src/assets/svg/enable.svg: -------------------------------------------------------------------------------- 1 | <svg t="1712735583481" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6804" 2 | width="22" height="22"> 3 | <path 4 | d="M 512 0 a 512 512 0 1 0 0 1024 A 512 512 0 0 0 512 0 z m 0 990.2 A 438.2 438.2 0 1 1 512 33.8 a 438.2 438.2 0 0 1 0 956.4 z" 5 | fill="#abefc6" p-id="6805"></path> 6 | 7 | <path d="M 448.1 584.3 L 322.4 458.6 L 243.5 537.5 l 205.6 205.5 h 0.1 l 0.5 0.5 l 325.9 -325.9 l -80.4 -80.4 z" 8 | fill="#17b26a" p-id="6806"></path> 9 | </svg> -------------------------------------------------------------------------------- /web/src/assets/svg/file-icon/webp.svg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infiniflow/ragflow/f2909ea0c4d0d8739f487bb54851e508b39bee62/web/src/assets/svg/file-icon/webp.svg -------------------------------------------------------------------------------- /web/src/assets/svg/google-scholar.svg: -------------------------------------------------------------------------------- 1 | <svg t="1722910855180" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5111" 2 | width="200" height="200"> 3 | <path d="M512 822.24L0 405.334 512 0z" fill="#4285F4" p-id="5112"></path> 4 | <path d="M512 822.24l512-416.906L512 0z" fill="#356AC3" p-id="5113"></path> 5 | <path d="M512 725.334m-298.666 0a298.666 298.666 0 1 0 597.332 0 298.666 298.666 0 1 0-597.332 0Z" fill="#A0C3FF" 6 | p-id="5114"></path> 7 | <path d="M242.074 597.334c47.936-100.906 150.784-170.668 269.926-170.668s221.99 69.762 269.926 170.668H242.074z" 8 | fill="#76A7FA" p-id="5115"></path> 9 | </svg> -------------------------------------------------------------------------------- /web/src/assets/svg/knowledge-dataset.svg: -------------------------------------------------------------------------------- 1 | <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> 2 | <path 3 | d="M14 11H8M10 15H8M16 7H8M20 6.8V17.2C20 18.8802 20 19.7202 19.673 20.362C19.3854 20.9265 18.9265 21.3854 18.362 21.673C17.7202 22 16.8802 22 15.2 22H8.8C7.11984 22 6.27976 22 5.63803 21.673C5.07354 21.3854 4.6146 20.9265 4.32698 20.362C4 19.7202 4 18.8802 4 17.2V6.8C4 5.11984 4 4.27976 4.32698 3.63803C4.6146 3.07354 5.07354 2.6146 5.63803 2.32698C6.27976 2 7.11984 2 8.8 2H15.2C16.8802 2 17.7202 2 18.362 2.32698C18.9265 2.6146 19.3854 3.07354 19.673 3.63803C20 4.27976 20 5.11984 20 6.8Z" 4 | stroke="#667085" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" /> 5 | </svg> -------------------------------------------------------------------------------- /web/src/assets/svg/llm/anthropic.svg: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1724743631411" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4224" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M710 196.2H572.9l250 631.6H960L710 196.2z m-396 0L64 827.8h139.8l51.1-132.6h261.5l51.1 132.6h139.8l-250-631.6H314z m-13.9 381.7l85.5-222 85.5 222h-171z" p-id="4225"></path></svg> -------------------------------------------------------------------------------- /web/src/assets/svg/llm/azure.svg: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1720424442450" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5104" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M558.848 165.76L269.269333 781.952l-203.477333-2.218667 227.114667-390.869333 265.941333-223.146667m31.232 48.64l368.085333 643.84H277.333333l414.976-74.026666-217.301333-258.346667z" fill="#1E88E5" p-id="5105"></path></svg> -------------------------------------------------------------------------------- /web/src/assets/svg/llm/cohere.svg: -------------------------------------------------------------------------------- 1 | <svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" xml:space="preserve" style="enable-background:new 0 0 75 75" viewBox="0 0 75 75" width="75" height="75" ><path d="M24.3 44.7c2 0 6-.1 11.6-2.4 6.5-2.7 19.3-7.5 28.6-12.5 6.5-3.5 9.3-8.1 9.3-14.3C73.8 7 66.9 0 58.3 0h-36C10 0 0 10 0 22.3s9.4 22.4 24.3 22.4z" style="fill-rule:evenodd;clip-rule:evenodd;fill:#39594d"/><path d="M30.4 60c0-6 3.6-11.5 9.2-13.8l11.3-4.7C62.4 36.8 75 45.2 75 57.6 75 67.2 67.2 75 57.6 75H45.3c-8.2 0-14.9-6.7-14.9-15z" style="fill-rule:evenodd;clip-rule:evenodd;fill:#d18ee2"/><path d="M12.9 47.6C5.8 47.6 0 53.4 0 60.5v1.7C0 69.2 5.8 75 12.9 75c7.1 0 12.9-5.8 12.9-12.9v-1.7c-.1-7-5.8-12.8-12.9-12.8z" style="fill:#ff7759"/></svg> -------------------------------------------------------------------------------- /web/src/assets/svg/llm/modelscope.svg: -------------------------------------------------------------------------------- 1 | <svg id="_层_2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 274.37 172.76"><defs><style>.cls-2{fill:#36cfd1}.cls-3{fill:#624aff}</style></defs><g id="_层_1-2"><path class="cls-3" d="M24.78 73.55h25.65V99.2H24.78zm99.14 25.66h25.65v25.65h-25.65zm76.95 25.65h-25.65v22.19h47.84V99.21h-22.19v25.65z"/><path class="cls-2" d="M149.57 73.55h25.65V99.2h-25.65zM24.78 47.9h25.65v25.65H24.78z"/><path class="cls-3" d="M223.06 73.55h25.65V99.2h-25.65z"/><path class="cls-2" d="M223.06 47.9h25.65v25.65h-25.65z"/><path class="cls-3" d="M175.22 25.71V47.9h25.65v25.65h22.19V25.71h-47.84z"/><path class="cls-2" d="M98.27 73.55h25.65V99.2H98.27z"/><path class="cls-3" d="M72.62 47.9h25.65V25.71H50.43v47.84h22.19V47.9zm0 51.31H50.43v47.84h47.84v-22.19H72.62V99.21z"/><path style="fill:none" d="M0 0h274.37v172.76H0z"/></g></svg> 2 | -------------------------------------------------------------------------------- /web/src/assets/svg/llm/novita-ai.svg: -------------------------------------------------------------------------------- 1 | <svg width="103" height="103" viewBox="0 0 103 103" fill="none" xmlns="http://www.w3.org/2000/svg"> 2 | <path d="M39.9443 20.2672V43.8733L1.74731 82.0703H39.9443V58.4629L63.5528 82.0703H101.747L39.9443 20.2672Z" fill="black"/> 3 | </svg> 4 | -------------------------------------------------------------------------------- /web/src/assets/svg/llm/replicate.svg: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1723795491606" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4258" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M0 0m256 0l512 0q256 0 256 256l0 512q0 256-256 256l-512 0q-256 0-256-256l0-512q0-256 256-256Z" fill="#000000" p-id="4259"></path><path d="M853.162667 170.666667v76.373333H338.602667v602.112H256V170.666667h597.162667zM853.333333 315.52v76.373333h-358.528V849.066667H412.117333V315.52H853.333333z m-0.170666 221.098667v-76.8h-285.226667v389.290666h82.645333v-312.490666h202.581334z" fill="#FFFFFF" p-id="4260"></path></svg> -------------------------------------------------------------------------------- /web/src/assets/svg/llm/siliconflow.svg: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <svg id="_图层_2" data-name="图层 2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 111.08 53.12"> 3 | <defs> 4 | <style> 5 | .cls-1 { 6 | fill: #6e29f5; 7 | } 8 | </style> 9 | </defs> 10 | <g id="_图层_1-2" data-name="图层 1"> 11 | <path class="cls-1" d="M106.25,0h-48.3c-2.67,0-4.83,2.16-4.83,4.83v14.49c0,2.67-2.16,4.83-4.83,4.83H4.83c-2.67,0-4.83,2.16-4.83,4.83v19.32c0,2.67,2.16,4.83,4.83,4.83h48.3c2.67,0,4.83-2.16,4.83-4.83v-14.49c0-2.67,2.16-4.83,4.83-4.83h43.47c2.67,0,4.83-2.16,4.83-4.83V4.83c0-2.67-2.16-4.83-4.83-4.83Z"/> 12 | </g> 13 | </svg> -------------------------------------------------------------------------------- /web/src/assets/svg/login-star.svg: -------------------------------------------------------------------------------- 1 | <svg width="80" height="80" viewBox="0 0 80 80" fill="none" xmlns="http://www.w3.org/2000/svg"> 2 | <path fill-rule="evenodd" clip-rule="evenodd" 3 | d="M0 40C25.4247 40 40 25.4247 40 0C40 25.4247 54.5753 40 80 40C54.5753 40 40 54.5753 40 80C40 54.5753 25.4247 40 0 40Z" 4 | fill="white" /> 5 | <path fill-rule="evenodd" clip-rule="evenodd" 6 | d="M0 12C7.62742 12 12 7.62742 12 0C12 7.62742 16.3726 12 24 12C16.3726 12 12 16.3726 12 24C12 16.3726 7.62742 12 0 12Z" 7 | fill="#FEC84B" /> 8 | <path fill-rule="evenodd" clip-rule="evenodd" 9 | d="M64 24C69.0849 24 72 21.0849 72 16C72 21.0849 74.9151 24 80 24C74.9151 24 72 26.9151 72 32C72 26.9151 69.0849 24 64 24Z" 10 | fill="#FEC84B" /> 11 | </svg> -------------------------------------------------------------------------------- /web/src/assets/svg/logout.svg: -------------------------------------------------------------------------------- 1 | <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> 2 | <path 3 | d="M16 17L21 12M21 12L16 7M21 12H9M9 3H7.8C6.11984 3 5.27976 3 4.63803 3.32698C4.07354 3.6146 3.6146 4.07354 3.32698 4.63803C3 5.27976 3 6.11984 3 7.8V16.2C3 17.8802 3 18.7202 3.32698 19.362C3.6146 19.9265 4.07354 20.3854 4.63803 20.673C5.27976 21 6.11984 21 7.8 21H9" 4 | stroke="#667085" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" /> 5 | </svg> -------------------------------------------------------------------------------- /web/src/assets/svg/moon.svg: -------------------------------------------------------------------------------- 1 | <svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg"> 2 | <path 3 | d="M12.2815 8.68261C12.3175 8.56966 12.2062 8.46792 12.0932 8.50385C11.5907 8.66372 11.0554 8.74999 10.4999 8.74999C7.60042 8.74999 5.24992 6.39948 5.24992 3.49999C5.24992 2.94453 5.33618 2.40922 5.49604 1.90672C5.53198 1.79376 5.43023 1.68247 5.31728 1.71842C3.07937 2.43077 1.45825 4.52608 1.45825 7.00002C1.45825 10.0606 3.93934 12.5417 6.99992 12.5417C9.47388 12.5417 11.5692 10.9205 12.2815 8.68261Z" 4 | fill="#4E5969" /> 5 | </svg> -------------------------------------------------------------------------------- /web/src/assets/svg/paper-clip.svg: -------------------------------------------------------------------------------- 1 | <svg t="1723702162999" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8508" 2 | width="200" height="200"> 3 | <path 4 | d="M780.8 166.4V742.4c0 92.928-56.32 268.8-268.8 268.8S243.2 835.328 243.2 742.4V204.8a230.4 230.4 0 0 1 23.296-93.952A179.2 179.2 0 0 1 435.2 12.8a179.2 179.2 0 0 1 168.704 98.048A228.608 228.608 0 0 1 627.2 204.8v499.2A111.872 111.872 0 0 1 512 819.2a111.872 111.872 0 0 1-115.2-115.2V358.4a38.4 38.4 0 0 1 76.8 0v345.6A35.072 35.072 0 0 0 512 742.4a35.328 35.328 0 0 0 38.4-38.912V204.8A109.568 109.568 0 0 0 435.2 89.6a102.4 102.4 0 0 0-100.096 55.552A158.976 158.976 0 0 0 320 204.8v537.6c0 19.456 6.912 192 192 192 189.952 0 192-184.064 192-192V166.4a38.4 38.4 0 0 1 76.8 0" 5 | fill="#030000" p-id="8509"></path> 6 | </svg> -------------------------------------------------------------------------------- /web/src/assets/svg/password.svg: -------------------------------------------------------------------------------- 1 | <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> 2 | <path 3 | d="M17 10V8C17 5.23858 14.7614 3 12 3C9.23858 3 7 5.23858 7 8V10M12 14.5V16.5M8.8 21H15.2C16.8802 21 17.7202 21 18.362 20.673C18.9265 20.3854 19.3854 19.9265 19.673 19.362C20 18.7202 20 17.8802 20 16.2V14.8C20 13.1198 20 12.2798 19.673 11.638C19.3854 11.0735 18.9265 10.6146 18.362 10.327C17.7202 10 16.8802 10 15.2 10H8.8C7.11984 10 6.27976 10 5.63803 10.327C5.07354 10.6146 4.6146 11.0735 4.32698 11.638C4 12.2798 4 13.1198 4 14.8V16.2C4 17.8802 4 18.7202 4.32698 19.362C4.6146 19.9265 5.07354 20.3854 5.63803 20.673C6.27976 21 7.11984 21 8.8 21Z" 4 | stroke="#667085" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" /> 5 | </svg> -------------------------------------------------------------------------------- /web/src/assets/svg/plus-circle-fill.svg: -------------------------------------------------------------------------------- 1 | <svg t="1727489529326" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4261" 2 | width="200" height="200"> 3 | 4 | <circle cx="512" cy="512" r="400" fill="white" /> 5 | <path 6 | d="M448 448H192v128h256v256h128V576h256V448H576V192H448v256z m64 576A512 512 0 1 1 512 0a512 512 0 0 1 0 1024z" 7 | fill="#1677ff" p-id="4262"></path> 8 | </svg> -------------------------------------------------------------------------------- /web/src/assets/svg/plus.svg: -------------------------------------------------------------------------------- 1 | <svg t="1729507531032" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4259" 2 | width="200" height="200"> 3 | <path d="M474 152m8 0l60 0q8 0 8 8l0 704q0 8-8 8l-60 0q-8 0-8-8l0-704q0-8 8-8Z" fill="#ffffff" p-id="4260"></path> 4 | <path d="M168 474m8 0l672 0q8 0 8 8l0 60q0 8-8 8l-672 0q-8 0-8-8l0-60q0-8 8-8Z" fill="#ffffff" p-id="4261"></path> 5 | </svg> -------------------------------------------------------------------------------- /web/src/assets/svg/profile.svg: -------------------------------------------------------------------------------- 1 | <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> 2 | <path 3 | d="M20 21C20 19.6044 20 18.9067 19.8278 18.3389C19.44 17.0605 18.4395 16.06 17.1611 15.6722C16.5933 15.5 15.8956 15.5 14.5 15.5H9.5C8.10444 15.5 7.40665 15.5 6.83886 15.6722C5.56045 16.06 4.56004 17.0605 4.17224 18.3389C4 18.9067 4 19.6044 4 21M16.5 7.5C16.5 9.98528 14.4853 12 12 12C9.51472 12 7.5 9.98528 7.5 7.5C7.5 5.01472 9.51472 3 12 3C14.4853 3 16.5 5.01472 16.5 7.5Z" 4 | stroke="#667085" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" /> 5 | </svg> -------------------------------------------------------------------------------- /web/src/assets/svg/pubmed.svg: -------------------------------------------------------------------------------- 1 | <svg t="1721281989464" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4310" 2 | width="200" height="200"> 3 | <path d="M128 64h448l192 448-192 448H128a128 128 0 0 1-128-128V192a128 128 0 0 1 128-128z" fill="#205992" 4 | p-id="4311"></path> 5 | <path d="M704 64h128l192 448-192 448h-128l192-448z" fill="#205992" p-id="4312"></path> 6 | </svg> -------------------------------------------------------------------------------- /web/src/assets/svg/refresh.svg: -------------------------------------------------------------------------------- 1 | <svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg"> 2 | <path 3 | d="M14.1667 4.27108C15.9345 5.55903 17.0834 7.6453 17.0834 9.99992C17.0834 13.9119 13.9121 17.0833 10.0001 17.0833H9.58342M5.83341 15.7288C4.06564 14.4408 2.91675 12.3545 2.91675 9.99992C2.91675 6.0879 6.08806 2.91659 10.0001 2.91659H10.4167M10.8334 18.6666L9.16675 16.9999L10.8334 15.3333M9.16675 4.66659L10.8334 2.99992L9.16675 1.33325" 4 | stroke="#17B26A" stroke-width="1.66667" stroke-linecap="round" stroke-linejoin="round" /> 5 | </svg> -------------------------------------------------------------------------------- /web/src/assets/svg/resize.svg: -------------------------------------------------------------------------------- 1 | <svg t="1729759831217" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" 2 | p-id="22909" width="200" height="200"> 3 | <path 4 | d="M319.20128 974.56128L348.16 1003.52l655.36-655.36-28.95872-28.95872-655.36 655.36zM675.84 1003.52l327.68-327.68-28.95872-28.95872-327.68 327.68L675.84 1003.52z" 5 | fill="#000000" p-id="22910"></path> 6 | </svg> -------------------------------------------------------------------------------- /web/src/assets/svg/selected-files-collapse.svg: -------------------------------------------------------------------------------- 1 | <svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg"> 2 | <path 3 | d="M6.66667 10H13.3333M6.5 17.5H13.5C14.9001 17.5 15.6002 17.5 16.135 17.2275C16.6054 16.9878 16.9878 16.6054 17.2275 16.135C17.5 15.6002 17.5 14.9001 17.5 13.5V6.5C17.5 5.09987 17.5 4.3998 17.2275 3.86502C16.9878 3.39462 16.6054 3.01217 16.135 2.77248C15.6002 2.5 14.9001 2.5 13.5 2.5H6.5C5.09987 2.5 4.3998 2.5 3.86502 2.77248C3.39462 3.01217 3.01217 3.39462 2.77248 3.86502C2.5 4.3998 2.5 5.09987 2.5 6.5V13.5C2.5 14.9001 2.5 15.6002 2.77248 16.135C3.01217 16.6054 3.39462 16.9878 3.86502 17.2275C4.3998 17.5 5.09987 17.5 6.5 17.5Z" 4 | stroke="#7F56D9" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" /> 5 | </svg> -------------------------------------------------------------------------------- /web/src/assets/svg/team.svg: -------------------------------------------------------------------------------- 1 | <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> 2 | <path 3 | d="M22 21V19C22 17.1362 20.7252 15.5701 19 15.126M15.5 3.29076C16.9659 3.88415 18 5.32131 18 7C18 8.67869 16.9659 10.1159 15.5 10.7092M17 21C17 19.1362 17 18.2044 16.6955 17.4693C16.2895 16.4892 15.5108 15.7105 14.5307 15.3045C13.7956 15 12.8638 15 11 15H8C6.13623 15 5.20435 15 4.46927 15.3045C3.48915 15.7105 2.71046 16.4892 2.30448 17.4693C2 18.2044 2 19.1362 2 21M13.5 7C13.5 9.20914 11.7091 11 9.5 11C7.29086 11 5.5 9.20914 5.5 7C5.5 4.79086 7.29086 3 9.5 3C11.7091 3 13.5 4.79086 13.5 7Z" 4 | stroke="#667085" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" /> 5 | </svg> -------------------------------------------------------------------------------- /web/src/assets/yay.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infiniflow/ragflow/f2909ea0c4d0d8739f487bb54851e508b39bee62/web/src/assets/yay.jpg -------------------------------------------------------------------------------- /web/src/components/api-service/chat-overview-modal/index.less: -------------------------------------------------------------------------------- 1 | .chartWrapper { 2 | height: 40vh; 3 | overflow: auto; 4 | } 5 | 6 | .chartItem { 7 | height: 300px; 8 | padding: 10px 0 50px; 9 | } 10 | 11 | .chartLabel { 12 | display: inline-block; 13 | padding-left: 60px; 14 | padding-bottom: 20px; 15 | } 16 | .apiLinkText { 17 | .linkText(); 18 | margin: 0 !important; 19 | background-color: rgba(255, 255, 255, 0.1); 20 | } 21 | -------------------------------------------------------------------------------- /web/src/components/api-service/embed-modal/index.less: -------------------------------------------------------------------------------- 1 | .codeCard { 2 | .clearCardBody(); 3 | } 4 | 5 | .codeText { 6 | padding: 10px; 7 | background-color: #ffffff09; 8 | } 9 | 10 | .id { 11 | .linkText(); 12 | } 13 | 14 | .darkBg { 15 | background-color: rgb(69, 68, 68); 16 | } 17 | 18 | .darkId { 19 | color: white; 20 | .darkBg(); 21 | } 22 | -------------------------------------------------------------------------------- /web/src/components/chunk-method-modal/index.less: -------------------------------------------------------------------------------- 1 | .pageInputNumber { 2 | width: 220px; 3 | } 4 | 5 | .questionIcon { 6 | margin-inline-start: 4px; 7 | color: rgba(0, 0, 0, 0.45); 8 | cursor: help; 9 | writing-mode: horizontal-tb; 10 | } 11 | 12 | .chunkMethod { 13 | margin-bottom: 0; 14 | } 15 | -------------------------------------------------------------------------------- /web/src/components/dataset-configuration-container.tsx: -------------------------------------------------------------------------------- 1 | import { cn } from '@/lib/utils'; 2 | import { PropsWithChildren } from 'react'; 3 | 4 | type DatasetConfigurationContainerProps = { 5 | className?: string; 6 | show?: boolean; 7 | } & PropsWithChildren; 8 | 9 | export function DatasetConfigurationContainer({ 10 | children, 11 | className, 12 | show = true, 13 | }: DatasetConfigurationContainerProps) { 14 | return show ? ( 15 | <div 16 | className={cn( 17 | 'border p-2 rounded-lg bg-slate-50 dark:bg-gray-600', 18 | className, 19 | )} 20 | > 21 | {children} 22 | </div> 23 | ) : ( 24 | children 25 | ); 26 | } 27 | -------------------------------------------------------------------------------- /web/src/components/entity-types-item.tsx: -------------------------------------------------------------------------------- 1 | import { useTranslate } from '@/hooks/common-hooks'; 2 | import { Form } from 'antd'; 3 | import EditTag from './edit-tag'; 4 | 5 | const initialEntityTypes = [ 6 | 'organization', 7 | 'person', 8 | 'geo', 9 | 'event', 10 | 'category', 11 | ]; 12 | 13 | type IProps = { 14 | field?: string[]; 15 | }; 16 | 17 | const EntityTypesItem = ({ 18 | field = ['parser_config', 'entity_types'], 19 | }: IProps) => { 20 | const { t } = useTranslate('knowledgeConfiguration'); 21 | return ( 22 | <Form.Item 23 | name={field} 24 | label={t('entityTypes')} 25 | rules={[{ required: true }]} 26 | initialValue={initialEntityTypes} 27 | > 28 | <EditTag value={field}></EditTag> 29 | </Form.Item> 30 | ); 31 | }; 32 | 33 | export default EntityTypesItem; 34 | -------------------------------------------------------------------------------- /web/src/components/excel-to-html.tsx: -------------------------------------------------------------------------------- 1 | import { useTranslate } from '@/hooks/common-hooks'; 2 | import { Form, Switch } from 'antd'; 3 | 4 | const ExcelToHtml = () => { 5 | const { t } = useTranslate('knowledgeDetails'); 6 | return ( 7 | <Form.Item 8 | name={['parser_config', 'html4excel']} 9 | label={t('html4excel')} 10 | initialValue={false} 11 | valuePropName="checked" 12 | tooltip={t('html4excelTip')} 13 | > 14 | <Switch /> 15 | </Form.Item> 16 | ); 17 | }; 18 | 19 | export default ExcelToHtml; 20 | -------------------------------------------------------------------------------- /web/src/components/file-icon/index.less: -------------------------------------------------------------------------------- 1 | .thumbnailImg { 2 | display: inline-block; 3 | max-width: 20px; 4 | } 5 | -------------------------------------------------------------------------------- /web/src/components/file-upload-modal/index.less: -------------------------------------------------------------------------------- 1 | .uploader { 2 | :global { 3 | .ant-upload-list { 4 | max-height: 40vh; 5 | overflow-y: auto; 6 | } 7 | } 8 | } 9 | 10 | .uploadLimit { 11 | color: red; 12 | font-size: 12px; 13 | } 14 | -------------------------------------------------------------------------------- /web/src/components/form-container.tsx: -------------------------------------------------------------------------------- 1 | import { cn } from '@/lib/utils'; 2 | import { PropsWithChildren } from 'react'; 3 | 4 | export type FormContainerProps = { 5 | className?: string; 6 | show?: boolean; 7 | } & PropsWithChildren; 8 | 9 | export function FormContainer({ 10 | children, 11 | show = true, 12 | className, 13 | }: FormContainerProps) { 14 | return show ? ( 15 | <section className={cn('border rounded-lg p-5 space-y-5', className)}> 16 | {children} 17 | </section> 18 | ) : ( 19 | children 20 | ); 21 | } 22 | -------------------------------------------------------------------------------- /web/src/components/highlight-markdown/index.less: -------------------------------------------------------------------------------- 1 | .text { 2 | .chunkText; 3 | font-size: 16px; 4 | li { 5 | padding: 4px 0px; 6 | } 7 | // p { 8 | // white-space: pre-wrap; // https://stackoverflow.com/questions/60332183/new-line-with-react-markdown 9 | // } 10 | } 11 | 12 | .code { 13 | padding: 3px 6px 6px; 14 | margin: 0; 15 | white-space: break-spaces; 16 | background-color: rgba(129, 139, 152, 0.12); 17 | border-radius: 4px; 18 | color: var(--ant-color-text-base); 19 | } 20 | -------------------------------------------------------------------------------- /web/src/components/hooks/use-mobile.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | const MOBILE_BREAKPOINT = 768; 4 | 5 | export function useIsMobile() { 6 | const [isMobile, setIsMobile] = React.useState<boolean | undefined>( 7 | undefined, 8 | ); 9 | 10 | React.useEffect(() => { 11 | const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`); 12 | const onChange = () => { 13 | setIsMobile(window.innerWidth < MOBILE_BREAKPOINT); 14 | }; 15 | mql.addEventListener('change', onChange); 16 | setIsMobile(window.innerWidth < MOBILE_BREAKPOINT); 17 | return () => mql.removeEventListener('change', onChange); 18 | }, []); 19 | 20 | return !!isMobile; 21 | } 22 | -------------------------------------------------------------------------------- /web/src/components/icon-font.tsx: -------------------------------------------------------------------------------- 1 | import { FileIconMap } from '@/constants/file'; 2 | import { cn } from '@/lib/utils'; 3 | import { getExtension } from '@/utils/document-util'; 4 | 5 | type IconFontType = { 6 | name: string; 7 | className?: string; 8 | }; 9 | 10 | export const IconFont = ({ name, className }: IconFontType) => ( 11 | <svg className={cn('fill-current size-4', className)}> 12 | <use xlinkHref={`#icon-${name}`} /> 13 | </svg> 14 | ); 15 | 16 | export function FileIcon({ 17 | name, 18 | className, 19 | type, 20 | }: IconFontType & { type?: string }) { 21 | const isFolder = type === 'folder'; 22 | return ( 23 | <span className={cn('size-4', className)}> 24 | <IconFont 25 | name={isFolder ? 'file-sub' : FileIconMap[getExtension(name)]} 26 | ></IconFont> 27 | </span> 28 | ); 29 | } 30 | -------------------------------------------------------------------------------- /web/src/components/list-filter-bar/interface.ts: -------------------------------------------------------------------------------- 1 | export type FilterType = { 2 | id: string; 3 | label: string; 4 | count: number; 5 | }; 6 | 7 | export type FilterCollection = { 8 | field: string; 9 | label: string; 10 | list: FilterType[]; 11 | }; 12 | 13 | export type FilterValue = Record<string, Array<string>>; 14 | 15 | export type FilterChange = (value: FilterValue) => void; 16 | -------------------------------------------------------------------------------- /web/src/components/list-filter-bar/use-handle-filter-submit.ts: -------------------------------------------------------------------------------- 1 | import { useGetPaginationWithRouter } from '@/hooks/logic-hooks'; 2 | import { useCallback, useState } from 'react'; 3 | import { FilterChange, FilterValue } from './interface'; 4 | 5 | export function useHandleFilterSubmit() { 6 | const [filterValue, setFilterValue] = useState<FilterValue>({}); 7 | const { setPagination } = useGetPaginationWithRouter(); 8 | const handleFilterSubmit: FilterChange = useCallback( 9 | (value) => { 10 | setFilterValue(value); 11 | setPagination({ page: 1 }); 12 | }, 13 | [setPagination], 14 | ); 15 | 16 | return { filterValue, setFilterValue, handleFilterSubmit }; 17 | } 18 | -------------------------------------------------------------------------------- /web/src/components/llm-select/index.less: -------------------------------------------------------------------------------- 1 | .llmLabel { 2 | font-size: 14px; 3 | } 4 | -------------------------------------------------------------------------------- /web/src/components/llm-select/llm-label.tsx: -------------------------------------------------------------------------------- 1 | import { getLLMIconName, getLlmNameAndFIdByLlmId } from '@/utils/llm-util'; 2 | import { memo } from 'react'; 3 | import { LlmIcon } from '../svg-icon'; 4 | 5 | interface IProps { 6 | id?: string; 7 | value?: string; 8 | onChange?: (value: string) => void; 9 | disabled?: boolean; 10 | } 11 | 12 | const LLMLabel = ({ value }: IProps) => { 13 | const { llmName, fId } = getLlmNameAndFIdByLlmId(value); 14 | 15 | return ( 16 | <div className="flex items-center gap-1"> 17 | <LlmIcon 18 | name={getLLMIconName(fId, llmName)} 19 | width={20} 20 | height={20} 21 | size={'small'} 22 | /> 23 | {llmName} 24 | </div> 25 | ); 26 | }; 27 | 28 | export default memo(LLMLabel); 29 | -------------------------------------------------------------------------------- /web/src/components/llm-setting-items/index.less: -------------------------------------------------------------------------------- 1 | .sliderInputNumber { 2 | width: 80px; 3 | } 4 | .variableSlider { 5 | width: 100%; 6 | } 7 | -------------------------------------------------------------------------------- /web/src/components/max-token-number-from-field.tsx: -------------------------------------------------------------------------------- 1 | import { FormLayout } from '@/constants/form'; 2 | import { useTranslate } from '@/hooks/common-hooks'; 3 | import { SliderInputFormField } from './slider-input-form-field'; 4 | 5 | interface IProps { 6 | initialValue?: number; 7 | max?: number; 8 | } 9 | 10 | export function MaxTokenNumberFormField({ max = 2048, initialValue }: IProps) { 11 | const { t } = useTranslate('knowledgeConfiguration'); 12 | 13 | return ( 14 | <SliderInputFormField 15 | name={'parser_config.chunk_token_num'} 16 | label={t('chunkTokenNumber')} 17 | max={max} 18 | defaultValue={initialValue ?? 0} 19 | layout={FormLayout.Horizontal} 20 | ></SliderInputFormField> 21 | ); 22 | } 23 | -------------------------------------------------------------------------------- /web/src/components/message-input/index.less: -------------------------------------------------------------------------------- 1 | .messageInputWrapper { 2 | margin-right: 20px; 3 | padding: '0px 0px 10px 0px'; 4 | border: 1px solid #d9d9d9; 5 | &:hover { 6 | border-color: #40a9ff; 7 | box-shadow: #40a9ff; 8 | } 9 | border-radius: 8px; 10 | :global(.ant-input-affix-wrapper) { 11 | border-bottom-right-radius: 0; 12 | border-bottom-left-radius: 0; 13 | } 14 | } 15 | 16 | .documentCard { 17 | :global(.ant-card-body) { 18 | padding: 10px; 19 | position: relative; 20 | width: 100%; 21 | } 22 | } 23 | .listWrapper { 24 | padding: 0 10px; 25 | overflow: auto; 26 | max-height: 170px; 27 | width: 100%; 28 | } 29 | .inputWrapper { 30 | border-radius: 8px; 31 | } 32 | .deleteIcon { 33 | position: absolute; 34 | right: -4px; 35 | top: -4px; 36 | color: #d92d20; 37 | } 38 | -------------------------------------------------------------------------------- /web/src/components/modal-manager.tsx: -------------------------------------------------------------------------------- 1 | import { useState } from 'react'; 2 | 3 | export interface IModalManagerChildrenProps { 4 | showModal(): void; 5 | hideModal(): void; 6 | visible: boolean; 7 | } 8 | interface IProps { 9 | children: (props: IModalManagerChildrenProps) => React.ReactNode; 10 | } 11 | 12 | const ModalManager = ({ children }: IProps) => { 13 | const [visible, setVisible] = useState(false); 14 | 15 | const showModal = () => { 16 | setVisible(true); 17 | }; 18 | const hideModal = () => { 19 | setVisible(false); 20 | }; 21 | 22 | return children({ visible, showModal, hideModal }); 23 | }; 24 | 25 | export default ModalManager; 26 | -------------------------------------------------------------------------------- /web/src/components/more-button.tsx: -------------------------------------------------------------------------------- 1 | import { cn } from '@/lib/utils'; 2 | import { Ellipsis } from 'lucide-react'; 3 | import React from 'react'; 4 | import { Button, ButtonProps } from './ui/button'; 5 | 6 | export const MoreButton = React.forwardRef<HTMLButtonElement, ButtonProps>( 7 | ({ className, size, ...props }, ref) => { 8 | return ( 9 | <Button 10 | ref={ref} 11 | variant="ghost" 12 | size={size || 'icon'} 13 | className={cn('invisible group-hover:visible size-3.5', className)} 14 | {...props} 15 | > 16 | <Ellipsis /> 17 | </Button> 18 | ); 19 | }, 20 | ); 21 | -------------------------------------------------------------------------------- /web/src/components/operate-dropdown/index.less: -------------------------------------------------------------------------------- 1 | .delete { 2 | // height: 24px; 3 | display: inline-block; 4 | } 5 | -------------------------------------------------------------------------------- /web/src/components/page-rank-form-field.tsx: -------------------------------------------------------------------------------- 1 | import { FormLayout } from '@/constants/form'; 2 | import { useTranslate } from '@/hooks/common-hooks'; 3 | import { SliderInputFormField } from './slider-input-form-field'; 4 | 5 | export function PageRankFormField() { 6 | const { t } = useTranslate('knowledgeConfiguration'); 7 | 8 | return ( 9 | <SliderInputFormField 10 | name={'pagerank'} 11 | label={t('pageRank')} 12 | tooltip={t('pageRankTip')} 13 | defaultValue={0} 14 | max={100} 15 | min={0} 16 | layout={FormLayout.Horizontal} 17 | ></SliderInputFormField> 18 | ); 19 | } 20 | 21 | export default PageRankFormField; 22 | -------------------------------------------------------------------------------- /web/src/components/pdf-previewer/hooks.ts: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | import { useCallback, useEffect, useState } from 'react'; 3 | 4 | export const useCatchDocumentError = (url: string) => { 5 | const [error, setError] = useState<string>(''); 6 | 7 | const fetchDocument = useCallback(async () => { 8 | const { data } = await axios.get(url); 9 | if (data.code !== 0) { 10 | setError(data?.message); 11 | } 12 | }, [url]); 13 | useEffect(() => { 14 | fetchDocument(); 15 | }, [fetchDocument]); 16 | 17 | return error; 18 | }; 19 | -------------------------------------------------------------------------------- /web/src/components/pdf-previewer/index.less: -------------------------------------------------------------------------------- 1 | .documentContainer { 2 | width: 100%; 3 | height: 100%; 4 | position: relative; 5 | :global(.PdfHighlighter) { 6 | overflow-x: hidden; 7 | } 8 | :global(.Highlight--scrolledTo .Highlight__part) { 9 | overflow-x: hidden; 10 | background-color: rgba(255, 226, 143, 1); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /web/src/components/prompt-editor/constant.ts: -------------------------------------------------------------------------------- 1 | export const ProgrammaticTag = 'programmatic'; 2 | -------------------------------------------------------------------------------- /web/src/components/retrieval-documents/index.less: -------------------------------------------------------------------------------- 1 | .selectFilesCollapse { 2 | :global(.ant-collapse-header) { 3 | padding-left: 22px; 4 | } 5 | margin-bottom: 32px; 6 | overflow-y: auto; 7 | } 8 | 9 | .selectFilesTitle { 10 | padding-right: 10px; 11 | } 12 | -------------------------------------------------------------------------------- /web/src/components/skeleton-card.tsx: -------------------------------------------------------------------------------- 1 | import { Skeleton } from '@/components/ui/skeleton'; 2 | 3 | export function SkeletonCard() { 4 | return ( 5 | <div className="flex flex-col space-y-3 items-center"> 6 | <Skeleton className="h-[125px] w-[250px] rounded-xl" /> 7 | <div className="space-y-2 w-[250px]"> 8 | <Skeleton className="h-4 w-[250px]" /> 9 | <Skeleton className="h-4 w-[200px]" /> 10 | </div> 11 | </div> 12 | ); 13 | } 14 | -------------------------------------------------------------------------------- /web/src/components/ui/aspect-ratio.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import * as AspectRatioPrimitive from '@radix-ui/react-aspect-ratio'; 4 | 5 | const AspectRatio = AspectRatioPrimitive.Root; 6 | 7 | export { AspectRatio }; 8 | -------------------------------------------------------------------------------- /web/src/components/ui/collapsible.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import * as CollapsiblePrimitive from '@radix-ui/react-collapsible'; 4 | 5 | const Collapsible = CollapsiblePrimitive.Root; 6 | 7 | const CollapsibleTrigger = CollapsiblePrimitive.CollapsibleTrigger; 8 | 9 | const CollapsibleContent = CollapsiblePrimitive.CollapsibleContent; 10 | 11 | export { Collapsible, CollapsibleContent, CollapsibleTrigger }; 12 | -------------------------------------------------------------------------------- /web/src/components/ui/container.tsx: -------------------------------------------------------------------------------- 1 | import { cn } from '@/lib/utils'; 2 | 3 | export function Container({ 4 | children, 5 | className, 6 | ...props 7 | }: React.PropsWithChildren<React.HTMLAttributes<HTMLDivElement>>) { 8 | return ( 9 | <div 10 | className={cn( 11 | 'px-2 py-1 bg-colors-background-inverse-standard inline-flex items-center rounded-sm gap-2', 12 | className, 13 | )} 14 | {...props} 15 | > 16 | {children} 17 | </div> 18 | ); 19 | } 20 | -------------------------------------------------------------------------------- /web/src/components/ui/message.ts: -------------------------------------------------------------------------------- 1 | import { toast } from 'sonner'; 2 | 3 | const message = { 4 | success: (msg: string) => { 5 | toast.success(msg, { 6 | position: 'top-center', 7 | closeButton: false, 8 | }); 9 | }, 10 | error: (msg: string) => { 11 | toast.error(msg, { 12 | position: 'top-center', 13 | closeButton: false, 14 | }); 15 | }, 16 | warning: (msg: string) => { 17 | toast.warning(msg, { 18 | position: 'top-center', 19 | closeButton: false, 20 | }); 21 | }, 22 | info: (msg: string) => { 23 | toast.info(msg, { 24 | position: 'top-center', 25 | closeButton: false, 26 | }); 27 | }, 28 | }; 29 | export default message; 30 | -------------------------------------------------------------------------------- /web/src/components/xyflow/base-node.tsx: -------------------------------------------------------------------------------- 1 | import { forwardRef, HTMLAttributes } from 'react'; 2 | 3 | import { cn } from '@/lib/utils'; 4 | 5 | export const BaseNode = forwardRef< 6 | HTMLDivElement, 7 | HTMLAttributes<HTMLDivElement> & { selected?: boolean } 8 | >(({ className, selected, ...props }, ref) => ( 9 | <div 10 | ref={ref} 11 | className={cn( 12 | 'relative rounded-md bg-card text-card-foreground', 13 | className, 14 | selected ? 'border-muted-foreground shadow-lg' : '', 15 | 'hover:ring-1', 16 | )} 17 | tabIndex={0} 18 | {...props} 19 | /> 20 | )); 21 | 22 | BaseNode.displayName = 'BaseNode'; 23 | -------------------------------------------------------------------------------- /web/src/conf.json: -------------------------------------------------------------------------------- 1 | { 2 | "appName": "RAGFlow" 3 | } 4 | -------------------------------------------------------------------------------- /web/src/constants/authorization.ts: -------------------------------------------------------------------------------- 1 | export const Authorization = 'Authorization'; 2 | export const Token = 'token'; 3 | export const UserInfo = 'userInfo'; 4 | -------------------------------------------------------------------------------- /web/src/constants/file.ts: -------------------------------------------------------------------------------- 1 | export const FileIconMap = { 2 | doc: 'doc', 3 | docx: 'doc', 4 | pdf: 'pdf', 5 | xls: 'excel', 6 | xlsx: 'excel', 7 | ppt: 'ppt', 8 | pptx: 'ppt', 9 | jpg: 'jpg', 10 | jpeg: 'jpg', 11 | png: 'png', 12 | txt: 'text', 13 | csv: 'pdf', 14 | md: 'md', 15 | }; 16 | -------------------------------------------------------------------------------- /web/src/constants/form.ts: -------------------------------------------------------------------------------- 1 | export enum FormLayout { 2 | Horizontal = 'horizontal', 3 | Vertical = 'vertical', 4 | Inline = 'inline', 5 | } 6 | -------------------------------------------------------------------------------- /web/src/custom.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.md' { 2 | const content: string; 3 | export default content; 4 | } 5 | -------------------------------------------------------------------------------- /web/src/hooks/plugin-hooks.tsx: -------------------------------------------------------------------------------- 1 | import { ILLMTools } from '@/interfaces/database/plugin'; 2 | import pluginService from '@/services/plugin-service'; 3 | import { useQuery } from '@tanstack/react-query'; 4 | 5 | export const useLlmToolsList = (): ILLMTools => { 6 | const { data } = useQuery({ 7 | queryKey: ['llmTools'], 8 | initialData: [], 9 | queryFn: async () => { 10 | const { data } = await pluginService.getLlmTools(); 11 | 12 | return data?.data ?? []; 13 | }, 14 | }); 15 | 16 | return data; 17 | }; 18 | -------------------------------------------------------------------------------- /web/src/hooks/system-hooks.ts: -------------------------------------------------------------------------------- 1 | import userService from '@/services/user-service'; 2 | import { useQuery } from '@tanstack/react-query'; 3 | 4 | /** 5 | * Hook to fetch system configuration including register enable status 6 | * @returns System configuration with loading status 7 | */ 8 | export const useSystemConfig = () => { 9 | const { data, isLoading } = useQuery({ 10 | queryKey: ['systemConfig'], 11 | queryFn: async () => { 12 | const { data = {} } = await userService.getSystemConfig(); 13 | return data.data || { registerEnabled: 1 }; // Default to enabling registration 14 | }, 15 | }); 16 | 17 | return { config: data, loading: isLoading }; 18 | }; 19 | -------------------------------------------------------------------------------- /web/src/interfaces/common.ts: -------------------------------------------------------------------------------- 1 | export interface Pagination { 2 | current: number; 3 | pageSize: number; 4 | total: number; 5 | } 6 | 7 | export interface BaseState { 8 | pagination: Pagination; 9 | searchString: string; 10 | } 11 | 12 | export interface IModalProps<T> { 13 | showModal?(): void; 14 | hideModal?(): void; 15 | switchVisible?(visible: boolean): void; 16 | visible?: boolean; 17 | loading?: boolean; 18 | onOk?(payload?: T): Promise<any> | void; 19 | } 20 | -------------------------------------------------------------------------------- /web/src/interfaces/database/base.ts: -------------------------------------------------------------------------------- 1 | export interface ResponseType<T = any> { 2 | code: number; 3 | data: T; 4 | message: string; 5 | status: number; 6 | } 7 | 8 | export interface ResponseGetType<T = any> { 9 | data: T; 10 | loading?: boolean; 11 | } 12 | 13 | export interface ResponsePostType<T = any> { 14 | data: T; 15 | loading?: boolean; 16 | [key: string]: unknown; 17 | } 18 | -------------------------------------------------------------------------------- /web/src/interfaces/database/mcp-server.ts: -------------------------------------------------------------------------------- 1 | export enum McpServerType { 2 | Sse = 'sse', 3 | StreamableHttp = 'streamable-http', 4 | } 5 | 6 | export interface IMcpServerVariable { 7 | key: string; 8 | name: string; 9 | } 10 | 11 | export interface IMcpServerInfo { 12 | id: string; 13 | name: string; 14 | url: string; 15 | server_type: McpServerType; 16 | description?: string; 17 | variables?: IMcpServerVariable[]; 18 | headers: Map<string, string>; 19 | } 20 | -------------------------------------------------------------------------------- /web/src/interfaces/database/plugin.ts: -------------------------------------------------------------------------------- 1 | export type ILLMTools = ILLMToolMetadata[]; 2 | 3 | export interface ILLMToolMetadata { 4 | name: string; 5 | displayName: string; 6 | displayDescription: string; 7 | parameters: Map<string, ILLMToolParameter>; 8 | } 9 | 10 | export interface ILLMToolParameter { 11 | type: string; 12 | displayDescription: string; 13 | } 14 | -------------------------------------------------------------------------------- /web/src/interfaces/database/system.ts: -------------------------------------------------------------------------------- 1 | export interface ILangfuseConfig { 2 | secret_key: string; 3 | public_key: string; 4 | host: string; 5 | project_id: string; 6 | project_name: string; 7 | } 8 | -------------------------------------------------------------------------------- /web/src/interfaces/request/base.ts: -------------------------------------------------------------------------------- 1 | export interface IPaginationRequestBody { 2 | keywords?: string; 3 | page?: number; 4 | page_size?: number; // name|create|doc_num|create_time|update_time, default:create_time 5 | orderby?: string; 6 | desc?: string; 7 | } 8 | -------------------------------------------------------------------------------- /web/src/interfaces/request/chat.ts: -------------------------------------------------------------------------------- 1 | export interface IFeedbackRequestBody { 2 | messageId?: string; 3 | thumbup?: boolean; 4 | feedback?: string; 5 | } 6 | 7 | export interface IAskRequestBody { 8 | question: string; 9 | kb_ids: string[]; 10 | } 11 | -------------------------------------------------------------------------------- /web/src/interfaces/request/document.ts: -------------------------------------------------------------------------------- 1 | export interface IChangeParserConfigRequestBody { 2 | pages: number[][]; 3 | chunk_token_num: number; 4 | layout_recognize: boolean; 5 | task_page_size: number; 6 | } 7 | 8 | export interface IChangeParserRequestBody { 9 | parser_id: string; 10 | doc_id: string; 11 | parser_config: IChangeParserConfigRequestBody; 12 | } 13 | 14 | export interface IDocumentMetaRequestBody { 15 | documentId: string; 16 | meta: string; // json format string 17 | } 18 | -------------------------------------------------------------------------------- /web/src/interfaces/request/file-manager.ts: -------------------------------------------------------------------------------- 1 | import { IPaginationRequestBody } from './base'; 2 | 3 | export interface IFileListRequestBody extends IPaginationRequestBody { 4 | parent_id?: string; // folder id 5 | } 6 | 7 | interface BaseRequestBody { 8 | parentId: string; 9 | } 10 | 11 | export interface IConnectRequestBody { 12 | fileIds: string[]; 13 | kbIds: string[]; 14 | } 15 | -------------------------------------------------------------------------------- /web/src/interfaces/request/flow.ts: -------------------------------------------------------------------------------- 1 | export interface IDebugSingleRequestBody { 2 | component_id: string; 3 | params: any[]; 4 | } 5 | -------------------------------------------------------------------------------- /web/src/interfaces/request/knowledge.ts: -------------------------------------------------------------------------------- 1 | export interface ITestRetrievalRequestBody { 2 | question: string; 3 | similarity_threshold: number; 4 | keywords_similarity_weight: number; 5 | rerank_id?: string; 6 | top_k?: number; 7 | use_kg?: boolean; 8 | highlight?: boolean; 9 | kb_id?: string[]; 10 | } 11 | 12 | export interface IFetchKnowledgeListRequestBody { 13 | owner_ids?: string[]; 14 | } 15 | 16 | export interface IFetchKnowledgeListRequestParams { 17 | kb_id?: string; 18 | keywords?: string; 19 | page?: number; 20 | page_size?: number; 21 | } 22 | 23 | export interface IFetchDocumentListRequestBody { 24 | suffix?: string[]; 25 | run_status?: string[]; 26 | } 27 | -------------------------------------------------------------------------------- /web/src/interfaces/request/llm.ts: -------------------------------------------------------------------------------- 1 | export interface IAddLlmRequestBody { 2 | llm_factory: string; // Ollama 3 | llm_name: string; 4 | model_type: string; 5 | api_base?: string; // chat|embedding|speech2text|image2text 6 | api_key: string; 7 | max_tokens: number; 8 | } 9 | 10 | export interface IDeleteLlmRequestBody { 11 | llm_factory: string; // Ollama 12 | llm_name?: string; 13 | } 14 | -------------------------------------------------------------------------------- /web/src/interfaces/request/mcp.ts: -------------------------------------------------------------------------------- 1 | import { IExportedMcpServer } from '@/interfaces/database/mcp'; 2 | 3 | export interface ITestMcpRequestBody { 4 | server_type: string; 5 | url: string; 6 | headers?: Record<string, any>; 7 | variables?: Record<string, any>; 8 | timeout?: number; 9 | } 10 | 11 | export interface IImportMcpServersRequestBody { 12 | mcpServers: Record< 13 | string, 14 | Pick<IExportedMcpServer, 'type' | 'url' | 'authorization_token'> 15 | >; 16 | } 17 | -------------------------------------------------------------------------------- /web/src/interfaces/request/system.ts: -------------------------------------------------------------------------------- 1 | export interface ISetLangfuseConfigRequestBody { 2 | secret_key: string; 3 | public_key: string; 4 | host: string; 5 | } 6 | -------------------------------------------------------------------------------- /web/src/layouts/components/right-toolbar/index.less: -------------------------------------------------------------------------------- 1 | .toolbarWrapper { 2 | :global(.ant-avatar) { 3 | background-color: rgba(242, 243, 245, 1); 4 | } 5 | } 6 | 7 | .circle { 8 | display: inline-block; 9 | line-height: 32px; 10 | width: 32px; 11 | text-align: center; 12 | height: 32px; 13 | border-radius: 50%; 14 | background-color: rgba(242, 243, 245, 0.4); 15 | vertical-align: middle; 16 | cursor: pointer; 17 | display: flex; 18 | flex-direction: column; 19 | justify-content: center; 20 | align-items: center; 21 | } 22 | 23 | .language { 24 | cursor: pointer; 25 | } 26 | -------------------------------------------------------------------------------- /web/src/layouts/components/user/index.tsx: -------------------------------------------------------------------------------- 1 | import { useFetchUserInfo } from '@/hooks/user-setting-hooks'; 2 | import { Avatar } from 'antd'; 3 | import React from 'react'; 4 | import { history } from 'umi'; 5 | 6 | import styles from '../../index.less'; 7 | 8 | const App: React.FC = () => { 9 | const { data: userInfo } = useFetchUserInfo(); 10 | 11 | const toSetting = () => { 12 | history.push('/user-setting'); 13 | }; 14 | 15 | return ( 16 | <Avatar 17 | size={32} 18 | onClick={toSetting} 19 | className={styles.clickAvailable} 20 | src={ 21 | userInfo.avatar ?? 22 | 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png' 23 | } 24 | /> 25 | ); 26 | }; 27 | 28 | export default App; 29 | -------------------------------------------------------------------------------- /web/src/layouts/index.less: -------------------------------------------------------------------------------- 1 | .navs { 2 | ul { 3 | padding: 0; 4 | list-style: none; 5 | display: flex; 6 | } 7 | 8 | li { 9 | margin-right: 1em; 10 | } 11 | } 12 | 13 | .layout { 14 | height: 100vh; 15 | } 16 | 17 | body { 18 | margin: 0; 19 | } 20 | 21 | .divider { 22 | margin: 0; 23 | } 24 | 25 | .clickAvailable { 26 | cursor: pointer; 27 | } 28 | -------------------------------------------------------------------------------- /web/src/layouts/next.tsx: -------------------------------------------------------------------------------- 1 | import { Outlet } from 'umi'; 2 | import { Header } from './next-header'; 3 | 4 | export default function NextLayout() { 5 | return ( 6 | <section className="h-full flex flex-col text-colors-text-neutral-strong"> 7 | <Header></Header> 8 | <Outlet /> 9 | </section> 10 | ); 11 | } 12 | -------------------------------------------------------------------------------- /web/src/less/index.less: -------------------------------------------------------------------------------- 1 | @import './variable.less'; 2 | @import './mixins.less'; 3 | -------------------------------------------------------------------------------- /web/src/less/variable.less: -------------------------------------------------------------------------------- 1 | @fontWeight600: 600; 2 | @fontWeight700: 700; 3 | 4 | @grayBackground: rgba(247, 248, 250, 0.1); 5 | @gray2: rgba(29, 25, 41, 1); 6 | @gray3: rgba(52, 48, 62, 1); 7 | @gray8: rgba(165, 163, 169, 1); 8 | @gray11: rgba(232, 232, 234, 1); 9 | @purple: rgba(127, 86, 217, 1); 10 | @selectedBackgroundColor: rgba(239, 248, 255, 1); 11 | @blurBackground: rgba(22, 119, 255, 0.5); 12 | @blurBackgroundHover: rgba(22, 119, 255, 0.2); 13 | 14 | @fontSize12: 12px; 15 | @fontSize14: 14px; 16 | @fontSize16: 16px; 17 | @fontSize18: 18px; 18 | -------------------------------------------------------------------------------- /web/src/lib/utils.ts: -------------------------------------------------------------------------------- 1 | import { clsx, type ClassValue } from 'clsx'; 2 | import { twMerge } from 'tailwind-merge'; 3 | 4 | export function cn(...inputs: ClassValue[]) { 5 | return twMerge(clsx(inputs)); 6 | } 7 | 8 | export function formatBytes( 9 | bytes: number, 10 | opts: { 11 | decimals?: number; 12 | sizeType?: 'accurate' | 'normal'; 13 | } = {}, 14 | ) { 15 | const { decimals = 0, sizeType = 'normal' } = opts; 16 | 17 | const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB']; 18 | const accurateSizes = ['Bytes', 'KiB', 'MiB', 'GiB', 'TiB']; 19 | if (bytes === 0) return '0 Byte'; 20 | const i = Math.floor(Math.log(bytes) / Math.log(1024)); 21 | return `${(bytes / Math.pow(1024, i)).toFixed(decimals)} ${ 22 | sizeType === 'accurate' ? accurateSizes[i] ?? 'Bytes' : sizes[i] ?? 'Bytes' 23 | }`; 24 | } 25 | -------------------------------------------------------------------------------- /web/src/pages/404.jsx: -------------------------------------------------------------------------------- 1 | import { Button, Result } from 'antd'; 2 | import { history } from 'umi'; 3 | 4 | const NoFoundPage = () => { 5 | return ( 6 | <Result 7 | status="404" 8 | title="404" 9 | subTitle="Page not found, please enter a correct address." 10 | extra={ 11 | <Button type="primary" onClick={() => history.push('/')}> 12 | Business 13 | </Button> 14 | } 15 | /> 16 | ); 17 | }; 18 | 19 | export default NoFoundPage; 20 | -------------------------------------------------------------------------------- /web/src/pages/add-knowledge/components/knowledge-chunk/components/chunk-card/index.less: -------------------------------------------------------------------------------- 1 | .image { 2 | width: 100px !important; 3 | object-fit: contain; 4 | } 5 | 6 | .imagePreview { 7 | max-width: 50vw; 8 | max-height: 50vh; 9 | object-fit: contain; 10 | } 11 | 12 | .content { 13 | flex: 1; 14 | .chunkText; 15 | } 16 | 17 | .contentEllipsis { 18 | .multipleLineEllipsis(3); 19 | } 20 | 21 | .contentText { 22 | word-break: break-all !important; 23 | } 24 | 25 | .chunkCard { 26 | width: 100%; 27 | } 28 | 29 | .cardSelected { 30 | background-color: @selectedBackgroundColor; 31 | } 32 | .cardSelectedDark { 33 | background-color: #ffffff2f; 34 | } 35 | -------------------------------------------------------------------------------- /web/src/pages/add-knowledge/components/knowledge-chunk/components/document-preview/index.less: -------------------------------------------------------------------------------- 1 | .documentContainer { 2 | width: 100%; 3 | height: calc(100vh - 284px); 4 | position: relative; 5 | :global(.PdfHighlighter) { 6 | overflow-x: hidden; 7 | } 8 | :global(.Highlight--scrolledTo .Highlight__part) { 9 | overflow-x: hidden; 10 | background-color: rgba(255, 226, 143, 1); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /web/src/pages/add-knowledge/components/knowledge-chunk/constant.ts: -------------------------------------------------------------------------------- 1 | export enum ChunkTextMode { 2 | Full = 'full', 3 | Ellipse = 'ellipse', 4 | } 5 | -------------------------------------------------------------------------------- /web/src/pages/add-knowledge/components/knowledge-chunk/utils.ts: -------------------------------------------------------------------------------- 1 | export type FormListItem = { 2 | frequency: number; 3 | tag: string; 4 | }; 5 | 6 | export function transformTagFeaturesArrayToObject( 7 | list: Array<FormListItem> = [], 8 | ) { 9 | return list.reduce<Record<string, number>>((pre, cur) => { 10 | pre[cur.tag] = cur.frequency; 11 | 12 | return pre; 13 | }, {}); 14 | } 15 | 16 | export function transformTagFeaturesObjectToArray( 17 | object: Record<string, number> = {}, 18 | ) { 19 | return Object.keys(object).reduce<Array<FormListItem>>((pre, key) => { 20 | pre.push({ frequency: object[key], tag: key }); 21 | 22 | return pre; 23 | }, []); 24 | } 25 | -------------------------------------------------------------------------------- /web/src/pages/add-knowledge/components/knowledge-dataset/index.less: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infiniflow/ragflow/f2909ea0c4d0d8739f487bb54851e508b39bee62/web/src/pages/add-knowledge/components/knowledge-dataset/index.less -------------------------------------------------------------------------------- /web/src/pages/add-knowledge/components/knowledge-dataset/index.tsx: -------------------------------------------------------------------------------- 1 | import { Outlet } from 'umi'; 2 | 3 | export const KnowledgeDataset = () => { 4 | return <Outlet></Outlet>; 5 | }; 6 | 7 | export default KnowledgeDataset; 8 | -------------------------------------------------------------------------------- /web/src/pages/add-knowledge/components/knowledge-file/constant.ts: -------------------------------------------------------------------------------- 1 | import { RunningStatus } from '@/constants/knowledge'; 2 | 3 | export const RunningStatusMap = { 4 | [RunningStatus.UNSTART]: { 5 | label: 'UNSTART', 6 | color: 'cyan', 7 | }, 8 | [RunningStatus.RUNNING]: { 9 | label: 'Parsing', 10 | color: 'blue', 11 | }, 12 | [RunningStatus.CANCEL]: { label: 'CANCEL', color: 'orange' }, 13 | [RunningStatus.DONE]: { label: 'SUCCESS', color: 'geekblue' }, 14 | [RunningStatus.FAIL]: { label: 'FAIL', color: 'red' }, 15 | }; 16 | 17 | export * from '@/constants/knowledge'; 18 | -------------------------------------------------------------------------------- /web/src/pages/add-knowledge/components/knowledge-file/parsing-action-cell/index.less: -------------------------------------------------------------------------------- 1 | .iconButton { 2 | padding: 4px 8px; 3 | } 4 | -------------------------------------------------------------------------------- /web/src/pages/add-knowledge/components/knowledge-file/parsing-status-cell/index.less: -------------------------------------------------------------------------------- 1 | .popoverContent { 2 | width: 40vw; 3 | 4 | .popoverContentItem { 5 | display: flex; 6 | gap: 10px; 7 | } 8 | 9 | .popoverContentText { 10 | white-space: pre-line; 11 | max-height: 50vh; 12 | overflow: auto; 13 | .popoverContentErrorLabel { 14 | color: red; 15 | } 16 | } 17 | } 18 | 19 | .operationIcon { 20 | text-align: center; 21 | display: flex; 22 | &:hover { 23 | cursor: pointer; 24 | } 25 | } 26 | .operationIconSpin { 27 | animation: spin 1s linear infinite; 28 | @keyframes spin { 29 | 0% { 30 | transform: rotate(0deg); 31 | } 32 | 100% { 33 | transform: rotate(360deg); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /web/src/pages/add-knowledge/components/knowledge-file/utils.ts: -------------------------------------------------------------------------------- 1 | import { RunningStatus } from './constant'; 2 | 3 | export const isParserRunning = (text: RunningStatus) => { 4 | const isRunning = text === RunningStatus.RUNNING; 5 | return isRunning; 6 | }; 7 | -------------------------------------------------------------------------------- /web/src/pages/add-knowledge/components/knowledge-graph/index.less: -------------------------------------------------------------------------------- 1 | .forceContainer { 2 | :global(.tooltip) { 3 | border-radius: 10px !important; 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /web/src/pages/add-knowledge/components/knowledge-graph/use-delete-graph.ts: -------------------------------------------------------------------------------- 1 | import { 2 | useKnowledgeBaseId, 3 | useRemoveKnowledgeGraph, 4 | } from '@/hooks/knowledge-hooks'; 5 | import { useCallback } from 'react'; 6 | import { useNavigate } from 'umi'; 7 | 8 | export function useDeleteKnowledgeGraph() { 9 | const { removeKnowledgeGraph, loading } = useRemoveKnowledgeGraph(); 10 | const navigate = useNavigate(); 11 | const knowledgeBaseId = useKnowledgeBaseId(); 12 | 13 | const handleDeleteKnowledgeGraph = useCallback(async () => { 14 | const ret = await removeKnowledgeGraph(); 15 | if (ret === 0) { 16 | navigate(`/knowledge/dataset?id=${knowledgeBaseId}`); 17 | } 18 | }, [knowledgeBaseId, navigate, removeKnowledgeGraph]); 19 | 20 | return { handleDeleteKnowledgeGraph, loading }; 21 | } 22 | -------------------------------------------------------------------------------- /web/src/pages/add-knowledge/components/knowledge-setting/configuration/knowledge-graph.tsx: -------------------------------------------------------------------------------- 1 | import Delimiter from '@/components/delimiter'; 2 | import EntityTypesItem from '@/components/entity-types-item'; 3 | import MaxTokenNumber from '@/components/max-token-number'; 4 | import PageRank from '@/components/page-rank'; 5 | import { ChunkMethodItem, EmbeddingModelItem } from './common-item'; 6 | 7 | export function KnowledgeGraphConfiguration() { 8 | return ( 9 | <> 10 | <EmbeddingModelItem></EmbeddingModelItem> 11 | <ChunkMethodItem></ChunkMethodItem> 12 | 13 | <PageRank></PageRank> 14 | 15 | <> 16 | <EntityTypesItem></EntityTypesItem> 17 | <MaxTokenNumber max={8192 * 2}></MaxTokenNumber> 18 | <Delimiter></Delimiter> 19 | </> 20 | </> 21 | ); 22 | } 23 | -------------------------------------------------------------------------------- /web/src/pages/add-knowledge/components/knowledge-setting/configuration/picture.tsx: -------------------------------------------------------------------------------- 1 | import { 2 | AutoKeywordsItem, 3 | AutoQuestionsItem, 4 | } from '@/components/auto-keywords-item'; 5 | import PageRank from '@/components/page-rank'; 6 | import { TagItems } from '../tag-item'; 7 | import { ChunkMethodItem, EmbeddingModelItem } from './common-item'; 8 | 9 | export function PictureConfiguration() { 10 | return ( 11 | <> 12 | <EmbeddingModelItem></EmbeddingModelItem> 13 | <ChunkMethodItem></ChunkMethodItem> 14 | 15 | <PageRank></PageRank> 16 | 17 | <> 18 | <AutoKeywordsItem></AutoKeywordsItem> 19 | <AutoQuestionsItem></AutoQuestionsItem> 20 | </> 21 | <TagItems></TagItems> 22 | </> 23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /web/src/pages/add-knowledge/components/knowledge-setting/configuration/qa.tsx: -------------------------------------------------------------------------------- 1 | import PageRank from '@/components/page-rank'; 2 | import { TagItems } from '../tag-item'; 3 | import { ChunkMethodItem, EmbeddingModelItem } from './common-item'; 4 | 5 | export function QAConfiguration() { 6 | return ( 7 | <> 8 | <EmbeddingModelItem></EmbeddingModelItem> 9 | <ChunkMethodItem></ChunkMethodItem> 10 | 11 | <PageRank></PageRank> 12 | 13 | <TagItems></TagItems> 14 | </> 15 | ); 16 | } 17 | -------------------------------------------------------------------------------- /web/src/pages/add-knowledge/components/knowledge-setting/configuration/resume.tsx: -------------------------------------------------------------------------------- 1 | import PageRank from '@/components/page-rank'; 2 | import { TagItems } from '../tag-item'; 3 | import { ChunkMethodItem, EmbeddingModelItem } from './common-item'; 4 | 5 | export function ResumeConfiguration() { 6 | return ( 7 | <> 8 | <EmbeddingModelItem></EmbeddingModelItem> 9 | <ChunkMethodItem></ChunkMethodItem> 10 | 11 | <PageRank></PageRank> 12 | 13 | <TagItems></TagItems> 14 | </> 15 | ); 16 | } 17 | -------------------------------------------------------------------------------- /web/src/pages/add-knowledge/components/knowledge-setting/configuration/table.tsx: -------------------------------------------------------------------------------- 1 | import PageRank from '@/components/page-rank'; 2 | import { ChunkMethodItem, EmbeddingModelItem } from './common-item'; 3 | 4 | export function TableConfiguration() { 5 | return ( 6 | <> 7 | <EmbeddingModelItem></EmbeddingModelItem> 8 | <ChunkMethodItem></ChunkMethodItem> 9 | 10 | <PageRank></PageRank> 11 | </> 12 | ); 13 | } 14 | -------------------------------------------------------------------------------- /web/src/pages/add-knowledge/components/knowledge-setting/configuration/tag.tsx: -------------------------------------------------------------------------------- 1 | import PageRank from '@/components/page-rank'; 2 | import { ChunkMethodItem, EmbeddingModelItem } from './common-item'; 3 | 4 | export function TagConfiguration() { 5 | return ( 6 | <> 7 | <EmbeddingModelItem></EmbeddingModelItem> 8 | <ChunkMethodItem></ChunkMethodItem> 9 | 10 | <PageRank></PageRank> 11 | </> 12 | ); 13 | } 14 | -------------------------------------------------------------------------------- /web/src/pages/add-knowledge/components/knowledge-setting/utils.ts: -------------------------------------------------------------------------------- 1 | const getImageName = (prefix: string, length: number) => 2 | new Array(length) 3 | .fill(0) 4 | .map((x, idx) => `chunk-method/${prefix}-0${idx + 1}`); 5 | 6 | export const ImageMap = { 7 | book: getImageName('book', 4), 8 | laws: getImageName('law', 2), 9 | manual: getImageName('manual', 4), 10 | picture: getImageName('media', 2), 11 | naive: getImageName('naive', 2), 12 | paper: getImageName('paper', 2), 13 | presentation: getImageName('presentation', 2), 14 | qa: getImageName('qa', 2), 15 | resume: getImageName('resume', 2), 16 | table: getImageName('table', 2), 17 | one: getImageName('one', 2), 18 | knowledge_graph: getImageName('knowledge-graph', 2), 19 | tag: getImageName('tag', 2), 20 | }; 21 | -------------------------------------------------------------------------------- /web/src/pages/add-knowledge/components/knowledge-testing/index.less: -------------------------------------------------------------------------------- 1 | .testingWrapper { 2 | flex: 1; 3 | height: 100%; 4 | } 5 | -------------------------------------------------------------------------------- /web/src/pages/add-knowledge/components/knowledge-testing/testing-control/index.less: -------------------------------------------------------------------------------- 1 | .testingControlWrapper { 2 | width: 350px; 3 | background-color: rgba(255, 255, 255, 0.1); 4 | padding: 30px 20px; 5 | overflow: auto; 6 | height: calc(100vh - 160px); 7 | 8 | .historyTitle { 9 | padding: 30px 0 20px; 10 | } 11 | .historyIcon { 12 | vertical-align: middle; 13 | } 14 | .historyCardWrapper { 15 | width: 100%; 16 | } 17 | .historyCard { 18 | width: 100%; 19 | :global(.ant-card-body) { 20 | padding: 10px; 21 | } 22 | } 23 | .historyText { 24 | overflow: hidden; 25 | text-overflow: ellipsis; 26 | white-space: nowrap; 27 | flex: 1; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /web/src/pages/add-knowledge/constant.ts: -------------------------------------------------------------------------------- 1 | import { KnowledgeRouteKey } from '@/constants/knowledge'; 2 | 3 | export const routeMap = { 4 | [KnowledgeRouteKey.Dataset]: 'Dataset', 5 | [KnowledgeRouteKey.Testing]: 'Retrieval testing', 6 | [KnowledgeRouteKey.Configuration]: 'Configuration', 7 | }; 8 | 9 | export enum KnowledgeDatasetRouteKey { 10 | Chunk = 'chunk', 11 | File = 'file', 12 | } 13 | 14 | export const datasetRouteMap = { 15 | [KnowledgeDatasetRouteKey.Chunk]: 'Chunk', 16 | [KnowledgeDatasetRouteKey.File]: 'File Upload', 17 | }; 18 | 19 | export * from '@/constants/knowledge'; 20 | 21 | export const TagRenameId = 'tagRename'; 22 | -------------------------------------------------------------------------------- /web/src/pages/add-knowledge/index.less: -------------------------------------------------------------------------------- 1 | .container { 2 | display: flex; 3 | height: 100%; 4 | width: 100%; 5 | .contentWrapper { 6 | flex: 1; 7 | overflow-x: auto; 8 | height: 100%; 9 | background-color: rgba(255, 255, 255, 0.1); 10 | padding: 16px 20px 28px 40px; 11 | display: flex; 12 | flex-direction: column; 13 | } 14 | .content { 15 | background-color: rgba(255, 255, 255, 0.1); 16 | margin-top: 16px; 17 | flex: 1; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /web/src/pages/agent/canvas/context-menu/index.less: -------------------------------------------------------------------------------- 1 | .contextMenu { 2 | background: rgba(255, 255, 255, 0.1); 3 | border-style: solid; 4 | box-shadow: 10px 19px 20px rgba(0, 0, 0, 10%); 5 | position: absolute; 6 | z-index: 10; 7 | button { 8 | border: none; 9 | display: block; 10 | padding: 0.5em; 11 | text-align: left; 12 | width: 100%; 13 | } 14 | 15 | button:hover { 16 | background: rgba(255, 255, 255, 0.1); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /web/src/pages/agent/canvas/edge/index.less: -------------------------------------------------------------------------------- 1 | .edgeButton { 2 | width: 14px; 3 | height: 14px; 4 | background: #eee; 5 | border: 1px solid #fff; 6 | padding: 0; 7 | cursor: pointer; 8 | border-radius: 50%; 9 | font-size: 10px; 10 | line-height: 1; 11 | } 12 | 13 | .edgeButton:hover { 14 | box-shadow: 0 0 2px 2px rgba(0, 0, 0, 0.08); 15 | } 16 | 17 | .edgeButtonDark { 18 | width: 14px; 19 | height: 14px; 20 | background: #0e0c0c; 21 | border: 1px solid #fff; 22 | padding: 0; 23 | cursor: pointer; 24 | border-radius: 50%; 25 | font-size: 10px; 26 | line-height: 1; 27 | } 28 | 29 | .edgeButtonDark:hover { 30 | box-shadow: 0 0 2px 2px rgba(0, 0, 0, 0.08); 31 | } 32 | -------------------------------------------------------------------------------- /web/src/pages/agent/canvas/index.less: -------------------------------------------------------------------------------- 1 | .canvasWrapper { 2 | position: relative; 3 | height: calc(100% - 64px); 4 | :global(.react-flow__node-group) { 5 | .commonNode(); 6 | border-radius: 0 0 10px 10px; 7 | padding: 0; 8 | border: 0; 9 | background-color: transparent; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /web/src/pages/agent/canvas/node/handle-icon.tsx: -------------------------------------------------------------------------------- 1 | import { PlusOutlined } from '@ant-design/icons'; 2 | import { CSSProperties } from 'react'; 3 | 4 | export const HandleIcon = () => { 5 | return ( 6 | <PlusOutlined 7 | style={{ fontSize: 6, color: 'white', position: 'absolute', zIndex: 10 }} 8 | /> 9 | ); 10 | }; 11 | 12 | export const RightHandleStyle: CSSProperties = { 13 | right: 0, 14 | }; 15 | 16 | export const LeftHandleStyle: CSSProperties = { 17 | left: 0, 18 | }; 19 | 20 | export default HandleIcon; 21 | -------------------------------------------------------------------------------- /web/src/pages/agent/canvas/node/node-wrapper.tsx: -------------------------------------------------------------------------------- 1 | import { cn } from '@/lib/utils'; 2 | import { HTMLAttributes, PropsWithChildren } from 'react'; 3 | 4 | export function NodeWrapper({ 5 | children, 6 | className, 7 | }: PropsWithChildren & HTMLAttributes<HTMLDivElement>) { 8 | return ( 9 | <section 10 | className={cn( 11 | 'bg-background-header-bar p-2.5 rounded-md w-[200px] text-xs', 12 | className, 13 | )} 14 | > 15 | {children} 16 | </section> 17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /web/src/pages/agent/chat/chat-sheet.tsx: -------------------------------------------------------------------------------- 1 | import { Sheet, SheetContent } from '@/components/ui/sheet'; 2 | import { IModalProps } from '@/interfaces/common'; 3 | import { cn } from '@/lib/utils'; 4 | import { useTranslation } from 'react-i18next'; 5 | import AgentChatBox from './box'; 6 | 7 | export function ChatSheet({ hideModal }: IModalProps<any>) { 8 | const { t } = useTranslation(); 9 | return ( 10 | <Sheet open modal={false} onOpenChange={hideModal}> 11 | <SheetContent 12 | className={cn('top-20 p-0')} 13 | onInteractOutside={(e) => e.preventDefault()} 14 | > 15 | <div className="pl-5 pt-2">{t('chat.chat')}</div> 16 | <AgentChatBox></AgentChatBox> 17 | </SheetContent> 18 | </Sheet> 19 | ); 20 | } 21 | -------------------------------------------------------------------------------- /web/src/pages/agent/flow-tooltip.tsx: -------------------------------------------------------------------------------- 1 | import { 2 | Tooltip, 3 | TooltipContent, 4 | TooltipTrigger, 5 | } from '@/components/ui/tooltip'; 6 | import { PropsWithChildren } from 'react'; 7 | import { useTranslation } from 'react-i18next'; 8 | 9 | export const RunTooltip = ({ children }: PropsWithChildren) => { 10 | const { t } = useTranslation(); 11 | return ( 12 | <Tooltip> 13 | <TooltipTrigger>{children}</TooltipTrigger> 14 | <TooltipContent> 15 | <p>{t('flow.testRun')}</p> 16 | </TooltipContent> 17 | </Tooltip> 18 | ); 19 | }; 20 | -------------------------------------------------------------------------------- /web/src/pages/agent/form-sheet/index.less: -------------------------------------------------------------------------------- 1 | .title { 2 | flex-basis: 60px; 3 | } 4 | 5 | .formWrapper { 6 | :global(.ant-form-item-label) { 7 | font-weight: 600; 8 | } 9 | } 10 | 11 | .operatorDescription { 12 | font-size: 14px; 13 | padding-top: 16px; 14 | font-weight: normal; 15 | } 16 | 17 | .formDrawer { 18 | :global(.ant-drawer-content-wrapper) { 19 | transform: translateX(0) !important; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /web/src/pages/agent/form/akshare-form/index.tsx: -------------------------------------------------------------------------------- 1 | import { TopNFormField } from '@/components/top-n-item'; 2 | import { Form } from '@/components/ui/form'; 3 | import { INextOperatorForm } from '../../interface'; 4 | import { DynamicInputVariable } from '../components/next-dynamic-input-variable'; 5 | 6 | const AkShareForm = ({ form, node }: INextOperatorForm) => { 7 | return ( 8 | <Form {...form}> 9 | <form 10 | className="space-y-6" 11 | onSubmit={(e) => { 12 | e.preventDefault(); 13 | }} 14 | > 15 | <DynamicInputVariable node={node}></DynamicInputVariable> 16 | <TopNFormField max={99}></TopNFormField> 17 | </form> 18 | </Form> 19 | ); 20 | }; 21 | 22 | export default AkShareForm; 23 | -------------------------------------------------------------------------------- /web/src/pages/agent/form/answer-form/index.tsx: -------------------------------------------------------------------------------- 1 | const AnswerForm = () => { 2 | return <div></div>; 3 | }; 4 | 5 | export default AnswerForm; 6 | -------------------------------------------------------------------------------- /web/src/pages/agent/form/baidu-form/index.tsx: -------------------------------------------------------------------------------- 1 | import { TopNFormField } from '@/components/top-n-item'; 2 | import { Form } from '@/components/ui/form'; 3 | import { INextOperatorForm } from '../../interface'; 4 | import { DynamicInputVariable } from '../components/next-dynamic-input-variable'; 5 | 6 | const BaiduForm = ({ form, node }: INextOperatorForm) => { 7 | return ( 8 | <Form {...form}> 9 | <form 10 | className="space-y-6" 11 | onSubmit={(e) => { 12 | e.preventDefault(); 13 | }} 14 | > 15 | <DynamicInputVariable node={node}></DynamicInputVariable> 16 | <TopNFormField></TopNFormField> 17 | </form> 18 | </Form> 19 | ); 20 | }; 21 | 22 | export default BaiduForm; 23 | -------------------------------------------------------------------------------- /web/src/pages/agent/form/begin-form/utils.ts: -------------------------------------------------------------------------------- 1 | import { BeginQuery } from '../../interface'; 2 | 3 | export function buildBeginInputListFromObject( 4 | inputs: Record<string, Omit<BeginQuery, 'key'>>, 5 | ) { 6 | return Object.entries(inputs || {}).reduce<BeginQuery[]>( 7 | (pre, [key, value]) => { 8 | pre.push({ ...(value || {}), key }); 9 | 10 | return pre; 11 | }, 12 | [], 13 | ); 14 | } 15 | -------------------------------------------------------------------------------- /web/src/pages/agent/form/code-form/schema.ts: -------------------------------------------------------------------------------- 1 | import { ProgrammingLanguage } from '@/constants/agent'; 2 | import { z } from 'zod'; 3 | 4 | export const FormSchema = z.object({ 5 | lang: z.enum([ProgrammingLanguage.Python, ProgrammingLanguage.Javascript]), 6 | script: z.string(), 7 | arguments: z.array(z.object({ name: z.string(), type: z.string() })), 8 | outputs: z.union([ 9 | z.array(z.object({ name: z.string(), type: z.string() })).optional(), 10 | z.object({ name: z.string(), type: z.string() }), 11 | ]), 12 | }); 13 | 14 | export type FormSchemaType = z.infer<typeof FormSchema>; 15 | -------------------------------------------------------------------------------- /web/src/pages/agent/form/components/description-field.tsx: -------------------------------------------------------------------------------- 1 | import { 2 | FormControl, 3 | FormField, 4 | FormItem, 5 | FormLabel, 6 | } from '@/components/ui/form'; 7 | import { Textarea } from '@/components/ui/textarea'; 8 | import { useFormContext } from 'react-hook-form'; 9 | 10 | export function DescriptionField() { 11 | const form = useFormContext(); 12 | return ( 13 | <FormField 14 | control={form.control} 15 | name={`description`} 16 | render={({ field }) => ( 17 | <FormItem className="flex-1"> 18 | <FormLabel>Description</FormLabel> 19 | <FormControl> 20 | <Textarea {...field}></Textarea> 21 | </FormControl> 22 | </FormItem> 23 | )} 24 | /> 25 | ); 26 | } 27 | -------------------------------------------------------------------------------- /web/src/pages/agent/form/components/index.less: -------------------------------------------------------------------------------- 1 | .dynamicInputVariable { 2 | background-color: #ebe9e950; 3 | :global(.ant-collapse-content) { 4 | background-color: #f6f6f657; 5 | } 6 | margin-bottom: 20px; 7 | .title { 8 | font-weight: 600; 9 | font-size: 16px; 10 | } 11 | .variableType { 12 | width: 30%; 13 | } 14 | .variableValue { 15 | flex: 1; 16 | } 17 | 18 | .addButton { 19 | color: rgb(22, 119, 255); 20 | font-weight: 600; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /web/src/pages/agent/form/components/prompt-editor/constant.ts: -------------------------------------------------------------------------------- 1 | export const ProgrammaticTag = 'programmatic'; 2 | -------------------------------------------------------------------------------- /web/src/pages/agent/form/concentrator-form/index.tsx: -------------------------------------------------------------------------------- 1 | import { Form } from 'antd'; 2 | import { IOperatorForm } from '../../interface'; 3 | 4 | const ConcentratorForm = ({ onValuesChange, form }: IOperatorForm) => { 5 | return ( 6 | <Form 7 | name="basic" 8 | labelCol={{ span: 8 }} 9 | wrapperCol={{ span: 16 }} 10 | autoComplete="off" 11 | form={form} 12 | onValuesChange={onValuesChange} 13 | ></Form> 14 | ); 15 | }; 16 | 17 | export default ConcentratorForm; 18 | -------------------------------------------------------------------------------- /web/src/pages/agent/form/github-form/index.tsx: -------------------------------------------------------------------------------- 1 | import TopNItem from '@/components/top-n-item'; 2 | import { Form } from 'antd'; 3 | import { IOperatorForm } from '../../interface'; 4 | import DynamicInputVariable from '../components/dynamic-input-variable'; 5 | 6 | const GithubForm = ({ onValuesChange, form, node }: IOperatorForm) => { 7 | return ( 8 | <Form 9 | name="basic" 10 | autoComplete="off" 11 | form={form} 12 | onValuesChange={onValuesChange} 13 | layout={'vertical'} 14 | > 15 | <DynamicInputVariable node={node}></DynamicInputVariable> 16 | <TopNItem initialValue={5}></TopNItem> 17 | </Form> 18 | ); 19 | }; 20 | 21 | export default GithubForm; 22 | -------------------------------------------------------------------------------- /web/src/pages/agent/form/iteration-form/interface.ts: -------------------------------------------------------------------------------- 1 | export type OutputArray = Array<{ name: string; ref: string; type?: string }>; 2 | export type OutputObject = Record<string, { ref: string; type?: string }>; 3 | -------------------------------------------------------------------------------- /web/src/pages/agent/form/iteration-start-from/index.tsx: -------------------------------------------------------------------------------- 1 | import { Output, OutputType } from '@/pages/agent/form/components/output'; 2 | import { memo } from 'react'; 3 | import { initialIterationStartValues } from '../../constant'; 4 | 5 | const outputs = initialIterationStartValues.outputs; 6 | 7 | const outputList = Object.entries(outputs).reduce<OutputType[]>( 8 | (pre, [key, value]) => { 9 | pre.push({ title: key, type: value.type }); 10 | 11 | return pre; 12 | }, 13 | [], 14 | ); 15 | function IterationStartForm() { 16 | return ( 17 | <section className="space-y-6 p-4"> 18 | <Output list={outputList}></Output> 19 | </section> 20 | ); 21 | } 22 | 23 | export default memo(IterationStartForm); 24 | -------------------------------------------------------------------------------- /web/src/pages/agent/form/message-form/use-values.ts: -------------------------------------------------------------------------------- 1 | import { RAGFlowNodeType } from '@/interfaces/database/flow'; 2 | import { isEmpty } from 'lodash'; 3 | import { useMemo } from 'react'; 4 | import { initialMessageValues } from '../../constant'; 5 | import { convertToObjectArray } from '../../utils'; 6 | 7 | export function useValues(node?: RAGFlowNodeType) { 8 | const values = useMemo(() => { 9 | const formData = node?.data?.form; 10 | 11 | if (isEmpty(formData)) { 12 | return initialMessageValues; 13 | } 14 | 15 | return { 16 | ...formData, 17 | content: convertToObjectArray(formData.content), 18 | }; 19 | }, [node]); 20 | 21 | return values; 22 | } 23 | -------------------------------------------------------------------------------- /web/src/pages/agent/form/retrieval-form/use-values.ts: -------------------------------------------------------------------------------- 1 | import { RAGFlowNodeType } from '@/interfaces/database/flow'; 2 | import { isEmpty } from 'lodash'; 3 | import { useMemo } from 'react'; 4 | import { initialRetrievalValues } from '../../constant'; 5 | 6 | export function useValues(node?: RAGFlowNodeType) { 7 | const defaultValues = useMemo( 8 | () => ({ 9 | ...initialRetrievalValues, 10 | }), 11 | [], 12 | ); 13 | 14 | const values = useMemo(() => { 15 | const formData = node?.data?.form; 16 | 17 | if (isEmpty(formData)) { 18 | return defaultValues; 19 | } 20 | 21 | return formData; 22 | }, [defaultValues, node?.data?.form]); 23 | 24 | return values; 25 | } 26 | -------------------------------------------------------------------------------- /web/src/pages/agent/form/switch-form/use-values.ts: -------------------------------------------------------------------------------- 1 | import { RAGFlowNodeType } from '@/interfaces/database/flow'; 2 | import { isEmpty } from 'lodash'; 3 | import { useMemo } from 'react'; 4 | import { initialSwitchValues } from '../../constant'; 5 | 6 | export function useValues(node?: RAGFlowNodeType) { 7 | const values = useMemo(() => { 8 | const formData = node?.data?.form; 9 | if (isEmpty(formData)) { 10 | return initialSwitchValues; 11 | } 12 | 13 | return formData; 14 | }, [node]); 15 | 16 | return values; 17 | } 18 | -------------------------------------------------------------------------------- /web/src/pages/agent/form/tavily-form/use-values.ts: -------------------------------------------------------------------------------- 1 | import { RAGFlowNodeType } from '@/interfaces/database/agent'; 2 | import { isEmpty } from 'lodash'; 3 | import { useMemo } from 'react'; 4 | import { initialTavilyValues } from '../../constant'; 5 | import { convertToObjectArray } from '../../utils'; 6 | 7 | export function useValues(node?: RAGFlowNodeType) { 8 | const values = useMemo(() => { 9 | const formData = node?.data?.form; 10 | 11 | if (isEmpty(formData)) { 12 | return initialTavilyValues; 13 | } 14 | 15 | return { 16 | ...formData, 17 | include_domains: convertToObjectArray(formData.include_domains), 18 | exclude_domains: convertToObjectArray(formData.exclude_domains), 19 | }; 20 | }, [node?.data?.form]); 21 | 22 | return values; 23 | } 24 | -------------------------------------------------------------------------------- /web/src/pages/agent/form/template-form/index.tsx: -------------------------------------------------------------------------------- 1 | import { Form } from 'antd'; 2 | import { useTranslation } from 'react-i18next'; 3 | import { IOperatorForm } from '../../interface'; 4 | import { PromptEditor } from '../components/prompt-editor'; 5 | 6 | const TemplateForm = ({ onValuesChange, form }: IOperatorForm) => { 7 | const { t } = useTranslation(); 8 | 9 | return ( 10 | <Form 11 | name="basic" 12 | autoComplete="off" 13 | form={form} 14 | onValuesChange={onValuesChange} 15 | layout={'vertical'} 16 | > 17 | <Form.Item name={['content']} label={t('flow.content')}> 18 | <PromptEditor></PromptEditor> 19 | </Form.Item> 20 | </Form> 21 | ); 22 | }; 23 | 24 | export default TemplateForm; 25 | -------------------------------------------------------------------------------- /web/src/pages/agent/form/tool-form/index.tsx: -------------------------------------------------------------------------------- 1 | import { memo } from 'react'; 2 | import useGraphStore from '../../store'; 3 | import { ToolFormConfigMap } from './constant'; 4 | import MCPForm from './mcp-form'; 5 | 6 | const EmptyContent = () => <div></div>; 7 | 8 | function ToolForm() { 9 | const clickedToolId = useGraphStore((state) => state.clickedToolId); 10 | 11 | const ToolForm = 12 | ToolFormConfigMap[clickedToolId as keyof typeof ToolFormConfigMap] ?? 13 | MCPForm ?? 14 | EmptyContent; 15 | 16 | return ( 17 | <section> 18 | <ToolForm key={clickedToolId}></ToolForm> 19 | </section> 20 | ); 21 | } 22 | 23 | export default memo(ToolForm); 24 | -------------------------------------------------------------------------------- /web/src/pages/agent/form/tool-form/mcp-form/mcp-card.tsx: -------------------------------------------------------------------------------- 1 | import { Card, CardContent } from '@/components/ui/card'; 2 | import { IMCPTool } from '@/interfaces/database/mcp'; 3 | import { PropsWithChildren } from 'react'; 4 | 5 | export function MCPCard({ 6 | data, 7 | children, 8 | }: { data: IMCPTool } & PropsWithChildren) { 9 | return ( 10 | <Card className="p-3"> 11 | <CardContent className="p-0 flex gap-3"> 12 | {children} 13 | <section> 14 | <div className="pb-3 text-sm">{data.name}</div> 15 | <p className="text-text-sub-title text-xs">{data.description}</p> 16 | </section> 17 | </CardContent> 18 | </Card> 19 | ); 20 | } 21 | -------------------------------------------------------------------------------- /web/src/pages/agent/form/user-fill-up-form/use-values.ts: -------------------------------------------------------------------------------- 1 | import { RAGFlowNodeType } from '@/interfaces/database/flow'; 2 | import { isEmpty } from 'lodash'; 3 | import { useMemo } from 'react'; 4 | import { initialUserFillUpValues } from '../../constant'; 5 | import { buildBeginInputListFromObject } from '../begin-form/utils'; 6 | 7 | export function useValues(node?: RAGFlowNodeType) { 8 | const values = useMemo(() => { 9 | const formData = node?.data?.form; 10 | 11 | if (isEmpty(formData)) { 12 | return initialUserFillUpValues; 13 | } 14 | 15 | const inputs = buildBeginInputListFromObject(formData?.inputs); 16 | 17 | return { ...(formData || {}), inputs }; 18 | }, [node?.data?.form]); 19 | 20 | return values; 21 | } 22 | -------------------------------------------------------------------------------- /web/src/pages/agent/hooks/use-fetch-data.ts: -------------------------------------------------------------------------------- 1 | import { useFetchAgent } from '@/hooks/use-agent-request'; 2 | import { IGraph } from '@/interfaces/database/flow'; 3 | import { useEffect } from 'react'; 4 | import { useSetGraphInfo } from './use-set-graph'; 5 | 6 | export const useFetchDataOnMount = () => { 7 | const { loading, data, refetch } = useFetchAgent(); 8 | const setGraphInfo = useSetGraphInfo(); 9 | 10 | useEffect(() => { 11 | setGraphInfo(data?.dsl?.graph ?? ({} as IGraph)); 12 | }, [setGraphInfo, data]); 13 | 14 | useEffect(() => { 15 | refetch(); 16 | }, [refetch]); 17 | 18 | return { loading, flowDetail: data }; 19 | }; 20 | -------------------------------------------------------------------------------- /web/src/pages/agent/hooks/use-find-mcp-by-id.ts: -------------------------------------------------------------------------------- 1 | import { useListMcpServer } from '@/hooks/use-mcp-request'; 2 | 3 | export function useFindMcpById() { 4 | const { data } = useListMcpServer(); 5 | 6 | const findMcpById = (id: string) => 7 | data.mcp_servers.find((item) => item.id === id); 8 | 9 | return { 10 | findMcpById, 11 | }; 12 | } 13 | -------------------------------------------------------------------------------- /web/src/pages/agent/hooks/use-form-values.ts: -------------------------------------------------------------------------------- 1 | import { RAGFlowNodeType } from '@/interfaces/database/flow'; 2 | import { isEmpty } from 'lodash'; 3 | import { useMemo } from 'react'; 4 | 5 | export function useFormValues( 6 | defaultValues: Record<string, any>, 7 | node?: RAGFlowNodeType, 8 | ) { 9 | const values = useMemo(() => { 10 | const formData = node?.data?.form; 11 | 12 | if (isEmpty(formData)) { 13 | return defaultValues; 14 | } 15 | 16 | return formData; 17 | }, [defaultValues, node?.data?.form]); 18 | 19 | return values; 20 | } 21 | -------------------------------------------------------------------------------- /web/src/pages/agent/hooks/use-iteration.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infiniflow/ragflow/f2909ea0c4d0d8739f487bb54851e508b39bee62/web/src/pages/agent/hooks/use-iteration.ts -------------------------------------------------------------------------------- /web/src/pages/agent/hooks/use-open-document.ts: -------------------------------------------------------------------------------- 1 | import { useCallback } from 'react'; 2 | 3 | export function useOpenDocument() { 4 | const openDocument = useCallback(() => { 5 | window.open( 6 | 'https://ragflow.io/docs/dev/category/agent-components', 7 | '_blank', 8 | ); 9 | }, []); 10 | 11 | return openDocument; 12 | } 13 | -------------------------------------------------------------------------------- /web/src/pages/agent/hooks/use-set-graph.ts: -------------------------------------------------------------------------------- 1 | import { IGraph } from '@/interfaces/database/flow'; 2 | import { useCallback } from 'react'; 3 | import useGraphStore from '../store'; 4 | 5 | export const useSetGraphInfo = () => { 6 | const { setEdges, setNodes } = useGraphStore((state) => state); 7 | const setGraphInfo = useCallback( 8 | ({ nodes = [], edges = [] }: IGraph) => { 9 | if (nodes.length || edges.length) { 10 | setNodes(nodes); 11 | setEdges(edges); 12 | } 13 | }, 14 | [setEdges, setNodes], 15 | ); 16 | return setGraphInfo; 17 | }; 18 | -------------------------------------------------------------------------------- /web/src/pages/agent/hooks/use-watch-form-change.ts: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react'; 2 | import { UseFormReturn, useWatch } from 'react-hook-form'; 3 | import useGraphStore from '../store'; 4 | 5 | export function useWatchFormChange(id?: string, form?: UseFormReturn<any>) { 6 | let values = useWatch({ control: form?.control }); 7 | const updateNodeForm = useGraphStore((state) => state.updateNodeForm); 8 | 9 | useEffect(() => { 10 | // Manually triggered form updates are synchronized to the canvas 11 | if (id) { 12 | values = form?.getValues() || {}; 13 | let nextValues: any = values; 14 | 15 | updateNodeForm(id, nextValues); 16 | } 17 | }, [form?.formState.isDirty, id, updateNodeForm, values]); 18 | } 19 | -------------------------------------------------------------------------------- /web/src/pages/agent/utils/build-output-list.ts: -------------------------------------------------------------------------------- 1 | import { OutputType } from '../form/components/output'; 2 | 3 | export function buildOutputList(outputs: Record<string, Record<string, any>>) { 4 | return Object.entries(outputs).reduce<OutputType[]>((pre, [key, val]) => { 5 | pre.push({ title: key, type: val.type }); 6 | return pre; 7 | }, []); 8 | } 9 | -------------------------------------------------------------------------------- /web/src/pages/agent/utils/chat.ts: -------------------------------------------------------------------------------- 1 | import { MessageType } from '@/constants/chat'; 2 | import { IReference } from '@/interfaces/database/chat'; 3 | import { IMessage } from '@/pages/chat/interface'; 4 | import { isEmpty } from 'lodash'; 5 | 6 | export const buildAgentMessageItemReference = ( 7 | conversation: { message: IMessage[]; reference: IReference[] }, 8 | message: IMessage, 9 | ) => { 10 | const assistantMessages = conversation.message?.filter( 11 | (x) => x.role === MessageType.Assistant, 12 | ); 13 | const referenceIndex = assistantMessages.findIndex( 14 | (x) => x.id === message.id, 15 | ); 16 | const reference = !isEmpty(message?.reference) 17 | ? message?.reference 18 | : (conversation?.reference ?? [])[referenceIndex]; 19 | 20 | return reference ?? { doc_aggs: [], chunks: [], total: 0 }; 21 | }; 22 | -------------------------------------------------------------------------------- /web/src/pages/chat/chat-container/index.less: -------------------------------------------------------------------------------- 1 | .chatContainer { 2 | padding: 0 0 24px 24px; 3 | .messageContainer { 4 | overflow-y: auto; 5 | padding-right: 24px; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /web/src/pages/chat/chat-id-modal/index.less: -------------------------------------------------------------------------------- 1 | .id { 2 | .linkText(); 3 | } 4 | -------------------------------------------------------------------------------- /web/src/pages/chat/constants.ts: -------------------------------------------------------------------------------- 1 | export const EmptyConversationId = 'empty'; 2 | -------------------------------------------------------------------------------- /web/src/pages/chat/context.ts: -------------------------------------------------------------------------------- 1 | import { createContext } from 'react'; 2 | 3 | export const ConversationContext = createContext< 4 | null | ((isPlaying: boolean) => void) 5 | >(null); 6 | -------------------------------------------------------------------------------- /web/src/pages/chat/share/index.less: -------------------------------------------------------------------------------- 1 | .chatWrapper { 2 | height: 100vh; 3 | } 4 | 5 | .chatContainer { 6 | padding: 10px; 7 | box-sizing: border-box; 8 | height: 100%; 9 | .messageContainer { 10 | overflow-y: auto; 11 | padding-right: 6px; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /web/src/pages/chat/share/index.tsx: -------------------------------------------------------------------------------- 1 | import ChatContainer from './large'; 2 | 3 | import styles from './index.less'; 4 | 5 | const SharedChat = () => { 6 | return ( 7 | <div className={styles.chatWrapper}> 8 | <ChatContainer></ChatContainer> 9 | </div> 10 | ); 11 | }; 12 | 13 | export default SharedChat; 14 | -------------------------------------------------------------------------------- /web/src/pages/chunk/chunk-result/index.tsx: -------------------------------------------------------------------------------- 1 | import ChunkedResultPanel from '../chunked-result-panel'; 2 | import ParsedResultPanel from '../parsed-result-panel'; 3 | 4 | export default function ChunkResult() { 5 | return ( 6 | <section className="flex"> 7 | <ParsedResultPanel></ParsedResultPanel> 8 | <div className="flex-1"> 9 | <ChunkedResultPanel></ChunkedResultPanel> 10 | </div> 11 | </section> 12 | ); 13 | } 14 | -------------------------------------------------------------------------------- /web/src/pages/chunk/chunk-toolbar.tsx: -------------------------------------------------------------------------------- 1 | import { Button } from '@/components/ui/button'; 2 | import { Copy } from 'lucide-react'; 3 | 4 | interface ChunkToolbarProps { 5 | text: string; 6 | } 7 | 8 | export function ChunkToolbar({ text }: ChunkToolbarProps) { 9 | return ( 10 | <div className="flex justify-between px-9"> 11 | <span className="text-colors-text-neutral-strong text-3xl font-bold"> 12 | {text} 13 | </span> 14 | <div className="flex items-center gap-3"> 15 | <Button variant={'icon'} size={'icon'}> 16 | <Copy /> 17 | </Button> 18 | <Button variant={'outline'} size={'sm'}> 19 | Export 20 | </Button> 21 | </div> 22 | </div> 23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /web/src/pages/chunk/parsed-result/add-knowledge/components/knowledge-chunk/components/chunk-card/index.less: -------------------------------------------------------------------------------- 1 | .image { 2 | width: 100px !important; 3 | object-fit: contain; 4 | } 5 | 6 | .imagePreview { 7 | max-width: 50vw; 8 | max-height: 50vh; 9 | object-fit: contain; 10 | } 11 | 12 | .content { 13 | flex: 1; 14 | .chunkText; 15 | } 16 | 17 | .contentEllipsis { 18 | .multipleLineEllipsis(3); 19 | } 20 | 21 | .contentText { 22 | word-break: break-all !important; 23 | } 24 | 25 | .chunkCard { 26 | width: 100%; 27 | padding: 18px 10px; 28 | } 29 | 30 | .cardSelected { 31 | background-color: @selectedBackgroundColor; 32 | } 33 | 34 | .cardSelectedDark { 35 | background-color: #ffffff2f; 36 | } 37 | -------------------------------------------------------------------------------- /web/src/pages/chunk/parsed-result/add-knowledge/components/knowledge-chunk/components/document-preview/document-header.tsx: -------------------------------------------------------------------------------- 1 | import { formatDate } from '@/utils/date'; 2 | import { formatBytes } from '@/utils/file-util'; 3 | 4 | type Props = { 5 | size: number; 6 | name: string; 7 | create_date: string; 8 | }; 9 | 10 | export default ({ size, name, create_date }: Props) => { 11 | const sizeName = formatBytes(size); 12 | const dateStr = formatDate(create_date); 13 | return ( 14 | <div> 15 | <h2 className="text-[24px]">{name}</h2> 16 | <div className="text-[#979AAB] pt-[5px]"> 17 | Size:{sizeName} Uploaded Time:{dateStr} 18 | </div> 19 | </div> 20 | ); 21 | }; 22 | -------------------------------------------------------------------------------- /web/src/pages/chunk/parsed-result/add-knowledge/components/knowledge-chunk/components/document-preview/excel-preview.tsx: -------------------------------------------------------------------------------- 1 | import { useFetchExcel } from '@/pages/document-viewer/hooks'; 2 | import classNames from 'classnames'; 3 | import { useGetDocumentUrl } from './hooks'; 4 | 5 | interface ExcelCsvPreviewerProps { 6 | className?: string; 7 | } 8 | 9 | export const ExcelCsvPreviewer: React.FC<ExcelCsvPreviewerProps> = ({ 10 | className, 11 | }) => { 12 | const url = useGetDocumentUrl(); 13 | const { containerRef } = useFetchExcel(url); 14 | 15 | return ( 16 | <div 17 | ref={containerRef} 18 | className={classNames( 19 | 'relative w-full h-full p-4 bg-background-paper border border-border-normal rounded-md excel-csv-previewer', 20 | className, 21 | )} 22 | ></div> 23 | ); 24 | }; 25 | -------------------------------------------------------------------------------- /web/src/pages/chunk/parsed-result/add-knowledge/components/knowledge-chunk/components/document-preview/index.less: -------------------------------------------------------------------------------- 1 | .documentContainer { 2 | width: 100%; 3 | // height: calc(100vh - 284px); 4 | height: calc(100vh - 170px); 5 | position: relative; 6 | :global(.PdfHighlighter) { 7 | overflow-x: hidden; 8 | } 9 | :global(.Highlight--scrolledTo .Highlight__part) { 10 | overflow-x: hidden; 11 | background-color: rgba(255, 226, 143, 1); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /web/src/pages/chunk/parsed-result/add-knowledge/components/knowledge-chunk/constant.ts: -------------------------------------------------------------------------------- 1 | export enum ChunkTextMode { 2 | Full = 'full', 3 | Ellipse = 'ellipse', 4 | } 5 | -------------------------------------------------------------------------------- /web/src/pages/chunk/parsed-result/add-knowledge/components/knowledge-chunk/utils.ts: -------------------------------------------------------------------------------- 1 | export type FormListItem = { 2 | frequency: number; 3 | tag: string; 4 | }; 5 | 6 | export function transformTagFeaturesArrayToObject( 7 | list: Array<FormListItem> = [], 8 | ) { 9 | return list.reduce<Record<string, number>>((pre, cur) => { 10 | pre[cur.tag] = cur.frequency; 11 | 12 | return pre; 13 | }, {}); 14 | } 15 | 16 | export function transformTagFeaturesObjectToArray( 17 | object: Record<string, number> = {}, 18 | ) { 19 | return Object.keys(object).reduce<Array<FormListItem>>((pre, key) => { 20 | pre.push({ frequency: object[key], tag: key }); 21 | 22 | return pre; 23 | }, []); 24 | } 25 | -------------------------------------------------------------------------------- /web/src/pages/chunk/parsed-result/add-knowledge/constant.ts: -------------------------------------------------------------------------------- 1 | import { KnowledgeRouteKey } from '@/constants/knowledge'; 2 | 3 | export const routeMap = { 4 | [KnowledgeRouteKey.Dataset]: 'Dataset', 5 | [KnowledgeRouteKey.Testing]: 'Retrieval testing', 6 | [KnowledgeRouteKey.Configuration]: 'Configuration', 7 | }; 8 | 9 | export enum KnowledgeDatasetRouteKey { 10 | Chunk = 'chunk', 11 | File = 'file', 12 | } 13 | 14 | export const datasetRouteMap = { 15 | [KnowledgeDatasetRouteKey.Chunk]: 'Chunk', 16 | [KnowledgeDatasetRouteKey.File]: 'File Upload', 17 | }; 18 | 19 | export * from '@/constants/knowledge'; 20 | 21 | export const TagRenameId = 'tagRename'; 22 | -------------------------------------------------------------------------------- /web/src/pages/chunk/parsed-result/add-knowledge/index.less: -------------------------------------------------------------------------------- 1 | .container { 2 | display: flex; 3 | height: 100%; 4 | width: 100%; 5 | .contentWrapper { 6 | flex: 1; 7 | overflow-x: auto; 8 | height: 100%; 9 | background-color: rgba(255, 255, 255, 0.1); 10 | padding: 16px 20px 28px 40px; 11 | display: flex; 12 | flex-direction: column; 13 | } 14 | .content { 15 | background-color: rgba(255, 255, 255, 0.1); 16 | margin-top: 16px; 17 | flex: 1; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /web/src/pages/chunk/parsed-result/index-old.tsx: -------------------------------------------------------------------------------- 1 | import ParsedResultPanel from '../parsed-result-panel'; 2 | 3 | export default function ParsedResult() { 4 | return ( 5 | <section className="flex"> 6 | <div className="flex-1"></div> 7 | <ParsedResultPanel></ParsedResultPanel> 8 | </section> 9 | ); 10 | } 11 | -------------------------------------------------------------------------------- /web/src/pages/chunk/parsed-result/index.tsx: -------------------------------------------------------------------------------- 1 | import ParsedResultPanel from '../parsed-result-panel'; 2 | 3 | export default function ParsedResult() { 4 | return ( 5 | <section className="flex"> 6 | <div className="flex-1"></div> 7 | <ParsedResultPanel></ParsedResultPanel> 8 | </section> 9 | ); 10 | } 11 | -------------------------------------------------------------------------------- /web/src/pages/chunk/parsed-result/knowledge-chunk/components/chunk-card/index.less: -------------------------------------------------------------------------------- 1 | .image { 2 | width: 100px !important; 3 | object-fit: contain; 4 | } 5 | 6 | .imagePreview { 7 | max-width: 50vw; 8 | max-height: 50vh; 9 | object-fit: contain; 10 | } 11 | 12 | .content { 13 | flex: 1; 14 | .chunkText; 15 | } 16 | 17 | .contentEllipsis { 18 | .multipleLineEllipsis(3); 19 | } 20 | 21 | .contentText { 22 | word-break: break-all !important; 23 | } 24 | 25 | .chunkCard { 26 | width: 100%; 27 | } 28 | 29 | .cardSelected { 30 | background-color: @selectedBackgroundColor; 31 | } 32 | .cardSelectedDark { 33 | background-color: #ffffff2f; 34 | } 35 | -------------------------------------------------------------------------------- /web/src/pages/chunk/parsed-result/knowledge-chunk/components/document-preview/index.less: -------------------------------------------------------------------------------- 1 | .documentContainer { 2 | width: 100%; 3 | height: calc(100vh - 284px); 4 | position: relative; 5 | :global(.PdfHighlighter) { 6 | overflow-x: hidden; 7 | } 8 | :global(.Highlight--scrolledTo .Highlight__part) { 9 | overflow-x: hidden; 10 | background-color: rgba(255, 226, 143, 1); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /web/src/pages/chunk/parsed-result/knowledge-chunk/constant.ts: -------------------------------------------------------------------------------- 1 | export enum ChunkTextMode { 2 | Full = 'full', 3 | Ellipse = 'ellipse', 4 | } 5 | -------------------------------------------------------------------------------- /web/src/pages/chunk/parsed-result/knowledge-chunk/utils.ts: -------------------------------------------------------------------------------- 1 | export type FormListItem = { 2 | frequency: number; 3 | tag: string; 4 | }; 5 | 6 | export function transformTagFeaturesArrayToObject( 7 | list: Array<FormListItem> = [], 8 | ) { 9 | return list.reduce<Record<string, number>>((pre, cur) => { 10 | pre[cur.tag] = cur.frequency; 11 | 12 | return pre; 13 | }, {}); 14 | } 15 | 16 | export function transformTagFeaturesObjectToArray( 17 | object: Record<string, number> = {}, 18 | ) { 19 | return Object.keys(object).reduce<Array<FormListItem>>((pre, key) => { 20 | pre.push({ frequency: object[key], tag: key }); 21 | 22 | return pre; 23 | }, []); 24 | } 25 | -------------------------------------------------------------------------------- /web/src/pages/chunk/result-view/index.tsx: -------------------------------------------------------------------------------- 1 | import ChunkedResultPanel from '../chunked-result-panel'; 2 | 3 | export default function ResultView() { 4 | return ( 5 | <section className="flex"> 6 | <div className="flex-1">xxx</div> 7 | <div className="flex-1"> 8 | <ChunkedResultPanel></ChunkedResultPanel> 9 | </div> 10 | </section> 11 | ); 12 | } 13 | -------------------------------------------------------------------------------- /web/src/pages/dataset/dataset-title.tsx: -------------------------------------------------------------------------------- 1 | import { ReactNode } from 'react'; 2 | 3 | type TopTitleProps = { 4 | title: ReactNode; 5 | description: ReactNode; 6 | }; 7 | 8 | export function TopTitle({ title, description }: TopTitleProps) { 9 | return ( 10 | <div className="pb-5"> 11 | <div className="text-2xl font-semibold">{title}</div> 12 | <p className="text-text-sub-title pt-2">{description}</p> 13 | </div> 14 | ); 15 | } 16 | -------------------------------------------------------------------------------- /web/src/pages/dataset/dataset/constant.ts: -------------------------------------------------------------------------------- 1 | import { RunningStatus } from '@/constants/knowledge'; 2 | 3 | export const RunningStatusMap = { 4 | [RunningStatus.UNSTART]: { 5 | label: 'UNSTART', 6 | color: 'cyan', 7 | }, 8 | [RunningStatus.RUNNING]: { 9 | label: 'Parsing', 10 | color: 'blue', 11 | }, 12 | [RunningStatus.CANCEL]: { label: 'CANCEL', color: 'orange' }, 13 | [RunningStatus.DONE]: { label: 'SUCCESS', color: 'blue' }, 14 | [RunningStatus.FAIL]: { label: 'FAIL', color: 'red' }, 15 | }; 16 | 17 | export * from '@/constants/knowledge'; 18 | -------------------------------------------------------------------------------- /web/src/pages/dataset/dataset/utils.ts: -------------------------------------------------------------------------------- 1 | import { RunningStatus } from './constant'; 2 | 3 | export const isParserRunning = (text: RunningStatus) => { 4 | const isRunning = text === RunningStatus.RUNNING; 5 | return isRunning; 6 | }; 7 | -------------------------------------------------------------------------------- /web/src/pages/dataset/index.tsx: -------------------------------------------------------------------------------- 1 | import { PageHeader } from '@/components/page-header'; 2 | import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks'; 3 | import { Outlet } from 'umi'; 4 | import { SideBar } from './sidebar'; 5 | 6 | export default function DatasetWrapper() { 7 | const { navigateToDatasetList } = useNavigatePage(); 8 | 9 | return ( 10 | <section> 11 | <PageHeader 12 | title="Dataset details" 13 | back={navigateToDatasetList} 14 | ></PageHeader> 15 | <div className="flex flex-1"> 16 | <SideBar></SideBar> 17 | <div className="flex-1"> 18 | <Outlet /> 19 | </div> 20 | </div> 21 | </section> 22 | ); 23 | } 24 | -------------------------------------------------------------------------------- /web/src/pages/dataset/setting/configuration-form-container.tsx: -------------------------------------------------------------------------------- 1 | import { FormContainer, FormContainerProps } from '@/components/form-container'; 2 | import { cn } from '@/lib/utils'; 3 | import { PropsWithChildren } from 'react'; 4 | 5 | export function ConfigurationFormContainer({ 6 | children, 7 | className, 8 | }: FormContainerProps) { 9 | return ( 10 | <FormContainer className={cn('p-10', className)}>{children}</FormContainer> 11 | ); 12 | } 13 | 14 | export function MainContainer({ children }: PropsWithChildren) { 15 | return <section className="space-y-5">{children}</section>; 16 | } 17 | -------------------------------------------------------------------------------- /web/src/pages/dataset/setting/configuration/qa.tsx: -------------------------------------------------------------------------------- 1 | import PageRankFormField from '@/components/page-rank-form-field'; 2 | import { ConfigurationFormContainer } from '../configuration-form-container'; 3 | import { TagItems } from '../tag-item'; 4 | import { ChunkMethodItem, EmbeddingModelItem } from './common-item'; 5 | 6 | export function QAConfiguration() { 7 | return ( 8 | <ConfigurationFormContainer> 9 | <ChunkMethodItem></ChunkMethodItem> 10 | <EmbeddingModelItem></EmbeddingModelItem> 11 | 12 | <PageRankFormField></PageRankFormField> 13 | 14 | <TagItems></TagItems> 15 | </ConfigurationFormContainer> 16 | ); 17 | } 18 | -------------------------------------------------------------------------------- /web/src/pages/dataset/setting/configuration/resume.tsx: -------------------------------------------------------------------------------- 1 | import PageRankFormField from '@/components/page-rank-form-field'; 2 | import { ConfigurationFormContainer } from '../configuration-form-container'; 3 | import { TagItems } from '../tag-item'; 4 | import { ChunkMethodItem, EmbeddingModelItem } from './common-item'; 5 | 6 | export function ResumeConfiguration() { 7 | return ( 8 | <ConfigurationFormContainer> 9 | <ChunkMethodItem></ChunkMethodItem> 10 | <EmbeddingModelItem></EmbeddingModelItem> 11 | 12 | <PageRankFormField></PageRankFormField> 13 | 14 | <TagItems></TagItems> 15 | </ConfigurationFormContainer> 16 | ); 17 | } 18 | -------------------------------------------------------------------------------- /web/src/pages/dataset/setting/configuration/table.tsx: -------------------------------------------------------------------------------- 1 | import PageRankFormField from '@/components/page-rank-form-field'; 2 | import { ConfigurationFormContainer } from '../configuration-form-container'; 3 | import { ChunkMethodItem, EmbeddingModelItem } from './common-item'; 4 | 5 | export function TableConfiguration() { 6 | return ( 7 | <ConfigurationFormContainer> 8 | <ChunkMethodItem></ChunkMethodItem> 9 | <EmbeddingModelItem></EmbeddingModelItem> 10 | 11 | <PageRankFormField></PageRankFormField> 12 | </ConfigurationFormContainer> 13 | ); 14 | } 15 | -------------------------------------------------------------------------------- /web/src/pages/dataset/setting/configuration/tag.tsx: -------------------------------------------------------------------------------- 1 | import PageRankFormField from '@/components/page-rank-form-field'; 2 | import { ConfigurationFormContainer } from '../configuration-form-container'; 3 | import { ChunkMethodItem, EmbeddingModelItem } from './common-item'; 4 | 5 | export function TagConfiguration() { 6 | return ( 7 | <ConfigurationFormContainer> 8 | <ChunkMethodItem></ChunkMethodItem> 9 | <EmbeddingModelItem></EmbeddingModelItem> 10 | 11 | <PageRankFormField></PageRankFormField> 12 | </ConfigurationFormContainer> 13 | ); 14 | } 15 | -------------------------------------------------------------------------------- /web/src/pages/dataset/setting/index.less: -------------------------------------------------------------------------------- 1 | .tags { 2 | margin-bottom: 24px; 3 | } 4 | 5 | .preset { 6 | display: flex; 7 | height: 80px; 8 | background-color: rgba(0, 0, 0, 0.1); 9 | border-radius: 5px; 10 | padding: 5px; 11 | margin-bottom: 24px; 12 | 13 | .left { 14 | flex: 1; 15 | } 16 | 17 | .right { 18 | width: 100px; 19 | border-left: 1px solid rgba(0, 0, 0, 0.4); 20 | margin: 10px 0px; 21 | padding: 5px; 22 | } 23 | } 24 | 25 | .configurationWrapper { 26 | padding: 0 52px; 27 | .buttonWrapper { 28 | text-align: right; 29 | } 30 | .variableSlider { 31 | width: 100%; 32 | } 33 | } 34 | 35 | .categoryPanelWrapper { 36 | .topTitle { 37 | margin-top: 0; 38 | } 39 | .imageRow { 40 | margin-top: 16px; 41 | } 42 | .image { 43 | width: 100%; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /web/src/pages/dataset/setting/utils.ts: -------------------------------------------------------------------------------- 1 | const getImageName = (prefix: string, length: number) => 2 | new Array(length) 3 | .fill(0) 4 | .map((x, idx) => `chunk-method/${prefix}-0${idx + 1}`); 5 | 6 | export const ImageMap = { 7 | book: getImageName('book', 4), 8 | laws: getImageName('law', 2), 9 | manual: getImageName('manual', 4), 10 | picture: getImageName('media', 2), 11 | naive: getImageName('naive', 2), 12 | paper: getImageName('paper', 2), 13 | presentation: getImageName('presentation', 2), 14 | qa: getImageName('qa', 2), 15 | resume: getImageName('resume', 2), 16 | table: getImageName('table', 2), 17 | one: getImageName('one', 2), 18 | knowledge_graph: getImageName('knowledge-graph', 2), 19 | }; 20 | -------------------------------------------------------------------------------- /web/src/pages/dataset/sidebar/hooks.tsx: -------------------------------------------------------------------------------- 1 | import { Routes } from '@/routes'; 2 | import { useCallback } from 'react'; 3 | import { useNavigate, useParams } from 'umi'; 4 | 5 | export const useHandleMenuClick = () => { 6 | const navigate = useNavigate(); 7 | const { id } = useParams(); 8 | 9 | const handleMenuClick = useCallback( 10 | (key: Routes) => () => { 11 | navigate(`${Routes.DatasetBase}${key}/${id}`); 12 | }, 13 | [id, navigate], 14 | ); 15 | 16 | return { handleMenuClick }; 17 | }; 18 | -------------------------------------------------------------------------------- /web/src/pages/datasets/use-display-owner.ts: -------------------------------------------------------------------------------- 1 | import { useFetchTenantInfo } from '@/hooks/user-setting-hooks'; 2 | import { useCallback } from 'react'; 3 | 4 | export function useDisplayOwnerName() { 5 | const { data } = useFetchTenantInfo(); 6 | const getOwnerName = useCallback( 7 | (tenantId: string, nickname: string) => { 8 | if (tenantId === data.tenant_id) { 9 | return null; 10 | } 11 | return nickname; 12 | }, 13 | [data.tenant_id], 14 | ); 15 | 16 | return getOwnerName; 17 | } 18 | -------------------------------------------------------------------------------- /web/src/pages/datasets/use-select-owners.ts: -------------------------------------------------------------------------------- 1 | import { FilterCollection } from '@/components/list-filter-bar/interface'; 2 | import { useFetchKnowledgeList } from '@/hooks/knowledge-hooks'; 3 | import { groupListByType } from '@/utils/dataset-util'; 4 | import { useMemo } from 'react'; 5 | 6 | export function useSelectOwners() { 7 | const { list } = useFetchKnowledgeList(); 8 | 9 | const owners = useMemo(() => { 10 | return groupListByType(list, 'tenant_id', 'nickname'); 11 | }, [list]); 12 | 13 | const filters: FilterCollection[] = [ 14 | { field: 'owner', list: owners, label: 'Owner' }, 15 | ]; 16 | 17 | return filters; 18 | } 19 | -------------------------------------------------------------------------------- /web/src/pages/document-viewer/docx/index.tsx: -------------------------------------------------------------------------------- 1 | import { Spin } from 'antd'; 2 | import FileError from '../file-error'; 3 | 4 | import { useFetchDocx } from '../hooks'; 5 | import styles from './index.less'; 6 | 7 | const Docx = ({ filePath }: { filePath: string }) => { 8 | const { succeed, containerRef, error } = useFetchDocx(filePath); 9 | 10 | return ( 11 | <> 12 | {succeed ? ( 13 | <section className={styles.docxViewerWrapper}> 14 | <div id="docx" ref={containerRef} className={styles.box}> 15 | <Spin /> 16 | </div> 17 | </section> 18 | ) : ( 19 | <FileError>{error}</FileError> 20 | )} 21 | </> 22 | ); 23 | }; 24 | 25 | export default Docx; 26 | -------------------------------------------------------------------------------- /web/src/pages/document-viewer/excel/index.tsx: -------------------------------------------------------------------------------- 1 | import '@js-preview/excel/lib/index.css'; 2 | import FileError from '../file-error'; 3 | import { useFetchExcel } from '../hooks'; 4 | 5 | const Excel = ({ filePath }: { filePath: string }) => { 6 | const { status, containerRef, error } = useFetchExcel(filePath); 7 | 8 | return ( 9 | <div 10 | id="excel" 11 | ref={containerRef} 12 | style={{ height: '100%', width: '100%' }} 13 | > 14 | {status || <FileError>{error}</FileError>} 15 | </div> 16 | ); 17 | }; 18 | 19 | export default Excel; 20 | -------------------------------------------------------------------------------- /web/src/pages/document-viewer/file-error/index.less: -------------------------------------------------------------------------------- 1 | .errorWrapper { 2 | width: 100%; 3 | height: 100%; 4 | } 5 | -------------------------------------------------------------------------------- /web/src/pages/document-viewer/file-error/index.tsx: -------------------------------------------------------------------------------- 1 | import { Alert, Flex } from 'antd'; 2 | 3 | import { useTranslate } from '@/hooks/common-hooks'; 4 | import React from 'react'; 5 | import styles from './index.less'; 6 | 7 | const FileError = ({ children }: React.PropsWithChildren) => { 8 | const { t } = useTranslate('fileManager'); 9 | return ( 10 | <Flex align="center" justify="center" className={styles.errorWrapper}> 11 | <Alert 12 | type="error" 13 | message={<h2>{children || t('fileError')}</h2>} 14 | ></Alert> 15 | </Flex> 16 | ); 17 | }; 18 | 19 | export default FileError; 20 | -------------------------------------------------------------------------------- /web/src/pages/document-viewer/index.less: -------------------------------------------------------------------------------- 1 | .viewerWrapper { 2 | width: 100%; 3 | height: 100%; 4 | :global { 5 | .pdf-canvas { 6 | text-align: center; 7 | } 8 | } 9 | .image { 10 | width: 100%; 11 | height: 100%; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /web/src/pages/file-manager/index.less: -------------------------------------------------------------------------------- 1 | .fileManagerWrapper { 2 | width: 100%; 3 | padding: 32px; 4 | } 5 | 6 | .filter { 7 | height: 32px; 8 | display: flex; 9 | margin: 10px 0; 10 | justify-content: space-between; 11 | padding: 24px 0; 12 | align-items: center; 13 | } 14 | 15 | .deleteIconWrapper { 16 | width: 22px; 17 | text-align: center; 18 | } 19 | 20 | .linkButton { 21 | padding: 0; 22 | } 23 | 24 | .breadcrumbItemButton { 25 | cursor: pointer; 26 | color: #1677ff; 27 | padding: 0; 28 | height: auto; 29 | } 30 | -------------------------------------------------------------------------------- /web/src/pages/files/use-delete-file.ts: -------------------------------------------------------------------------------- 1 | import { useDeleteFile } from '@/hooks/use-file-request'; 2 | import { useCallback } from 'react'; 3 | import { useGetFolderId } from './hooks'; 4 | 5 | export const useHandleDeleteFile = () => { 6 | const { deleteFile: removeDocument } = useDeleteFile(); 7 | const parentId = useGetFolderId(); 8 | 9 | const handleRemoveFile = useCallback( 10 | async (fileIds: string[]) => { 11 | const code = await removeDocument({ fileIds, parentId }); 12 | 13 | return code; 14 | }, 15 | [parentId, removeDocument], 16 | ); 17 | 18 | return { handleRemoveFile }; 19 | }; 20 | -------------------------------------------------------------------------------- /web/src/pages/files/util.ts: -------------------------------------------------------------------------------- 1 | export function isFolderType(type: string) { 2 | return type === 'folder'; 3 | } 4 | -------------------------------------------------------------------------------- /web/src/pages/flow/canvas/context-menu/index.less: -------------------------------------------------------------------------------- 1 | .contextMenu { 2 | background: rgba(255, 255, 255, 0.1); 3 | border-style: solid; 4 | box-shadow: 10px 19px 20px rgba(0, 0, 0, 10%); 5 | position: absolute; 6 | z-index: 10; 7 | button { 8 | border: none; 9 | display: block; 10 | padding: 0.5em; 11 | text-align: left; 12 | width: 100%; 13 | } 14 | 15 | button:hover { 16 | background: rgba(255, 255, 255, 0.1); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /web/src/pages/flow/canvas/edge/index.less: -------------------------------------------------------------------------------- 1 | .edgeButton { 2 | width: 14px; 3 | height: 14px; 4 | background: #eee; 5 | border: 1px solid #fff; 6 | padding: 0; 7 | cursor: pointer; 8 | border-radius: 50%; 9 | font-size: 10px; 10 | line-height: 1; 11 | } 12 | 13 | .edgeButton:hover { 14 | box-shadow: 0 0 2px 2px rgba(0, 0, 0, 0.08); 15 | } 16 | 17 | .edgeButtonDark { 18 | width: 14px; 19 | height: 14px; 20 | background: #0e0c0c; 21 | border: 1px solid #fff; 22 | padding: 0; 23 | cursor: pointer; 24 | border-radius: 50%; 25 | font-size: 10px; 26 | line-height: 1; 27 | } 28 | 29 | .edgeButtonDark:hover { 30 | box-shadow: 0 0 2px 2px rgba(0, 0, 0, 0.08); 31 | } 32 | -------------------------------------------------------------------------------- /web/src/pages/flow/canvas/index.less: -------------------------------------------------------------------------------- 1 | .canvasWrapper { 2 | position: relative; 3 | height: 100%; 4 | :global(.react-flow__node-group) { 5 | .commonNode(); 6 | padding: 0; 7 | border: 0; 8 | background-color: transparent; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /web/src/pages/flow/canvas/node/handle-icon.tsx: -------------------------------------------------------------------------------- 1 | import { PlusOutlined } from '@ant-design/icons'; 2 | import { CSSProperties } from 'react'; 3 | 4 | export const HandleIcon = () => { 5 | return ( 6 | <PlusOutlined 7 | style={{ fontSize: 6, color: 'white', position: 'absolute', zIndex: 10 }} 8 | /> 9 | ); 10 | }; 11 | 12 | export const RightHandleStyle: CSSProperties = { 13 | right: 0, 14 | }; 15 | 16 | export const LeftHandleStyle: CSSProperties = { 17 | left: 0, 18 | }; 19 | 20 | export default HandleIcon; 21 | -------------------------------------------------------------------------------- /web/src/pages/flow/chat/drawer.tsx: -------------------------------------------------------------------------------- 1 | import { useFetchFlow } from '@/hooks/flow-hooks'; 2 | import { IModalProps } from '@/interfaces/common'; 3 | import { Drawer } from 'antd'; 4 | import { getDrawerWidth } from '../utils'; 5 | import FlowChatBox from './box'; 6 | 7 | const ChatDrawer = ({ visible, hideModal }: IModalProps<any>) => { 8 | const { data } = useFetchFlow(); 9 | 10 | return ( 11 | <Drawer 12 | title={data.title} 13 | placement="right" 14 | onClose={hideModal} 15 | open={visible} 16 | getContainer={false} 17 | width={getDrawerWidth()} 18 | mask={false} 19 | > 20 | <FlowChatBox></FlowChatBox> 21 | </Drawer> 22 | ); 23 | }; 24 | 25 | export default ChatDrawer; 26 | -------------------------------------------------------------------------------- /web/src/pages/flow/chat/index.less: -------------------------------------------------------------------------------- 1 | .chatContainer { 2 | padding: 0; 3 | height: 100%; 4 | .messageContainer { 5 | overflow-y: auto; 6 | padding-right: 24px; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /web/src/pages/flow/context.ts: -------------------------------------------------------------------------------- 1 | import { RAGFlowNodeType } from '@/interfaces/database/flow'; 2 | import { createContext } from 'react'; 3 | 4 | export const FlowFormContext = createContext<RAGFlowNodeType | undefined>( 5 | undefined, 6 | ); 7 | -------------------------------------------------------------------------------- /web/src/pages/flow/debug-content/index.less: -------------------------------------------------------------------------------- 1 | .formWrapper { 2 | :global(.ant-form-item-label) { 3 | font-weight: 600 !important; 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /web/src/pages/flow/flow-drawer/index.less: -------------------------------------------------------------------------------- 1 | .title { 2 | flex-basis: 60px; 3 | } 4 | 5 | .formWrapper { 6 | :global(.ant-form-item-label) { 7 | font-weight: 600; 8 | } 9 | } 10 | 11 | .operatorDescription { 12 | font-size: 14px; 13 | padding-top: 16px; 14 | font-weight: normal; 15 | } 16 | 17 | .formDrawer { 18 | :global(.ant-drawer-content-wrapper) { 19 | transform: translateX(0) !important; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /web/src/pages/flow/flow-id-modal/index.less: -------------------------------------------------------------------------------- 1 | .id { 2 | .linkText(); 3 | } 4 | -------------------------------------------------------------------------------- /web/src/pages/flow/flow-setting/index.less: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infiniflow/ragflow/f2909ea0c4d0d8739f487bb54851e508b39bee62/web/src/pages/flow/flow-setting/index.less -------------------------------------------------------------------------------- /web/src/pages/flow/flow-sider/index.less: -------------------------------------------------------------------------------- 1 | .operatorCard { 2 | :global(.ant-card-body) { 3 | padding: 10px; 4 | } 5 | .cubeIcon { 6 | &:hover { 7 | cursor: pointer; 8 | } 9 | } 10 | } 11 | 12 | .siderContent { 13 | padding: 10px 4px; 14 | overflow: auto; 15 | height: calc(100vh - 80px); 16 | } 17 | -------------------------------------------------------------------------------- /web/src/pages/flow/flow-tooltip.tsx: -------------------------------------------------------------------------------- 1 | import { 2 | Tooltip, 3 | TooltipContent, 4 | TooltipTrigger, 5 | } from '@/components/ui/tooltip'; 6 | import { PropsWithChildren } from 'react'; 7 | import { useTranslation } from 'react-i18next'; 8 | 9 | export const RunTooltip = ({ children }: PropsWithChildren) => { 10 | const { t } = useTranslation(); 11 | return ( 12 | <Tooltip> 13 | <TooltipTrigger>{children}</TooltipTrigger> 14 | <TooltipContent> 15 | <p>{t('flow.testRun')}</p> 16 | </TooltipContent> 17 | </Tooltip> 18 | ); 19 | }; 20 | -------------------------------------------------------------------------------- /web/src/pages/flow/form/akshare-form/index.tsx: -------------------------------------------------------------------------------- 1 | import TopNItem from '@/components/top-n-item'; 2 | import { Form } from 'antd'; 3 | import { IOperatorForm } from '../../interface'; 4 | import DynamicInputVariable from '../components/dynamic-input-variable'; 5 | 6 | const AkShareForm = ({ onValuesChange, form, node }: IOperatorForm) => { 7 | return ( 8 | <Form 9 | name="basic" 10 | autoComplete="off" 11 | form={form} 12 | onValuesChange={onValuesChange} 13 | layout={'vertical'} 14 | > 15 | <DynamicInputVariable node={node}></DynamicInputVariable> 16 | <TopNItem initialValue={10} max={99}></TopNItem> 17 | </Form> 18 | ); 19 | }; 20 | 21 | export default AkShareForm; 22 | -------------------------------------------------------------------------------- /web/src/pages/flow/form/answer-form/index.tsx: -------------------------------------------------------------------------------- 1 | const AnswerForm = () => { 2 | return <div></div>; 3 | }; 4 | 5 | export default AnswerForm; 6 | -------------------------------------------------------------------------------- /web/src/pages/flow/form/baidu-form/index.tsx: -------------------------------------------------------------------------------- 1 | import TopNItem from '@/components/top-n-item'; 2 | import { Form } from 'antd'; 3 | import { IOperatorForm } from '../../interface'; 4 | import DynamicInputVariable from '../components/dynamic-input-variable'; 5 | 6 | const BaiduForm = ({ onValuesChange, form, node }: IOperatorForm) => { 7 | return ( 8 | <Form 9 | name="basic" 10 | autoComplete="off" 11 | form={form} 12 | onValuesChange={onValuesChange} 13 | layout={'vertical'} 14 | > 15 | <DynamicInputVariable node={node}></DynamicInputVariable> 16 | <TopNItem initialValue={10}></TopNItem> 17 | </Form> 18 | ); 19 | }; 20 | 21 | export default BaiduForm; 22 | -------------------------------------------------------------------------------- /web/src/pages/flow/form/begin-form/index.less: -------------------------------------------------------------------------------- 1 | .dynamicInputVariable { 2 | background-color: #ebe9e950; 3 | :global(.ant-collapse-content) { 4 | background-color: #f6f6f657; 5 | } 6 | :global(.ant-collapse-content-box) { 7 | padding: 0 !important; 8 | } 9 | margin-bottom: 20px; 10 | .title { 11 | font-weight: 600; 12 | font-size: 16px; 13 | } 14 | 15 | .addButton { 16 | color: rgb(22, 119, 255); 17 | font-weight: 600; 18 | } 19 | } 20 | 21 | .addButton { 22 | color: rgb(22, 119, 255); 23 | font-weight: 600; 24 | } 25 | -------------------------------------------------------------------------------- /web/src/pages/flow/form/categorize-form/index.less: -------------------------------------------------------------------------------- 1 | @lightBackgroundColor: rgba(150, 150, 150, 0.07); 2 | @darkBackgroundColor: rgba(150, 150, 150, 0.12); 3 | 4 | .caseCard { 5 | :global(.ant-collapse-content) { 6 | background-color: @darkBackgroundColor; 7 | } 8 | } 9 | 10 | .addButton { 11 | color: rgb(22, 119, 255); 12 | font-weight: 600; 13 | } 14 | -------------------------------------------------------------------------------- /web/src/pages/flow/form/code-form/index.less: -------------------------------------------------------------------------------- 1 | .languageItem { 2 | margin: 0; 3 | :global(.ant-select-selector) { 4 | background: transparent !important; 5 | border: none !important; 6 | box-shadow: none !important; 7 | } 8 | :global(.ant-select-selector:hover) { 9 | border: none !important; 10 | box-shadow: none !important; 11 | } 12 | :global(.ant-select-focused .ant-select-selector) { 13 | border: none !important; 14 | box-shadow: none !important; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /web/src/pages/flow/form/components/index.less: -------------------------------------------------------------------------------- 1 | .dynamicInputVariable { 2 | background-color: #ebe9e950; 3 | :global(.ant-collapse-content) { 4 | background-color: #f6f6f657; 5 | } 6 | margin-bottom: 20px; 7 | .title { 8 | font-weight: 600; 9 | font-size: 16px; 10 | } 11 | .variableType { 12 | width: 30%; 13 | } 14 | .variableValue { 15 | flex: 1; 16 | } 17 | 18 | .addButton { 19 | color: rgb(22, 119, 255); 20 | font-weight: 600; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /web/src/pages/flow/form/concentrator-form/index.tsx: -------------------------------------------------------------------------------- 1 | import { Form } from 'antd'; 2 | import { IOperatorForm } from '../../interface'; 3 | 4 | const ConcentratorForm = ({ onValuesChange, form }: IOperatorForm) => { 5 | return ( 6 | <Form 7 | name="basic" 8 | labelCol={{ span: 8 }} 9 | wrapperCol={{ span: 16 }} 10 | autoComplete="off" 11 | form={form} 12 | onValuesChange={onValuesChange} 13 | ></Form> 14 | ); 15 | }; 16 | 17 | export default ConcentratorForm; 18 | -------------------------------------------------------------------------------- /web/src/pages/flow/form/generate-form/index.less: -------------------------------------------------------------------------------- 1 | .variableTable { 2 | margin-top: 14px; 3 | } 4 | .editableRow { 5 | :global(.editable-cell) { 6 | position: relative; 7 | } 8 | 9 | :global(.editable-cell-value-wrap) { 10 | padding: 5px 12px; 11 | cursor: pointer; 12 | height: 30px !important; 13 | } 14 | &:hover { 15 | :global(.editable-cell-value-wrap) { 16 | padding: 4px 11px; 17 | border: 1px solid #d9d9d9; 18 | border-radius: 2px; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /web/src/pages/flow/form/github-form/index.tsx: -------------------------------------------------------------------------------- 1 | import TopNItem from '@/components/top-n-item'; 2 | import { Form } from 'antd'; 3 | import { IOperatorForm } from '../../interface'; 4 | import DynamicInputVariable from '../components/dynamic-input-variable'; 5 | 6 | const GithubForm = ({ onValuesChange, form, node }: IOperatorForm) => { 7 | return ( 8 | <Form 9 | name="basic" 10 | autoComplete="off" 11 | form={form} 12 | onValuesChange={onValuesChange} 13 | layout={'vertical'} 14 | > 15 | <DynamicInputVariable node={node}></DynamicInputVariable> 16 | <TopNItem initialValue={5}></TopNItem> 17 | </Form> 18 | ); 19 | }; 20 | 21 | export default GithubForm; 22 | -------------------------------------------------------------------------------- /web/src/pages/flow/form/message-form/index.less: -------------------------------------------------------------------------------- 1 | .dynamicDeleteButton { 2 | position: relative; 3 | top: 4px; 4 | margin: 0 8px; 5 | color: #999; 6 | font-size: 24px; 7 | cursor: pointer; 8 | transition: all 0.3s; 9 | &:hover { 10 | color: #777; 11 | } 12 | &[disabled] { 13 | cursor: not-allowed; 14 | opacity: 0.5; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /web/src/pages/flow/form/switch-form/index.less: -------------------------------------------------------------------------------- 1 | @lightBackgroundColor: rgba(150, 150, 150, 0.07); 2 | @darkBackgroundColor: rgba(150, 150, 150, 0.12); 3 | 4 | .caseCard { 5 | background-color: @lightBackgroundColor; 6 | } 7 | 8 | .conditionCard { 9 | background-color: @darkBackgroundColor; 10 | } 11 | 12 | .elseCase { 13 | background-color: @lightBackgroundColor; 14 | padding: 12px; 15 | border-radius: 8px; 16 | } 17 | 18 | .addButton { 19 | color: rgb(22, 119, 255); 20 | font-weight: 600; 21 | } 22 | -------------------------------------------------------------------------------- /web/src/pages/flow/form/template-form/index.tsx: -------------------------------------------------------------------------------- 1 | import { PromptEditor } from '@/components/prompt-editor'; 2 | import { Form } from 'antd'; 3 | import { useTranslation } from 'react-i18next'; 4 | import { IOperatorForm } from '../../interface'; 5 | 6 | const TemplateForm = ({ onValuesChange, form }: IOperatorForm) => { 7 | const { t } = useTranslation(); 8 | 9 | return ( 10 | <Form 11 | name="basic" 12 | autoComplete="off" 13 | form={form} 14 | onValuesChange={onValuesChange} 15 | layout={'vertical'} 16 | > 17 | <Form.Item name={['content']} label={t('flow.content')}> 18 | <PromptEditor></PromptEditor> 19 | </Form.Item> 20 | </Form> 21 | ); 22 | }; 23 | 24 | export default TemplateForm; 25 | -------------------------------------------------------------------------------- /web/src/pages/flow/header/index.less: -------------------------------------------------------------------------------- 1 | .flowHeader { 2 | padding: 10px 20px; 3 | } 4 | .hideRibbon { 5 | display: none !important; 6 | } 7 | 8 | .ribbon { 9 | top: 4px; 10 | } 11 | -------------------------------------------------------------------------------- /web/src/pages/flow/hooks/use-fetch-data.ts: -------------------------------------------------------------------------------- 1 | import { useFetchFlow } from '@/hooks/flow-hooks'; 2 | import { IGraph } from '@/interfaces/database/flow'; 3 | import { useEffect } from 'react'; 4 | import { useSetGraphInfo } from './use-set-graph'; 5 | 6 | export const useFetchDataOnMount = () => { 7 | const { loading, data, refetch } = useFetchFlow(); 8 | const setGraphInfo = useSetGraphInfo(); 9 | 10 | useEffect(() => { 11 | setGraphInfo(data?.dsl?.graph ?? ({} as IGraph)); 12 | }, [setGraphInfo, data]); 13 | 14 | useEffect(() => { 15 | refetch(); 16 | }, [refetch]); 17 | 18 | return { loading, flowDetail: data }; 19 | }; 20 | -------------------------------------------------------------------------------- /web/src/pages/flow/hooks/use-iteration.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infiniflow/ragflow/f2909ea0c4d0d8739f487bb54851e508b39bee62/web/src/pages/flow/hooks/use-iteration.ts -------------------------------------------------------------------------------- /web/src/pages/flow/hooks/use-open-document.ts: -------------------------------------------------------------------------------- 1 | import { useCallback } from 'react'; 2 | 3 | export function useOpenDocument() { 4 | const openDocument = useCallback(() => { 5 | window.open( 6 | 'https://ragflow.io/docs/dev/category/agent-components', 7 | '_blank', 8 | ); 9 | }, []); 10 | 11 | return openDocument; 12 | } 13 | -------------------------------------------------------------------------------- /web/src/pages/flow/hooks/use-set-graph.ts: -------------------------------------------------------------------------------- 1 | import { IGraph } from '@/interfaces/database/flow'; 2 | import { useCallback } from 'react'; 3 | import useGraphStore from '../store'; 4 | 5 | export const useSetGraphInfo = () => { 6 | const { setEdges, setNodes } = useGraphStore((state) => state); 7 | const setGraphInfo = useCallback( 8 | ({ nodes = [], edges = [] }: IGraph) => { 9 | if (nodes.length || edges.length) { 10 | setNodes(nodes); 11 | setEdges(edges); 12 | } 13 | }, 14 | [setEdges, setNodes], 15 | ); 16 | return setGraphInfo; 17 | }; 18 | -------------------------------------------------------------------------------- /web/src/pages/flow/interface.ts: -------------------------------------------------------------------------------- 1 | import { RAGFlowNodeType } from '@/interfaces/database/flow'; 2 | import { FormInstance } from 'antd'; 3 | 4 | export interface IOperatorForm { 5 | onValuesChange?(changedValues: any, values: any): void; 6 | form?: FormInstance; 7 | node?: RAGFlowNodeType; 8 | nodeId?: string; 9 | } 10 | 11 | export interface IGenerateParameter { 12 | id?: string; 13 | key: string; 14 | component_id?: string; 15 | } 16 | 17 | export interface IInvokeVariable extends IGenerateParameter { 18 | value?: string; 19 | } 20 | 21 | export type IPosition = { top: number; right: number; idx: number }; 22 | 23 | export interface BeginQuery { 24 | key: string; 25 | type: string; 26 | value: string; 27 | optional: boolean; 28 | name: string; 29 | options: (number | string | boolean)[]; 30 | } 31 | -------------------------------------------------------------------------------- /web/src/pages/flow/json-upload-modal/index.less: -------------------------------------------------------------------------------- 1 | .uploader { 2 | :global { 3 | .ant-upload-list { 4 | max-height: 40vh; 5 | overflow-y: auto; 6 | } 7 | } 8 | } 9 | 10 | .uploadLimit { 11 | color: red; 12 | font-size: 12px; 13 | } 14 | -------------------------------------------------------------------------------- /web/src/pages/flow/list/graph-avatar.tsx: -------------------------------------------------------------------------------- 1 | import { ReactComponent as NothingIcon } from '@/assets/svg/nothing.svg'; 2 | import { Avatar } from 'antd'; 3 | 4 | const GraphAvatar = ({ avatar }: { avatar?: string | null }) => { 5 | return ( 6 | <div> 7 | {avatar ? ( 8 | <Avatar size={40} icon={<NothingIcon />} src={avatar} /> 9 | ) : ( 10 | <NothingIcon width={40} height={30} /> 11 | )} 12 | </div> 13 | ); 14 | }; 15 | 16 | export default GraphAvatar; 17 | -------------------------------------------------------------------------------- /web/src/pages/flow/operator-icon/index.less: -------------------------------------------------------------------------------- 1 | .icon { 2 | color: rgb(59, 118, 244); 3 | font-size: 24px; 4 | max-width: 24px; 5 | max-height: 24px; 6 | } 7 | -------------------------------------------------------------------------------- /web/src/pages/flow/operator-icon/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Operator, operatorIconMap } from '../constant'; 3 | 4 | import styles from './index.less'; 5 | 6 | interface IProps { 7 | name: Operator; 8 | fontSize?: number; 9 | width?: number; 10 | color?: string; 11 | } 12 | 13 | const OperatorIcon = ({ name, fontSize, width, color }: IProps) => { 14 | const Icon = operatorIconMap[name] || React.Fragment; 15 | return ( 16 | <Icon 17 | className={styles.icon} 18 | style={{ fontSize, color }} 19 | width={width} 20 | ></Icon> 21 | ); 22 | }; 23 | 24 | export default OperatorIcon; 25 | -------------------------------------------------------------------------------- /web/src/pages/flow/run-drawer/index.less: -------------------------------------------------------------------------------- 1 | .formWrapper { 2 | :global(.ant-form-item-label) { 3 | font-weight: 600 !important; 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /web/src/pages/home/agent-list.tsx: -------------------------------------------------------------------------------- 1 | import { useFetchAgentListByPage } from '@/hooks/use-agent-request'; 2 | import { ApplicationCard } from './application-card'; 3 | 4 | export function Agents() { 5 | const { data } = useFetchAgentListByPage(); 6 | 7 | return data 8 | .slice(0, 10) 9 | .map((x) => <ApplicationCard key={x.id} app={x}></ApplicationCard>); 10 | } 11 | -------------------------------------------------------------------------------- /web/src/pages/home/chat-list.tsx: -------------------------------------------------------------------------------- 1 | import { useFetchDialogList } from '@/hooks/use-chat-request'; 2 | import { ApplicationCard } from './application-card'; 3 | 4 | export function ChatList() { 5 | const { data } = useFetchDialogList(true); 6 | 7 | return data 8 | .slice(0, 10) 9 | .map((x) => ( 10 | <ApplicationCard 11 | key={x.id} 12 | app={{ avatar: x.icon, title: x.name, update_time: x.update_time }} 13 | ></ApplicationCard> 14 | )); 15 | } 16 | -------------------------------------------------------------------------------- /web/src/pages/home/index.tsx: -------------------------------------------------------------------------------- 1 | import { Applications } from './applications'; 2 | import { NextBanner } from './banner'; 3 | import { Datasets } from './datasets'; 4 | 5 | const Home = () => { 6 | return ( 7 | <div className="mx-8"> 8 | <section> 9 | <NextBanner></NextBanner> 10 | <Datasets></Datasets> 11 | <Applications></Applications> 12 | </section> 13 | </div> 14 | ); 15 | }; 16 | 17 | export default Home; 18 | -------------------------------------------------------------------------------- /web/src/pages/login-next/hooks.ts: -------------------------------------------------------------------------------- 1 | import { useCallback } from 'react'; 2 | import { useSearchParams } from 'umi'; 3 | 4 | export enum Step { 5 | SignIn, 6 | SignUp, 7 | ForgotPassword, 8 | ResetPassword, 9 | VerifyEmail, 10 | } 11 | 12 | export const useSwitchStep = (step: Step) => { 13 | const [_, setSearchParams] = useSearchParams(); 14 | const switchStep = useCallback(() => { 15 | setSearchParams(new URLSearchParams({ step: step.toString() })); 16 | }, [setSearchParams, step]); 17 | 18 | return { switchStep }; 19 | }; 20 | -------------------------------------------------------------------------------- /web/src/pages/next-chats/chat/app-settings/subhead.tsx: -------------------------------------------------------------------------------- 1 | import { PropsWithChildren } from 'react'; 2 | 3 | export function Subhead({ children }: PropsWithChildren) { 4 | return ( 5 | <div className="text-xl font-bold mb-4 text-colors-text-neutral-strong"> 6 | {children} 7 | </div> 8 | ); 9 | } 10 | -------------------------------------------------------------------------------- /web/src/pages/next-chats/chat/chat-box.tsx: -------------------------------------------------------------------------------- 1 | import { ChatInput } from '@/components/chat-input'; 2 | 3 | export function ChatBox() { 4 | return ( 5 | <section className="border-x flex-1"> 6 | <ChatInput></ChatInput> 7 | </section> 8 | ); 9 | } 10 | -------------------------------------------------------------------------------- /web/src/pages/next-search/index.tsx: -------------------------------------------------------------------------------- 1 | import { PageHeader } from '@/components/page-header'; 2 | import { Button } from '@/components/ui/button'; 3 | import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks'; 4 | import { EllipsisVertical } from 'lucide-react'; 5 | 6 | export default function SearchPage() { 7 | const { navigateToSearchList } = useNavigatePage(); 8 | 9 | return ( 10 | <section> 11 | <PageHeader back={navigateToSearchList} title="Search app 01"> 12 | <div className="flex items-center gap-2"> 13 | <Button variant={'icon'} size={'icon'}> 14 | <EllipsisVertical /> 15 | </Button> 16 | <Button variant={'tertiary'} size={'sm'}> 17 | Publish 18 | </Button> 19 | </div> 20 | </PageHeader> 21 | </section> 22 | ); 23 | } 24 | -------------------------------------------------------------------------------- /web/src/pages/profile-setting/components.tsx: -------------------------------------------------------------------------------- 1 | import { PropsWithChildren } from 'react'; 2 | 3 | export function Title({ children }: PropsWithChildren) { 4 | return <span className="font-bold text-xl">{children}</span>; 5 | } 6 | -------------------------------------------------------------------------------- /web/src/pages/profile-setting/mcp/tool-card.tsx: -------------------------------------------------------------------------------- 1 | import { Card, CardContent } from '@/components/ui/card'; 2 | import { IMCPTool } from '@/interfaces/database/mcp'; 3 | 4 | export type McpToolCardProps = { 5 | data: IMCPTool; 6 | }; 7 | 8 | export function McpToolCard({ data }: McpToolCardProps) { 9 | return ( 10 | <Card> 11 | <CardContent className="p-2.5 pt-2 group"> 12 | <h3 className="text-sm font-semibold line-clamp-1 pb-2">{data.name}</h3> 13 | <div className="text-xs font-normal mb-3 text-text-sub-title"> 14 | {data.description} 15 | </div> 16 | </CardContent> 17 | </Card> 18 | ); 19 | } 20 | -------------------------------------------------------------------------------- /web/src/pages/profile-setting/mcp/use-export-mcp.ts: -------------------------------------------------------------------------------- 1 | import { useExportMcpServer } from '@/hooks/use-mcp-request'; 2 | import { downloadJsonFile } from '@/utils/file-util'; 3 | import { useCallback } from 'react'; 4 | 5 | export function useExportMcp() { 6 | const { exportMcpServer } = useExportMcpServer(); 7 | 8 | const handleExportMcpJson = useCallback( 9 | (ids: string[]) => async () => { 10 | const data = await exportMcpServer(ids); 11 | if (data.code === 0) { 12 | downloadJsonFile(data.data, `mcp.json`); 13 | } 14 | }, 15 | [exportMcpServer], 16 | ); 17 | 18 | return { 19 | handleExportMcpJson, 20 | }; 21 | } 22 | -------------------------------------------------------------------------------- /web/src/pages/profile-setting/sidebar/hooks.tsx: -------------------------------------------------------------------------------- 1 | import { useLogout } from '@/hooks/login-hooks'; 2 | import { Routes } from '@/routes'; 3 | import { useCallback } from 'react'; 4 | import { useNavigate } from 'umi'; 5 | 6 | export const useHandleMenuClick = () => { 7 | const navigate = useNavigate(); 8 | const { logout } = useLogout(); 9 | 10 | const handleMenuClick = useCallback( 11 | (key: Routes) => () => { 12 | if (key === Routes.Logout) { 13 | logout(); 14 | } else { 15 | navigate(`${Routes.ProfileSetting}${key}`); 16 | } 17 | }, 18 | [logout, navigate], 19 | ); 20 | 21 | return { handleMenuClick }; 22 | }; 23 | -------------------------------------------------------------------------------- /web/src/pages/user-setting/hooks.ts: -------------------------------------------------------------------------------- 1 | import { Form } from 'antd'; 2 | import { useEffect, useState } from 'react'; 3 | 4 | export const useValidateSubmittable = () => { 5 | const [form] = Form.useForm(); 6 | const [submittable, setSubmittable] = useState<boolean>(false); 7 | 8 | // Watch all values 9 | const values = Form.useWatch([], form); 10 | 11 | useEffect(() => { 12 | form 13 | .validateFields({ validateOnly: true }) 14 | .then(() => setSubmittable(true)) 15 | .catch(() => setSubmittable(false)); 16 | }, [form, values]); 17 | 18 | return { submittable, form }; 19 | }; 20 | -------------------------------------------------------------------------------- /web/src/pages/user-setting/index.less: -------------------------------------------------------------------------------- 1 | .settingWrapper { 2 | width: 100%; 3 | 4 | .outletWrapper { 5 | padding: 32px 32px 0; 6 | height: 100%; 7 | overflow-y: auto; 8 | } 9 | 10 | .itemDescription { 11 | padding: 10px 0; 12 | margin: 0; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /web/src/pages/user-setting/index.tsx: -------------------------------------------------------------------------------- 1 | import { Flex } from 'antd'; 2 | import { Outlet } from 'umi'; 3 | import SideBar from './sidebar'; 4 | 5 | import styles from './index.less'; 6 | 7 | const UserSetting = () => { 8 | return ( 9 | <Flex className={styles.settingWrapper}> 10 | <SideBar></SideBar> 11 | <Flex flex={1} className={styles.outletWrapper}> 12 | <Outlet></Outlet> 13 | </Flex> 14 | </Flex> 15 | ); 16 | }; 17 | 18 | export default UserSetting; 19 | -------------------------------------------------------------------------------- /web/src/pages/user-setting/interface.ts: -------------------------------------------------------------------------------- 1 | export interface ApiKeyPostBody { 2 | api_key: string; 3 | base_url: string; 4 | group_id?: string; 5 | } 6 | -------------------------------------------------------------------------------- /web/src/pages/user-setting/setting-api/index.less: -------------------------------------------------------------------------------- 1 | .apiWrapper { 2 | width: 100%; 3 | 4 | div[class^='chartWrapper'] { 5 | height: auto !important; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /web/src/pages/user-setting/setting-api/index.tsx: -------------------------------------------------------------------------------- 1 | import ApiContent from '@/components/api-service/chat-overview-modal/api-content'; 2 | 3 | import styles from './index.less'; 4 | 5 | const ApiPage = () => { 6 | return ( 7 | <div className={styles.apiWrapper}> 8 | <ApiContent idKey="dialogId" hideChatPreviewCard></ApiContent> 9 | </div> 10 | ); 11 | }; 12 | 13 | export default ApiPage; 14 | -------------------------------------------------------------------------------- /web/src/pages/user-setting/setting-locale/index.tsx: -------------------------------------------------------------------------------- 1 | import { translationTable } from '@/locales/config'; 2 | import TranslationTable from './TranslationTable'; 3 | 4 | function UserSettingLocale() { 5 | return ( 6 | <TranslationTable 7 | data={translationTable} 8 | languages={[ 9 | 'English', 10 | 'Vietnamese', 11 | 'Spanish', 12 | 'zh', 13 | 'zh-TRADITIONAL', 14 | 'ja', 15 | 'pt-br', 16 | 'German', 17 | ]} 18 | /> 19 | ); 20 | } 21 | 22 | export default UserSettingLocale; 23 | -------------------------------------------------------------------------------- /web/src/pages/user-setting/setting-model/constant.ts: -------------------------------------------------------------------------------- 1 | export const BedrockRegionList = [ 2 | 'us-east-1', 3 | 'us-west-2', 4 | 'ap-southeast-1', 5 | 'ap-northeast-1', 6 | 'eu-central-1', 7 | 'us-gov-west-1', 8 | 'ap-southeast-2', 9 | ]; 10 | -------------------------------------------------------------------------------- /web/src/pages/user-setting/setting-password/index.less: -------------------------------------------------------------------------------- 1 | .passwordWrapper { 2 | width: 100%; 3 | } 4 | -------------------------------------------------------------------------------- /web/src/pages/user-setting/setting-profile/index.less: -------------------------------------------------------------------------------- 1 | .profileWrapper { 2 | width: 100%; 3 | .emailDescription { 4 | padding: 10px 0; 5 | margin: 0; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /web/src/pages/user-setting/setting-system/index.less: -------------------------------------------------------------------------------- 1 | .systemInfo { 2 | width: 100%; 3 | .title { 4 | font-size: 20px; 5 | font-weight: 600; 6 | } 7 | .text { 8 | height: 26px; 9 | line-height: 26px; 10 | } 11 | .badge { 12 | :global(.ant-badge-status-dot) { 13 | width: 10px; 14 | height: 10px; 15 | } 16 | } 17 | .error { 18 | color: red; 19 | } 20 | } 21 | 22 | .taskBarTooltip { 23 | font-size: 16px; 24 | } 25 | 26 | .taskBar { 27 | width: '100%'; 28 | height: 200px; 29 | } 30 | 31 | .taskBarTitle { 32 | font-size: 16px; 33 | } 34 | -------------------------------------------------------------------------------- /web/src/pages/user-setting/setting-team/index.less: -------------------------------------------------------------------------------- 1 | .teamWrapper { 2 | width: 100%; 3 | display: flex; 4 | flex-direction: column; 5 | gap: 20px; 6 | .teamCard { 7 | // width: 100%; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /web/src/pages/user-setting/sidebar/index.less: -------------------------------------------------------------------------------- 1 | .sideBarWrapper { 2 | padding-top: 32px; 3 | .version { 4 | color: rgb(17, 206, 17); 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /web/src/pages/user-setting/utils.ts: -------------------------------------------------------------------------------- 1 | import { LocalLlmFactories } from './constants'; 2 | 3 | export const isLocalLlmFactory = (llmFactory: string) => 4 | LocalLlmFactories.some((x) => x === llmFactory); 5 | -------------------------------------------------------------------------------- /web/src/services/plugin-service.ts: -------------------------------------------------------------------------------- 1 | import api from '@/utils/api'; 2 | import registerServer from '@/utils/register-server'; 3 | import request from '@/utils/request'; 4 | 5 | const { 6 | llm_tools 7 | } = api; 8 | 9 | const methods = { 10 | getLlmTools: { 11 | url: llm_tools, 12 | method: 'get', 13 | }, 14 | } as const; 15 | 16 | const pluginService = registerServer<keyof typeof methods>(methods, request); 17 | 18 | export default pluginService; 19 | -------------------------------------------------------------------------------- /web/src/theme/theme.ts: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | 'primary-color': '#338AFF', // '#338AFF', 3 | 'border-radius-base': '4px', 4 | // 'menu-dark-color': '', 5 | // 'menu-dark-danger-color': '', 6 | 'menu-dark-bg': '#092140', 7 | 'menu-dark-item-active-bg': '#092140', 8 | 9 | // 'menu-dark-arrow-color': '', 10 | // 'menu-dark-inline-submenu-bg': '', 11 | }; 12 | -------------------------------------------------------------------------------- /web/src/theme/vars.less: -------------------------------------------------------------------------------- 1 | @header-height: 64px; 2 | @menu-width: 200px; 3 | @menu-small-width: 83px; 4 | @layout-bg: #f2f3f6; 5 | @logo-font-size: 22px; 6 | @border-color: #d9d9d9; 7 | @dashboard-desc-color: #9d9fa2; 8 | @primary-color: #338aff; 9 | @primary-color-light: rgba(21, 65, 255, 0.5); 10 | -------------------------------------------------------------------------------- /web/src/utils/component-util.ts: -------------------------------------------------------------------------------- 1 | export function buildSelectOptions(list: Array<string>) { 2 | return list.map((x) => ({ label: x, value: x })); 3 | } 4 | -------------------------------------------------------------------------------- /web/src/utils/date.ts: -------------------------------------------------------------------------------- 1 | import dayjs from 'dayjs'; 2 | 3 | export function formatDate(date: any) { 4 | if (!date) { 5 | return ''; 6 | } 7 | return dayjs(date).format('DD/MM/YYYY HH:mm:ss'); 8 | } 9 | 10 | export function formatTime(date: any) { 11 | if (!date) { 12 | return ''; 13 | } 14 | return dayjs(date).format('HH:mm:ss'); 15 | } 16 | 17 | export function today() { 18 | return formatDate(dayjs()); 19 | } 20 | 21 | export function lastDay() { 22 | return formatDate(dayjs().subtract(1, 'days')); 23 | } 24 | 25 | export function lastWeek() { 26 | return formatDate(dayjs().subtract(1, 'weeks')); 27 | } 28 | 29 | export function formatPureDate(date: any) { 30 | if (!date) { 31 | return ''; 32 | } 33 | return dayjs(date).format('DD/MM/YYYY'); 34 | } 35 | -------------------------------------------------------------------------------- /web/src/utils/dom-util.ts: -------------------------------------------------------------------------------- 1 | export const scrollToBottom = (element: HTMLElement) => { 2 | element.scrollTo(0, element.scrollHeight); 3 | }; 4 | -------------------------------------------------------------------------------- /web/src/utils/llm-util.ts: -------------------------------------------------------------------------------- 1 | export const getLLMIconName = (fid: string, llm_name: string) => { 2 | if (fid === 'FastEmbed') { 3 | return llm_name.split('/').at(0) ?? ''; 4 | } 5 | 6 | return fid; 7 | }; 8 | 9 | export const getLlmNameAndFIdByLlmId = (llmId?: string) => { 10 | const [llmName, fId] = llmId?.split('@') || []; 11 | 12 | return { fId, llmName }; 13 | }; 14 | 15 | // The names of the large models returned by the interface are similar to "deepseek-r1___OpenAI-API" 16 | export function getRealModelName(llmName: string) { 17 | return llmName.split('__').at(0) ?? ''; 18 | } 19 | -------------------------------------------------------------------------------- /web/src/utils/store-util.ts: -------------------------------------------------------------------------------- 1 | export const getOneNamespaceEffectsLoading = ( 2 | namespace: string, 3 | effects: Record<string, boolean>, 4 | effectNames: Array<string>, 5 | ) => { 6 | return effectNames.some( 7 | (effectName) => effects[`${namespace}/${effectName}`], 8 | ); 9 | }; 10 | 11 | export const delay = (ms: number) => 12 | new Promise((resolve) => { 13 | setTimeout(resolve, ms); 14 | }); 15 | -------------------------------------------------------------------------------- /web/src/wrappers/auth.tsx: -------------------------------------------------------------------------------- 1 | import { useAuth } from '@/hooks/auth-hooks'; 2 | import { redirectToLogin } from '@/utils/authorization-util'; 3 | import { Outlet } from 'umi'; 4 | 5 | export default () => { 6 | const { isLogin } = useAuth(); 7 | if (isLogin === true) { 8 | return <Outlet />; 9 | } else if (isLogin === false) { 10 | redirectToLogin(); 11 | } 12 | 13 | return <></>; 14 | }; 15 | -------------------------------------------------------------------------------- /web/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./src/.umi/tsconfig.json", 3 | "@@/*": ["src/.umi/*"], 4 | "root": ["../*"], 5 | } 6 | -------------------------------------------------------------------------------- /web/typings.d.ts: -------------------------------------------------------------------------------- 1 | import '@tanstack/react-table'; 2 | declare module 'lodash'; 3 | 4 | declare global { 5 | type Nullable<T> = T | null; 6 | } 7 | 8 | declare module '@tanstack/react-table' { 9 | interface ColumnMeta { 10 | headerClassName?: string; 11 | cellClassName?: string; 12 | } 13 | } 14 | --------------------------------------------------------------------------------