Repository: antgroup/agentUniverse (language: python)

Issue:
add sql tool
add sql langchain Tool Support


Discussion / hints:

Fix patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6d663bf4..132b6b2f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -24,6 +24,19 @@ Note - Additional remarks regarding the version.
 ***************************************************
 
 # Version Update History
+## [0.0.11] - 2024-07-11
+### Added
+- DataAgent Autonomous Data Agent MVP Version Released
+  - Minimum Viable Product version, DataAgent aims to empower your agent with the capability of self-assessment and evolution through intelligent agent abilities. For detailed information, please refer to the user documentation.
+- Added intermediate information streaming output capabilities in PEER and ReAct modes
+
+### Note
+- Latest PEER research findings released
+  - This paper provides a detailed introduction to the mechanisms and principles of the PEER multi-agent framework. Experimental validation proves the advancement of the PEER model. For detailed information, please refer to the user documentation.
+- Added use cases
+  - Andrew Ng's Reflexive Workflow Translation Agent Replication
+- Some code optimizations and documentation updates.
+
 ## [0.0.10] - 2024-06-28
 ### Added
 - Added standard integration for the DeepSeek model in the LLM module.
diff --git a/CHANGELOG_zh.md b/CHANGELOG_zh.md
index c8fc95c9..999b56eb 100644
--- a/CHANGELOG_zh.md
+++ b/CHANGELOG_zh.md
@@ -24,6 +24,19 @@ Note - 对于版本的额外说明。
 ***************************************************
 
 # 版本更新记录
+## [0.0.11] - 2024-07-11
+### Added
+- DataAgent数据自治智能体MVP版本发布
+  - Minimum Viable Product版本，DataAgent旨在使用智能体能力让您的Agent拥有自我评价与演进的能力，详细内容请查阅用户文档。
+- 增加PEER、ReAct模式中间信息流式输出能力
+
+### Note
+- PEER最新研究成果发布
+  - 该文献详细介绍了介绍了PEER多智能体框架的机制原理，同时在实验部分通过验证证明了PEER模式的先进性，详细内容请查阅用户文档。
+- 新增使用案例
+  - 吴恩达反思工作流翻译智能体复刻
+- 部分代码优化与文档更新
+
 ## [0.0.10] - 2024-06-28
 ### Added
 - LLM组件新增DeepSeek模型标准接入
