dataset_retrieval.py 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. from typing import Optional, cast
  2. from langchain.tools import BaseTool
  3. from core.app.app_config.entities import DatasetEntity, DatasetRetrieveConfigEntity
  4. from core.app.entities.app_invoke_entities import InvokeFrom, ModelConfigWithCredentialsEntity
  5. from core.callback_handler.index_tool_callback_handler import DatasetIndexToolCallbackHandler
  6. from core.entities.agent_entities import PlanningStrategy
  7. from core.memory.token_buffer_memory import TokenBufferMemory
  8. from core.model_runtime.entities.model_entities import ModelFeature
  9. from core.model_runtime.model_providers.__base.large_language_model import LargeLanguageModel
  10. from core.rag.retrieval.agent_based_dataset_executor import AgentConfiguration, AgentExecutor
  11. from core.tools.tool.dataset_retriever.dataset_multi_retriever_tool import DatasetMultiRetrieverTool
  12. from core.tools.tool.dataset_retriever.dataset_retriever_tool import DatasetRetrieverTool
  13. from extensions.ext_database import db
  14. from models.dataset import Dataset
  15. class DatasetRetrieval:
  16. def retrieve(self, tenant_id: str,
  17. model_config: ModelConfigWithCredentialsEntity,
  18. config: DatasetEntity,
  19. query: str,
  20. invoke_from: InvokeFrom,
  21. show_retrieve_source: bool,
  22. hit_callback: DatasetIndexToolCallbackHandler,
  23. memory: Optional[TokenBufferMemory] = None) -> Optional[str]:
  24. """
  25. Retrieve dataset.
  26. :param tenant_id: tenant id
  27. :param model_config: model config
  28. :param config: dataset config
  29. :param query: query
  30. :param invoke_from: invoke from
  31. :param show_retrieve_source: show retrieve source
  32. :param hit_callback: hit callback
  33. :param memory: memory
  34. :return:
  35. """
  36. dataset_ids = config.dataset_ids
  37. retrieve_config = config.retrieve_config
  38. # check model is support tool calling
  39. model_type_instance = model_config.provider_model_bundle.model_type_instance
  40. model_type_instance = cast(LargeLanguageModel, model_type_instance)
  41. # get model schema
  42. model_schema = model_type_instance.get_model_schema(
  43. model=model_config.model,
  44. credentials=model_config.credentials
  45. )
  46. if not model_schema:
  47. return None
  48. planning_strategy = PlanningStrategy.REACT_ROUTER
  49. features = model_schema.features
  50. if features:
  51. if ModelFeature.TOOL_CALL in features \
  52. or ModelFeature.MULTI_TOOL_CALL in features:
  53. planning_strategy = PlanningStrategy.ROUTER
  54. dataset_retriever_tools = self.to_dataset_retriever_tool(
  55. tenant_id=tenant_id,
  56. dataset_ids=dataset_ids,
  57. retrieve_config=retrieve_config,
  58. return_resource=show_retrieve_source,
  59. invoke_from=invoke_from,
  60. hit_callback=hit_callback
  61. )
  62. if len(dataset_retriever_tools) == 0:
  63. return None
  64. agent_configuration = AgentConfiguration(
  65. strategy=planning_strategy,
  66. model_config=model_config,
  67. tools=dataset_retriever_tools,
  68. memory=memory,
  69. max_iterations=10,
  70. max_execution_time=400.0,
  71. early_stopping_method="generate"
  72. )
  73. agent_executor = AgentExecutor(agent_configuration)
  74. should_use_agent = agent_executor.should_use_agent(query)
  75. if not should_use_agent:
  76. return None
  77. result = agent_executor.run(query)
  78. return result.output
  79. def to_dataset_retriever_tool(self, tenant_id: str,
  80. dataset_ids: list[str],
  81. retrieve_config: DatasetRetrieveConfigEntity,
  82. return_resource: bool,
  83. invoke_from: InvokeFrom,
  84. hit_callback: DatasetIndexToolCallbackHandler) \
  85. -> Optional[list[BaseTool]]:
  86. """
  87. A dataset tool is a tool that can be used to retrieve information from a dataset
  88. :param tenant_id: tenant id
  89. :param dataset_ids: dataset ids
  90. :param retrieve_config: retrieve config
  91. :param return_resource: return resource
  92. :param invoke_from: invoke from
  93. :param hit_callback: hit callback
  94. """
  95. tools = []
  96. available_datasets = []
  97. for dataset_id in dataset_ids:
  98. # get dataset from dataset id
  99. dataset = db.session.query(Dataset).filter(
  100. Dataset.tenant_id == tenant_id,
  101. Dataset.id == dataset_id
  102. ).first()
  103. # pass if dataset is not available
  104. if not dataset:
  105. continue
  106. # pass if dataset is not available
  107. if (dataset and dataset.available_document_count == 0
  108. and dataset.available_document_count == 0):
  109. continue
  110. available_datasets.append(dataset)
  111. if retrieve_config.retrieve_strategy == DatasetRetrieveConfigEntity.RetrieveStrategy.SINGLE:
  112. # get retrieval model config
  113. default_retrieval_model = {
  114. 'search_method': 'semantic_search',
  115. 'reranking_enable': False,
  116. 'reranking_model': {
  117. 'reranking_provider_name': '',
  118. 'reranking_model_name': ''
  119. },
  120. 'top_k': 2,
  121. 'score_threshold_enabled': False
  122. }
  123. for dataset in available_datasets:
  124. retrieval_model_config = dataset.retrieval_model \
  125. if dataset.retrieval_model else default_retrieval_model
  126. # get top k
  127. top_k = retrieval_model_config['top_k']
  128. # get score threshold
  129. score_threshold = None
  130. score_threshold_enabled = retrieval_model_config.get("score_threshold_enabled")
  131. if score_threshold_enabled:
  132. score_threshold = retrieval_model_config.get("score_threshold")
  133. tool = DatasetRetrieverTool.from_dataset(
  134. dataset=dataset,
  135. top_k=top_k,
  136. score_threshold=score_threshold,
  137. hit_callbacks=[hit_callback],
  138. return_resource=return_resource,
  139. retriever_from=invoke_from.to_source()
  140. )
  141. tools.append(tool)
  142. elif retrieve_config.retrieve_strategy == DatasetRetrieveConfigEntity.RetrieveStrategy.MULTIPLE:
  143. tool = DatasetMultiRetrieverTool.from_dataset(
  144. dataset_ids=[dataset.id for dataset in available_datasets],
  145. tenant_id=tenant_id,
  146. top_k=retrieve_config.top_k or 2,
  147. score_threshold=retrieve_config.score_threshold,
  148. hit_callbacks=[hit_callback],
  149. return_resource=return_resource,
  150. retriever_from=invoke_from.to_source(),
  151. reranking_provider_name=retrieve_config.reranking_model.get('reranking_provider_name'),
  152. reranking_model_name=retrieve_config.reranking_model.get('reranking_model_name')
  153. )
  154. tools.append(tool)
  155. return tools