flowllm 0.1.0__py3-none-any.whl → 0.1.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (141) hide show
  1. flowllm/__init__.py +21 -0
  2. flowllm/app.py +15 -0
  3. flowllm/client/__init__.py +25 -0
  4. flowllm/client/async_http_client.py +81 -0
  5. flowllm/client/http_client.py +81 -0
  6. flowllm/client/mcp_client.py +133 -0
  7. flowllm/client/sync_mcp_client.py +116 -0
  8. flowllm/config/__init__.py +1 -0
  9. flowllm/config/default.yaml +77 -0
  10. flowllm/config/empty.yaml +37 -0
  11. flowllm/config/pydantic_config_parser.py +242 -0
  12. flowllm/context/base_context.py +79 -0
  13. flowllm/context/flow_context.py +16 -0
  14. llmflow/op/prompt_mixin.py → flowllm/context/prompt_handler.py +25 -14
  15. flowllm/context/registry.py +30 -0
  16. flowllm/context/service_context.py +147 -0
  17. flowllm/embedding_model/__init__.py +1 -0
  18. {llmflow → flowllm}/embedding_model/base_embedding_model.py +93 -2
  19. {llmflow → flowllm}/embedding_model/openai_compatible_embedding_model.py +71 -13
  20. flowllm/flow/__init__.py +1 -0
  21. flowllm/flow/base_flow.py +72 -0
  22. flowllm/flow/base_tool_flow.py +15 -0
  23. flowllm/flow/gallery/__init__.py +8 -0
  24. flowllm/flow/gallery/cmd_flow.py +11 -0
  25. flowllm/flow/gallery/code_tool_flow.py +30 -0
  26. flowllm/flow/gallery/dashscope_search_tool_flow.py +34 -0
  27. flowllm/flow/gallery/deepsearch_tool_flow.py +39 -0
  28. flowllm/flow/gallery/expression_tool_flow.py +18 -0
  29. flowllm/flow/gallery/mock_tool_flow.py +67 -0
  30. flowllm/flow/gallery/tavily_search_tool_flow.py +30 -0
  31. flowllm/flow/gallery/terminate_tool_flow.py +30 -0
  32. flowllm/flow/parser/expression_parser.py +171 -0
  33. flowllm/llm/__init__.py +2 -0
  34. {llmflow → flowllm}/llm/base_llm.py +100 -18
  35. flowllm/llm/litellm_llm.py +455 -0
  36. flowllm/llm/openai_compatible_llm.py +439 -0
  37. flowllm/op/__init__.py +11 -0
  38. llmflow/op/react/react_v1_op.py → flowllm/op/agent/react_op.py +17 -22
  39. flowllm/op/akshare/__init__.py +3 -0
  40. flowllm/op/akshare/get_ak_a_code_op.py +108 -0
  41. flowllm/op/akshare/get_ak_a_code_prompt.yaml +21 -0
  42. flowllm/op/akshare/get_ak_a_info_op.py +140 -0
  43. flowllm/op/base_llm_op.py +64 -0
  44. flowllm/op/base_op.py +148 -0
  45. flowllm/op/base_ray_op.py +313 -0
  46. flowllm/op/code/__init__.py +1 -0
  47. flowllm/op/code/execute_code_op.py +42 -0
  48. flowllm/op/gallery/__init__.py +2 -0
  49. flowllm/op/gallery/mock_op.py +42 -0
  50. flowllm/op/gallery/terminate_op.py +29 -0
  51. flowllm/op/parallel_op.py +23 -0
  52. flowllm/op/search/__init__.py +3 -0
  53. flowllm/op/search/dashscope_deep_research_op.py +260 -0
  54. flowllm/op/search/dashscope_search_op.py +179 -0
  55. flowllm/op/search/dashscope_search_prompt.yaml +13 -0
  56. flowllm/op/search/tavily_search_op.py +102 -0
  57. flowllm/op/sequential_op.py +21 -0
  58. flowllm/schema/flow_request.py +12 -0
  59. flowllm/schema/flow_response.py +12 -0
  60. flowllm/schema/message.py +35 -0
  61. flowllm/schema/service_config.py +72 -0
  62. flowllm/schema/tool_call.py +118 -0
  63. {llmflow → flowllm}/schema/vector_node.py +1 -0
  64. flowllm/service/__init__.py +3 -0
  65. flowllm/service/base_service.py +68 -0
  66. flowllm/service/cmd_service.py +15 -0
  67. flowllm/service/http_service.py +79 -0
  68. flowllm/service/mcp_service.py +47 -0
  69. flowllm/storage/__init__.py +1 -0
  70. flowllm/storage/cache/__init__.py +1 -0
  71. flowllm/storage/cache/cache_data_handler.py +104 -0
  72. flowllm/storage/cache/data_cache.py +375 -0
  73. flowllm/storage/vector_store/__init__.py +3 -0
  74. flowllm/storage/vector_store/base_vector_store.py +44 -0
  75. {llmflow → flowllm/storage}/vector_store/chroma_vector_store.py +11 -10
  76. {llmflow → flowllm/storage}/vector_store/es_vector_store.py +11 -11
  77. llmflow/vector_store/file_vector_store.py → flowllm/storage/vector_store/local_vector_store.py +110 -11
  78. flowllm/utils/common_utils.py +52 -0
  79. flowllm/utils/fetch_url.py +117 -0
  80. flowllm/utils/llm_utils.py +28 -0
  81. flowllm/utils/ridge_v2.py +54 -0
  82. {llmflow → flowllm}/utils/timer.py +5 -4
  83. {flowllm-0.1.0.dist-info → flowllm-0.1.2.dist-info}/METADATA +45 -388
  84. flowllm-0.1.2.dist-info/RECORD +99 -0
  85. flowllm-0.1.2.dist-info/entry_points.txt +2 -0
  86. {flowllm-0.1.0.dist-info → flowllm-0.1.2.dist-info}/licenses/LICENSE +1 -1
  87. flowllm-0.1.2.dist-info/top_level.txt +1 -0
  88. flowllm-0.1.0.dist-info/RECORD +0 -66
  89. flowllm-0.1.0.dist-info/entry_points.txt +0 -3
  90. flowllm-0.1.0.dist-info/top_level.txt +0 -1
  91. llmflow/app.py +0 -53
  92. llmflow/config/config_parser.py +0 -80
  93. llmflow/config/mock_config.yaml +0 -58
  94. llmflow/embedding_model/__init__.py +0 -5
  95. llmflow/enumeration/agent_state.py +0 -8
  96. llmflow/llm/__init__.py +0 -5
  97. llmflow/llm/openai_compatible_llm.py +0 -283
  98. llmflow/mcp_server.py +0 -110
  99. llmflow/op/__init__.py +0 -10
  100. llmflow/op/base_op.py +0 -125
  101. llmflow/op/mock_op.py +0 -40
  102. llmflow/op/vector_store/__init__.py +0 -13
  103. llmflow/op/vector_store/recall_vector_store_op.py +0 -48
  104. llmflow/op/vector_store/update_vector_store_op.py +0 -28
  105. llmflow/op/vector_store/vector_store_action_op.py +0 -46
  106. llmflow/pipeline/pipeline.py +0 -94
  107. llmflow/pipeline/pipeline_context.py +0 -37
  108. llmflow/schema/app_config.py +0 -69
  109. llmflow/schema/experience.py +0 -144
  110. llmflow/schema/message.py +0 -68
  111. llmflow/schema/request.py +0 -32
  112. llmflow/schema/response.py +0 -29
  113. llmflow/service/__init__.py +0 -0
  114. llmflow/service/llmflow_service.py +0 -96
  115. llmflow/tool/__init__.py +0 -9
  116. llmflow/tool/base_tool.py +0 -80
  117. llmflow/tool/code_tool.py +0 -43
  118. llmflow/tool/dashscope_search_tool.py +0 -162
  119. llmflow/tool/mcp_tool.py +0 -77
  120. llmflow/tool/tavily_search_tool.py +0 -109
  121. llmflow/tool/terminate_tool.py +0 -23
  122. llmflow/utils/__init__.py +0 -0
  123. llmflow/utils/common_utils.py +0 -17
  124. llmflow/utils/file_handler.py +0 -25
  125. llmflow/utils/http_client.py +0 -156
  126. llmflow/utils/op_utils.py +0 -102
  127. llmflow/utils/registry.py +0 -33
  128. llmflow/vector_store/__init__.py +0 -7
  129. llmflow/vector_store/base_vector_store.py +0 -136
  130. {llmflow → flowllm/context}/__init__.py +0 -0
  131. {llmflow/config → flowllm/enumeration}/__init__.py +0 -0
  132. {llmflow → flowllm}/enumeration/chunk_enum.py +0 -0
  133. {llmflow → flowllm}/enumeration/http_enum.py +0 -0
  134. {llmflow → flowllm}/enumeration/role.py +0 -0
  135. {llmflow/enumeration → flowllm/flow/parser}/__init__.py +0 -0
  136. {llmflow/op/react → flowllm/op/agent}/__init__.py +0 -0
  137. /llmflow/op/react/react_v1_prompt.yaml → /flowllm/op/agent/react_prompt.yaml +0 -0
  138. {llmflow/pipeline → flowllm/schema}/__init__.py +0 -0
  139. {llmflow/schema → flowllm/utils}/__init__.py +0 -0
  140. {llmflow → flowllm}/utils/singleton.py +0 -0
  141. {flowllm-0.1.0.dist-info → flowllm-0.1.2.dist-info}/WHEEL +0 -0
