-
Notifications
You must be signed in to change notification settings - Fork 32
Feat/deepresearch for serving #50
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Feat/deepresearch for serving #50
Conversation
|
Zhicheng Zhang seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account. You have signed the CLA already but the status is still pending? Let us recheck it. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR adds support for deploying the Deep Research agent as a service with a web UI, integrating ModelStudio web search as the default search tool, and adding optional Aliyun OSS storage for generated reports.
Key changes:
- Added deployment capability via
deploy.pywith AgentScope runtime integration - Switched default search from Tavily to ModelStudio web search while maintaining Tavily as optional
- Added Aliyun OSS integration for uploading generated research reports with signed URLs
Reviewed changes
Copilot reviewed 10 out of 11 changed files in this pull request and generated 16 comments.
Show a summary per file
| File | Description |
|---|---|
tests/agent_deep_research_test.py |
Updated import to use renamed run function instead of main |
deep_research/agent_deep_research/utils.py |
Added OSS upload utility function and reduced TOOL_RESULTS_MAX_WORDS from 5000 to 500 |
deep_research/agent_deep_research/requirements.txt |
Added agentscope-runtime and oss2 dependencies |
deep_research/agent_deep_research/main.py |
Renamed main function to run and changed example query to Chinese |
deep_research/agent_deep_research/deploy.py |
New file implementing agent deployment with session management and state persistence |
deep_research/agent_deep_research/deep_research_agent.py |
Integrated ModelStudio search, added OSS upload to report generation, modified message handling for list inputs, and uncommented debug print statements |
deep_research/agent_deep_research/built_in_prompt/*.md |
Added language sensitivity instructions to prompts to maintain user's input language |
deep_research/agent_deep_research/README.md |
Updated documentation for ModelStudio search setup and deployment instructions |
.gitignore |
Added log/ directory to ignore list |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| Once run the deploy script, the deepresearch will run at `http://0.0.0.0:8090/process` with sync manner, | ||
| and a webui will start at `http://localhost:5173/`, then user could test the service at the webui. | ||
|
|
||
|
|
Copilot
AI
Dec 10, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The word "sync" should be "asynchronous" or "async". The description "with sync manner" is grammatically awkward and technically inaccurate since the deploy script uses async functions. Consider rewording to: "the deepresearch will run at http://0.0.0.0:8090/process and a webui will start at http://localhost:5173/, then user could test the service at the webui."
| Once run the deploy script, the deepresearch will run at `http://0.0.0.0:8090/process` with sync manner, | |
| and a webui will start at `http://localhost:5173/`, then user could test the service at the webui. | |
| Once you run the deploy script, the deepresearch service will be available at `http://0.0.0.0:8090/process`, and a webui will start at `http://localhost:5173/`. You can test the service using the webui. |
| ) | ||
| await tavily_search_client.connect() | ||
| ``` | ||
| and make sure disable modelstudio_web_search, and enable tavily-search, in `deep_research_agent.py` at line 170 and line 177, respectively. |
Copilot
AI
Dec 10, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Grammar error: "and make sure disable" should be "and make sure to disable". Also, the instruction could be clearer about the specific changes needed.
| and make sure disable modelstudio_web_search, and enable tavily-search, in `deep_research_agent.py` at line 170 and line 177, respectively. | |
| and make sure to disable `modelstudio_web_search` and to enable `tavily-search` in `deep_research_agent.py` at line 170 and line 177, respectively. |
| return write_report_tool_res_msg, detailed_report_path, oss_url | ||
|
|
||
| async def _summarizing(self) -> Msg: | ||
| """Generate a report based on the exsisting findings when the |
Copilot
AI
Dec 10, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo in the docstring: "exsisting" should be "existing".
| """Generate a report based on the exsisting findings when the | |
| """Generate a report based on the existing findings when the |
| await self.toolkit.register_mcp_client(search_mcp_client) | ||
| # using modelstudio web search | ||
| self.toolkit.tools.pop("tavily-search") |
Copilot
AI
Dec 10, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When search_mcp_client is None (which is now allowed by the Optional parameter), calling await self.toolkit.register_mcp_client(search_mcp_client) will likely fail. The code should check if search_mcp_client is not None before attempting to register it.
| await self.toolkit.register_mcp_client(search_mcp_client) | |
| # using modelstudio web search | |
| self.toolkit.tools.pop("tavily-search") | |
| if search_mcp_client is not None: | |
| await self.toolkit.register_mcp_client(search_mcp_client) | |
| # using modelstudio web search | |
| self.toolkit.tools.pop("tavily-search") |
| loop = asyncio.get_running_loop() | ||
|
|
||
| async def _init_mcp_client(): | ||
| await self.toolkit.register_mcp_client(search_mcp_client) | ||
| # using modelstudio web search | ||
| self.toolkit.tools.pop("tavily-search") | ||
|
|
||
| loop.create_task(_init_mcp_client()) |
Copilot
AI
Dec 10, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The task to initialize the MCP client is created but not awaited, which could lead to race conditions. The code immediately sets self.search_function = "modelstudio_web_search" on line 187, but attempts to pop "tavily-search" from self.toolkit.tools inside the unawaited task. If the agent is used before this task completes, "tavily-search" might still be present in the toolkit, or the registration might not be complete.
| and make sure disable modelstudio_web_search, and enable tavily-search, in `deep_research_agent.py` at line 170 and line 177, respectively. | ||
Copilot
AI
Dec 10, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The line number references (line 170 and line 177) are now outdated after the code changes. With the new code structure, line 170 is where self.toolkit.register_tool_function(self.generate_response) is, and line 177 is within the modelstudio tool registration. The instructions should be updated to provide accurate line numbers or be more descriptive (e.g., "comment out the modelstudio search registration and uncomment the tavily-search line").
| and make sure disable modelstudio_web_search, and enable tavily-search, in `deep_research_agent.py` at line 170 and line 177, respectively. | |
| In `deep_research_agent.py`, make sure to disable the modelstudio web search registration and enable the tavily-search registration. | |
| Specifically, comment out the line that registers the modelstudio search tool, and uncomment the line that registers the tavily-search tool. |
| make sure `export DASHSCOPE_API_KEY="your_dashscope_api_key_here" have enable the web search from | ||
| [here](https://bailian.console.aliyun.com/?tab=app#/mcp-market/detail/WebSearch) | ||
|
|
||
| 3. **Optional:Test Tavily MCP Server**: |
Copilot
AI
Dec 10, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing colon after "Optional". The correct formatting should be "3. Optional: Test Tavily MCP Server:"
| 3. **Optional:Test Tavily MCP Server**: | |
| 3. **Optional: Test Tavily MCP Server**: |
| request: AgentRequest = None, | ||
| **kwargs, | ||
| ): | ||
| assert kwargs is not None, "kwargs is Required for query_func" |
Copilot
AI
Dec 10, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The assert statement is checking kwargs which is always truthy (it's a dict, even if empty). This assertion will never fail. If you want to check that kwargs is not empty, use assert kwargs or assert len(kwargs) > 0. However, the comment suggests kwargs is required but the code doesn't actually use kwargs, so this assertion may not be needed at all.
| assert kwargs is not None, "kwargs is Required for query_func" |
| # if ( | ||
| # tool_call["name"] != self.finish_function_name | ||
| # or (tool_call["name"] == self.finish_function_name | ||
| # and not chunk.metadata.get("success")) | ||
| # ): | ||
| await self.print(tool_res_msg, chunk.is_last) |
Copilot
AI
Dec 10, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The commented-out code should be removed rather than left in place. If this conditional printing logic is no longer needed, remove it. If it might be needed later, document why it was removed in a comment or commit message. The unconditional await self.print(tool_res_msg, chunk.is_last) on line 352 now prints all tool results including the finish function, which may not be the desired behavior based on the original logic.
| # ): | ||
| await self.print(tool_res_msg, chunk.is_last) | ||
|
|
||
| logger.info(f"chunk: {chunk}") |
Copilot
AI
Dec 10, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This debug logging statement should be removed or changed to use the appropriate log level (debug instead of info). Logging "chunk" for every iteration could produce excessive logs in production.
| logger.info(f"chunk: {chunk}") | |
| logger.debug(f"chunk: {chunk}") |
📝 PR Type
support deepresearch serving and webui.
📚 Description
[Please briefly describe the background, changes, and purpose of this PR. For example:
game_werewolvesto demonstrate XYZ functionality inagentscope.game_test.pycaused byagentscopeinterface changes.README.mdofagentscope-samples.]🧪 Testing Validation
[Please explain how to validate the changes:
agentscoperequired?pre-commit)?]✅ Checklist
Please complete the following checks before submitting the PR:
pre-commit run --all-filespytest tests/)agentscopebest practices (e.g., config management, logging)agentscope-sampleshas been updated (e.g.,README.md)