diff --git a/README.md b/README.md
index 23299e7b..563522c9 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@ Language version: [English](./README.md) | [中文](./README_zh.md) | [日本語
 ![](https://img.shields.io/badge/framework-agentUniverse-pink)
 ![](https://img.shields.io/badge/python-3.10%2B-blue?logo=Python)
 [![](https://img.shields.io/badge/%20license-Apache--2.0-yellow)](LICENSE)
-[![Static Badge](https://img.shields.io/badge/pypi-v0.0.10-blue?logo=pypi)](https://pypi.org/project/agentUniverse/)
+[![Static Badge](https://img.shields.io/badge/pypi-v0.0.11-blue?logo=pypi)](https://pypi.org/project/agentUniverse/)
 
 ![](docs/guidebook/_picture/logo_bar.jpg)
 ****************************************
@@ -35,6 +35,7 @@ More patterns are coming soon...
   * [User Guide](#User-Guide)
   * [API Reference](#API-Reference)
   * [Support](#Support)
+  * [Citation](#Citation)
   * [Acknowledgements](#Acknowledgements)
 ****************************************
 ## Quick Start
@@ -64,6 +65,11 @@ For more details, please read the [Quick Start](./docs/guidebook/en/1_3_Quick_St
 
 [Financial Event Analysis Based on PEER Multi-Agent Mode](./docs/guidebook/en/6_4_1_Financial_Event_Analysis_Case.md)
 
+[Andrew Ng's Reflexive Workflow Translation Agent Replication](./docs/guidebook/en/7_1_1_Translation_Case.md)
+
+#### 🚩 DataAgent - Data Autonomous Agent
+agentUniverse has launched DataAgent (Minimum Viable Product Version). DataAgent aims to empower your agent with the capability of self-assessment and evolution through the use of intelligent agent abilities. For more details, please refer to the documentation. [DataAgent - Data Autonomous Agent](./docs/guidebook/en/8_1_1_data_autonomous_agent.md)
+
 ### 🌟 Example Projects
 [agentUniverse Example Projects](sample_standard_app)
 
@@ -98,11 +104,26 @@ For more details, please read the [Quick Start](./docs/guidebook/en/1_3_Quick_St
 #### Contact Us via Administrator Email
 😊 Email: [jerry.zzw@antgroup.com](mailto:jerry.zzw@antgroup.com)
 
-#### WeChat Official Account
-
-😊 Official Account ID: **agentUniverse智多星** 
-
-You can get more related articles and information in our WeChat Official Account.
+#### twitter
+ID: [@agentuniverse_](https://x.com/agentuniverse_)
+
+### Citation
+The agentUniverse project is supported by the following research achievements.
+
+BibTeX formatted
+```text
+@misc{wang2024peerexpertizingdomainspecifictasks,
+      title={PEER: Expertizing Domain-Specific Tasks with a Multi-Agent Framework and Tuning Methods}, 
+      author={Yiying Wang and Xiaojing Li and Binzhu Wang and Yueyang Zhou and Han Ji and Hong Chen and Jinshi Zhang and Fei Yu and Zewei Zhao and Song Jin and Renji Gong and Wanqing Xu},
+      year={2024},
+      eprint={2407.06985},
+      archivePrefix={arXiv},
+      primaryClass={cs.AI},
+      url={https://arxiv.org/abs/2407.06985}, 
+}
+```
+Overview: This document provides a detailed introduction to the mechanisms and principles of the PEER multi-agent framework. In the experimental section, scores were assigned across seven dimensions: completeness, relevance, conciseness, factualness, logicality, structure, and comprehensiveness (each dimension has a maximum score of 5 points). The PEER model scored higher on average in each evaluation dimension compared to BabyAGI and demonstrated significant advantages in the dimensions of completeness, relevance, logicality, structure, and comprehensiveness. Additionally, the PEER model achieved a superior rate of 83% over BabyAGI using the GPT-3.5 Turbo (16k) model, and 81% using the GPT-4 model. For more details, please refer to the document.
+https://arxiv.org/pdf/2407.06985
 
 ## Acknowledgements
 This project is partially built on excellent open-source projects such as langchain, pydantic, gunicorn, flask, SQLAlchemy, chromadb, etc. (The detailed dependency list can be found in pyproject.toml). We would like to extend special thanks to the related projects and contributors. 🙏🙏🙏
diff --git a/README_zh.md b/README_zh.md
index bf096bbe..4cd29a73 100644
--- a/README_zh.md
+++ b/README_zh.md
@@ -5,7 +5,7 @@
 ![](https://img.shields.io/badge/framework-agentUniverse-pink)
 ![](https://img.shields.io/badge/python-3.10%2B-blue?logo=Python)
 [![](https://img.shields.io/badge/%20license-Apache--2.0-yellow)](LICENSE)
-[![Static Badge](https://img.shields.io/badge/pypi-v0.0.10-blue?logo=pypi)](https://pypi.org/project/agentUniverse/)
+[![Static Badge](https://img.shields.io/badge/pypi-v0.0.11-blue?logo=pypi)](https://pypi.org/project/agentUniverse/)
 
 ![](docs/guidebook/_picture/logo_bar.jpg)
 ****************************************
@@ -34,6 +34,7 @@
   * [用户指南](#用户指南)
   * [API参考](#API参考)
   * [支持](#支持)
+  * [文献](#文献)
   * [鸣谢](#鸣谢)
 ****************************************
 ## 快速开始
@@ -61,6 +62,12 @@ pip install agentUniverse
 
 [基于PEER协同模式的金融事件分析](./docs/guidebook/zh/6_4_1_金融事件分析案例.md)
 
+[吴恩达反思工作流翻译智能体复刻](./docs/guidebook/zh/7_1_1_翻译案例.md)
+
+
+#### 🚩 DataAgent - 数据自治智能体
+agentUniverse推出了DataAgent（Minimum Viable Product版本）, DataAgent旨在使用智能体能力让您的Agent拥有自我评价与演进的能力。详情见文档: [DataAgent - 数据自治智能体](./docs/guidebook/zh/8_1_1_数据自治智能体.md)
+
 ### 🌟 示例项目
 [agentUniverse 示例项目](sample_standard_app)
 
@@ -105,7 +112,30 @@ pip install agentUniverse
 
 😊 公众号ID：**agentUniverse智多星**
 
+![](./docs/guidebook/_picture/wechat_official.png)
+
 更多相关的文章与资讯你可以在微信公众号中获取。
 
+#### twitter
+ID: [@agentuniverse_](https://x.com/agentuniverse_)
+
+### 文献
+agentUniverse项目基于以下的研究成果支撑。
+
+BibTeX formatted
+```text
+@misc{wang2024peerexpertizingdomainspecifictasks,
+      title={PEER: Expertizing Domain-Specific Tasks with a Multi-Agent Framework and Tuning Methods}, 
+      author={Yiying Wang and Xiaojing Li and Binzhu Wang and Yueyang Zhou and Han Ji and Hong Chen and Jinshi Zhang and Fei Yu and Zewei Zhao and Song Jin and Renji Gong and Wanqing Xu},
+      year={2024},
+      eprint={2407.06985},
+      archivePrefix={arXiv},
+      primaryClass={cs.AI},
+      url={https://arxiv.org/abs/2407.06985}, 
+}
+```
+文献简介：该文献详细介绍了介绍了PEER多智能体框架的机制原理，同时在实验部分分别从**完整性、相关性、紧凑性、事实性、逻辑性、结构性和全面性七个维度进行打分（各纬度满分为5分）**，PEER模式在每个测评维度的平均分数均高于BabyAGI，且在**完整性、相关性、逻辑性、结构性和全面性五个纬度有显著优势**；同时PEER模式在 GPT-3.5 turbo (16k) 模型下相较于 BabyAGI 的择优胜率达到 83%，在 GPT-4o 模型下择优胜率达到 81%，更多详情请阅读文献。
+https://arxiv.org/pdf/2407.06985
+
 ## 鸣谢
 本项目部分基于langchain、pydantic、gunicorn、flask、SQLAlchemy、chromadb等（详细依赖列表可见pyproject.toml）优秀开源项目实现，在此特别感谢相关项目与关联方。 🙏🙏🙏
diff --git a/agentuniverse/agent/default/executing_agent/executing_agent.py b/agentuniverse/agent/default/executing_agent/executing_agent.py
index 63ac6a44..4e4a5aa5 100644
--- a/agentuniverse/agent/default/executing_agent/executing_agent.py
+++ b/agentuniverse/agent/default/executing_agent/executing_agent.py
@@ -76,7 +76,8 @@ def execute(self, input_object: InputObject, agent_input: dict) -> dict:
         framework = agent_input.get('framework', [])
         futures = []
         for task in framework:
-            agent_input_copy: dict = copy.deepcopy(agent_input)
+            # note: agent input shallow copy.
+            agent_input_copy: dict = dict(agent_input)
             agent_input_copy['input'] = task
             planner: Planner = PlannerManager().get_instance_obj(self.agent_model.plan.get('planner').get('name'))
             futures.append(
@@ -99,7 +100,8 @@ def process_intput_object(self, input_object: InputObject, subtask: str, planner
         # get agent toolsets.
         action: dict = self.agent_model.action or dict()
         tools: list = action.get('tool') or list()
-        input_object_copy: InputObject = copy.deepcopy(input_object)
+        # note: input object shallow copy.
+        input_object_copy: InputObject = InputObject(input_object.to_dict())
         # wrap input_object for agent knowledge.
         input_object_copy.add_data(planner_input_key, subtask)
         # wrap input_object for agent toolsets.
diff --git a/agentuniverse/agent/memory/chat_memory.py b/agentuniverse/agent/memory/chat_memory.py
index 4e29d158..8eb297ff 100644
--- a/agentuniverse/agent/memory/chat_memory.py
+++ b/agentuniverse/agent/memory/chat_memory.py
@@ -50,17 +50,18 @@ def as_langchain(self) -> BaseChatMemory:
                                                      max_token_limit=self.max_tokens, messages=self.messages,
                                                      prompt_version=self.prompt_version)
 
-    def set_by_agent_model(self, **kwargs) -> None:
+    def set_by_agent_model(self, **kwargs):
         """ Assign values of parameters to the ChatMemory model in the agent configuration."""
-        super().set_by_agent_model(**kwargs)
+        copied_obj = super().set_by_agent_model(**kwargs)
         if 'messages' in kwargs and kwargs['messages']:
-            self.messages = kwargs['messages']
+            copied_obj.messages = kwargs['messages']
         if 'llm' in kwargs and kwargs['llm']:
-            self.llm = kwargs['llm']
+            copied_obj.llm = kwargs['llm']
         if 'input_key' in kwargs and kwargs['input_key']:
-            self.input_key = kwargs['input_key']
+            copied_obj.input_key = kwargs['input_key']
         if 'output_key' in kwargs and kwargs['output_key']:
-            self.output_key = kwargs['output_key']
+            copied_obj.output_key = kwargs['output_key']
+        return copied_obj
 
     def initialize_by_component_configer(self, component_configer: MemoryConfiger) -> 'ChatMemory':
         """Initialize the chat memory by the ComponentConfiger object.
diff --git a/agentuniverse/agent/memory/memory.py b/agentuniverse/agent/memory/memory.py
index a76389d5..edee9235 100644
--- a/agentuniverse/agent/memory/memory.py
+++ b/agentuniverse/agent/memory/memory.py
@@ -40,12 +40,15 @@ def as_langchain(self) -> BaseMemory:
         """Convert the agentUniverse(aU) memory class to the langchain memory class."""
         pass
 
-    def set_by_agent_model(self, **kwargs) -> None:
+    def set_by_agent_model(self, **kwargs):
         """ Assign values of parameters to the Memory model in the agent configuration."""
+        # note: default shallow copy
+        copied_obj = self.model_copy()
         if 'memory_key' in kwargs and kwargs['memory_key']:
-            self.memory_key = kwargs['memory_key']
+            copied_obj.memory_key = kwargs['memory_key']
         if 'max_tokens' in kwargs and kwargs['max_tokens']:
-            self.max_tokens = kwargs['max_tokens']
+            copied_obj.max_tokens = kwargs['max_tokens']
+        return copied_obj
 
     def get_instance_code(self) -> str:
         """Return the full name of the memory."""
diff --git a/agentuniverse/agent/plan/planner/expressing_planner/expressing_planner.py b/agentuniverse/agent/plan/planner/expressing_planner/expressing_planner.py
index 928b723d..6c944d43 100644
--- a/agentuniverse/agent/plan/planner/expressing_planner/expressing_planner.py
+++ b/agentuniverse/agent/plan/planner/expressing_planner/expressing_planner.py
@@ -51,8 +51,8 @@ def invoke(self, agent_model: AgentModel, planner_input: dict, input_object: Inp
             history_messages_key="chat_history",
             input_messages_key=self.input_key,
         ) | StrOutputParser()
-        res = asyncio.run(
-            chain_with_history.ainvoke(input=planner_input, config={"configurable": {"session_id": "unused"}}))
+
+        res = self.invoke_chain(agent_model, chain_with_history, planner_input, chat_history, input_object)
         return {**planner_input, self.output_key: res, 'chat_history': generate_memories(chat_history)}
 
     def handle_prompt(self, agent_model: AgentModel, planner_input: dict) -> Prompt:
diff --git a/agentuniverse/agent/plan/planner/peer_planner/peer_planner.py b/agentuniverse/agent/plan/planner/peer_planner/peer_planner.py
index e552a876..c8de55bb 100644
--- a/agentuniverse/agent/plan/planner/peer_planner/peer_planner.py
+++ b/agentuniverse/agent/plan/planner/peer_planner/peer_planner.py
@@ -42,7 +42,7 @@ def invoke(self, agent_model: AgentModel, planner_input: dict, input_object: Inp
         """
         planner_config = agent_model.plan.get('planner')
         sub_agents = self.generate_sub_agents(planner_config)
-        return self.agents_run(sub_agents, planner_config, planner_input, input_object)
+        return self.agents_run(agent_model, sub_agents, planner_config, planner_input, input_object)
 
     @staticmethod
     def generate_sub_agents(planner_config: dict) -> dict:
@@ -79,7 +79,8 @@ def build_expert_framework(planner_config: dict, input_object: InputObject):
             elif context:
                 input_object.add_data('expert_framework', context)
 
-    def agents_run(self, agents: dict, planner_config: dict, agent_input: dict, input_object: InputObject) -> dict:
+    def agents_run(self, agent_mode: AgentModel, agents: dict, planner_config: dict, agent_input: dict,
+                   input_object: InputObject) -> dict:
         """Planner agents run.
 
         Args:
@@ -125,6 +126,10 @@ def agents_run(self, agents: dict, planner_config: dict, agent_input: dict, inpu
                 for index, one_framework in enumerate(planning_result.get_data('framework')):
                     logger_info += f"[{index + 1}] {one_framework} \n"
                 LOGGER.info(logger_info)
+                self.stream_output(input_object, {"data": {
+                    'output': planning_result.to_dict(),
+                    "agent_info": agent_mode.info
+                }, "type": "planning"})
 
             if not executing_result or jump_step in ["planning", "executing"]:
                 if not executingAgent:
@@ -143,6 +148,10 @@ def agents_run(self, agents: dict, planner_config: dict, agent_input: dict, inpu
                         one_exec_log_info += f"[{index + 1}] output: {one_exec_res['output']}\n"
                         logger_info += one_exec_log_info
                 LOGGER.info(logger_info)
+                self.stream_output(input_object, {"data": {
+                    'output': executing_result.to_dict(),
+                    "agent_info": agent_mode.info
+                }, "type": "executing"})
 
             if not expressing_result or jump_step in ["planning", "executing", "expressing"]:
                 if not expressingAgent:
@@ -157,6 +166,10 @@ def agents_run(self, agents: dict, planner_config: dict, agent_input: dict, inpu
                 logger_info = f"\nExpressing agent execution result is :\n"
                 logger_info += f"{expressing_result.get_data('output')}"
                 LOGGER.info(logger_info)
+                self.stream_output(input_object, {"data": {
+                    'output': expressing_result.get_data('output'),
+                    "agent_info": agent_mode.info
+                }, "type": "expressing"})
 
             if not reviewing_result or jump_step in ["planning", "executing", "expressing", "reviewing"]:
                 if not reviewingAgent:
@@ -172,6 +185,7 @@ def agents_run(self, agents: dict, planner_config: dict, agent_input: dict, inpu
                 else:
                     LOGGER.info(f"Starting reviewing agent.")
                     reviewing_result = reviewingAgent.run(**input_object.to_dict())
+
                     input_object.add_data('reviewing_result', reviewing_result)
 
                     # add reviewing agent log info
@@ -179,7 +193,7 @@ def agents_run(self, agents: dict, planner_config: dict, agent_input: dict, inpu
                     reviewing_info_str = f"review suggestion: {reviewing_result.get_data('suggestion')} \n"
                     reviewing_info_str += f"review score: {reviewing_result.get_data('score')} \n"
                     LOGGER.info(logger_info + reviewing_info_str)
-
+                    self.stream_output(input_object, {"data": reviewing_result.to_dict(), "type": "reviewing"})
                     if reviewing_result.get_data('score') and reviewing_result.get_data('score') >= eval_threshold:
                         loopResults.append({
                             "planning_result": planning_result,
diff --git a/agentuniverse/agent/plan/planner/planner.py b/agentuniverse/agent/plan/planner/planner.py
index c30fd311..4cf36d70 100644
--- a/agentuniverse/agent/plan/planner/planner.py
+++ b/agentuniverse/agent/plan/planner/planner.py
@@ -6,15 +6,18 @@
 # @FileName: planner.py
 """Base class for Planner."""
 from abc import abstractmethod
-import copy
 import logging
-from typing import Optional, List
+from queue import Queue
+from typing import Optional, List, Any
+
+from langchain_core.runnables import RunnableSerializable
 
 from agentuniverse.agent.action.knowledge.knowledge import Knowledge
 from agentuniverse.agent.action.knowledge.knowledge_manager import KnowledgeManager
 from agentuniverse.agent.action.knowledge.store.document import Document
 from agentuniverse.agent.action.knowledge.store.query import Query
 from agentuniverse.agent.action.tool.tool_manager import ToolManager
+from agentuniverse.agent.agent_manager import AgentManager
 from agentuniverse.agent.agent_model import AgentModel
 from agentuniverse.agent.input_object import InputObject
 from agentuniverse.agent.memory.chat_memory import ChatMemory
@@ -27,7 +30,7 @@
 from agentuniverse.llm.llm import LLM
 from agentuniverse.llm.llm_manager import LLMManager
 from agentuniverse.prompt.prompt import Prompt
-from agentuniverse.base.util.memory_util import generate_messages
+from agentuniverse.base.util.memory_util import generate_messages, generate_memories
 
 logging.getLogger().setLevel(logging.ERROR)
 
@@ -84,11 +87,10 @@ def handle_memory(self, agent_model: AgentModel, planner_input: dict) -> ChatMem
         params['input_key'] = self.input_key
         params['output_key'] = self.output_key
 
-        memory: ChatMemory = MemoryManager().get_instance_obj(component_instance_name=memory_name, new_instance=True)
+        memory: ChatMemory = MemoryManager().get_instance_obj(component_instance_name=memory_name)
         if memory is None:
             return None
-        memory.set_by_agent_model(**params)
-        return memory
+        return memory.set_by_agent_model(**params)
 
     def run_all_actions(self, agent_model: AgentModel, planner_input: dict, input_object: InputObject):
         """Tool and knowledge processing.
@@ -101,6 +103,7 @@ def run_all_actions(self, agent_model: AgentModel, planner_input: dict, input_ob
         action: dict = agent_model.action or dict()
         tools: list = action.get('tool') or list()
         knowledge: list = action.get('knowledge') or list()
+        agents: list = action.get('agent') or list()
 
         action_result: list = list()
 
@@ -120,6 +123,16 @@ def run_all_actions(self, agent_model: AgentModel, planner_input: dict, input_ob
             for document in knowledge_res:
                 action_result.append(document.text)
 
+        for agent_name in agents:
+            agent = AgentManager().get_instance_obj(agent_name)
+            if agent is None:
+                continue
+            agent_input = {key: input_object.get_data(key) for key in agent.input_keys()}
+            output_object = agent.run(**agent_input)
+            action_result.append("\n".join([output_object.get_data(key)
+                                            for key in agent.output_keys()
+                                            if output_object.get_data(key) is not None]))
+
         planner_input['background'] = planner_input['background'] or '' + "\n".join(action_result)
 
     def handle_prompt(self, agent_model: AgentModel, planner_input: dict):
@@ -142,9 +155,8 @@ def handle_llm(self, agent_model: AgentModel) -> LLM:
             LLM: The language model.
         """
         llm_name = agent_model.profile.get('llm_model').get('name')
-        llm: LLM = LLMManager().get_instance_obj(component_instance_name=llm_name, new_instance=True)
-        llm.set_by_agent_model(**agent_model.profile.get('llm_model'))
-        return llm
+        llm: LLM = LLMManager().get_instance_obj(component_instance_name=llm_name)
+        return llm.set_by_agent_model(**agent_model.profile.get('llm_model'))
 
     def initialize_by_component_configer(self, component_configer: PlannerConfiger) -> 'Planner':
         """Initialize the planner by the PlannerConfiger object.
@@ -159,3 +171,35 @@ def initialize_by_component_configer(self, component_configer: PlannerConfiger)
         self.input_key = component_configer.input_key or self.input_key
         self.output_key = component_configer.output_key or self.output_key
         return self
+
+    @staticmethod
+    def stream_output(input_object: InputObject, data: dict):
+        """Stream output.
+
+        Args:
+            input_object (InputObject): Agent input object.
+            data (dict): The data to be streamed.
+        """
+        output_stream: Queue = input_object.get_data('output_stream', None)
+        if output_stream is None:
+            return
+        output_stream.put_nowait(data)
+
+    def invoke_chain(self, agent_model: AgentModel, chain: RunnableSerializable[Any, str], planner_input: dict, chat_history,
+               input_object: InputObject):
+
+        if not input_object.get_data('output_stream'):
+            res = chain.invoke(input=planner_input, config={"configurable": {"session_id": "unused"}})
+            return res
+        result = []
+        for token in chain.stream(input=planner_input, config={"configurable": {"session_id": "unused"}}):
+            self.stream_output(input_object, {
+                'type': 'token',
+                'data': {
+                    'chunk': token,
+                    'agent_info': agent_model.info
+                }
+            })
+            result.append(token)
+        return "".join(result)
+
diff --git a/agentuniverse/agent/plan/planner/planning_planner/planning_planner.py b/agentuniverse/agent/plan/planner/planning_planner/planning_planner.py
index 1ca05a0e..d0af3ac4 100644
--- a/agentuniverse/agent/plan/planner/planning_planner/planning_planner.py
+++ b/agentuniverse/agent/plan/planner/planning_planner/planning_planner.py
@@ -52,8 +52,7 @@ def invoke(self, agent_model: AgentModel, planner_input: dict,
             history_messages_key="chat_history",
             input_messages_key=self.input_key,
         ) | StrOutputParser()
-        res = asyncio.run(
-            chain_with_history.ainvoke(input=planner_input, config={"configurable": {"session_id": "unused"}}))
+        res = self.invoke_chain(agent_model, chain_with_history, planner_input, chat_history, input_object)
         return {**planner_input, self.output_key: res, 'chat_history': generate_memories(chat_history)}
 
     def handle_prompt(self, agent_model: AgentModel, planner_input: dict) -> Prompt:
diff --git a/agentuniverse/agent/plan/planner/rag_planner/rag_planner.py b/agentuniverse/agent/plan/planner/rag_planner/rag_planner.py
index 4edb1f6a..984128d6 100644
--- a/agentuniverse/agent/plan/planner/rag_planner/rag_planner.py
+++ b/agentuniverse/agent/plan/planner/rag_planner/rag_planner.py
@@ -5,7 +5,6 @@
 # @Email   : lc299034@antgroup.com
 # @FileName: rag_planner.py
 """Rag planner module."""
-import asyncio
 
 from langchain_core.chat_history import InMemoryChatMessageHistory
 from langchain_core.output_parsers import StrOutputParser
@@ -55,8 +54,7 @@ def invoke(self, agent_model: AgentModel, planner_input: dict,
             history_messages_key="chat_history",
             input_messages_key=self.input_key,
         ) | StrOutputParser()
-        res = asyncio.run(
-            chain_with_history.ainvoke(input=planner_input, config={"configurable": {"session_id": "unused"}}))
+        res = self.invoke_chain(agent_model, chain_with_history, planner_input, chat_history, input_object)
         return {**planner_input, self.output_key: res, 'chat_history': generate_memories(chat_history)}
 
     def handle_prompt(self, agent_model: AgentModel, planner_input: dict) -> ChatPrompt:
diff --git a/agentuniverse/agent/plan/planner/react_planner/react_planner.py b/agentuniverse/agent/plan/planner/react_planner/react_planner.py
index b3f20211..9381b6b5 100644
--- a/agentuniverse/agent/plan/planner/react_planner/react_planner.py
+++ b/agentuniverse/agent/plan/planner/react_planner/react_planner.py
@@ -64,14 +64,14 @@ def invoke(self, agent_model: AgentModel, planner_input: dict,
                                        max_iterations=agent_model.plan.get('planner').get("max_iterations", 15))
 
         return agent_executor.invoke(input=planner_input, memory=memory.as_langchain() if memory else None,
-                                     chat_history=chat_history, config=self.get_run_config(input_object))
+                                     chat_history=chat_history, config=self.get_run_config(agent_model, input_object))
 
     @staticmethod
-    def get_run_config(input_object: InputObject) -> RunnableConfig:
+    def get_run_config(agent_model: AgentModel, input_object: InputObject) -> RunnableConfig:
         config = RunnableConfig()
         callbacks = []
         output_stream = input_object.get_data('output_stream')
-        callbacks.append(StreamOutPutCallbackHandler(output_stream))
+        callbacks.append(StreamOutPutCallbackHandler(output_stream, agent_info=agent_model.info))
         config.setdefault("callbacks", callbacks)
         return config
 
diff --git a/agentuniverse/agent/plan/planner/react_planner/stream_callback.py b/agentuniverse/agent/plan/planner/react_planner/stream_callback.py
index 87ec6acd..e417bb3d 100644
--- a/agentuniverse/agent/plan/planner/react_planner/stream_callback.py
+++ b/agentuniverse/agent/plan/planner/react_planner/stream_callback.py
@@ -16,10 +16,13 @@
 class StreamOutPutCallbackHandler(BaseCallbackHandler):
     """Callback Handler that prints to std out."""
 
-    def __init__(self, queue_stream: asyncio.Queue, color: Optional[str] = None) -> None:
+    def __init__(self, queue_stream: asyncio.Queue, color: Optional[str] = None, agent_info: dict = None) -> None:
         """Initialize callback handler."""
         self.queueStream = queue_stream
         self.color = color
+        if agent_info is None:
+            agent_info = {}
+        self.agent_info = agent_info
 
     def on_chain_start(
             self, serialized: Dict[str, Any], inputs: Dict[str, Any], **kwargs: Any
@@ -32,7 +35,13 @@ def on_chain_end(self, outputs: Dict[str, Any], **kwargs: Any) -> None:
     def on_agent_action(
             self, action: AgentAction, color: Optional[str] = None, **kwargs: Any
     ) -> Any:
-        self.queueStream.put_nowait("Thought:"+action.log)
+        self.queueStream.put_nowait({
+            "type": "ReAct",
+            "data": {
+                "output": "\nThought:" + action.log,
+                "agent_info": self.agent_info
+            }
+        })
 
     def on_tool_end(
             self,
@@ -44,9 +53,21 @@ def on_tool_end(
     ) -> None:
         """If not the final action, print out observation."""
         if observation_prefix is not None:
-            self.queueStream.put_nowait(observation_prefix + output)
+            self.queueStream.put_nowait({
+                "type": "ReAct",
+                "data": {
+                    "output": '\n' + observation_prefix + output,
+                    "agent_info": self.agent_info
+                }
+            })
         else:
-            self.queueStream.put_nowait('Observation:'+output)
+            self.queueStream.put_nowait({
+                "type": "ReAct",
+                "data": {
+                    "output": '\n Observation:' + output,
+                    "agent_info": self.agent_info
+                }
+            })
 
     def on_text(
             self,
@@ -61,4 +82,10 @@ def on_agent_finish(
             self, finish: AgentFinish, color: Optional[str] = None, **kwargs: Any
     ) -> None:
         """Run on agent end."""
-        self.queueStream.put_nowait("Thought:" + finish.log + "\n")
+        self.queueStream.put_nowait({
+            "type": "ReAct",
+            "data": {
+                "output": '\nThought:' + finish.output,
+                "agent_info": self.agent_info
+            }
+        })
diff --git a/agentuniverse/agent/plan/planner/reviewing_planner/reviewing_planner.py b/agentuniverse/agent/plan/planner/reviewing_planner/reviewing_planner.py
index 8702bee7..5f304fb2 100644
--- a/agentuniverse/agent/plan/planner/reviewing_planner/reviewing_planner.py
+++ b/agentuniverse/agent/plan/planner/reviewing_planner/reviewing_planner.py
@@ -51,8 +51,7 @@ def invoke(self, agent_model: AgentModel, planner_input: dict, input_object: Inp
             history_messages_key="chat_history",
             input_messages_key=self.input_key,
         ) | StrOutputParser()
-        res = asyncio.run(
-            chain_with_history.ainvoke(input=planner_input, config={"configurable": {"session_id": "unused"}}))
+        res = self.invoke_chain(agent_model, chain_with_history, planner_input, chat_history, input_object)
         return {**planner_input, self.output_key: res, 'chat_history': generate_memories(chat_history)}
 
     def handle_prompt(self, agent_model: AgentModel, planner_input: dict) -> Prompt:
diff --git a/agentuniverse/agent_serve/web/request_task.py b/agentuniverse/agent_serve/web/request_task.py
index 5f32ae8b..3cb13720 100644
--- a/agentuniverse/agent_serve/web/request_task.py
+++ b/agentuniverse/agent_serve/web/request_task.py
@@ -73,8 +73,13 @@ def receive_steps(self):
                                        ensure_ascii=False) + "\n\n"
         if self.canceled():
             return
-        yield "data:" + json.dumps({"result": self.thread.result()},
-                                   ensure_ascii=False) + "\n\n"
+        try:
+            result = self.thread.result()
+            yield "data:" + json.dumps({"result": result},
+                                       ensure_ascii=False) + "\n\n "
+        except Exception as e:
+            LOGGER.error("request task execute Fail: " + str(e))
+            yield "data:" + json.dumps({"error": {"error_msg": str(e)}}) + "\n\n "
 
     def append_steps(self):
         """Tracing async service running state and update it to database."""
@@ -225,7 +230,7 @@ def finished(self):
         self.__request_do__.state = TaskStateEnum.FINISHED.value
 
     @staticmethod
-    def query_request_state(request_id: str) -> dict|None:
+    def query_request_state(request_id: str) -> dict | None:
         """Query the request data in database by given request_id.
 
         Args:
diff --git a/agentuniverse/agent_serve/web/thread_with_result.py b/agentuniverse/agent_serve/web/thread_with_result.py
index 96414c9c..4d0d030e 100644
--- a/agentuniverse/agent_serve/web/thread_with_result.py
+++ b/agentuniverse/agent_serve/web/thread_with_result.py
@@ -30,6 +30,9 @@ def run(self):
                 self._return = self.target(*self.args, **self.kwargs)
             except Exception as e:
                 self.error = e
+            finally:
+                if 'output_stream' in self.kwargs:
+                    self.kwargs['output_stream'].put('{"type": "EOF"}')
 
     def result(self):
         """Wait for target func finished, then return the result or raise an
diff --git a/agentuniverse/base/annotation/trace.py b/agentuniverse/base/annotation/trace.py
index 428856f1..7c7c2078 100644
--- a/agentuniverse/base/annotation/trace.py
+++ b/agentuniverse/base/annotation/trace.py
@@ -128,11 +128,8 @@ def wrapper_sync(*args, **kwargs):
 
         # invoke function
         result = func(*args, **kwargs)
-        # serialize agent input and output dict
-        agent_input = serialize_agent_invocation(agent_input)
-        agent_output = serialize_agent_invocation(result)
         # add agent invocation info to monitor
-        Monitor().trace_agent_invocation(source=source, agent_input=agent_input, agent_output=agent_output)
+        Monitor().trace_agent_invocation(source=source, agent_input=agent_input, agent_output=result)
         return result
 
     # sync function
@@ -145,16 +142,3 @@ def _get_agent_input(func, *args, **kwargs) -> dict:
     bound_args = sig.bind(*args, **kwargs)
     bound_args.apply_defaults()
     return {k: v for k, v in bound_args.arguments.items()}
-
-
-def default_serializer(obj):
-    if isinstance(obj, InputObject):
-        return obj.to_dict()
-    elif isinstance(obj, OutputObject):
-        return obj.to_dict()
-    raise TypeError(f"Object of type {type(obj).__name__} is not JSON serializable")
-
-
-def serialize_agent_invocation(agent_invocation):
-    agent_invocation_serialized = json.loads(json.dumps(agent_invocation, default=default_serializer))
-    return agent_invocation_serialized
diff --git a/agentuniverse/base/component/component_manager_base.py b/agentuniverse/base/component/component_manager_base.py
index 465e492d..f3ba0efb 100644
--- a/agentuniverse/base/component/component_manager_base.py
+++ b/agentuniverse/base/component/component_manager_base.py
@@ -38,7 +38,7 @@ def unregister(self, component_instance_name: str):
         self._instance_obj_map.pop(component_instance_name)
 
     def get_instance_obj(self, component_instance_name: str,
-                         appname: str = None, new_instance: bool = None) -> ComponentTypeVar:
+                         appname: str = None, new_instance: bool = False) -> ComponentTypeVar:
         """Return the component instance object."""
         appname = appname or ApplicationConfigManager().app_configer.base_info_appname
         instance_code = f'{appname}.{self._component_type.value.lower()}.{component_instance_name}'
diff --git a/agentuniverse/base/util/monitor/monitor.py b/agentuniverse/base/util/monitor/monitor.py
index e69388af..3980583b 100644
--- a/agentuniverse/base/util/monitor/monitor.py
+++ b/agentuniverse/base/util/monitor/monitor.py
@@ -12,6 +12,8 @@
 
 from pydantic import BaseModel
 
+from agentuniverse.agent.input_object import InputObject
+from agentuniverse.agent.output_object import OutputObject
 from agentuniverse.base.annotation.singleton import singleton
 from agentuniverse.base.config.configer import Configer
 
@@ -57,12 +59,6 @@ def trace_llm_invocation(self, source: str, llm_input: Union[str, dict], llm_out
             with jsonlines.open(path_save, 'a') as writer:
                 writer.write(llm_invocation)
 
-    def _get_or_create_subdir(self, subdir: str) -> str:
-        """Get or create a subdirectory if it doesn't exist in the monitor directory."""
-        path = os.path.join(self.dir, subdir)
-        os.makedirs(path, exist_ok=True)
-        return path
-
     def trace_agent_invocation(self, source: str, agent_input: Union[str, dict],
                                agent_output: Union[str, dict]) -> None:
         """Trace the agent invocation and save it to the monitor jsonl file."""
@@ -78,8 +74,8 @@ def trace_agent_invocation(self, source: str, agent_input: Union[str, dict],
             agent_invocation = {
                 "source": source,
                 "date": date.strftime("%Y-%m-%d %H:%M:%S"),
-                "agent_input": agent_input,
-                "agent_output": agent_output,
+                "agent_input": self.serialize_obj(agent_input),
+                "agent_output": self.serialize_obj(agent_output),
             }
             # files are stored in hours
             filename = f"agent_{source}_{date.strftime('%Y-%m-%d-%H')}.jsonl"
@@ -90,3 +86,52 @@ def trace_agent_invocation(self, source: str, agent_input: Union[str, dict],
             with jsonlines.open(path_save, 'a') as writer:
                 writer.write(agent_invocation)
 
+    def _get_or_create_subdir(self, subdir: str) -> str:
+        """Get or create a subdirectory if it doesn't exist in the monitor directory."""
+        path = os.path.join(self.dir, subdir)
+        os.makedirs(path, exist_ok=True)
+        return path
+
+    @staticmethod
+    def default_serializer(obj):
+        """Default serializer for objects."""
+        if isinstance(obj, InputObject):
+            return obj.to_dict()
+        elif isinstance(obj, OutputObject):
+            return obj.to_dict()
+        elif isinstance(obj, BaseModel):
+            try:
+                return obj.dict()
+            except TypeError:
+                raise TypeError(f"Object of type {type(obj).__name__} is not JSON serializable")
+        else:
+            raise TypeError(f"Object of type {type(obj).__name__} is not JSON serializable")
+
+    def serialize_obj(self, obj):
+        """Serialize an object and filter out non-serializable values."""
+        filtered_obj = self.filter_and_serialize(obj)
+        return json.loads(json.dumps(filtered_obj, default=self.default_serializer))
+
+    def filter_and_serialize(self, obj):
+        """Recursively filter out non-serializable values from an object."""
+
+        def is_json_serializable(value):
+            """Check if value is a JSON serializable object."""
+            try:
+                json.dumps(value, default=self.default_serializer)
+                return True
+            except (TypeError, OverflowError):
+                return False
+
+        def filter_dict(d):
+            return {k: v for k, v in d.items() if is_json_serializable(v)}
+
+        def recursive_filter(o):
+            if isinstance(o, dict):
+                return filter_dict({k: recursive_filter(v) for k, v in o.items()})
+            elif isinstance(o, list):
+                return [recursive_filter(i) for i in o if is_json_serializable(i)]
+            else:
+                return o
+
+        return recursive_filter(obj)
diff --git a/agentuniverse/llm/llm.py b/agentuniverse/llm/llm.py
index 4d33c629..b295132d 100644
--- a/agentuniverse/llm/llm.py
+++ b/agentuniverse/llm/llm.py
@@ -107,22 +107,25 @@ def initialize_by_component_configer(self, component_configer: LLMConfiger) -> '
             self._max_context_length = component_configer.configer.value['max_context_length']
         return self
 
-    def set_by_agent_model(self, **kwargs) -> None:
+    def set_by_agent_model(self, **kwargs):
         """ Assign values of parameters to the LLM model in the agent configuration."""
+        # note: default shallow copy
+        copied_obj = self.model_copy()
         if 'model_name' in kwargs and kwargs['model_name']:
-            self.model_name = kwargs['model_name']
+            copied_obj.model_name = kwargs['model_name']
         if 'temperature' in kwargs and kwargs['temperature']:
-            self.temperature = kwargs['temperature']
+            copied_obj.temperature = kwargs['temperature']
         if 'request_timeout' in kwargs and kwargs['request_timeout']:
-            self.request_timeout = kwargs['request_timeout']
+            copied_obj.request_timeout = kwargs['request_timeout']
         if 'max_tokens' in kwargs and kwargs['max_tokens']:
-            self.max_tokens = kwargs['max_tokens']
+            copied_obj.max_tokens = kwargs['max_tokens']
         if 'max_retries' in kwargs and kwargs['max_retries']:
-            self.max_retries = kwargs['max_retries']
+            copied_obj.max_retries = kwargs['max_retries']
         if 'streaming' in kwargs and kwargs['streaming']:
-            self.streaming = kwargs['streaming']
+            copied_obj.streaming = kwargs['streaming']
         if 'max_context_length' in kwargs and kwargs['max_context_length']:
-            self._max_context_length = kwargs['max_context_length']
+            copied_obj._max_context_length = kwargs['max_context_length']
+        return copied_obj
 
     def max_context_length(self) -> int:
         """Max context length.
diff --git a/agentuniverse/llm/openai_llm.py b/agentuniverse/llm/openai_llm.py
index 1839b036..77a7a851 100644
--- a/agentuniverse/llm/openai_llm.py
+++ b/agentuniverse/llm/openai_llm.py
@@ -93,8 +93,7 @@ def call(self, messages: list, **kwargs: Any) -> Union[LLMOutput, Iterator[LLMOu
             **kwargs: Arbitrary keyword arguments.
         """
         streaming = kwargs.pop("streaming") if "streaming" in kwargs else self.streaming
-        if self.client is None:
-            self.client = self._new_client()
+        self.client = self._new_client()
         chat_completion = self.client.chat.completions.create(
             messages=messages,
             model=kwargs.pop('model', self.model_name),
@@ -116,8 +115,7 @@ async def acall(self, messages: list, **kwargs: Any) -> Union[LLMOutput, AsyncIt
             **kwargs: Arbitrary keyword arguments.
         """
         streaming = kwargs.pop("streaming") if "streaming" in kwargs else self.streaming
-        if self.async_client is None:
-            self.async_client = self._new_async_client()
+        self.async_client = self._new_async_client()
         chat_completion = await self.async_client.chat.completions.create(
             messages=messages,
             model=kwargs.pop('model', self.model_name),
@@ -135,17 +133,18 @@ def as_langchain(self) -> BaseLanguageModel:
         """Convert the agentUniverse(aU) openai llm class to the langchain openai llm class."""
         return LangchainOpenAI(self)
 
-    def set_by_agent_model(self, **kwargs) -> None:
+    def set_by_agent_model(self, **kwargs):
         """ Assign values of parameters to the OpenAILLM model in the agent configuration."""
-        super().set_by_agent_model(**kwargs)
+        copied_obj = super().set_by_agent_model(**kwargs)
         if 'openai_api_key' in kwargs and kwargs['openai_api_key']:
-            self.openai_api_key = kwargs['openai_api_key']
+            copied_obj.openai_api_key = kwargs['openai_api_key']
         if 'openai_api_base' in kwargs and kwargs['openai_api_base']:
-            self.openai_api_base = kwargs['openai_api_base']
+            copied_obj.openai_api_base = kwargs['openai_api_base']
         if 'openai_proxy' in kwargs and kwargs['openai_proxy']:
-            self.openai_proxy = kwargs['openai_proxy']
+            copied_obj.openai_proxy = kwargs['openai_proxy']
         if 'openai_client_args' in kwargs and kwargs['openai_client_args']:
-            self.openai_client_args = kwargs['openai_client_args']
+            copied_obj.openai_client_args = kwargs['openai_client_args']
+        return copied_obj
 
     def max_context_length(self) -> int:
         """Max context length.
diff --git a/agentuniverse/llm/openai_style_llm.py b/agentuniverse/llm/openai_style_llm.py
index 0981e47a..bc7deb2d 100644
--- a/agentuniverse/llm/openai_style_llm.py
+++ b/agentuniverse/llm/openai_style_llm.py
@@ -49,7 +49,7 @@ def _new_client(self):
             base_url=self.api_base,
             timeout=self.request_timeout,
             max_retries=self.max_retries,
-            http_client=httpx.Client(proxy=self.openai_proxy) if self.proxy else None,
+            http_client=httpx.Client(proxy=self.proxy) if self.proxy else None,
             **(self.client_args or {}),
         )
 
@@ -121,15 +121,17 @@ def as_langchain(self) -> BaseLanguageModel:
 
     def set_by_agent_model(self, **kwargs) -> None:
         """ Assign values of parameters to the OpenAILLM model in the agent configuration."""
-        super().set_by_agent_model(**kwargs)
+        copied_obj = super().set_by_agent_model(**kwargs)
         if 'api_key' in kwargs and kwargs['api_key']:
-            self.api_key = kwargs['api_key']
+            copied_obj.api_key = kwargs['api_key']
         if 'api_base' in kwargs and kwargs['api_base']:
-            self.api_base = kwargs['api_base']
+            copied_obj.api_base = kwargs['api_base']
         if 'proxy' in kwargs and kwargs['proxy']:
-            self.proxy = kwargs['proxy']
+            copied_obj.proxy = kwargs['proxy']
         if 'client_args' in kwargs and kwargs['client_args']:
-            self.client_args = kwargs['client_args']
+            copied_obj.client_args = kwargs['client_args']
+        return copied_obj
+
 
     @staticmethod
     def parse_result(chunk):
@@ -205,4 +207,3 @@ def max_context_length(self) -> int:
         """Return the maximum length of the context."""
         if super().max_context_length():
             return super().max_context_length()
-        return 4000
diff --git a/docs/guidebook/_picture/data_agent_dataset.png b/docs/guidebook/_picture/data_agent_dataset.png
new file mode 100644
index 00000000..a9e3e3cf
Binary files /dev/null and b/docs/guidebook/_picture/data_agent_dataset.png differ
diff --git a/docs/guidebook/_picture/data_agent_dataset_en.png b/docs/guidebook/_picture/data_agent_dataset_en.png
new file mode 100644
index 00000000..4e710412
Binary files /dev/null and b/docs/guidebook/_picture/data_agent_dataset_en.png differ
diff --git a/docs/guidebook/_picture/data_agent_eval_report.png b/docs/guidebook/_picture/data_agent_eval_report.png
new file mode 100644
index 00000000..26db9d77
Binary files /dev/null and b/docs/guidebook/_picture/data_agent_eval_report.png differ
diff --git a/docs/guidebook/_picture/data_agent_eval_report_en.png b/docs/guidebook/_picture/data_agent_eval_report_en.png
new file mode 100644
index 00000000..2f926b19
Binary files /dev/null and b/docs/guidebook/_picture/data_agent_eval_report_en.png differ
diff --git a/docs/guidebook/_picture/data_agent_eval_report_en_qwen7b.png b/docs/guidebook/_picture/data_agent_eval_report_en_qwen7b.png
new file mode 100644
index 00000000..d1f9a4cb
Binary files /dev/null and b/docs/guidebook/_picture/data_agent_eval_report_en_qwen7b.png differ
diff --git a/docs/guidebook/_picture/data_agent_eval_report_qwen72b.png b/docs/guidebook/_picture/data_agent_eval_report_qwen72b.png
new file mode 100644
index 00000000..19c453de
Binary files /dev/null and b/docs/guidebook/_picture/data_agent_eval_report_qwen72b.png differ
diff --git a/docs/guidebook/_picture/data_agent_eval_result.png b/docs/guidebook/_picture/data_agent_eval_result.png
new file mode 100644
index 00000000..d039405d
Binary files /dev/null and b/docs/guidebook/_picture/data_agent_eval_result.png differ
diff --git a/docs/guidebook/_picture/data_agent_eval_result_en.png b/docs/guidebook/_picture/data_agent_eval_result_en.png
new file mode 100644
index 00000000..45a29f2d
Binary files /dev/null and b/docs/guidebook/_picture/data_agent_eval_result_en.png differ
diff --git a/docs/guidebook/_picture/data_agent_flowchart.jpg b/docs/guidebook/_picture/data_agent_flowchart.jpg
new file mode 100644
index 00000000..cfdd0bfe
Binary files /dev/null and b/docs/guidebook/_picture/data_agent_flowchart.jpg differ
diff --git a/docs/guidebook/_picture/wechat_official.png b/docs/guidebook/_picture/wechat_official.png
new file mode 100644
index 00000000..dc187c18
Binary files /dev/null and b/docs/guidebook/_picture/wechat_official.png differ
diff --git a/docs/guidebook/en/0_index.md b/docs/guidebook/en/0_index.md
index 432fd39d..b17701c7 100644
--- a/docs/guidebook/en/0_index.md
+++ b/docs/guidebook/en/0_index.md
@@ -43,6 +43,8 @@
     * 2.4.4.1 [Logging Component](2_6_Logging_Utils.md)
   * 2.4.5 Data Collection
     * 2.4.5.1 [Monitor Module](2_5_1_Monitor_Module.md)
+  * 2.4.6 Data Autonomous
+    * 2.4.6.1 [Data Autonomous Agent](8_1_1_data_autonomous_agent.md)
 
 **3. Component Reference Manual**
 * 3.1 Domain Components
@@ -89,9 +91,12 @@
 * 6.3 [Discussion Group Based on Multi-Turn Multi-Agent Mode](6_2_1_Discussion_Group.md)
 * 6.4 PEER Multi-Agent Cooperation Examples
   * 6.4.1 [Financial Event Analysis Case](./6_4_1_Financial_Event_Analysis_Case.md)
+* 6.5 [Andrew Ng's Reflexive Workflow Translation Agent Replication](./7_1_1_Translation_Case.md)
 
 **7. Series of Articles**
 
 **8. Frequently Asked Questions (FAQ)**
 
-**[9. Contact Us](6_1_Contact_Us.md)**
+**[9.Citation](9_1_Citation.md)**
+
+**[10. Contact Us](6_1_Contact_Us.md)**
diff --git a/docs/guidebook/en/2_2_2_LLM_component_define_and_usage.md b/docs/guidebook/en/2_2_2_LLM_component_define_and_usage.md
index 1d2f76b9..bf49694f 100644
--- a/docs/guidebook/en/2_2_2_LLM_component_define_and_usage.md
+++ b/docs/guidebook/en/2_2_2_LLM_component_define_and_usage.md
@@ -467,7 +467,7 @@ module: 'agentuniverse.llm.default.default_openai_llm'
 class: 'DefaultOpenAILLM'
 ```
 
-If we need to configure and define an LLM instance based on the `gpt-3.5-turbo model`, with a maximum token limit of 1000 and a retry count of 2 for failures, the configuration would be as follows:
+If we need to configure and define an LLM instance based on the `gpt-3.5-turbo model`, with a maximum token limit of 1000 and a retry count is 2, the configuration would be as follows:
 ```yaml
 name: 'demo_llm'
 description: 'demo openai'
diff --git a/docs/guidebook/en/2_2_5_Memory_Define_And_Use.md b/docs/guidebook/en/2_2_5_Memory_Define_And_Use.md
index 52d08d89..63ac2b36 100644
--- a/docs/guidebook/en/2_2_5_Memory_Define_And_Use.md
+++ b/docs/guidebook/en/2_2_5_Memory_Define_And_Use.md
@@ -62,7 +62,7 @@ You can get the Memory instance corresponding to its name using the `.get_instan
 ```python
 from agentuniverse.agent.memory.memory_manager import MemoryManager
 
-memory = MemoryManager().get_instance_obj(component_instance_name=memory_name, new_instance=True)
+memory = MemoryManager().get_instance_obj(component_instance_name=memory_name)
 ```
 
 # Conclusion
diff --git a/docs/guidebook/en/6_1_Contact_Us.md b/docs/guidebook/en/6_1_Contact_Us.md
index c5a3cf33..64cbba0d 100644
--- a/docs/guidebook/en/6_1_Contact_Us.md
+++ b/docs/guidebook/en/6_1_Contact_Us.md
@@ -1,9 +1,12 @@
-# Contact Us
-* github: https://github.com/alipay/agentUniverse
-* gitee: https://gitee.com/agentUniverse/agentUniverse
-* gitcode: https://gitcode.com/agentUniverse
-* Stack Overflow: https://stackoverflowteams.com/c/agentuniverse/questions
-* Discord: https://discord.gg/VfhEvJzQ
-* WeChat Official Account: agentUniverse智多星
-* DingTalk Group:
-![](../_picture/dingtalk_util20250429.png)
\ No newline at end of file
+### Support
+#### Submit Questions via GitHub Issues
+😊 We recommend submitting your queries using [GitHub Issues](https://github.com/alipay/agentUniverse/issues), we typically respond within 2 days.
+
+#### Contact Us via Discord
+😊 Join our [Discord Channel](https://discord.gg/DHFcdkWAhn) to interact with us.
+
+#### Contact Us via Administrator Email
+😊 Email: [jerry.zzw@antgroup.com](mailto:jerry.zzw@antgroup.com)
+
+#### twitter
+ID: [@agentuniverse_](https://x.com/agentuniverse_)
\ No newline at end of file
diff --git a/docs/guidebook/en/8_1_1_data_autonomous_agent.md b/docs/guidebook/en/8_1_1_data_autonomous_agent.md
new file mode 100644
index 00000000..4b59614d
--- /dev/null
+++ b/docs/guidebook/en/8_1_1_data_autonomous_agent.md
@@ -0,0 +1,169 @@
+# Data Autonomous Agent
+## Introduction
+The comprehensive view of the Data Autonomous Agent: Through **automated batch execution of multiple rounds of agent invocation**, **offline adaptive data collection**, **production of evaluation datasets**, **production of fine-tuning datasets**, **model inference training**, and **automatic multidimensional assessment of datasets**, a complete workflow is established to enhance the data autonomy process of large language models and Agents.
+
+The current agentUniverse has released the **Data Autonomous MVP (Minimum Viable Product) version**, which, based on the **query sets** specified by the user, performs **automated batch execution of multiple rounds of agent invocation**, **produces evaluation datasets**, **automatically assesses datasets in multiple dimensions**, and **generates evaluation reports**. It conveys the concept of data autonomy to the open-source community, and will gradually open up the complete capabilities of the data autonomous workflow in the future.
+
+## Background
+Currently, the evaluation of the performance of Agents within the industry often relies on the expertise of specialists in specific fields to conduct a significant amount of manual review and annotation, ensuring the high quality and accuracy of the assessment results.
+
+The dataAgent hopes to use the agent's own capabilities to **self-collect**, **self-manage**, and **intelligently evaluate the data of the Agent**.
+
+In the MVP version, you can use the `dataset_build_agent` to make multiple rounds of batch invocation on the query sets to be evaluated, producing evaluation datasets. Then, by using the `dataset_eval_agent`, you can apply the **Fin-Eva** data evaluation standards published by Ant Group based on seven dimensions (relevance, factuality, rationality, timeliness, structure, integrity, and comprehensiveness) to conduct intelligent data assessment and annotation. The results of multiple rounds of evaluation are subjected to a rich statistical analysis to provide users with a more intuitive view of the changes in the Agent's capabilities.
+
+By utilizing a complete set of data autonomy capabilities, you can easily understand the current level of your agent through intelligently generated evaluation reports.
+
+It needs to be particularly emphasized that the scores in the entire evaluation report are reference values. In the actual production environment, we will conduct a comprehensive comparison of scores from multiple rounds to distinguish the effectiveness of the agent.
+
+## DataAgent Flowchart
+![data_agent_flowchart](../_picture/data_agent_flowchart.jpg)
+- data_agent consists of two parts. **dataset_build_agent** is responsible for automating batch execution of multiple rounds of agent invocation and producing evaluation datasets.
+- **dataset_eval_agent** is responsible for automating the multidimensional evaluation of the dataset and generating evaluation report.
+
+## DataAgent Execution Steps
+### Step1 Establish Agent Queryset
+In DataAgent, you first need to construct an agent queryset in the JSONL file format, where each line represents a complete input for an agent invocation.
+
+As shown below, establish a queryset of 3 items, where "input" corresponds to the query information for the agent:
+```jsonl
+{"input": "Help me predict the 2024 European Cup championship"}
+{"input": "Can Tesla's stock still be bought?"}
+{"input": "What's the weather in New York today?"}
+```
+
+### Step2 Configure DataAgent
+Configure the DataAgent as follows, the configuration file, in addition to the basic configuration of the agent, mainly includes two important items: `dataset_builder` corresponds to the name of the agent for producing the evaluation dataset, and `dataset_evaluator` corresponds to the name of the agent for dataset evaluation and annotation.
+```yaml
+info:
+  name: 'data_agent'
+  description: 'data agent'
+plan:
+  planner:
+    dataset_builder: 'dataset_build_agent'
+    dataset_evaluator: 'dataset_eval_agent'
+metadata:
+  type: 'AGENT'
+  module: 'sample_standard_app.app.core.agent.data_agent_case.data_agent'
+  class: 'DataAgent'
+```
+[data_agent sample configuration file](../../../sample_standard_app/app/core/agent/data_agent_case/data_agent.yaml)
+
+[data_agent sample python file](../../../sample_standard_app/app/core/agent/data_agent_case/data_agent.py)
+
+### Step3 Configure the agent for producing the evaluation dataset.
+Use the **dataset_build_agent** configured in step2 `dataset_builder`, and the following is the configuration file of dataset_build_agent. In addition to the basic configuration of the agent, the configuration file mainly includes two important items: `candidate` configures the name of the agent to be evaluated (for example, to evaluate the effectiveness of demo_rag_agent, candidate is configured as demo_rag_agent), and `concurrency_level` configures the level of concurrency when executing batch agent invocation (for example, setting it to 5 represents calling the candidate agent concurrently with 5).
+```yaml
+info:
+  name: 'dataset_build_agent'
+  description: 'dataset build agent'
+profile:
+  concurrency_level: 1
+plan:
+  planner:
+    candidate: 'demo_rag_agent'
+metadata:
+  type: 'AGENT'
+  module: 'sample_standard_app.app.core.agent.data_agent_case.dataset_build_agent'
+  class: 'DatasetBuildAgent'
+```
+[dataset_build_agent sample configuration file](../../../sample_standard_app/app/core/agent/data_agent_case/dataset_build_agent.yaml)
+
+[dataset_build_agent sample python file](../../../sample_standard_app/app/core/agent/data_agent_case/dataset_build_agent.py)
+
+### Step4 Configure the agent for dataset evaluation and annotation
+Use the **dataset_eval_agent** configured in step2 `dataset_evaluator`, and the following is the configuration file of dataset_eval_agent. In addition to the basic configuration of the agent, the configuration file mainly includes two important items: `llm_model` configures the agent model, and `max_eval_lines` configures the number of evaluation data lines (for example, setting it to 10 means only evaluate the first 10 rows of data, to avoid global evaluation and the consumption of a large number of tokens).
+```yaml
+info:
+  name: 'dataset_eval_agent'
+  description: 'dataset eval agent'
+profile:
+  prompt_version: dataset_eval_agent.en
+  max_eval_lines: 10
+  llm_model:
+    name: 'demo_llm'
+    model_name: 'gpt-4o'
+    temperature: 0.1
+metadata:
+  type: 'AGENT'
+  module: 'sample_standard_app.app.core.agent.data_agent_case.dataset_eval_agent'
+  class: 'DatasetEvalAgent'
+```
+[dataset_eval_agent sample configuration file](../../../sample_standard_app/app/core/agent/data_agent_case/dataset_eval_agent.yaml)
+
+[dataset_eval_agent sample python file](../../../sample_standard_app/app/core/agent/data_agent_case/dataset_eval_agent.py)
+
+### step5 Run DataAgent
+Through the [dataAgent code entry](../../../sample_standard_app/app/examples/data_agent.py), configure two parameters: `queryset_path` representing the path to the queryset, and `turn` representing the total number of rounds for the queryset execution, to start the dataAgent with one click.
+
+Tips: please configure the queryset and specific evaluation rows reasonably to avoid excessive computational and token consumption.
+
+## DataAgent Example Usage
+Refer to the **DataAgent Execution Steps** mentioned above, and start the configured dataAgent through 5 steps.
+
+### Evaluation Dataset
+First, generate the evaluation dataset, storing the agent's Q&A pairs in the JSONL file format.
+As shown in the figure below:
+- query: agent question 
+- answer: agent answer
+
+![data_agent_dataset](../_picture/data_agent_dataset_en.png)
+
+[dataAgent sample evaluation dataset](../../../sample_standard_app/app/examples/data/dataset_turn_1_2024-07-10-15:06:24.jsonl)
+
+
+### Complete Evaluation Results
+After producing the evaluation dataset, dataAgent begins multidimensional data assessment and annotation, generating complete evaluation results (if multiple rounds of dataAgent batch tasks are executed, multiple complete evaluation results will be produced).
+
+As shown in the figure below:
+- Line Number: The line number of the current evaluation data within the dataset.
+- Overall Score: comprehensive score = total of assessment scores from multiple dimensions / number of assessment dimensions (full score is 5, score range 0-5).
+- Query: agent question.
+- Answer: agent answer.
+- Relevance Score: represents the relevance of the agent answer to the question, the higher the score, the more relevant (full score is 5, score range 0-5).
+- Relevance Suggestion: represents issues and suggestions for improvement in the relevance dimension.
+- More dimensions Score/Suggestion: similar to the Relevance dimension.
+![data_agent_eval_result](../_picture/data_agent_eval_result_en.png)
+
+[dataAgent sample eval result](../../../sample_standard_app/app/examples/data/eval_result_turn_1_2024-07-10-15:06:24.xlsx)
+
+
+
+### Comprehensive Evaluation Report
+Generate a comprehensive evaluation report based on multiple complete evaluation results.
+
+As shown in the figure below:
+- Line Name: Includes two types, such as `Queryset Turn x` representing the evaluation dataset generated in the x-th round based on the queryset, and `Turn Avg Score` representing the average score of multiple rounds and dimensions.
+- Overall Avg Score: The sum of the overall scores of all data in a single round of the dataset / the amount of data in the dataset (full score is 5, score range 0-5).
+- Relevance Avg Score: The sum of the relevance scores of all data in a single round of the dataset / the amount of data in the dataset (full score is 5, score range 0-5).
+- More dimensions Avg Score: similar to the Relevance dimension.
+
+![data_agent_eval_report](../_picture/data_agent_eval_report_en.png)
+
+[dataAgent sample evaluation report](../../../sample_standard_app/app/examples/data/eval_report_2024-07-10-15:06:24.xlsx)
+
+### Comparative Experiment
+Adjust the llm model in demo_rag_agent within aU from the previous `qwen1.5-72b-chat` to `qwen1.5-7b-chat`, and after evaluation by dataAgent, the comprehensive evaluation reports are as follows:
+
+The following figure is the comprehensive evaluation report produced by the data autonomous agent when the model is qwen1.5-7b-chat:
+![data_agent_eval_report](../_picture/data_agent_eval_report_en_qwen7b.png)
+
+The following figure is the comprehensive evaluation report produced by the data autonomous agent when the model is qwen1.5-72b-chat:
+![data_agent_eval_report](../_picture/data_agent_eval_report_en.png)
+Comparing the two comprehensive evaluation reports, it can be observed that after the agent llm model was changed from qwen1.5-7b-chat to qwen1.5-72b-chat, there was a significant increase in the scores across all dimensions in multiple rounds. This method can quickly distinguish the difference in agent effects after the agent configuration was changed.
+
+## DataAgent Detailed Description
+### data_agent
+- [configuration file](../../../sample_standard_app/app/core/agent/data_agent_case/data_agent.yaml)
+- [agent file](../../../sample_standard_app/app/core/agent/data_agent_case/data_agent.py)
+
+### dataset_build_agent
+- [configuration file](../../../sample_standard_app/app/core/agent/data_agent_case/dataset_build_agent.yaml)
+- [agent file](../../../sample_standard_app/app/core/agent/data_agent_case/dataset_build_agent.py)
+- The evaluation data produced by dataset_build_agent is stored locally in jsonl format (the jsonl file name is dataset_turn_{i}_{date}, `i` represents the round, and `date` represents the generation time)
+
+### dataset_eval_agent
+- [configuration file](../../../sample_standard_app/app/core/agent/data_agent_case/dataset_eval_agent.yaml)
+- [agent file](../../../sample_standard_app/app/core/agent/data_agent_case/dataset_eval_agent.py)
+- [prompt file](../../../sample_standard_app/app/core/prompt/dataset_eval_agent_en.yaml)：agentUniverse currently opens six agent evaluation dimensions that are validated in the industry (the MVP version does not open **comprehensive dimension**. The current comprehensive evaluation standard is biased towards the financial field, so it is not mentioned in the open source community)
+- The **complete evaluation results** produced by dataset_eval_agent are stored locally in Excel format (the file name is eval_result_turn_{i}_{date}, `i` represents the round, and `date` represents the generation time)
+- The **comprehensive evaluation report** of dataset_eval_a_agent production is stored locally in Excel format (the file name is eval_report_{date}, and date represents the generation time)
\ No newline at end of file
diff --git a/docs/guidebook/en/9_1_Citation.md b/docs/guidebook/en/9_1_Citation.md
new file mode 100644
index 00000000..3936b644
--- /dev/null
+++ b/docs/guidebook/en/9_1_Citation.md
@@ -0,0 +1,17 @@
+### Citation
+The agentUniverse project is supported by the following research achievements.
+
+BibTeX formatted
+```text
+@misc{wang2024peerexpertizingdomainspecifictasks,
+      title={PEER: Expertizing Domain-Specific Tasks with a Multi-Agent Framework and Tuning Methods}, 
+      author={Yiying Wang and Xiaojing Li and Binzhu Wang and Yueyang Zhou and Han Ji and Hong Chen and Jinshi Zhang and Fei Yu and Zewei Zhao and Song Jin and Renji Gong and Wanqing Xu},
+      year={2024},
+      eprint={2407.06985},
+      archivePrefix={arXiv},
+      primaryClass={cs.AI},
+      url={https://arxiv.org/abs/2407.06985}, 
+}
+```
+Overview: In the experimental section of this study, scores were assigned across seven dimensions: completeness, relevance, conciseness, factualness, logicality, structure, and comprehensiveness (each dimension has a maximum score of 5 points). The PEER model scored higher on average in each evaluation dimension compared to BabyAGI, and demonstrated significant advantages in the dimensions of completeness, relevance, logicality, structure, and comprehensiveness. Additionally, the PEER model achieved an 83% superior rate over BabyAGI using the GPT-3.5 turbo (16k) model, and an 81% superior rate using the GPT-4o model. For more details, please refer to the literature.
+https://arxiv.org/pdf/2407.06985
\ No newline at end of file
diff --git "a/docs/guidebook/zh/0_\347\233\256\345\275\225.md" "b/docs/guidebook/zh/0_\347\233\256\345\275\225.md"
index 9dbf3c8b..fafa18a2 100644
--- "a/docs/guidebook/zh/0_\347\233\256\345\275\225.md"
+++ "b/docs/guidebook/zh/0_\347\233\256\345\275\225.md"
@@ -47,6 +47,8 @@
     * 2.4.4.1 [日志组件](2_4_4_日志组件.md)
   * 2.4.5 数据采集
     * 2.4.5.1 [monitor模块](2_5_1_监控模块.md)
+  * 2.4.6 数据自治
+    * 2.4.6.1 [数据自治智能体](8_1_1_数据自治智能体.md)
 
 **3.组件参考手册**
 * 3.1 领域组件
@@ -93,9 +95,12 @@
 * 6.3 [基于多轮多Agent的讨论小组](6_2_1_讨论组.md)
 * 6.4 PEER多Agent协作案例
   * 6.4.1 [金融事件分析案例](./6_4_1_金融事件分析案例.md)
+* 6.5 [吴恩达反思工作流翻译智能体复刻](./7_1_1_翻译案例.md)
 
 **7.系列文章**
 
 **8.常见问题FAQ**
 
-**[9.联系我们](6_1_联系我们.md)**
+**[9.研究文献](9_1_研究文献.md)**
+
+**[10.联系我们](6_1_联系我们.md)**
diff --git "a/docs/guidebook/zh/2_2_2_\346\250\241\345\236\213\345\256\232\344\271\211\344\270\216\344\275\277\347\224\250.md" "b/docs/guidebook/zh/2_2_2_\346\250\241\345\236\213\345\256\232\344\271\211\344\270\216\344\275\277\347\224\250.md"
index 77f90a8b..1d513e6e 100644
--- "a/docs/guidebook/zh/2_2_2_\346\250\241\345\236\213\345\256\232\344\271\211\344\270\216\344\275\277\347\224\250.md"
+++ "b/docs/guidebook/zh/2_2_2_\346\250\241\345\236\213\345\256\232\344\271\211\344\270\216\344\275\277\347\224\250.md"
@@ -462,7 +462,7 @@ module: 'agentuniverse.llm.default.default_openai_llm'
 class: 'DefaultOpenAILLM'
 ```
 
-假如我们需要配置定义一个基于`gpt-3.5-turbo`模型，最大token限制为1000，失败重试次数未2次的LLM实例，其配置如下:
+假如我们需要配置定义一个基于`gpt-3.5-turbo`模型，最大token限制为1000，失败重试次数为2次的LLM实例，其配置如下:
 ```yaml
 name: 'demo_llm'
 description: 'demo openai'
diff --git "a/docs/guidebook/zh/2_2_5_\350\256\260\345\277\206\345\256\232\344\271\211\344\270\216\344\275\277\347\224\250.md" "b/docs/guidebook/zh/2_2_5_\350\256\260\345\277\206\345\256\232\344\271\211\344\270\216\344\275\277\347\224\250.md"
index 386ea213..b7b5c9b3 100644
--- "a/docs/guidebook/zh/2_2_5_\350\256\260\345\277\206\345\256\232\344\271\211\344\270\216\344\275\277\347\224\250.md"
+++ "b/docs/guidebook/zh/2_2_5_\350\256\260\345\277\206\345\256\232\344\271\211\344\270\216\344\275\277\347\224\250.md"
@@ -64,7 +64,7 @@ chat_history=[{"content": "你好", "type": "human"}, {"content": "你好", "typ
 ```python
 from agentuniverse.agent.memory.memory_manager import MemoryManager
 
-memory = MemoryManager().get_instance_obj(component_instance_name=memory_name, new_instance=True)
+memory = MemoryManager().get_instance_obj(component_instance_name=memory_name)
 ```
 
 # 总结
diff --git "a/docs/guidebook/zh/6_1_\350\201\224\347\263\273\346\210\221\344\273\254.md" "b/docs/guidebook/zh/6_1_\350\201\224\347\263\273\346\210\221\344\273\254.md"
index 86c11e9d..f15bbfc4 100644
--- "a/docs/guidebook/zh/6_1_\350\201\224\347\263\273\346\210\221\344\273\254.md"
+++ "b/docs/guidebook/zh/6_1_\350\201\224\347\263\273\346\210\221\344\273\254.md"
@@ -1,9 +1,24 @@
-# 联系我们
-* github: https://github.com/alipay/agentUniverse
-* gitee: https://gitee.com/agentUniverse/agentUniverse
-* gitcode: https://gitcode.com/agentUniverse
-* Stack Overflow: https://stackoverflowteams.com/c/agentuniverse/questions
-* Discord: https://discord.gg/VfhEvJzQ
-* 微信公众号: agentUniverse智多星
-* 钉钉交流群:
-![](../_picture/dingtalk_util20250429.png)
\ No newline at end of file
+### 支持
+#### 通过github issue提交疑问
+😊 我们建议您使用[github issue](https://github.com/alipay/agentUniverse/issues) 提交您的疑问, 我们通常会在2日内回复。
+
+#### 通过Discord联系我们
+😊 加入我们的 [Discord频道](https://discord.gg/DHFcdkWAhn) 与我们进行交流。
+
+#### 通过钉钉群联系我们
+😊 加入我们的钉钉答疑群与我们联系。
+![](../_picture/dingtalk_util20250429.png)
+
+#### 通过管理员Email联系我们
+😊 Email: [jerry.zzw@antgroup.com](mailto:jerry.zzw@antgroup.com)
+
+#### 微信公众号
+
+😊 公众号ID：**agentUniverse智多星**
+
+![](../_picture/wechat_official.png)
+
+更多相关的文章与资讯你可以在微信公众号中获取。
+
+#### twitter
+ID: [@agentuniverse_](https://x.com/agentuniverse_)
\ No newline at end of file
diff --git "a/docs/guidebook/zh/8_1_1_\346\225\260\346\215\256\350\207\252\346\262\273\346\231\272\350\203\275\344\275\223.md" "b/docs/guidebook/zh/8_1_1_\346\225\260\346\215\256\350\207\252\346\262\273\346\231\272\350\203\275\344\275\223.md"
new file mode 100644
index 00000000..dbfc5277
--- /dev/null
+++ "b/docs/guidebook/zh/8_1_1_\346\225\260\346\215\256\350\207\252\346\262\273\346\231\272\350\203\275\344\275\223.md"
@@ -0,0 +1,172 @@
+# 数据自治智能体
+## 介绍
+
+数据自治智能体全貌：通过**自动化批量执行多轮智能体调用**，**离线自适应数据采集**，**生产评测数据集**，**生产微调数据集**，**模型推理训练**，**数据集多维度自动评估**等完整的workflow，以强化大模型和Agent的数据自治流程。
+
+当前agentUniverse开放了**数据自治MVP（最小可行产品）版本**，根据用户指定的**问题集**，**自动化批量执行多轮智能体调用**，**生产评测数据集**，**数据集多维度自动评估**，**产出评测报告**，将数据自治思想传递到开源社区，后续将陆续开放数据自治workflow完整能力。
+
+## 背景
+
+当前，行业内对Agent智能体效果的测评，通常需要依赖于特定领域的专家进行大量的人工评审和标注，以确保评估结果的高质量和准确性。
+
+dataAgent希望通过智能体本身的能力，对Agent数据进行**自采集、自管理，以及智能化评判**。
+
+在我们开放的mvp版本中，您可以通过`dataset_build_agent`智能体对于待评测的问题集进行多轮次的批量调用，生产评测数据集；之后通过`dataset_eval_agent`智能体采用蚂蚁公布的Fin-Eva数据评测标准基于7个维度（相关性、事实性、合理性、时效性、结构性、整体性、全面性）进行智能体数据评估和标注，将多轮次评测结果进行丰富的统计学分析，以提供给用户更直观的Agent能力变化。
+
+通过一整套数据自治能力，可以非常轻松的通过智能化产出的评测报告，了解到您的智能体当前处于什么水平。
+
+需要特别说明的是，整个评测报告分数为参考值，在实际投产过程中，我们将多轮多次得分进行综合对比，以分辨智能体效果好坏。
+
+
+## dataAgent流程图
+![data_agent_flowchart](../_picture/data_agent_flowchart.jpg)
+- data_agent包含两部分，**dataset_build_agent**负责自动化批量执行多轮智能体调用，生产评测数据集
+- **dataset_eval_agent**负责自动化多维度评估数据集，产出评测报告
+
+## dataAgent执行步骤
+### step1 建立智能体问题集
+在dataAgent中，首先需要构建一个智能体问题集，以jsonl文件格式，其中每一行代表一次智能体调用的完整输入。
+
+如下所示，建立3条问题集，input对应智能体的query信息：
+```jsonl
+{"input": "帮我预测下2024欧洲杯冠军"}
+{"input": "半导体还能继续持有吗"}
+{"input": "北京今天天气如何"}
+```
+### step2 配置dataAgent
+配置dataAgent智能体，如下所示，配置文件除智能体基本配置外，主要包含两个重要项，`dataset_builder`对应生产评测数据集的智能体名称，`dataset_evaluator`对应数据集评估标注的智能体名称。
+```yaml
+info:
+  name: 'data_agent'
+  description: 'data agent'
+plan:
+  planner:
+    dataset_builder: 'dataset_build_agent'
+    dataset_evaluator: 'dataset_eval_agent'
+metadata:
+  type: 'AGENT'
+  module: 'sample_standard_app.app.core.agent.data_agent_case.data_agent'
+  class: 'DataAgent'
+```
+[data_agent配置文件样例地址](../../../sample_standard_app/app/core/agent/data_agent_case/data_agent.yaml)
+
+[data_agent代码地址](../../../sample_standard_app/app/core/agent/data_agent_case/data_agent.py)
+
+### step3 配置生产评测数据集的智能体
+以step2中`dataset_builder`配置的**dataset_build_agent**，如下所示为dataset_build_agent的配置文件，配置文件除智能体基本配置外，主要包含两个重要项，`candidate`配置待评测的智能体名称（如评测demo_rag_agent效果，candidate配置demo_rag_agent），`concurrency_level`配置批量执行智能体调用时的并发度（如配置5，代表并发5调用candidate智能体）
+```yaml
+info:
+  name: 'dataset_build_agent'
+  description: 'dataset build agent'
+profile:
+  concurrency_level: 1
+plan:
+  planner:
+    candidate: 'demo_rag_agent'
+metadata:
+  type: 'AGENT'
+  module: 'sample_standard_app.app.core.agent.data_agent_case.dataset_build_agent'
+  class: 'DatasetBuildAgent'
+```
+[dataset_build_agent配置文件样例地址](../../../sample_standard_app/app/core/agent/data_agent_case/dataset_build_agent.yaml)
+
+[dataset_build_agent代码地址](../../../sample_standard_app/app/core/agent/data_agent_case/dataset_build_agent.py)
+
+### step4 配置数据集评估标注的智能体
+以step2中`dataset_evaluator`配置的**dataset_eval_agent**，如下所示为dataset_eval_agent的配置文件，配置文件除智能体基本配置外，主要包含两个重要项，`llm_model`配置智能体模型，`max_eval_lines`配置评测数据行数（如配置10代表只评估前10条评测数据，避免全局评测，消耗巨大token量）
+```yaml
+info:
+  name: 'dataset_eval_agent'
+  description: 'dataset eval agent'
+profile:
+  prompt_version: dataset_eval_agent.cn
+  max_eval_lines: 10
+  llm_model:
+    name: 'qwen_llm'
+    model_name: 'qwen2-72b-instruct'
+    temperature: 0.1
+metadata:
+  type: 'AGENT'
+  module: 'sample_standard_app.app.core.agent.data_agent_case.dataset_eval_agent'
+  class: 'DatasetEvalAgent'
+```
+[dataset_eval_agent配置文件样例地址](../../../sample_standard_app/app/core/agent/data_agent_case/dataset_eval_agent.yaml)
+
+[dataset_eval_agent代码地址](../../../sample_standard_app/app/core/agent/data_agent_case/dataset_eval_agent.py)
+
+### step5 运行dataAgent
+通过 [dataAgent代码入口](../../../sample_standard_app/app/examples/data_agent.py)，分别配置两个参数，`queryset_path`代表问题集路径，`turn`代表问题集总体执行轮次，一键启动dataAgent。
+
+tips: 请合理配置问题集及具体评测行数，以免造成大量算力及token损耗。
+
+## dataAgent使用示例
+参考上文**dataAgent执行步骤**，通过5步，启动配置好的dataAgent。
+
+### 评测数据集
+首先生成评测数据集，以jsonl文件的格式存储智能体的q&a对。
+如下图所示：
+ - query: 评测数据问题
+ - answer: 评测数据答案
+
+![data_agent_dataset](../_picture/data_agent_dataset.png)
+
+[dataAgent生产的评测数据集样例地址](../../../sample_standard_app/app/examples/data/dataset_turn_1_2024-07-10-10:48:30.jsonl)
+
+### 完整评测结果
+生产评测数据集后，dataAgent开始数据多维度评估标注，产出完整评测结果（若执行多轮dataAgent跑批任务，则产出多个完整评测结果）。
+
+如下图所示: 
+ - Line Number: 当前评测数据在数据集中的行数
+ - Overall Score: 综合分数 = 多个维度的评估分数总和 / 评估维度个数（满分5分，分数范围0-5）
+ - Query: 评测数据问题
+ - Answer: 评测数据答案
+ - 相关性 Score: 代表评测数据答案与问题的相关性，分数越高越相关（满分5分，分数范围0-5）
+ - 相关性 Suggestion: 代表相关性维度存在的问题和改进建议
+ - 更多维度 Score/Suggestion 以此类推
+![data_agent_eval_result](../_picture/data_agent_eval_result.png)
+
+评估节点发现的问题：
+ - 例如第1条数据在**相关性维度的suggestion**: 虽然回答了关于北京天气的问题，但提供的温度单位为华氏度，与国内用户习惯的摄氏度不符，建议转换为摄氏度并提供更全面的天气信息，如湿度、风力等。
+ - 例如第3条数据在**事实性维度的suggestion**: 回答中包含事实错误，如将阿根廷球星莱昂内尔·梅西错误地归入英格兰队。优化建议是确保所有提及的数据和事实准确无误，尤其是在涉及具体人物和事件时。
+
+[dataAgent生产的完整评测结果样例地址](../../../sample_standard_app/app/examples/data/eval_result_turn_1_2024-07-10-10:48:30.xlsx)
+
+### 综合评测报告
+根据多轮完整的评测结果，生成一份综合评测报告。
+
+如下图所示: 
+ - Line Name: 包含两种类型，如`Queryset Turn x`代表根据问题集第x轮生成的评测数据集, `Turn Avg Score`代表多轮多维度的平均分数
+ - Overall Avg Score: 单轮数据集中所有数据的综合分数总和 / 数据集中对应数据量（满分5分，分数范围0-5）
+ - 相关性 Avg Score: 单轮数据集中所有数据的相关性分数总和 / 数据集中对应数据量（满分5分，分数范围0-5）
+ - 更多维度 Avg Score 以此类推
+![data_agent_eval_report](../_picture/data_agent_eval_report.png)
+
+[dataAgent生产的综合评测报告样例地址](../../../sample_standard_app/app/examples/data/eval_report_2024-07-10-10:48:30.xlsx)
+
+### 对比实验
+调整aU中`demo_rag_agent`中的模型从上文生产评测报告时的**qwen1.5-7b-chat**改为**qwen1.5-72b-chat**，通过dataAgent评测后，生成的综合评测报告如下:
+
+下图为模型为qwen1.5-7b-chat时，数据自治智能体产出的综合评测报告:
+![data_agent_eval_report](../_picture/data_agent_eval_report.png)
+
+下图为模型为qwen1.5-72b-chat时，数据自治智能体产出的综合评测报告:
+![data_agent_eval_report](../_picture/data_agent_eval_report_qwen72b.png)
+对比两次综合评测报告，可以看到智能体模型从qwen1.5-7b-chat改为qwen1.5-72b-chat后，各维度多轮评分均存在大幅度上升，以此方法快速分辨智能体配置变更后，智能体效果差异。
+
+
+## dataAgent详细说明
+### data_agent
+- [配置文件](../../../sample_standard_app/app/core/agent/data_agent_case/data_agent.yaml)
+- [智能体文件](../../../sample_standard_app/app/core/agent/data_agent_case/data_agent.py)
+
+### dataset_build_agent
+- [配置文件](../../../sample_standard_app/app/core/agent/data_agent_case/dataset_build_agent.yaml)
+- [智能体文件](../../../sample_standard_app/app/core/agent/data_agent_case/dataset_build_agent.py)
+- dataset_build_agent生产的评测数据以jsonl格式本地存储（jsonl文件名称为dataset_turn_{i}_{date}，`i`代表轮次，`date`代表生成时间）
+
+### dataset_eval_agent
+- [配置文件](../../../sample_standard_app/app/core/agent/data_agent_case/dataset_eval_agent.yaml)
+- [智能体文件](../../../sample_standard_app/app/core/agent/data_agent_case/dataset_eval_agent.py)
+- [提示词文件](../../../sample_standard_app/app/core/prompt/dataset_eval_agent_cn.yaml)：agentUniverse当前开放了6种产业中验证有效的智能体评估标准（MVP版本未开放**全面性维度**，当前全面性评估标准偏向金融领域，故未在开源社区中提及）
+- dataset_eval_agent生产的**完整评测结果**以excel格式本地存储（文件名称为eval_result_turn_{i}_{date}，`i`代表轮次，`date`代表生成时间）
+- dataset_eval_agent生产的**综合评测报告**以excel格式本地存储（文件名称为eval_report_{date}，date代表生成时间）
\ No newline at end of file
diff --git "a/docs/guidebook/zh/9_1_\347\240\224\347\251\266\346\226\207\347\214\256.md" "b/docs/guidebook/zh/9_1_\347\240\224\347\251\266\346\226\207\347\214\256.md"
new file mode 100644
index 00000000..6b333775
--- /dev/null
+++ "b/docs/guidebook/zh/9_1_\347\240\224\347\251\266\346\226\207\347\214\256.md"
@@ -0,0 +1,17 @@
+### 文献
+agentUniverse项目基于以下的研究成果支撑。
+
+BibTeX formatted
+```text
+@misc{wang2024peerexpertizingdomainspecifictasks,
+      title={PEER: Expertizing Domain-Specific Tasks with a Multi-Agent Framework and Tuning Methods}, 
+      author={Yiying Wang and Xiaojing Li and Binzhu Wang and Yueyang Zhou and Han Ji and Hong Chen and Jinshi Zhang and Fei Yu and Zewei Zhao and Song Jin and Renji Gong and Wanqing Xu},
+      year={2024},
+      eprint={2407.06985},
+      archivePrefix={arXiv},
+      primaryClass={cs.AI},
+      url={https://arxiv.org/abs/2407.06985}, 
+}
+```
+文献简介：该文献在研究实验部分分别从**完整性、相关性、紧凑性、事实性、逻辑性、结构性和全面性七个维度进行打分（各纬度满分为5分）**，**PEER模式在每个测评维度的平均分数均高于BabyAGI**，且在**完整性、相关性、逻辑性、结构性和全面性五个纬度有显著优势**；同时PEER模式在 GPT-3.5 turbo (16k) 模型下相较于 BabyAGI 的择优胜率达到 83%，在 GPT-4o 模型下择优胜率达到 81%，更多详情请阅读文献。
+https://arxiv.org/pdf/2407.06985
\ No newline at end of file
diff --git a/pyproject.toml b/pyproject.toml
index d3c32309..4efbd6b2 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
 [tool.poetry]
 name = "agentUniverse"
-version = "0.0.10"
+version = "0.0.11"
 description = "agentUniverse is a framework for developing applications powered by multi-agent base on large language model."
 
 authors = ["AntGroup <jerry.zzw@antgroup.com>"]
diff --git a/sample_standard_app/app/core/agent/data_agent_case/__init__.py b/sample_standard_app/app/core/agent/data_agent_case/__init__.py
new file mode 100644
index 00000000..cc95020c
--- /dev/null
+++ b/sample_standard_app/app/core/agent/data_agent_case/__init__.py
@@ -0,0 +1,7 @@
+# !/usr/bin/env python3
+# -*- coding:utf-8 -*-
+
+# @Time    : 2024/7/3 16:57
+# @Author  : wangchongshi
+# @Email   : wangchongshi.wcs@antgroup.com
+# @FileName: __init__.py.py
diff --git a/sample_standard_app/app/core/agent/data_agent_case/data_agent.py b/sample_standard_app/app/core/agent/data_agent_case/data_agent.py
new file mode 100644
index 00000000..058ebc35
--- /dev/null
+++ b/sample_standard_app/app/core/agent/data_agent_case/data_agent.py
@@ -0,0 +1,86 @@
+# !/usr/bin/env python3
+# -*- coding:utf-8 -*-
+
+# @Time    : 2024/7/1 15:50
+# @Author  : wangchongshi
+# @Email   : wangchongshi.wcs@antgroup.com
+# @FileName: data_agent.py
+import datetime
+
+from agentuniverse.agent.agent import Agent
+from agentuniverse.agent.agent_manager import AgentManager
+from agentuniverse.agent.input_object import InputObject
+from agentuniverse.agent.output_object import OutputObject
+from agentuniverse.base.util.logging.logging_util import LOGGER
+
+
+class DataAgent(Agent):
+    """Data Agent class."""
+
+    def input_keys(self) -> list[str]:
+        """Return the input keys of the Agent."""
+        return ['queryset_path']
+
+    def output_keys(self) -> list[str]:
+        """Return the output keys of the Agent."""
+        return []
+
+    def parse_input(self, input_object: InputObject, agent_input: dict) -> dict:
+        """Agent parameter parsing.
+
+        Args:
+            input_object (InputObject): input parameters passed by the user.
+            agent_input (dict): agent input preparsed by the agent.
+        Returns:
+            dict: agent input parsed from `input_object` by the user.
+        """
+        return {}
+
+    def parse_result(self, planner_result: dict) -> dict:
+        """Planner result parser.
+
+        Args:
+            planner_result(dict): Planner result
+        Returns:
+            dict: Agent result object.
+        """
+        return planner_result
+
+    def execute(self, input_object: InputObject, agent_input: dict):
+        """Execute agent instance.
+
+        Args:
+            input_object (InputObject): input parameters passed by the user.
+            agent_input (dict): agent input parsed from `input_object` by the user.
+        """
+        date = datetime.datetime.now().strftime("%Y-%m-%d-%H:%M:%S")
+        input_object.add_data('date', date)
+
+        # step1: build q&a dataset from the candidate agent which needs to be evaluated.
+        query_answer_list = self.dataset_build_agent(input_object)
+        input_object.add_data('query_answer_list', query_answer_list)
+
+        # step2: evaluate q&a dataset generated by the candidate agent and generate evaluation report.
+        eval_report_list = self.dataset_eval_agent(input_object)
+        return {'query_answer_list': query_answer_list, 'eval_report_list': eval_report_list}
+
+    def dataset_build_agent(self, input_object: InputObject):
+        """Build q&a dataset from the candidate agent which needs to be evaluated."""
+
+        planner = self.agent_model.plan.get('planner', {})
+        dataset_build_agent: Agent = AgentManager().get_instance_obj(planner.get('dataset_builder'))
+        if dataset_build_agent is None:
+            raise ValueError('The agent instance corresponding to `dataset_builder` parameter is empty')
+        output: OutputObject = dataset_build_agent.run(**input_object.to_dict())
+        return output.get_data('query_answer_list', [])
+
+    def dataset_eval_agent(self, input_object: InputObject):
+        """Evaluate q&a dataset generated by the candidate agent and generate evaluation report."""
+
+        planner = self.agent_model.plan.get('planner', {})
+        dataset_eval_agent: Agent = AgentManager().get_instance_obj(planner.get('dataset_evaluator'))
+        if dataset_eval_agent is None:
+            LOGGER.warn("The agent instance corresponding to `dataset_evaluator` parameter is empty")
+            return []
+        output: OutputObject = dataset_eval_agent.run(**input_object.to_dict())
+        return output.get_data('eval_report_json_list', [])
diff --git a/sample_standard_app/app/core/agent/data_agent_case/data_agent.yaml b/sample_standard_app/app/core/agent/data_agent_case/data_agent.yaml
new file mode 100644
index 00000000..0a782015
--- /dev/null
+++ b/sample_standard_app/app/core/agent/data_agent_case/data_agent.yaml
@@ -0,0 +1,11 @@
+info:
+  name: 'data_agent'
+  description: 'data agent'
+plan:
+  planner:
+    dataset_builder: 'dataset_build_agent'
+    dataset_evaluator: 'dataset_eval_agent'
+metadata:
+  type: 'AGENT'
+  module: 'sample_standard_app.app.core.agent.data_agent_case.data_agent'
+  class: 'DataAgent'
\ No newline at end of file
diff --git a/sample_standard_app/app/core/agent/data_agent_case/dataset_build_agent.py b/sample_standard_app/app/core/agent/data_agent_case/dataset_build_agent.py
new file mode 100644
index 00000000..2a5d6ab1
--- /dev/null
+++ b/sample_standard_app/app/core/agent/data_agent_case/dataset_build_agent.py
@@ -0,0 +1,138 @@
+# !/usr/bin/env python3
+# -*- coding:utf-8 -*-
+
+# @Time    : 2024/7/5 15:07
+# @Author  : wangchongshi
+# @Email   : wangchongshi.wcs@antgroup.com
+# @FileName: dataset_build_agent.py
+from concurrent.futures import ThreadPoolExecutor, wait, ALL_COMPLETED
+from typing import Tuple, List, Any, Optional
+
+from agentuniverse.agent.agent import Agent
+from agentuniverse.agent.agent_manager import AgentManager
+from agentuniverse.agent.input_object import InputObject
+from agentuniverse.agent.output_object import OutputObject
+from agentuniverse.base.util.logging.logging_util import LOGGER
+from sample_standard_app.app.util.jsonl_file_utils import JsonFileWriter, JsonFileReader
+
+
+class DatasetBuildAgent(Agent):
+    """Dataset Build Agent class."""
+
+    executor: Optional[Any] = ThreadPoolExecutor(max_workers=1, thread_name_prefix="data_agent")
+
+    def input_keys(self) -> list[str]:
+        """Return the input keys of the Agent."""
+        return ['queryset_path']
+
+    def output_keys(self) -> list[str]:
+        """Return the output keys of the Agent."""
+        return ['query_answer_list']
+
+    def parse_input(self, input_object: InputObject, agent_input: dict) -> dict:
+        """Agent parameter parsing.
+
+        Args:
+            input_object (InputObject): input parameters passed by the user.
+            agent_input (dict): agent input preparsed by the agent.
+        Returns:
+            dict: agent input parsed from `input_object` by the user.
+        """
+        agent_input['queryset_path'] = input_object.get_data('queryset_path')
+        agent_input['turn'] = input_object.get_data('turn', 1)
+        agent_input['candidate'] = input_object.get_data('candidate')
+        return agent_input
+
+    def parse_result(self, planner_result: dict) -> dict:
+        """Planner result parser.
+
+        Args:
+            planner_result(dict): Planner result
+        Returns:
+            dict: Agent result object.
+        """
+        return planner_result
+
+    def execute(self, input_object: InputObject, agent_input: dict):
+        """Execute agent instance.
+
+        Args:
+            input_object (InputObject): input parameters passed by the user.
+            agent_input (dict): agent input parsed from `input_object` by the user.
+        """
+        # init thread pool
+        profile = self.agent_model.profile or {}
+        self.executor = ThreadPoolExecutor(
+            max_workers=profile.get('concurrency_level') if profile.get('concurrency_level') else 1,
+            thread_name_prefix="data_agent")
+
+        # step1: build q&a dataset from the candidate agent which needs to be evaluated.
+        query_answer_list = self.build_dataset(agent_input)
+        input_object.add_data('query_answer_list', query_answer_list)
+
+        LOGGER.info("-------------------------------------------")
+        LOGGER.info("End: build q&a dataset from the candidate agent done.")
+        LOGGER.info("-------------------------------------------")
+
+        # step2: write the q&a dataset to json file.
+        date = input_object.get_data('date', '')
+        for i in range(len(query_answer_list)):
+            one_turn_query_answer_list = query_answer_list[i]
+            json_writer = JsonFileWriter(f'dataset_turn_{i + 1}_{date}')
+            json_writer.write_json_query_answer_list(one_turn_query_answer_list)
+        LOGGER.info(f"Progress: write the q&a dataset to local jsonl files.")
+        return {'query_answer_list': query_answer_list}
+
+    def build_dataset(self, agent_input: dict) -> List[List[Tuple[str, str]]]:
+        """Build q&a dataset from the candidate agent which needs to be evaluated."""
+
+        candidate_agent_name = agent_input.get('candidate') \
+            if agent_input.get('candidate') else self.agent_model.plan.get('planner', {}).get('candidate', '')
+        # get the candidate agent which needs to be evaluated
+        candidate_agent: Agent = AgentManager().get_instance_obj(candidate_agent_name)
+        if not candidate_agent:
+            raise ValueError('The agent instance corresponding to `candidate` parameter is empty')
+
+        # init jsonl file reader
+        jsonl_file_reader = JsonFileReader(agent_input.get('queryset_path'))
+        # read query list
+        query_list = jsonl_file_reader.read_json_obj_list()
+        if not query_list:
+            raise ValueError('query list information read from queryset_path is empty')
+
+        # init the input and output key in agent
+        first_input_key = candidate_agent.input_keys()[0]
+        first_output_key = candidate_agent.output_keys()[0]
+
+        query_answer_list = []
+
+        for i in range(agent_input.get('turn')):
+            LOGGER.info("-------------------------------------------")
+            LOGGER.info(f"Start: build q&a dataset from the candidate agent `{candidate_agent_name}`, turn {i + 1}.")
+            one_turn_query_answer_list = []
+            futures_to_query = {}
+
+            # single turn query and answer processing.
+            for j in range(len(query_list)):
+                query_dict: dict = query_list[j]
+                if query_dict:
+                    # run the target agent
+                    future = self.executor.submit(candidate_agent.run, **query_dict)
+                    futures_to_query[future] = query_dict
+
+            done, not_done = wait(futures_to_query.keys(), return_when=ALL_COMPLETED)
+
+            for future in done:
+                output_object: OutputObject = future.result()
+                # note: the first index of input_keys and output_keys is identified as the prompt and answer.
+                query = futures_to_query.get(future, {}).get(first_input_key, '')
+                answer = output_object.get_data(first_output_key, '')
+
+                one_turn_query_answer_list.append((query, answer))
+                LOGGER.info(f"Progress: the turn {i + 1} query: `{query}` has generated the answer successfully.")
+
+            LOGGER.info(f"End: the turn {i + 1} has generated the answer successfully.")
+
+            # build q&a dataset
+            query_answer_list.append(one_turn_query_answer_list)
+        return query_answer_list
diff --git a/sample_standard_app/app/core/agent/data_agent_case/dataset_build_agent.yaml b/sample_standard_app/app/core/agent/data_agent_case/dataset_build_agent.yaml
new file mode 100644
index 00000000..2d310094
--- /dev/null
+++ b/sample_standard_app/app/core/agent/data_agent_case/dataset_build_agent.yaml
@@ -0,0 +1,12 @@
+info:
+  name: 'dataset_build_agent'
+  description: 'dataset build agent'
+profile:
+  concurrency_level: 1
+plan:
+  planner:
+    candidate: 'demo_rag_agent'
+metadata:
+  type: 'AGENT'
+  module: 'sample_standard_app.app.core.agent.data_agent_case.dataset_build_agent'
+  class: 'DatasetBuildAgent'
\ No newline at end of file
diff --git a/sample_standard_app/app/core/agent/data_agent_case/dataset_eval_agent.py b/sample_standard_app/app/core/agent/data_agent_case/dataset_eval_agent.py
new file mode 100644
index 00000000..0f764e10
--- /dev/null
+++ b/sample_standard_app/app/core/agent/data_agent_case/dataset_eval_agent.py
@@ -0,0 +1,349 @@
+# !/usr/bin/env python3
+# -*- coding:utf-8 -*-
+
+# @Time    : 2024/7/1 17:00
+# @Author  : wangchongshi
+# @Email   : wangchongshi.wcs@antgroup.com
+# @FileName: dataset_eval_agent.py
+from typing import Tuple, List
+
+from langchain_core.output_parsers import StrOutputParser
+from langchain_core.utils.json import parse_json_markdown
+from openpyxl.reader.excel import load_workbook
+import pandas as pd
+
+from agentuniverse.agent.agent import Agent
+from agentuniverse.agent.input_object import InputObject
+from agentuniverse.base.util.logging.logging_util import LOGGER
+from agentuniverse.llm.llm import LLM
+from agentuniverse.llm.llm_manager import LLMManager
+from agentuniverse.prompt.chat_prompt import ChatPrompt
+from agentuniverse.prompt.prompt import Prompt
+from agentuniverse.prompt.prompt_manager import PromptManager
+from agentuniverse.prompt.prompt_model import AgentPromptModel
+
+
+class DatasetEvalAgent(Agent):
+    """Dataset Evaluation Agent class."""
+
+    def input_keys(self) -> list[str]:
+        """Return the input keys of the Agent."""
+        return ['query_answer_list']
+
+    def output_keys(self) -> list[str]:
+        """Return the output keys of the Agent."""
+        return ['eval_report_json_list', 'eval_dims_json_list']
+
+    def parse_input(self, input_object: InputObject, agent_input: dict) -> dict:
+        """Agent parameter parsing.
+
+        Args:
+            input_object (InputObject): input parameters passed by the user.
+            agent_input (dict): agent input preparsed by the agent.
+        Returns:
+            dict: agent input parsed from `input_object` by the user.
+        """
+        agent_input['query_answer_list'] = input_object.get_data('query_answer_list')
+        return agent_input
+
+    def parse_result(self, planner_result: dict) -> dict:
+        """Planner result parser.
+
+        Args:
+            planner_result(dict): Planner result
+        Returns:
+            dict: Agent result object.
+        """
+        return planner_result
+
+    def execute(self, input_object: InputObject, agent_input: dict):
+        """Execute agent instance.
+
+        Args:
+            input_object (InputObject): input parameters passed by the user.
+            agent_input (dict): agent input parsed from `input_object` by the user.
+        """
+        LOGGER.info("-------------------------------------------")
+        LOGGER.info(f"Start: use the evaluator agent to evaluate q&a dataset.")
+        LOGGER.info("-------------------------------------------")
+
+        query_answer_list: List[List[Tuple[str, str]]] = input_object.get_data('query_answer_list')
+        max_eval_lines = self.agent_model.profile.get('max_eval_lines', 100)
+        if len(query_answer_list) == 0:
+            raise ValueError('the `query_answer_list` is empty')
+
+        # step1: evaluate the dataset in multiple dimensions and give specific scores.
+        eval_dims_json_list: List[List[dict]] = self.eval(query_answer_list, max_eval_lines)
+        LOGGER.info(f"End: evaluate the dataset in multiple dimensions done.")
+
+        LOGGER.info("-------------------------------------------")
+        # step2: write the eval results to Excel file.
+        self.generate_eval_results_excel(query_answer_list, eval_dims_json_list, input_object.get_data('date', ''))
+
+        # step3: generate eval report
+        eval_report_json_list = self.generate_eval_report(eval_dims_json_list, input_object.get_data('date', ''))
+        LOGGER.info(f"End: generate evaluation report done.")
+        LOGGER.info("-------------------------------------------")
+        return {'eval_report_json_list': eval_report_json_list, 'eval_dims_json_list': eval_dims_json_list}
+
+    def eval(self, query_answer_list: List[List[Tuple[str, str]]], max_eval_lines: int) -> List[List[dict]]:
+        """Evaluate the dataset in multiple dimensions and give specific scores.
+
+        Args:
+            query_answer_list (List[List[Tuple[str, str]]]): the list of q&a pair from multiple turns,
+            the type of single turn is List[Tuple[str, str]].
+
+            max_eval_lines (int): the maximum number of lines to evaluate.
+
+        Returns:
+            res (List[List[dict]]): the list of eval results from multiple turns,
+            the type of single turn is List[dict].
+        """
+
+        eval_dims_json_list = []
+        # the q&a dataset from multiple turns.
+        for i in range(len(query_answer_list)):
+            line_num = 0
+            one_turn_query_answer_list = query_answer_list[i]
+            one_turn_eval_dims_json_list = []
+
+            # single turn query answer list.
+            for j in range(len(one_turn_query_answer_list)):
+
+                query = one_turn_query_answer_list[j][0]
+                answer = one_turn_query_answer_list[j][1]
+                if query is None or answer is None:
+                    break
+
+                line_num += 1
+                if line_num > max_eval_lines:
+                    break
+
+                if len(query) > 2000:
+                    query = query[0:2000]
+                if len(answer) > 5000:
+                    answer = answer[0:5000]
+
+                version_prompt: ChatPrompt = self.handle_prompt()
+
+                llm: LLM = self.handle_llm()
+
+                chain = version_prompt.as_langchain() | llm.as_langchain() | StrOutputParser()
+                res = chain.invoke(input={'query': query, 'answer': answer})
+
+                dim_score_json = {'line': line_num}
+                dimensions = []
+                overall_score = 0.0
+
+                try:
+                    if res is not None:
+                        data = parse_json_markdown(res)
+                        dimensions = data['dimensions']
+                        # calculate overall score from multiple dimensions.
+                        overall_score = sum(data['score'] for data in dimensions)
+                except Exception as e:
+                    LOGGER.warn(f'except[eval_query_answer_from_jsonl]>>> res: {res}, exception: {e}')
+                    continue
+                if len(dimensions) > 0:
+                    overall_score = overall_score / len(dimensions)
+                dim_score_json['overall_score'] = overall_score
+                dim_score_json['dimensions'] = dimensions
+                LOGGER.info(f"Progress: the turn {i + 1} query line {line_num} has been evaluated successfully.")
+
+                # single line evaluation from multiple dimensions.
+                one_turn_eval_dims_json_list.append(dim_score_json)
+
+            eval_dims_json_list.append(one_turn_eval_dims_json_list)
+        return eval_dims_json_list
+
+    def handle_prompt(self) -> ChatPrompt:
+        """Prompt module processing."""
+        profile: dict = self.agent_model.profile
+
+        profile_prompt_model: AgentPromptModel = AgentPromptModel(introduction=profile.get('introduction'),
+                                                                  target=profile.get('target'),
+                                                                  instruction=profile.get('instruction'))
+
+        # get the prompt by the prompt version
+        prompt_version: str = profile.get('prompt_version')
+        version_prompt: Prompt = PromptManager().get_instance_obj(prompt_version)
+
+        if version_prompt is None and not profile_prompt_model:
+            raise Exception("Either the `prompt_version` or `introduction & target & instruction`"
+                            " in agent profile configuration should be provided.")
+        if version_prompt:
+            version_prompt_model: AgentPromptModel = AgentPromptModel(
+                introduction=getattr(version_prompt, 'introduction', ''),
+                target=getattr(version_prompt, 'target', ''),
+                instruction=getattr(version_prompt, 'instruction', ''))
+            profile_prompt_model = profile_prompt_model + version_prompt_model
+
+        return ChatPrompt().build_prompt(profile_prompt_model, ['introduction', 'target', 'instruction'])
+
+    def handle_llm(self) -> LLM:
+        """Language model module processing.
+
+        Returns:
+            LLM: The language model.
+        """
+        llm_name = self.agent_model.profile.get('llm_model').get('name')
+        llm: LLM = LLMManager().get_instance_obj(component_instance_name=llm_name, new_instance=True)
+        llm.set_by_agent_model(**self.agent_model.profile.get('llm_model'))
+        return llm
+
+    def generate_eval_report(self, eval_dims_json_list: List[List[dict]], date: str):
+        """Integrate multidimensional evaluation scores and generate evaluation report
+
+        Args:
+            eval_dims_json_list (List[List[dict]]) : The list of evaluation results from multiple turns,
+            the type of single turn is List[dict].
+
+            date (str): The date of the evaluation.
+        Returns:
+            eval_report_json_list (List[dict]): The list of evaluation report.
+        """
+        LOGGER.info(f"Start: generate evaluation report.")
+
+        eval_report_json_list = []
+        for i in range(0, len(eval_dims_json_list)):
+            line_num = 0
+            overall_avg_score = 0.0
+            dim_avg_score = {}
+            # single turn eval dim json list.
+            one_turn_eval_dims_json_list = eval_dims_json_list[i]
+            for j in range(0, len(one_turn_eval_dims_json_list)):
+                one_row_eval_dims_json = one_turn_eval_dims_json_list[j]
+                line_num += 1
+
+                overall_avg_score += one_row_eval_dims_json['overall_score']
+                dimensions = one_row_eval_dims_json['dimensions']
+                for k in range(0, len(dimensions)):
+                    name = dimensions[k]['name']
+                    score = dimensions[k]['score']
+                    if name in dim_avg_score:
+                        dim_avg_score[name] += float(score)
+                    else:
+                        dim_avg_score[name] = float(score)
+
+            # calculate single turn overall avg score and dim avg score.
+            for key in dim_avg_score:
+                dim_total_score = dim_avg_score[key]
+                dim_avg_score[key] = dim_total_score / line_num
+            overall_avg_score = overall_avg_score / line_num
+
+            # generate one turn report.
+            one_turn_report = {
+                'line_name': f"Queryset Turn {i + 1}",
+                'overall_avg_score': overall_avg_score,
+                'dim_avg_score': dim_avg_score
+            }
+            LOGGER.info(f"Progress: turn {i + 1} evaluation report has generated successfully.")
+            eval_report_json_list.append(one_turn_report)
+
+        if len(eval_report_json_list) > 1:
+            self.generate_total_eval_report(eval_report_json_list)
+            LOGGER.info(f"Progress: total evaluation report has generated successfully.")
+
+        # generate excel report
+        self.generate_eval_report_excel(eval_report_json_list, date)
+        return eval_report_json_list
+
+    @staticmethod
+    def generate_total_eval_report(eval_report_json_list: List[dict]):
+        """Generate total evaluation report, integrate and calculate the total evaluation score for each turn.
+
+        Args:
+            eval_report_json_list (List[dict]): The list of evaluation report.
+        """
+
+        if len(eval_report_json_list) > 1:
+            total_avg_score = 0.0
+            total_dim_avg_score = {}
+            for i in range(len(eval_report_json_list)):
+                total_avg_score += eval_report_json_list[i]['overall_avg_score']
+                dim_avg_score: dict = eval_report_json_list[i]['dim_avg_score']
+                for key in dim_avg_score:
+                    if key in total_dim_avg_score:
+                        total_dim_avg_score[key] += float(dim_avg_score[key])
+                    else:
+                        total_dim_avg_score[key] = float(dim_avg_score[key])
+            total_avg_score = total_avg_score / len(eval_report_json_list)
+            for key in total_dim_avg_score:
+                total_dim_avg_score[key] = total_dim_avg_score[key] / len(eval_report_json_list)
+            report_line_obj = {
+                'line_name': 'Turn Avg Score',
+                'overall_avg_score': total_avg_score,
+                'dim_avg_score': total_dim_avg_score
+            }
+            eval_report_json_list.append(report_line_obj)
+
+    @staticmethod
+    def generate_eval_results_excel(query_answer_list: List[List[Tuple[str, str]]],
+                                    eval_dims_json_list: List[List[dict]], date: str):
+        """Generate evaluation results in excel format."""
+
+        columns: List[str] = ['Line Number', 'Overall Score', 'Query', 'Answer']
+        if len(eval_dims_json_list) > 0 and len(eval_dims_json_list[0]) > 0:
+            one_row_eval_result = eval_dims_json_list[0][0]
+            dims = one_row_eval_result.get('dimensions', [])
+            # wrap excel columns
+            for dim in dims:
+                columns.append(dim['name'] + ' Score')
+                columns.append(dim['name'] + ' Suggestion')
+
+            for i in range(len(eval_dims_json_list)):
+                one_turn_eval_results = eval_dims_json_list[i]
+                one_turn_query_answers = query_answer_list[i]
+                rows = []
+                # write for each turn
+                for j in range(len(one_turn_eval_results)):
+                    one_row_eval_result = one_turn_eval_results[j]
+                    one_row_query_answer = one_turn_query_answers[j]
+                    # wrap rows.
+                    line_number = one_row_eval_result['line']
+                    overall_score = one_row_eval_result['overall_score']
+                    dims = one_row_eval_result['dimensions']
+
+                    row = [line_number, overall_score, one_row_query_answer[0], one_row_query_answer[1]]
+                    for dim in dims:
+                        row.append(dim['score'])
+                        row.append(dim['suggestion'])
+                    rows.append(row)
+
+                df = pd.DataFrame(rows, columns=columns)
+
+                df.to_excel(f"./data/eval_result_turn_{i + 1}_{date}.xlsx", index=False, engine='openpyxl')
+            LOGGER.info(f"Progress: generate evaluation detailed results in excel format successfully.")
+            LOGGER.info("-------------------------------------------")
+
+    @staticmethod
+    def generate_eval_report_excel(eval_report_json_list: List[dict], date: str):
+        """Generate excel eval report."""
+
+        rows = []
+        columns: List[str] = ['Line Name', 'Overall Avg Score']
+        dim_avg_scores = eval_report_json_list[0]['dim_avg_score']
+        for dim, score in dim_avg_scores.items():
+            columns.append(dim + ' Avg Score')
+        for item in eval_report_json_list:
+            line_name = item['line_name']
+            overall_avg_score = item['overall_avg_score']
+            dim_avg_scores = item['dim_avg_score']
+
+            row = [line_name, overall_avg_score]
+            for dim, score in dim_avg_scores.items():
+                row.append(score)
+            rows.append(row)
+
+        df = pd.DataFrame(rows, columns=columns)
+
+        df.to_excel(f"./data/eval_report_{date}.xlsx", index=False, engine='openpyxl')
+
+        # tweak column width
+        workbook = load_workbook(f"./data/eval_report_{date}.xlsx")
+        worksheet = workbook.active
+        column_widths = [25, 20] + [20] * (len(columns) - 2)
+        for i, column_width in enumerate(column_widths, 1):
+            worksheet.column_dimensions[chr(64 + i)].width = column_width
+        workbook.save(f"./data/eval_report_{date}.xlsx")
+        LOGGER.info(f"Progress: generate evaluation excel file successfully.")
diff --git a/sample_standard_app/app/core/agent/data_agent_case/dataset_eval_agent.yaml b/sample_standard_app/app/core/agent/data_agent_case/dataset_eval_agent.yaml
new file mode 100644
index 00000000..23bf0a46
--- /dev/null
+++ b/sample_standard_app/app/core/agent/data_agent_case/dataset_eval_agent.yaml
@@ -0,0 +1,14 @@
+info:
+  name: 'dataset_eval_agent'
+  description: 'dataset eval agent'
+profile:
+  prompt_version: dataset_eval_agent.cn
+  max_eval_lines: 10
+  llm_model:
+    name: 'qwen_llm'
+    model_name: 'qwen2-72b-instruct'
+    temperature: 0.1
+metadata:
+  type: 'AGENT'
+  module: 'sample_standard_app.app.core.agent.data_agent_case.dataset_eval_agent'
+  class: 'DatasetEvalAgent'
\ No newline at end of file
diff --git a/sample_standard_app/app/core/agent/rag_agent_case/demo_rag_agent.yaml b/sample_standard_app/app/core/agent/rag_agent_case/demo_rag_agent.yaml
index fecdd274..d2641e06 100644
--- a/sample_standard_app/app/core/agent/rag_agent_case/demo_rag_agent.yaml
+++ b/sample_standard_app/app/core/agent/rag_agent_case/demo_rag_agent.yaml
@@ -2,29 +2,9 @@ info:
   name: 'demo_rag_agent'
   description: 'demo rag agent'
 profile:
-  introduction: 你是一位精通信息分析的ai助手。
-  target: 你的目标是判断问题对应的答案是否提供了有价值的信息，并对问题的答案做出建议和评价。
-  instruction: |
-    你需要遵守的规则是:
-    1. 必须使用中文结合查询的背景信息结合你所拥有的知识回答用户提出的问题。
-    2. 结构化答案生成，必要时通过空行提升阅读体验。
-    3. 不采用背景信息中的错误信息。
-    4. 要考虑答案和问题的相关性，不做对问题没有帮助的回答。
-    5. 详尽回答问题，重点突出，不过多花哨词藻。
-    6. 不说模糊的推测。
-    7. 尽量多的使用数值类信息。
-
-    背景信息是:
-    {background}
-  
-    之前的对话:
-    {chat_history}
-    
-    开始!
-
-    需要回答的问题是: {input}
+  prompt_version: demo_rag_agent.cn
   llm_model:
-    name: 'default_qwen_llm'
+    name: 'qwen_llm'
 #    model_name: 'gpt-4o'
 plan:
   planner:
diff --git a/sample_standard_app/app/core/llm/qwen_llm.yaml b/sample_standard_app/app/core/llm/qwen_llm.yaml
index 1115947c..57733656 100644
--- a/sample_standard_app/app/core/llm/qwen_llm.yaml
+++ b/sample_standard_app/app/core/llm/qwen_llm.yaml
@@ -1,6 +1,6 @@
 name: 'qwen_llm'
 description: 'demo qwen llm with spi'
-model_name: 'qwen-max'
+model_name: 'qwen2-72b-instruct'
 max_tokens: 2000
 metadata:
   type: 'LLM'
diff --git a/sample_standard_app/app/core/prompt/dataset_eval_agent_cn.yaml b/sample_standard_app/app/core/prompt/dataset_eval_agent_cn.yaml
new file mode 100644
index 00000000..1588c13a
--- /dev/null
+++ b/sample_standard_app/app/core/prompt/dataset_eval_agent_cn.yaml
@@ -0,0 +1,154 @@
+introduction: ｜
+  你是一个极致严谨的金融专家，需要帮助我按照如下要求在各维度评估query（用户输入）和answer（模型输出）的分数。  
+  
+  每个维度满分为5分，不符合准入条件直接判0分，符合门槛值加0-3分，如果再符合加分项要求，在门槛值的分数基础上再加0-2分。
+  打分要求，请精确到小数点后1位：
+  1.不符合准入条件（0.0分）
+  2.门槛值（0.0～3.0分）
+  3.加分项（0.0～2.0分）
+  
+  注意：严格打分，不能轻松给出高分
+instruction: |
+  --------------------------------
+    query:
+    {query}
+
+    --------------------------------
+    answer:
+    {answer}
+
+    --------------------------------
+    质量打分共6个维度，每个维度包含了不符合准入条件的要求（0.0分）/门槛值的要求（0.0～3.0分）/加分项（0.0～2.0分）
+    
+    质量打分维度描述如下:
+
+    dimension name: 相关性 
+    dimension requirement: 
+      1.不符合准入条件
+      答非所问，不相关
+
+      2.门槛值
+      能够知道到用户在问什么，并且所答即所问，包括：
+      
+      【有明确意图时】
+      识别出用户的问题并对问题有回复，且回复的内容有相关性
+      有主意图的时候，回复的内容要与主意图有相关
+      
+      【无明确意图时】
+      遇到模糊意图时进行恰当的意图反问确认，并给予准确回应
+
+      3.加分项
+      能够理解到用户在问什么问题后：
+      a、对用户的所有问题（包含情绪）都给出回应
+      b、回应的内容整体相关性都很高
+      c、回复的问题全面且易懂
+
+    --------------------------------
+    dimension name: 事实性 
+    dimension requirement: 
+      1.不符合准入条件
+      数据错误，不符合事实
+
+      2.门槛值
+      仅几个数据不准确，但不影响整体事实性
+
+      3.加分项
+      解读内容中所有引用数据真实可信，数据来源官方可信
+    --------------------------------
+
+    dimension name: 合理性 
+    dimension requirement: 
+      1.不符合准入条件
+      出现专业错误
+
+      2.门槛值
+      符合业内公认的事实逻辑，前后结论不要自相矛盾，不出现明显的专业错误
+
+      3.加分项
+      通篇解读要一以贯之、逻辑自洽，且逻辑推演是有逐层递进的（后文分析以前文结论为依据）
+
+    --------------------------------
+    dimension name: 时效性 
+    dimension requirement: 
+      1.不符合准入条件
+      数据陈旧过时，不符合现状
+
+      2.门槛值
+      数据次新，符合当下现状
+
+      3.加分项
+      引用官方发布的最新数据，包含清晰的发布日期
+
+    --------------------------------
+    dimension name: 结构性 
+    dimension requirement: 
+      1.不符合准入条件
+      答案如果是总分结构：
+        a、总论点和分论点只是抽取了原文中的部分内容，并没有真正的总结归纳
+        b、生成答案结构是总分结构，但是分论点是为了回答query而硬答，与query实际并没有关系
+        c、总结内容论点逻辑冲突
+  
+      答案如果是总结摘要结构：
+        a、摘要内容是抽取了部分段落，并没有真正的归纳总结
+        b、摘要内容，仅仅总结成一段文本，无摘要详述
+      
+      2.门槛值
+      答案如果是总分结构：
+        a、总分结构，有总结归纳，分论点有层次
+        b、答案总分结构，分论点之间有逻辑关系（互补、递进），分论点与query之间有相关性
+        c、总结的内容论点间无冲突
+  
+      答案如果是总结摘要结构：
+        a、总结内容有对原文进行归纳总结，不是抽取的原文段落
+        b、总结内容论点有展开叙述
+      
+      3.加分项
+      答案如果是总分结构：
+        a、总分结构，分论点有归类，有条理有逻辑
+        b、总分结构，分论点为1234分层结构，有条理
+  
+      答案如果是总结摘要结构：
+        a、总结内容论点叙述详细充分，有逻辑有条理
+        b、总结内容话术表达逻辑清晰，表达精炼
+    --------------------------------
+    dimension name: 整体性 
+    dimension requirement: 
+      1.不符合准入条件
+      满足以下任意一点，分数为0：
+        a、逻辑不通顺，或存在语法问题，或表达冗余内容超长
+        b、论点和论点之间存在重复：任意两条论点存在80%以上的重复度
+        c、答案存在倒装、错别字、语句不通顺、逻辑问题等
+        d、答案中存在特殊符号
+
+      2.门槛值
+        a、语句流畅、表达可阅读性强
+        b、答案表达直白（不反复说车轱辘话）
+        c、论点和论据在表达上无重复
+
+      3.加分项
+        a、答案对用户query有明确回应表达
+        b、语言简洁精炼，逻辑清晰
+
+    --------------------------------
+    输出格式要求：
+    1.根据具体打分维度要求，同时评价query和answer内容，进行打分。
+    2. 一定要给出suggestion，结合query和answer，给出具体的扣分原因和具体的优化建议。
+
+    请严格按照质量打分维度要求打分，不能轻松给出高分，请确保输出只包含如下的json格式字段，且每个字段不能为空:
+    {{
+      "dimensions": [
+          {{
+              "name":质量打分维度名称(string字符串格式),
+              "score":分数(float浮点数格式),
+              "suggestion":扣分的原因和给出的优化建议(string字符串格式)
+          }},
+          {{
+              "name":质量打分维度名称(string字符串格式),
+              "score":分数(float浮点数格式),
+              "suggestion":扣分的原因和给出的优化建议(string字符串格式)
+          }}
+      ]
+    }}
+metadata:
+  type: 'PROMPT'
+  version: 'dataset_eval_agent.cn'
diff --git a/sample_standard_app/app/core/prompt/dataset_eval_agent_en.yaml b/sample_standard_app/app/core/prompt/dataset_eval_agent_en.yaml
new file mode 100644
index 00000000..e09ad617
--- /dev/null
+++ b/sample_standard_app/app/core/prompt/dataset_eval_agent_en.yaml
@@ -0,0 +1,158 @@
+introduction: |
+  You are an extremely rigorous financial expert and need help me evaluate query (user input) and answer (model output) scores in various dimensions according to the following requirements.   
+
+  The full score for each dimension is 5 points. If you do not meet the entry conditions, you will be awarded 0 points directly, and if you meet the threshold value, you will be awarded 0-3 points. If you meet the additional requirements, you will add 0-2 points to the threshold value.
+  For scoring requirements, please be accurate to 1 decimal place:
+  1. Failure to meet access conditions (0.0 point)
+  2. Threshold value (0.0 - 3.0 points)
+  3. Bonus points (0.0 - 2.0 points)
+  
+  Note: Strict scoring and high scores cannot be easily given
+instruction: |
+  --------------------------------
+    query:
+    {query}
+
+    --------------------------------
+    answer:
+    {answer}
+
+    --------------------------------
+    There are 6 dimensions in quality scoring, each dimension contains requirements for non-compliance with access conditions (0.0 points)/threshold values (0.0 - 3.0 points)/bonus points (0.0 - 2.0 points)
+    
+    The quality scoring dimensions are described as follows:
+
+    dimension name: Relevance 
+    dimension requirement: 
+      1. non-compliance with access conditions
+      Answer is irrelevant.
+
+      2.threshold values
+      Being able to know what the user is asking, and the answer is exactly what the user is asking, including：
+  
+      【When there is a clear intention】
+      Identify user questions and respond to the questions, and the content of the reply is relevant.
+      When the question has the main intention, the reply content should be related to the main intention.
+  
+      【Without clear intention】
+      Conduct appropriate rhetorical confirmation of intention when encountering vague intentions and then give an accurate response.
+
+      3.bonus points
+      After being able to understand what questions users ask:
+      a、Respond to all user questions (including emotions)
+      b、The overall relevance of the response is very high
+      c、The answers are comprehensive and easy to understand
+
+    --------------------------------
+    dimension name: Factuality 
+    dimension requirement: 
+      1. non-compliance with access conditions
+      The data is wrong and does not conform to the facts
+
+      2.threshold values
+      Only a few data are inaccurate, but they do not affect the overall factual nature
+
+      3.bonus points
+      All quoted data in the interpretation content are true and credible, and the data source is officially credible
+    
+    --------------------------------
+    dimension name: Rationality 
+    dimension requirement: 
+      1. non-compliance with access conditions
+      Professional error occurred
+
+      2.threshold values
+      Adhere to the factual logic recognized by the industry, ensure that the conclusions are consistent and do not contradict each other, and avoid obvious professional errors.
+
+      3.bonus points
+      
+    The interpretation throughout the text must be consistent and logically coherent, with the logical reasoning advancing step by step (subsequent analysis is based on previous conclusions).
+
+    --------------------------------
+    dimension name: Timeliness 
+    dimension requirement: 
+      1. non-compliance with access conditions
+      The data is stale and no longer corresponds to the present reality.
+
+      2.threshold values
+      The data is relatively recent and aligns with the current situation.
+
+      3.bonus points
+      Cite the latest official data, including a clear publication date.
+
+    --------------------------------
+    dimension name: Structure
+    dimension requirement: 
+      1. non-compliance with access conditions
+      If the answer follows a general-specific structure:
+        a、The main thesis and sub-theses only extract parts of the content from the original text and do not truly summarize or generalize.
+        b、The structure of the answer is general-specific, but the sub-points are forced to respond to the query without actually being related to it.
+        c、The summary of the content has logical conflicts in the argument points.
+  
+      If the answer is a summary abstract structure:
+        a、The abstract content is extracted from certain paragraphs and does not truly synthesize or summarize.
+        b、The abstract content is merely summarized into a single paragraph, without a detailed abstract.
+        
+      2.threshold values
+      If the answer follows a general-specific structure:
+        a、The structure is general-specific, with summarization, and the sub-points are hierarchically organized.
+        b、The answer has a general-specific structure, with sub-points that have logical relationships (complementary, progressive), and the sub-points are relevant to the query.
+        c、Summary content without conflict between arguments
+  
+      If the answer is a summary structure:
+        a、The summary content summarizes the original text, not extracted original paragraphs
+        b、The summary content and arguments are described in an expanded manner
+      
+      3.bonus points
+      If the answer follows a general-specific structure:
+        a、The structure is general-specific, with categorized sub-points that are orderly and logical.
+        b、The structure is general-specific, with the main points organized in a hierarchical structure labeled 1, 2, 3, and 4, which is orderly.
+  
+      If the answer is a summary structure:
+        a、The summary content and arguments are detailed and sufficient, logical and organized
+        b、The summary should be expressed with clear logic and concise language.
+    
+    --------------------------------
+    dimension name: Integrity 
+    dimension requirement: 
+      1. non-compliance with access conditions
+      If any of the following points are satisfied, the score is 0:
+        a、Logic is not smooth, or there are grammatical problems, or redundant content is expressed too long
+        b、Repetition between arguments: Any two arguments have more than 80% repetition
+        c、The answers include inversion, typos, inconsistent sentences, logical problems, etc.
+        d、There are special symbols in the answer
+
+      2.threshold values
+        a、Smooth sentences and highly readable expressions
+        b、Express the answer directly (do not repeat it over and over again)
+        c、The thesis and evidence should be expressed without repetition.
+
+      3.bonus points
+        a、The answer is clearly expressed in response to user query
+        b、The language is concise, and the logic is clear
+
+    --------------------------------
+    Output format requirements:
+    1. According to the specific scoring dimension requirements, evaluate query and answer content at the same time and score.
+    2. Be sure to give the suggestion, combine query and answer, and give specific reasons for deducting points and specific optimization suggestions.
+
+    Please score strictly in accordance with the quality scoring dimensions. High scores cannot be easily given. 
+    Please ensure that the output only contains the following json format fields, and each field cannot be empty:
+  
+    {{
+      "dimensions": [
+          {{
+              "name": dimension name(string),
+              "score": score(float),
+              "suggestion": Reasons for deductions and optimization suggestions given in English(string)
+          }},
+          {{
+              "name": dimension name(string),
+              "score": score(float),
+              "suggestion": Reasons for deductions and optimization suggestions given in English(string)
+          }}
+      ]
+    }}
+metadata:
+  type: 'PROMPT'
+  version: 'dataset_eval_agent.en'
diff --git a/sample_standard_app/app/core/prompt/demo_rag_agent_cn.yaml b/sample_standard_app/app/core/prompt/demo_rag_agent_cn.yaml
new file mode 100644
index 00000000..cda9228f
--- /dev/null
+++ b/sample_standard_app/app/core/prompt/demo_rag_agent_cn.yaml
@@ -0,0 +1,24 @@
+introduction: 你是一位精通信息分析的ai助手。
+target: 你的目标是使用中文结合查询的背景信息及你所拥有的知识回答用户提出的问题。
+instruction: |
+  你需要遵守的规则是:
+  1. 必须使用中文结合查询的背景信息结合你所拥有的知识回答用户提出的问题。
+  2. 结构化答案生成，必要时通过空行提升阅读体验。
+  3. 不采用背景信息中的错误信息。
+  4. 要考虑答案和问题的相关性，不做对问题没有帮助的回答。
+  5. 详尽回答问题，重点突出，不过多花哨词藻。
+  6. 不说模糊的推测。
+  7. 尽量多的使用数值类信息。
+  
+  背景信息是:
+  {background}
+  
+  之前的对话:
+  {chat_history}
+  
+  开始!
+  
+  需要回答的问题是: {input}
+metadata:
+  type: 'PROMPT'
+  version: 'demo_rag_agent.cn'
diff --git a/sample_standard_app/app/core/prompt/demo_rag_agent_en.yaml b/sample_standard_app/app/core/prompt/demo_rag_agent_en.yaml
new file mode 100644
index 00000000..c3b96de8
--- /dev/null
+++ b/sample_standard_app/app/core/prompt/demo_rag_agent_en.yaml
@@ -0,0 +1,25 @@
+introduction:  You are an ai assistant who is proficient in information analysis.
+target: Your goal is to use English to combine the background information of the query and your knowledge to answer questions raised by users.
+instruction: |
+  The rules you need to follow are:
+  1. You must use English combined with the background information of the query and your knowledge to answer the questions raised by the user.
+  2. Structured answer generation and use blank lines to improve the reading experience if necessary.
+  3. Do not use background information that is incorrect.
+  4. Consider the relevance of the answer and question, do not answer questions that do not help.
+  5. Answer questions in detail, with emphasis on key points.
+  6. Do not make vague inferences.
+  7. Try to use numerical information as much as possible.
+  8. The answer should not exceed 500 words
+  
+  Background is:
+  {background}
+  
+  Previous conversations are:
+  {chat_history}
+  
+  Begin!
+  
+  The question needs to be answered is: {input}
+metadata:
+  type: 'PROMPT'
+  version: 'demo_rag_agent.en'
\ No newline at end of file
diff --git a/sample_standard_app/app/core/tool/langchain_tool/info_sql_database_tool.yaml b/sample_standard_app/app/core/tool/langchain_tool/info_sql_database_tool.yaml
new file mode 100644
index 00000000..7ceba6e2
--- /dev/null
+++ b/sample_standard_app/app/core/tool/langchain_tool/info_sql_database_tool.yaml
@@ -0,0 +1,13 @@
+name: 'info_sql_database_tool'
+description: ''
+tool_type: 'api'
+input_keys: ['input']
+langchain:
+  module: langchain_community.tools
+  class_name: InfoSQLDatabaseTool
+  init_params:
+    db_wrapper: demo_sqldb_wrapper
+metadata:
+  type: 'TOOL'
+  module: 'sample_standard_app.app.core.tool.langchain_tool.sql_langchain_tool'
+  class: 'SqlLangchainTool'
\ No newline at end of file
diff --git a/sample_standard_app/app/core/tool/langchain_tool/langchain_tool.py b/sample_standard_app/app/core/tool/langchain_tool/langchain_tool.py
index 5a8a3d7a..91ad7f41 100644
--- a/sample_standard_app/app/core/tool/langchain_tool/langchain_tool.py
+++ b/sample_standard_app/app/core/tool/langchain_tool/langchain_tool.py
@@ -29,7 +29,7 @@ def execute(self, tool_input: ToolInput):
     def initialize_by_component_configer(self, component_configer: ToolConfiger) -> 'Tool':
         super().initialize_by_component_configer(component_configer)
         self.tool = self.init_langchain_tool(component_configer)
-        if not component_configer.description:
+        if not component_configer.description and self.tool is not None:
             self.description = self.tool.description
         return self
 
diff --git a/sample_standard_app/app/core/tool/langchain_tool/list_sql_database_tool.yaml b/sample_standard_app/app/core/tool/langchain_tool/list_sql_database_tool.yaml
new file mode 100644
index 00000000..e2852d0b
--- /dev/null
+++ b/sample_standard_app/app/core/tool/langchain_tool/list_sql_database_tool.yaml
@@ -0,0 +1,13 @@
+name: 'list_sql_database_tool'
+description: ''
+tool_type: 'api'
+input_keys: ['input']
+langchain:
+  module: langchain_community.tools
+  class_name: ListSQLDatabaseTool
+  init_params:
+    db_wrapper: demo_sqldb_wrapper
+metadata:
+  type: 'TOOL'
+  module: 'sample_standard_app.app.core.tool.langchain_tool.sql_langchain_tool'
+  class: 'SqlLangchainTool'
\ No newline at end of file
diff --git a/sample_standard_app/app/core/tool/langchain_tool/query_sql_database_tool.yaml b/sample_standard_app/app/core/tool/langchain_tool/query_sql_database_tool.yaml
new file mode 100644
index 00000000..e2f739a7
--- /dev/null
+++ b/sample_standard_app/app/core/tool/langchain_tool/query_sql_database_tool.yaml
@@ -0,0 +1,13 @@
+name: 'query_sql_database_tool'
+description: ''
+tool_type: 'api'
+input_keys: ['input']
+langchain:
+  module: langchain_community.tools
+  class_name: QuerySQLDataBaseTool
+  init_params:
+    db_wrapper: demo_sqldb_wrapper
+metadata:
+  type: 'TOOL'
+  module: 'sample_standard_app.app.core.tool.langchain_tool.sql_langchain_tool'
+  class: 'SqlLangchainTool'
\ No newline at end of file
diff --git a/sample_standard_app/app/core/tool/langchain_tool/sql_langchain_tool.py b/sample_standard_app/app/core/tool/langchain_tool/sql_langchain_tool.py
new file mode 100644
index 00000000..502e44ce
--- /dev/null
+++ b/sample_standard_app/app/core/tool/langchain_tool/sql_langchain_tool.py
@@ -0,0 +1,39 @@
+# !/usr/bin/env python3
+# -*- coding:utf-8 -*-
+
+# @Time    : 2024/7/9 20:04
+# @Author  : weizjajj 
+# @Email   : weizhongjie.wzj@antgroup.com
+# @FileName: sql_langchain_tool.py
+
+from typing import Type, Optional
+
+from langchain_core.tools import BaseTool, Tool as LangchainTool
+
+from agentuniverse.agent.action.tool.tool import ToolInput
+from agentuniverse.database.sqldb_wrapper_manager import SQLDBWrapperManager
+from sample_standard_app.app.core.tool.langchain_tool.langchain_tool import LangChainTool
+
+
+class SqlLangchainTool(LangChainTool):
+    db_wrapper_name: Optional[str] = ""
+    clz: Type[BaseTool] = BaseTool
+
+    def execute(self, tool_input: ToolInput):
+        if self.tool is None:
+            self.get_sql_database()
+        return super().execute(tool_input)
+
+    def get_sql_database(self):
+        db_wrapper = SQLDBWrapperManager().get_instance_obj(self.db_wrapper_name)
+        self.tool = self.clz(db=db_wrapper.sql_database)
+        self.description = self.tool.description
+
+    def as_langchain(self) -> LangchainTool:
+        if self.tool is None:
+            self.get_sql_database()
+        return super().as_langchain()
+
+    def get_langchain_tool(self, init_params: dict, clz: Type[BaseTool]):
+        self.db_wrapper_name = init_params.get("db_wrapper")
+        self.clz = clz
diff --git a/sample_standard_app/app/core/tool/request_tool.py b/sample_standard_app/app/core/tool/request_tool.py
index ae007614..e41e57ce 100644
--- a/sample_standard_app/app/core/tool/request_tool.py
+++ b/sample_standard_app/app/core/tool/request_tool.py
@@ -62,6 +62,8 @@ def initialize_by_component_configer(self, component_configer: ToolConfiger) ->
         self.headers = component_configer.configer.value.get('headers')
         self.method = component_configer.configer.value.get('method')
         self.response_content_type = component_configer.configer.value.get('response_content_type')
+        if 'json_parser' in component_configer.configer.value:
+            self.json_parser = component_configer.configer.value.get('json_parser')
         self.requests_wrapper = GenericRequestsWrapper(
             headers=self.headers,
             response_content_type=self.response_content_type
diff --git a/sample_standard_app/app/examples/data/dataset_turn_1_2024-07-10-10:48:30.jsonl b/sample_standard_app/app/examples/data/dataset_turn_1_2024-07-10-10:48:30.jsonl
new file mode 100644
index 00000000..21289684
--- /dev/null
+++ b/sample_standard_app/app/examples/data/dataset_turn_1_2024-07-10-10:48:30.jsonl
@@ -0,0 +1,3 @@
+{"query": "北京今天天气如何", "answer": "北京今天气温为86°F，属于高温天气，建议外出携带防晒用品，并注意补充水分。"}
+{"query": "半导体还能继续持有吗", "answer": "关于这个问题，目前很难给出明确的答案。一方面，中国半导体产业的发展仍然面临诸多挑战，例如美国的制裁、需求下降、行业波动等等。另一方面，随着人工智能、新能源车等新兴领域的需求增长，中国的半导体产业也有很大的发展空间。\n因此，建议投资者在考虑是否持有半导体相关股票时，不仅要关注当前的市场情况，也要考虑到长期的产业发展趋势。同时，也需要密切关注政策动态以及国内外市场的变化，以便做出更明智的投资决策。"}
+{"query": "帮我预测下2024欧洲杯冠军", "answer": "根据我的分析，以下是我对2024年欧洲杯冠军的预测：\n1. 西班牙：虽然他们的表现有所下滑，但西班牙仍然是一个强大的对手，他们有着丰富的国际比赛经验，而且他们的进攻线实力强大。\n2. 英格兰：虽然他们在最近几年的表现有些起伏不定，但他们拥有世界级的球员如哈里·凯恩和莱昂内尔·梅西，如果他们能够发挥出最佳状态，那么他们有可能赢得冠军。\n3. 法国：法国队在2018年的世界杯中赢得了冠军，这表明他们具有强大的实力。虽然姆巴佩和博格巴等球员可能会缺席比赛，但其他球员如基利安·姆巴佩和恩戈洛·坎特仍然有能力带领法国队走向胜利。\n总的来说，我认为这四支球队都有可能赢得2024年欧洲杯冠军，最终的结果取决于他们在比赛中的表现和运气。"}
diff --git a/sample_standard_app/app/examples/data/dataset_turn_1_2024-07-10-15:06:24.jsonl b/sample_standard_app/app/examples/data/dataset_turn_1_2024-07-10-15:06:24.jsonl
new file mode 100644
index 00000000..80c57ce9
--- /dev/null
+++ b/sample_standard_app/app/examples/data/dataset_turn_1_2024-07-10-15:06:24.jsonl
@@ -0,0 +1,3 @@
+{"query": "Can Tesla's stock still be bought?", "answer": "The decision to buy Tesla (TSLA) stock depends on various factors and individual investment strategies. Tesla's stock has experienced significant volatility in recent times, with a retreat of around 30% in 2024. However, there have been moments of recovery, such as a 27% gain in a single week that erased yearly losses.\n\nThe company's valuation is a crucial consideration. Despite the stock price decline, Tesla still commands a high price-to-earnings (P/E) ratio of 47, which indicates that investors are paying a premium for future growth potential. This valuation is relatively expensive compared to its historical levels or industry averages, suggesting that the market expects strong earnings growth from Tesla.\n\nIt's important to note that analyst expectations have been revised downward, leading to an increase in the forward price-earnings ratio. This means that the stock is priced based on reduced earnings forecasts. If the company fails to meet these lowered expectations, the stock price could be negatively impacted.\n\nElon Musk's $56 billion pay package, which shareholders are likely to approve, could also influence investor sentiment. Such a large compensation package might raise concerns about executive pay and its alignment with shareholder interests.\n\nAdditionally, there are bearish opinions in the market, with some analysts and hedge fund managers, like Per Lekander, expressing concerns about Tesla potentially facing financial difficulties or even bankruptcy, with the stock possibly plummeting to $14.\n\nIn conclusion, whether to buy Tesla stock depends on one's risk tolerance, investment horizon, and belief in the company's ability to execute its growth strategy and meet or exceed revised market expectations. It's advisable to conduct thorough research, consider expert opinions, and consult with a financial advisor before making any investment decisions."}
+{"query": "Help me predict the 2024 European Cup championship", "answer": "Predicting the outcome of a major football tournament like the UEFA Euro 2024 is always a challenging task, as it involves multiple factors such as team form, injuries, tactics, and match-ups. However, based on current trends and past performances, we can make some educated guesses.\n\nSpain has emerged as the favorite for the tournament, likely due to their strong recent form and talented squad. They have a history of success in the Euros, having won the title twice, in 2008 and 2012. Their possession-based style and skilled players make them a formidable opponent.\n\nEngland, another strong contender, is seeking their first-ever Euro title. They reached the final in 2020, losing to Italy, and have a talented generation of players with experience from that run. Their solid defense and attacking prowess make them a force to be reckoned with.\n\nFrance, despite not being the top favorite, is always a strong competitor, having won the tournament twice and the World Cup most recently in 2018. They boast a star-studded lineup and could go deep into the competition.\n\nThe Netherlands, often considered a dark horse, have a promising team with a mix of experienced players and young talents. They could potentially reach the quarter-finals or even the semis, but consistency might be a key factor in their success.\n\nOther teams to watch out for include Denmark, Croatia, Turkey, and Austria, each with their own strengths and potential to cause upsets.\n\nBased on these considerations, a potential semi-final lineup could resemble:\n\n- Spain vs France: Both teams have a rich history in the tournament and possess quality across the pitch. This would be an exciting clash of styles, with Spain's possession game against France's counter-attacking prowess.\n\n- Netherlands vs England: A repeat of classic encounters, this match could see two attacking-minded sides battling it out. England's defensive stability might give them the edge over the Dutch.\n\nOf course, these predictions are subject to change depending on how teams perform leading up to the tournament and during the group stages. In football, anything can happen, and upsets are part of what makes the competition so thrilling. The actual results may differ significantly from these predictions, but they provide a starting point for discussion and anticipation ahead of Euro 2024."}
+{"query": "What's the weather in New York today?", "answer": "I'm sorry, but as an AI, I don't have real-time data for current weather conditions. However, I can tell you that typically, to find out the current weather in New York, you can check reliable sources such as the National Weather Service (NWS), the Weather Channel, or visit websites like weather.gov. These resources provide up-to-date information on temperature, precipitation, wind, and any advisories or warnings in effect. It's always a good idea to check these before planning your day, especially if you're concerned about weather conditions like a heat advisory."}
\ No newline at end of file
diff --git a/sample_standard_app/app/examples/data/eval_report_2024-07-10-10:48:30.xlsx b/sample_standard_app/app/examples/data/eval_report_2024-07-10-10:48:30.xlsx
new file mode 100644
index 00000000..8bcd64e7
Binary files /dev/null and b/sample_standard_app/app/examples/data/eval_report_2024-07-10-10:48:30.xlsx differ
diff --git a/sample_standard_app/app/examples/data/eval_report_2024-07-10-15:06:24.xlsx b/sample_standard_app/app/examples/data/eval_report_2024-07-10-15:06:24.xlsx
new file mode 100644
index 00000000..c45bf5e5
Binary files /dev/null and b/sample_standard_app/app/examples/data/eval_report_2024-07-10-15:06:24.xlsx differ
diff --git a/sample_standard_app/app/examples/data/eval_result_turn_1_2024-07-10-10:48:30.xlsx b/sample_standard_app/app/examples/data/eval_result_turn_1_2024-07-10-10:48:30.xlsx
new file mode 100644
index 00000000..40e25c16
Binary files /dev/null and b/sample_standard_app/app/examples/data/eval_result_turn_1_2024-07-10-10:48:30.xlsx differ
diff --git a/sample_standard_app/app/examples/data/eval_result_turn_1_2024-07-10-15:06:24.xlsx b/sample_standard_app/app/examples/data/eval_result_turn_1_2024-07-10-15:06:24.xlsx
new file mode 100644
index 00000000..f5c047c8
Binary files /dev/null and b/sample_standard_app/app/examples/data/eval_result_turn_1_2024-07-10-15:06:24.xlsx differ
diff --git a/sample_standard_app/app/examples/data/queryset_cn.jsonl b/sample_standard_app/app/examples/data/queryset_cn.jsonl
new file mode 100644
index 00000000..d5215aa3
--- /dev/null
+++ b/sample_standard_app/app/examples/data/queryset_cn.jsonl
@@ -0,0 +1,3 @@
+{"input": "帮我预测下2024欧洲杯冠军"}
+{"input": "半导体还能继续持有吗"}
+{"input": "北京今天天气如何"}
\ No newline at end of file
diff --git a/sample_standard_app/app/examples/data/queryset_en.jsonl b/sample_standard_app/app/examples/data/queryset_en.jsonl
new file mode 100644
index 00000000..dfb39bc8
--- /dev/null
+++ b/sample_standard_app/app/examples/data/queryset_en.jsonl
@@ -0,0 +1,3 @@
+{"input": "Help me predict the 2024 European Cup championship"}
+{"input": "Can Tesla's stock still be bought?"}
+{"input": "What's the weather in New York today?"}
\ No newline at end of file
diff --git a/sample_standard_app/app/examples/data_agent.py b/sample_standard_app/app/examples/data_agent.py
new file mode 100644
index 00000000..a3a52c7e
--- /dev/null
+++ b/sample_standard_app/app/examples/data_agent.py
@@ -0,0 +1,23 @@
+# !/usr/bin/env python3
+# -*- coding:utf-8 -*-
+
+# @Time    : 2024/7/2 16:58
+# @Author  : wangchongshi
+# @Email   : wangchongshi.wcs@antgroup.com
+# @FileName: data_agent.py
+from agentuniverse.base.agentuniverse import AgentUniverse
+from agentuniverse.agent.agent import Agent
+from agentuniverse.agent.agent_manager import AgentManager
+
+AgentUniverse().start(config_path='../../config/config.toml')
+
+
+def data_process(queryset_path: str, turn: int, **kwargs):
+    instance: Agent = AgentManager().get_instance_obj('data_agent')
+    instance.run(queryset_path=queryset_path, turn=turn, **kwargs)
+
+
+if __name__ == '__main__':
+    queryset_path_list = ["./data/queryset_cn.jsonl"]
+    for path in queryset_path_list:
+        data_process(queryset_path=path, turn=2)
diff --git a/sample_standard_app/app/util/__init__.py b/sample_standard_app/app/util/__init__.py
new file mode 100644
index 00000000..a5be5aa6
--- /dev/null
+++ b/sample_standard_app/app/util/__init__.py
@@ -0,0 +1,7 @@
+# !/usr/bin/env python3
+# -*- coding:utf-8 -*-
+
+# @Time    : 2024/7/1 16:05
+# @Author  : wangchongshi
+# @Email   : wangchongshi.wcs@antgroup.com
+# @FileName: __init__.py.py
diff --git a/sample_standard_app/app/util/jsonl_file_utils.py b/sample_standard_app/app/util/jsonl_file_utils.py
new file mode 100644
index 00000000..fd089c85
--- /dev/null
+++ b/sample_standard_app/app/util/jsonl_file_utils.py
@@ -0,0 +1,91 @@
+# !/usr/bin/env python3
+# -*- coding:utf-8 -*-
+
+# @Time    : 2024/7/1 21:09
+# @Author  : wangchongshi
+# @Email   : wangchongshi.wcs@antgroup.com
+# @FileName: jsonl_file_utils.py
+import json
+import os
+import sys
+
+from agentuniverse.base.util.logging.logging_util import LOGGER
+
+DATA_DIR = './data/'
+
+sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(__file__))))
+
+
+class JsonFileOps(object):
+    def __init__(self):
+        return
+
+    @classmethod
+    def is_file_exist(cls, file_path):
+        file_name, ext = os.path.splitext(file_path)
+        if ext.lower() != '.jsonl':
+            raise Exception('Unsupported file extension')
+        return os.path.exists(file_path)
+
+
+class JsonFileReader(object):
+    def __init__(self, file_path: str):
+        self.file_handler = None
+        self.file_name = file_path
+        if JsonFileOps.is_file_exist(file_path):
+            self.file_handler = open(file_path, 'r', encoding='utf-8')
+
+    def read_json_obj(self):
+        if not self.file_handler:
+            raise Exception(f"None json file to read: {self.file_name}")
+        json_line = self.file_handler.readline()
+        if json_line:
+            try:
+                json_obj = json.loads(json_line.strip())
+                return json_obj
+            except Exception as e:
+                LOGGER.warn(f"except[read_json_line]>>>{e}:{json_line}")
+                return json.loads('{}')
+        else:
+            return None
+
+    def read_json_obj_list(self):
+        obj_list = []
+        while True:
+            obj = self.read_json_obj()
+            if obj is None:
+                break
+            obj_list.append(obj)
+        return obj_list
+
+
+class JsonFileWriter(object):
+    def __init__(self, output_file_name: str, extension='jsonl', directory=DATA_DIR):
+        self.outfile_path = directory + output_file_name + '.' + extension
+        directory = os.path.dirname(self.outfile_path)
+        if not os.path.exists(directory):
+            os.makedirs(directory)
+        self.outfile_handler = open(self.outfile_path, 'w', encoding='utf-8')
+
+    def write_json_obj(self, json_obj: dict):
+        try:
+            # confirm that it's a json string and then write.
+            json_line = json.dumps(json_obj, ensure_ascii=False)
+            self.outfile_handler.write(json_line.strip() + '\n')
+            self.outfile_handler.flush()
+        except Exception as e:
+            LOGGER.warn(f"except[write_json_obj]>>>{e}:{json_obj}")
+        return
+
+    def write_json_obj_list(self, json_obj_list: list):
+        for i in range(0, len(json_obj_list)):
+            self.write_json_obj(json_obj_list[i])
+        return
+
+    def write_json_query_answer(self, query: str, answer: str):
+        json_obj = {"query": query, "answer": answer}
+        self.write_json_obj(json_obj)
+
+    def write_json_query_answer_list(self, query_answer_list: list):
+        for i in range(0, len(query_answer_list)):
+            self.write_json_query_answer(query_answer_list[i][0], query_answer_list[i][1])
diff --git a/sample_standard_app/app/util/txt_file_utils.py b/sample_standard_app/app/util/txt_file_utils.py
new file mode 100644
index 00000000..bd8f1ec1
--- /dev/null
+++ b/sample_standard_app/app/util/txt_file_utils.py
@@ -0,0 +1,50 @@
+# !/usr/bin/env python3
+# -*- coding:utf-8 -*-
+
+# @Time    : 2024/7/1 16:05
+# @Author  : wangchongshi
+# @Email   : wangchongshi.wcs@antgroup.com
+# @FileName: txt_file_utils.py
+import os
+import sys
+
+sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(__file__))))
+
+
+class TxtFileOps(object):
+    def __init__(self):
+        return
+
+    @classmethod
+    def is_file_exist(cls, file_path):
+        file_name, ext = os.path.splitext(file_path)
+        if ext.lower() != '.txt':
+            raise Exception('Unsupported file extension')
+        return os.path.exists(file_path)
+
+
+class TxtFileReader(object):
+
+    def __init__(self, file_path: str):
+        self.file_handler = None
+        self.file_name = file_path
+        if TxtFileOps.is_file_exist(file_path):
+            self.file_handler = open(file_path, 'r', encoding='utf-8')
+
+    def read_txt_obj(self):
+        if not self.file_handler:
+            raise Exception(f"No txt file to read: {self.file_name}")
+        txt_line = self.file_handler.readline()
+        if txt_line:
+            return txt_line.strip()
+        else:
+            return None
+
+    def read_txt_obj_list(self):
+        obj_list = []
+        while True:
+            obj = self.read_txt_obj()
+            if obj is None:
+                break
+            obj_list.append(obj)
+        return obj_list


Test patch:
diff --git a/sample_standard_app/app/test/test_data_agent.py b/sample_standard_app/app/test/test_data_agent.py
new file mode 100644
index 00000000..a19df2e8
--- /dev/null
+++ b/sample_standard_app/app/test/test_data_agent.py
@@ -0,0 +1,27 @@
+# !/usr/bin/env python3
+# -*- coding:utf-8 -*-
+
+# @Time    : 2024/7/1 16:48
+# @Author  : wangchongshi
+# @Email   : wangchongshi.wcs@antgroup.com
+# @FileName: test_data_agent.py
+import unittest
+
+from agentuniverse.agent.agent import Agent
+from agentuniverse.agent.agent_manager import AgentManager
+from agentuniverse.base.agentuniverse import AgentUniverse
+
+
+class DataAgentTest(unittest.TestCase):
+    """Test cases for the data agent"""
+
+    def setUp(self) -> None:
+        AgentUniverse().start(config_path='../../config/config.toml')
+
+    def test_data_agent(self):
+        instance: Agent = AgentManager().get_instance_obj('data_agent')
+        instance.run(queryset_path='', turn=2)
+
+
+if __name__ == '__main__':
+    unittest.main()