flowllm/__init__.py ADDED
@@ -0,0 +1,21 @@
1
+ import os
2
+
3
+ from flowllm.utils.common_utils import load_env
4
+
5
+ load_env()
6
+
7
+ from flowllm import embedding_model
8
+ from flowllm import llm
9
+ from flowllm import storage
10
+
11
+ if not os.environ.get("FLOW_USE_FRAMEWORK", "").lower() == "true":
12
+ from flowllm import flow
13
+ from flowllm import op
14
+
15
+ from flowllm import service
16
+
17
+ from flowllm.context.service_context import C
18
+ from flowllm.op import BaseOp, BaseRayOp, BaseLLMOp
19
+
20
+ __version__ = "0.1.2"
21
+
flowllm/app.py ADDED
@@ -0,0 +1,15 @@
1
+ import sys
2
+
3
+ from flowllm.service.base_service import BaseService
4
+
5
+
6
+ def main():
7
+ with BaseService.get_service(*sys.argv[1:]) as service:
8
+ service()
9
+
10
+
11
+ if __name__ == "__main__":
12
+ main()
13
+
14
+ # python -m build
15
+ # twine upload dist/*
@@ -0,0 +1,25 @@
1
+ """
2
+ FlowLLM service clients module
3
+
4
+ This module provides various client implementations for interacting with FlowLLM services:
5
+
6
+ - HttpClient: Synchronous HTTP client for FlowLLM HTTP service
7
+ - AsyncHttpClient: Asynchronous HTTP client for FlowLLM HTTP service
8
+ - MCPClient: Asynchronous client for FlowLLM MCP (Model Context Protocol) service
9
+ - SyncMCPClient: Synchronous wrapper around MCPClient for easier synchronous usage
10
+
11
+ Each client provides methods to execute tool flows, list available flows, and perform
12
+ health checks on the respective services.
13
+ """
14
+
15
+ from .async_http_client import AsyncHttpClient
16
+ from .http_client import HttpClient
17
+ from .mcp_client import MCPClient
18
+ from .sync_mcp_client import SyncMCPClient
19
+
20
+ __all__ = [
21
+ "HttpClient",
22
+ "AsyncHttpClient",
23
+ "MCPClient",
24
+ "SyncMCPClient"
25
+ ]
@@ -0,0 +1,81 @@
1
+ from typing import Dict
2
+
3
+ import httpx
4
+
5
+ from flowllm.schema.flow_response import FlowResponse
6
+
7
+
8
+ class AsyncHttpClient:
9
+ """Async client for interacting with FlowLLM HTTP service"""
10
+
11
+ def __init__(self, base_url: str = "http://localhost:8001", timeout: float = 3600.0):
12
+ """
13
+ Initialize async HTTP client
14
+
15
+ Args:
16
+ base_url: Base URL of the FlowLLM HTTP service
17
+ timeout: Request timeout in seconds
18
+ """
19
+ self.base_url = base_url.rstrip('/') # Remove trailing slash for consistent URL formatting
20
+ self.timeout = timeout
21
+ self.client = httpx.AsyncClient(timeout=timeout) # Create async HTTP client with timeout
22
+
23
+ async def __aenter__(self):
24
+ """Async context manager entry - returns self for 'async with' usage"""
25
+ return self
26
+
27
+ async def __aexit__(self, exc_type, exc_val, exc_tb):
28
+ """Async context manager exit - ensures proper cleanup of HTTP client"""
29
+ await self.client.aclose()
30
+
31
+ async def close(self):
32
+ """Explicitly close the HTTP client connection"""
33
+ await self.client.aclose()
34
+
35
+ async def health_check(self) -> Dict[str, str]:
36
+ """
37
+ Perform health check on the FlowLLM service
38
+
39
+ Returns:
40
+ Dict containing health status information from the service
41
+
42
+ Raises:
43
+ httpx.HTTPStatusError: If the service is not healthy or unreachable
44
+ """
45
+ response = await self.client.get(f"{self.base_url}/health")
46
+ response.raise_for_status() # Raise exception for HTTP error status codes
47
+ return response.json()
48
+
49
+ async def execute_tool_flow(self, flow_name: str, **kwargs) -> FlowResponse:
50
+ """
51
+ Execute a specific tool flow on the FlowLLM service
52
+
53
+ Args:
54
+ flow_name: Name of the tool flow to execute
55
+ **kwargs: Additional parameters to pass to the tool flow
56
+
57
+ Returns:
58
+ FlowResponse object containing the execution results
59
+
60
+ Raises:
61
+ httpx.HTTPStatusError: If the request fails or flow execution errors
62
+ """
63
+ endpoint = f"{self.base_url}/{flow_name}"
64
+ response = await self.client.post(endpoint, json=kwargs) # Send flow parameters as JSON
65
+ response.raise_for_status() # Raise exception for HTTP error status codes
66
+ result_data = response.json()
67
+ return FlowResponse(**result_data) # Parse response into FlowResponse schema
68
+
69
+ async def list_tool_flows(self) -> list:
70
+ """
71
+ Get list of available tool flows from the FlowLLM service
72
+
73
+ Returns:
74
+ List of available tool flow names and their metadata
75
+
76
+ Raises:
77
+ httpx.HTTPStatusError: If the service is unreachable or returns an error
78
+ """
79
+ response = await self.client.get(f"{self.base_url}/list")
80
+ response.raise_for_status() # Raise exception for HTTP error status codes
81
+ return response.json()
@@ -0,0 +1,81 @@
1
+ from typing import Dict
2
+
3
+ import httpx
4
+
5
+ from flowllm.schema.flow_response import FlowResponse
6
+
7
+
8
+ class HttpClient:
9
+ """Client for interacting with FlowLLM HTTP service"""
10
+
11
+ def __init__(self, base_url: str = "http://localhost:8001", timeout: float = 3600.0):
12
+ """
13
+ Initialize HTTP client
14
+
15
+ Args:
16
+ base_url: Base URL of the FlowLLM HTTP service
17
+ timeout: Request timeout in seconds
18
+ """
19
+ self.base_url = base_url.rstrip('/') # Remove trailing slash for consistent URL formatting
20
+ self.timeout = timeout
21
+ self.client = httpx.Client(timeout=timeout) # Create synchronous HTTP client with timeout
22
+
23
+ def __enter__(self):
24
+ """Context manager entry - returns self for 'with' usage"""
25
+ return self
26
+
27
+ def __exit__(self, exc_type, exc_val, exc_tb):
28
+ """Context manager exit - ensures proper cleanup of HTTP client"""
29
+ self.client.close()
30
+
31
+ def close(self):
32
+ """Explicitly close the HTTP client connection"""
33
+ self.client.close()
34
+
35
+ def health_check(self) -> Dict[str, str]:
36
+ """
37
+ Perform health check on the FlowLLM service
38
+
39
+ Returns:
40
+ Dict containing health status information from the service
41
+
42
+ Raises:
43
+ httpx.HTTPStatusError: If the service is not healthy or unreachable
44
+ """
45
+ response = self.client.get(f"{self.base_url}/health")
46
+ response.raise_for_status() # Raise exception for HTTP error status codes
47
+ return response.json()
48
+
49
+ def execute_tool_flow(self, flow_name: str, **kwargs) -> FlowResponse:
50
+ """
51
+ Execute a specific tool flow on the FlowLLM service
52
+
53
+ Args:
54
+ flow_name: Name of the tool flow to execute
55
+ **kwargs: Additional parameters to pass to the tool flow
56
+
57
+ Returns:
58
+ FlowResponse object containing the execution results
59
+
60
+ Raises:
61
+ httpx.HTTPStatusError: If the request fails or flow execution errors
62
+ """
63
+ endpoint = f"{self.base_url}/{flow_name}"
64
+ response = self.client.post(endpoint, json=kwargs) # Send flow parameters as JSON
65
+ response.raise_for_status() # Raise exception for HTTP error status codes
66
+ result_data = response.json()
67
+ return FlowResponse(**result_data) # Parse response into FlowResponse schema
68
+
69
+ def list_tool_flows(self) -> list:
70
+ """
71
+ Get list of available tool flows from the FlowLLM service
72
+
73
+ Returns:
74
+ List of available tool flow names and their metadata
75
+
76
+ Raises:
77
+ httpx.HTTPStatusError: If the service is unreachable or returns an error
78
+ """
79
+ response = self.client.get(f"{self.base_url}/list")
80
+ response.raise_for_status() # Raise exception for HTTP error status codes
81
+ return response.json()
@@ -0,0 +1,133 @@
1
+ from typing import Dict, Any, List, Optional
2
+
3
+ from fastmcp import Client
4
+ from loguru import logger
5
+ from mcp.types import CallToolResult, Tool
6
+
7
+
8
+ class MCPClient:
9
+ """Client for interacting with FlowLLM MCP service"""
10
+
11
+ def __init__(self, transport: str = "sse", host: str = "0.0.0.0", port: int = 8001):
12
+ """
13
+ Initialize MCP client
14
+
15
+ Args:
16
+ transport: Transport type ("sse" or "stdio")
17
+ host: Host address for SSE transport
18
+ port: Port number for SSE transport
19
+ """
20
+ self.transport = transport
21
+ self.host = host
22
+ self.port = port
23
+
24
+ # Configure connection URL based on transport type
25
+ if transport == "sse":
26
+ # Server-Sent Events transport over HTTP
27
+ self.connection_url = f"http://{host}:{port}/sse/"
28
+ elif transport == "stdio":
29
+ # Standard input/output transport for local processes
30
+ self.connection_url = "stdio"
31
+ else:
32
+ raise ValueError(f"Unsupported transport: {transport}")
33
+
34
+ self.client: Client | None = None # MCP client instance, initialized on connect
35
+
36
+ async def __aenter__(self):
37
+ """Async context manager entry - automatically connects to MCP service"""
38
+ await self.connect()
39
+ return self
40
+
41
+ async def __aexit__(self, exc_type, exc_val, exc_tb):
42
+ """Async context manager exit - ensures proper cleanup and disconnection"""
43
+ await self.disconnect()
44
+
45
+ async def connect(self):
46
+ """
47
+ Establish connection to the MCP service
48
+
49
+ Creates and initializes the MCP client based on the configured transport type.
50
+ For stdio transport, connects to a local process. For SSE transport, connects
51
+ to the HTTP endpoint.
52
+
53
+ Raises:
54
+ ConnectionError: If unable to connect to the MCP service
55
+ """
56
+ if self.transport == "stdio":
57
+ self.client = Client("stdio") # Connect to stdio-based MCP server
58
+ else:
59
+ self.client = Client(self.connection_url) # Connect to HTTP-based MCP server
60
+
61
+ await self.client.__aenter__() # Initialize the client connection
62
+ logger.info(f"Connected to MCP service at {self.connection_url}")
63
+
64
+ async def disconnect(self):
65
+ """
66
+ Disconnect from the MCP service and clean up resources
67
+
68
+ Safely closes the MCP client connection and resets the client instance.
69
+ """
70
+ if self.client:
71
+ await self.client.__aexit__(None, None, None) # Properly close the client connection
72
+ self.client = None # Reset client reference
73
+
74
+ async def list_tools(self) -> List[Tool]:
75
+ """
76
+ Retrieve list of available tools from the MCP service
77
+
78
+ Returns:
79
+ List of Tool objects representing available MCP tools
80
+
81
+ Raises:
82
+ RuntimeError: If client is not connected
83
+ ConnectionError: If communication with MCP service fails
84
+ """
85
+ if not self.client:
86
+ raise RuntimeError("Client not connected. Call connect() first or use context manager.")
87
+
88
+ tools = await self.client.list_tools()
89
+ logger.info(f"Found {len(tools)} available tools")
90
+ return tools
91
+
92
+ async def get_tool(self, tool_name: str) -> Optional[Tool]:
93
+ """
94
+ Get a specific tool by name from the MCP service
95
+
96
+ Args:
97
+ tool_name: Name of the tool to retrieve
98
+
99
+ Returns:
100
+ Tool object if found, None otherwise
101
+
102
+ Raises:
103
+ RuntimeError: If client is not connected
104
+ ConnectionError: If communication with MCP service fails
105
+ """
106
+ tools = await self.list_tools() # Get all available tools
107
+
108
+ # Search for the requested tool by name
109
+ for tool in tools:
110
+ if tool.name == tool_name:
111
+ return tool
112
+ return None # Tool not found
113
+
114
+ async def call_tool(self, tool_name: str, arguments: Dict[str, Any]) -> CallToolResult:
115
+ """
116
+ Execute a tool on the MCP service with the provided arguments
117
+
118
+ Args:
119
+ tool_name: Name of the tool to execute
120
+ arguments: Dictionary of arguments to pass to the tool
121
+
122
+ Returns:
123
+ CallToolResult containing the tool execution results
124
+
125
+ Raises:
126
+ RuntimeError: If client is not connected
127
+ ValueError: If tool_name is invalid or arguments are malformed
128
+ ConnectionError: If communication with MCP service fails
129
+ """
130
+ if not self.client:
131
+ raise RuntimeError("Client not connected. Call connect() first or use context manager.")
132
+
133
+ return await self.client.call_tool(tool_name, arguments=arguments)
@@ -0,0 +1,116 @@
1
+ import asyncio
2
+ from typing import Dict, Any, List, Optional
3
+
4
+ from mcp.types import CallToolResult, Tool
5
+
6
+ from flowllm.client import MCPClient
7
+
8
+
9
+ class SyncMCPClient:
10
+ """Synchronous wrapper for MCPClient"""
11
+
12
+ def __init__(self, transport: str = "sse", host: str = "0.0.0.0", port: int = 8001):
13
+ """
14
+ Initialize synchronous MCP client
15
+
16
+ This client wraps the asynchronous MCPClient to provide a synchronous interface.
17
+ It manages its own event loop for executing async operations synchronously.
18
+
19
+ Args:
20
+ transport: Transport type ("sse" or "stdio")
21
+ host: Host address for SSE transport
22
+ port: Port number for SSE transport
23
+ """
24
+ self.async_client = MCPClient(transport, host, port) # Create underlying async client
25
+ self._loop: asyncio.AbstractEventLoop | None = None # Event loop for async operations
26
+
27
+ def __enter__(self):
28
+ """
29
+ Context manager entry - sets up event loop and connects to MCP service
30
+
31
+ Creates a new event loop, establishes connection to the MCP service,
32
+ and returns self for use in 'with' statements.
33
+
34
+ Returns:
35
+ self for context manager usage
36
+ """
37
+ self._loop = asyncio.new_event_loop() # Create new event loop for this client
38
+ asyncio.set_event_loop(self._loop) # Set as current event loop
39
+ self._loop.run_until_complete(self.async_client.connect()) # Connect synchronously
40
+ return self
41
+
42
+ def __exit__(self, exc_type, exc_val, exc_tb):
43
+ """
44
+ Context manager exit - disconnects from MCP service and cleans up event loop
45
+
46
+ Ensures proper cleanup by disconnecting from the MCP service and
47
+ closing the event loop.
48
+ """
49
+ if self._loop:
50
+ self._loop.run_until_complete(self.async_client.disconnect()) # Disconnect synchronously
51
+ self._loop.close() # Close the event loop
52
+ self._loop = None # Reset loop reference
53
+
54
+ def _run_async(self, coro):
55
+ """
56
+ Execute an async coroutine synchronously using the managed event loop
57
+
58
+ Args:
59
+ coro: Coroutine to execute
60
+
61
+ Returns:
62
+ Result of the coroutine execution
63
+
64
+ Raises:
65
+ RuntimeError: If client is not connected (no event loop available)
66
+ """
67
+ if not self._loop:
68
+ raise RuntimeError("Client not connected. Use context manager first.")
69
+ return self._loop.run_until_complete(coro) # Run coroutine to completion
70
+
71
+ def list_tools(self) -> List[Tool]:
72
+ """
73
+ Synchronously retrieve list of available tools from the MCP service
74
+
75
+ Returns:
76
+ List of Tool objects representing available MCP tools
77
+
78
+ Raises:
79
+ RuntimeError: If client is not connected
80
+ ConnectionError: If communication with MCP service fails
81
+ """
82
+ return self._run_async(self.async_client.list_tools())
83
+
84
+ def get_tool(self, tool_name: str) -> Optional[Tool]:
85
+ """
86
+ Synchronously get a specific tool by name from the MCP service
87
+
88
+ Args:
89
+ tool_name: Name of the tool to retrieve
90
+
91
+ Returns:
92
+ Tool object if found, None otherwise
93
+
94
+ Raises:
95
+ RuntimeError: If client is not connected
96
+ ConnectionError: If communication with MCP service fails
97
+ """
98
+ return self._run_async(self.async_client.get_tool(tool_name))
99
+
100
+ def call_tool(self, tool_name: str, arguments: Dict[str, Any]) -> CallToolResult:
101
+ """
102
+ Synchronously execute a tool on the MCP service with the provided arguments
103
+
104
+ Args:
105
+ tool_name: Name of the tool to execute
106
+ arguments: Dictionary of arguments to pass to the tool
107
+
108
+ Returns:
109
+ CallToolResult containing the tool execution results
110
+
111
+ Raises:
112
+ RuntimeError: If client is not connected
113
+ ValueError: If tool_name is invalid or arguments are malformed
114
+ ConnectionError: If communication with MCP service fails
115
+ """
116
+ return self._run_async(self.async_client.call_tool(tool_name, arguments))
@@ -0,0 +1 @@
1
+ from .pydantic_config_parser import PydanticConfigParser
@@ -0,0 +1,77 @@
1
+ # default config.yaml
2
+ backend: mcp
3
+ language: ""
4
+ thread_pool_max_workers: 32
5
+ ray_max_workers: 1
6
+
7
+ mcp:
8
+ transport: sse
9
+ host: "0.0.0.0"
10
+ port: 8001
11
+
12
+ http:
13
+ host: "0.0.0.0"
14
+ port: 8001
15
+ timeout_keep_alive: 600
16
+ limit_concurrency: 64
17
+
18
+ flow:
19
+ get_a_stock_infos:
20
+ flow_content: get_ak_a_code_op >> get_ak_a_info_op >> get_ak_a_spot_op >> get_ak_a_money_flow_op >> get_ak_a_financial_info_op >> merge_ak_a_info_op
21
+ description: "Retrieve the A-share stock codes from the query, and fetch information about these stocks, including company basic information, current stock price and its change percentage, capital inflow and outflow data for the most recent day, and financial information from the latest quarter."
22
+ input_schema:
23
+ query:
24
+ type: "str"
25
+ description: "user question"
26
+
27
+ get_a_stock_news:
28
+ flow_content: get_ak_a_code_op >> get_ak_a_news_op >> merge_ak_a_info_op
29
+ description: "Retrieve the A-share stock codes from the query, and obtain the latest news information about these stocks."
30
+ input_schema:
31
+ query:
32
+ type: "str"
33
+ description: "user question"
34
+
35
+ mock_expression_flow:
36
+ flow_content: mock1_op>>((mock4_op>>mock2_op)|mock5_op)>>(mock3_op|mock6_op)
37
+ description: "mock flow"
38
+ input_schema:
39
+ a:
40
+ type: "str"
41
+ description: "mock attr a"
42
+ required: true
43
+ b:
44
+ type: "str"
45
+ description: "mock attr b"
46
+ required: true
47
+
48
+ op:
49
+ mock1_op:
50
+ backend: mock1_op
51
+ llm: default
52
+ vector_store: default
53
+
54
+ llm:
55
+ default:
56
+ backend: openai_compatible
57
+ model_name: qwen3-30b-a3b-thinking-2507
58
+ params:
59
+ temperature: 0.6
60
+
61
+ qwen3_30b_instruct:
62
+ backend: openai_compatible
63
+ model_name: qwen3-30b-a3b-instruct-2507
64
+
65
+ embedding_model:
66
+ default:
67
+ backend: openai_compatible
68
+ model_name: text-embedding-v4
69
+ params:
70
+ dimensions: 1024
71
+
72
+ vector_store:
73
+ default:
74
+ backend: elasticsearch
75
+ embedding_model: default
76
+ params:
77
+ hosts: "http://localhost:9200"
@@ -0,0 +1,37 @@
1
+ # default config.yaml
2
+ backend: http
3
+ language: ""
4
+ thread_pool_max_workers: 32
5
+ ray_max_workers: 1
6
+
7
+ mcp:
8
+ transport: sse
9
+ host: "0.0.0.0"
10
+ port: 8001
11
+
12
+ http:
13
+ host: "0.0.0.0"
14
+ port: 8001
15
+ timeout_keep_alive: 600
16
+ limit_concurrency: 64
17
+
18
+ llm:
19
+ default:
20
+ backend: openai_compatible
21
+ model_name: qwen3-30b-a3b-thinking-2507
22
+ params:
23
+ temperature: 0.6
24
+
25
+ embedding_model:
26
+ default:
27
+ backend: openai_compatible
28
+ model_name: text-embedding-v4
29
+ params:
30
+ dimensions: 1024
31
+
32
+ vector_store:
33
+ default:
34
+ backend: elasticsearch
35
+ embedding_model: default
36
+ params:
37
+ hosts: "http://localhost:9200"