flowllm 0.1.0__py3-none-any.whl → 0.1.1__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 (105) hide show
  1. flowllm/__init__.py +12 -0
  2. flowllm/app.py +25 -0
  3. flowllm/config/default_config.yaml +82 -0
  4. flowllm/config/pydantic_config_parser.py +242 -0
  5. flowllm/context/base_context.py +59 -0
  6. flowllm/context/flow_context.py +28 -0
  7. llmflow/op/prompt_mixin.py → flowllm/context/prompt_handler.py +25 -14
  8. flowllm/context/registry.py +26 -0
  9. flowllm/context/service_context.py +103 -0
  10. flowllm/embedding_model/__init__.py +1 -0
  11. {llmflow → flowllm}/embedding_model/base_embedding_model.py +2 -2
  12. {llmflow → flowllm}/embedding_model/openai_compatible_embedding_model.py +8 -8
  13. flowllm/flow_engine/__init__.py +1 -0
  14. flowllm/flow_engine/base_flow_engine.py +34 -0
  15. flowllm/flow_engine/simple_flow_engine.py +213 -0
  16. flowllm/llm/__init__.py +1 -0
  17. {llmflow → flowllm}/llm/base_llm.py +16 -24
  18. {llmflow → flowllm}/llm/openai_compatible_llm.py +64 -108
  19. flowllm/op/__init__.py +3 -0
  20. flowllm/op/akshare/get_ak_a_code_op.py +116 -0
  21. flowllm/op/akshare/get_ak_a_code_prompt.yaml +21 -0
  22. flowllm/op/akshare/get_ak_a_info_op.py +143 -0
  23. flowllm/op/base_op.py +169 -0
  24. flowllm/op/llm_base_op.py +63 -0
  25. flowllm/op/mock_op.py +42 -0
  26. flowllm/op/parallel_op.py +30 -0
  27. flowllm/op/sequential_op.py +29 -0
  28. flowllm/schema/flow_response.py +12 -0
  29. flowllm/schema/message.py +35 -0
  30. flowllm/schema/service_config.py +76 -0
  31. flowllm/schema/tool_call.py +110 -0
  32. flowllm/service/__init__.py +2 -0
  33. flowllm/service/base_service.py +59 -0
  34. flowllm/service/http_service.py +87 -0
  35. flowllm/service/mcp_service.py +45 -0
  36. flowllm/storage/__init__.py +1 -0
  37. flowllm/storage/vector_store/__init__.py +3 -0
  38. flowllm/storage/vector_store/base_vector_store.py +44 -0
  39. {llmflow → flowllm/storage}/vector_store/chroma_vector_store.py +11 -10
  40. {llmflow → flowllm/storage}/vector_store/es_vector_store.py +10 -9
  41. llmflow/vector_store/file_vector_store.py → flowllm/storage/vector_store/local_vector_store.py +110 -10
  42. flowllm/utils/common_utils.py +64 -0
  43. flowllm/utils/dataframe_cache.py +331 -0
  44. flowllm/utils/fetch_url.py +113 -0
  45. {llmflow → flowllm}/utils/timer.py +5 -4
  46. {flowllm-0.1.0.dist-info → flowllm-0.1.1.dist-info}/METADATA +31 -27
  47. flowllm-0.1.1.dist-info/RECORD +62 -0
  48. flowllm-0.1.1.dist-info/entry_points.txt +4 -0
  49. {flowllm-0.1.0.dist-info → flowllm-0.1.1.dist-info}/licenses/LICENSE +1 -1
  50. flowllm-0.1.1.dist-info/top_level.txt +1 -0
  51. flowllm-0.1.0.dist-info/RECORD +0 -66
  52. flowllm-0.1.0.dist-info/entry_points.txt +0 -3
  53. flowllm-0.1.0.dist-info/top_level.txt +0 -1
  54. llmflow/app.py +0 -53
  55. llmflow/config/config_parser.py +0 -80
  56. llmflow/config/mock_config.yaml +0 -58
  57. llmflow/embedding_model/__init__.py +0 -5
  58. llmflow/enumeration/agent_state.py +0 -8
  59. llmflow/llm/__init__.py +0 -5
  60. llmflow/mcp_server.py +0 -110
  61. llmflow/op/__init__.py +0 -10
  62. llmflow/op/base_op.py +0 -125
  63. llmflow/op/mock_op.py +0 -40
  64. llmflow/op/react/react_v1_op.py +0 -88
  65. llmflow/op/react/react_v1_prompt.yaml +0 -28
  66. llmflow/op/vector_store/__init__.py +0 -13
  67. llmflow/op/vector_store/recall_vector_store_op.py +0 -48
  68. llmflow/op/vector_store/update_vector_store_op.py +0 -28
  69. llmflow/op/vector_store/vector_store_action_op.py +0 -46
  70. llmflow/pipeline/pipeline.py +0 -94
  71. llmflow/pipeline/pipeline_context.py +0 -37
  72. llmflow/schema/app_config.py +0 -69
  73. llmflow/schema/experience.py +0 -144
  74. llmflow/schema/message.py +0 -68
  75. llmflow/schema/request.py +0 -32
  76. llmflow/schema/response.py +0 -29
  77. llmflow/service/__init__.py +0 -0
  78. llmflow/service/llmflow_service.py +0 -96
  79. llmflow/tool/__init__.py +0 -9
  80. llmflow/tool/base_tool.py +0 -80
  81. llmflow/tool/code_tool.py +0 -43
  82. llmflow/tool/dashscope_search_tool.py +0 -162
  83. llmflow/tool/mcp_tool.py +0 -77
  84. llmflow/tool/tavily_search_tool.py +0 -109
  85. llmflow/tool/terminate_tool.py +0 -23
  86. llmflow/utils/__init__.py +0 -0
  87. llmflow/utils/common_utils.py +0 -17
  88. llmflow/utils/file_handler.py +0 -25
  89. llmflow/utils/http_client.py +0 -156
  90. llmflow/utils/op_utils.py +0 -102
  91. llmflow/utils/registry.py +0 -33
  92. llmflow/vector_store/__init__.py +0 -7
  93. llmflow/vector_store/base_vector_store.py +0 -136
  94. {llmflow → flowllm/config}/__init__.py +0 -0
  95. {llmflow/config → flowllm/context}/__init__.py +0 -0
  96. {llmflow → flowllm}/enumeration/__init__.py +0 -0
  97. {llmflow → flowllm}/enumeration/chunk_enum.py +0 -0
  98. {llmflow → flowllm}/enumeration/http_enum.py +0 -0
  99. {llmflow → flowllm}/enumeration/role.py +0 -0
  100. {llmflow/op/react → flowllm/op/akshare}/__init__.py +0 -0
  101. {llmflow/pipeline → flowllm/schema}/__init__.py +0 -0
  102. {llmflow → flowllm}/schema/vector_node.py +0 -0
  103. {llmflow/schema → flowllm/utils}/__init__.py +0 -0
  104. {llmflow → flowllm}/utils/singleton.py +0 -0
  105. {flowllm-0.1.0.dist-info → flowllm-0.1.1.dist-info}/WHEEL +0 -0
@@ -0,0 +1,76 @@
1
+ from typing import Dict
2
+
3
+ from pydantic import BaseModel, Field
4
+
5
+ from flowllm.schema.tool_call import ToolCall
6
+
7
+
8
+ class MCPConfig(BaseModel):
9
+ transport: str = Field(default="", description="stdio/http/sse/streamable-http")
10
+ host: str = Field(default="0.0.0.0")
11
+ port: int = Field(default=8001)
12
+
13
+
14
+ class HttpConfig(BaseModel):
15
+ host: str = Field(default="0.0.0.0")
16
+ port: int = Field(default=8001)
17
+ timeout_keep_alive: int = Field(default=600)
18
+ limit_concurrency: int = Field(default=64)
19
+
20
+
21
+ class FlowConfig(ToolCall):
22
+ flow_content: str = Field(default="")
23
+
24
+ def set_name(self, name: str):
25
+ self.name = name
26
+ return self
27
+
28
+
29
+ class FlowEngineConfig(BaseModel):
30
+ backend: str = Field(default="")
31
+ params: dict = Field(default_factory=dict)
32
+
33
+
34
+ class OpConfig(BaseModel):
35
+ backend: str = Field(default="")
36
+ language: str = Field(default="")
37
+ raise_exception: bool = Field(default=True)
38
+ prompt_path: str = Field(default="")
39
+ llm: str = Field(default="default")
40
+ embedding_model: str = Field(default="default")
41
+ vector_store: str = Field(default="default")
42
+ params: dict = Field(default_factory=dict)
43
+
44
+
45
+ class LLMConfig(BaseModel):
46
+ backend: str = Field(default="")
47
+ model_name: str = Field(default="")
48
+ params: dict = Field(default_factory=dict)
49
+
50
+
51
+ class EmbeddingModelConfig(BaseModel):
52
+ backend: str = Field(default="")
53
+ model_name: str = Field(default="")
54
+ params: dict = Field(default_factory=dict)
55
+
56
+
57
+ class VectorStoreConfig(BaseModel):
58
+ backend: str = Field(default="")
59
+ embedding_model: str = Field(default="")
60
+ params: dict = Field(default_factory=dict)
61
+
62
+
63
+ class ServiceConfig(BaseModel):
64
+ backend: str = Field(default="")
65
+ language: str = Field(default="")
66
+ thread_pool_max_workers: int = Field(default=16)
67
+ ray_max_workers: int = Field(default=8)
68
+
69
+ mcp: MCPConfig = Field(default_factory=MCPConfig)
70
+ http: HttpConfig = Field(default_factory=HttpConfig)
71
+ flow_engine: FlowEngineConfig = Field(default_factory=FlowEngineConfig)
72
+ flow: Dict[str, FlowConfig] = Field(default_factory=dict)
73
+ op: Dict[str, OpConfig] = Field(default_factory=dict)
74
+ llm: Dict[str, LLMConfig] = Field(default_factory=dict)
75
+ embedding_model: Dict[str, EmbeddingModelConfig] = Field(default_factory=dict)
76
+ vector_store: Dict[str, VectorStoreConfig] = Field(default_factory=dict)
@@ -0,0 +1,110 @@
1
+ import json
2
+ from typing import Dict
3
+
4
+ from pydantic import BaseModel, Field
5
+
6
+
7
+ class ParamAttrs(BaseModel):
8
+ type: str = Field(default="str", description="tool parameter type")
9
+ description: str = Field(default="", description="tool parameter description")
10
+ required: bool = Field(default=True, description="tool parameter required")
11
+
12
+
13
+ class ToolCall(BaseModel):
14
+ """
15
+ input:
16
+ {
17
+ "type": "function",
18
+ "function": {
19
+ "name": "get_current_weather",
20
+ "description": "It is very useful when you want to check the weather of a specified city.",
21
+ "parameters": {
22
+ "type": "object",
23
+ "properties": {
24
+ "location": {
25
+ "type": "string",
26
+ "description": "Cities or counties, such as Beijing, Hangzhou, Yuhang District, etc.",
27
+ }
28
+ },
29
+ "required": ["location"]
30
+ }
31
+ }
32
+ }
33
+ output:
34
+ {
35
+ "index": 0
36
+ "id": "call_6596dafa2a6a46f7a217da",
37
+ "function": {
38
+ "arguments": "{\"location\": \"Beijing\"}",
39
+ "name": "get_current_weather"
40
+ },
41
+ "type": "function",
42
+ }
43
+ """
44
+
45
+ index: int = Field(default=0)
46
+ id: str = Field(default="")
47
+ type: str = Field(default="function")
48
+ name: str = Field(default="")
49
+
50
+ arguments: dict = Field(default_factory=dict, description="tool execution arguments")
51
+
52
+ description: str = Field(default="")
53
+ input_schema: Dict[str, ParamAttrs] = Field(default_factory=dict)
54
+ output_schema: Dict[str, ParamAttrs] = Field(default_factory=dict)
55
+
56
+ def simple_input_dump(self, version: str = "v1") -> dict:
57
+ if version == "v1":
58
+ required_list = [name for name, tool_param in self.input_schema.items() if tool_param.required]
59
+ properties = {name: {
60
+ "type": tool_param.type,
61
+ "description": tool_param.description
62
+ } for name, tool_param in self.input_schema.items()}
63
+
64
+ return {
65
+ "type": self.type,
66
+ self.type: {
67
+ "name": self.name,
68
+ "description": self.description,
69
+ "parameters": {
70
+ "type": "object",
71
+ "properties": properties,
72
+ "required": required_list
73
+ },
74
+ },
75
+ }
76
+
77
+ else:
78
+ raise NotImplementedError(f"version {version} not supported")
79
+
80
+ def simple_output_dump(self, version: str = "v1") -> dict:
81
+ if version == "v1":
82
+ return {
83
+ "index": self.index,
84
+ "id": self.id,
85
+ self.type: {
86
+ "arguments": json.dumps(self.arguments, ensure_ascii=False),
87
+ "name": self.name
88
+ },
89
+ "type": self.type,
90
+ }
91
+ else:
92
+ raise NotImplementedError(f"version {version} not supported")
93
+
94
+ def update_by_output(self, data: dict, version: str = "v1"):
95
+ if version == "v1":
96
+ self.index = data.get("index", 0)
97
+ self.id = data.get("id", "")
98
+ tool_type = data.get("type", "")
99
+ tool_type_dict = data.get(tool_type, {})
100
+ if tool_type_dict:
101
+ name = tool_type_dict.get("name", "")
102
+ arguments = tool_type_dict.get("arguments", "")
103
+ if name:
104
+ self.name = name
105
+ if arguments:
106
+ self.arguments = json.loads(arguments)
107
+ else:
108
+ raise NotImplementedError(f"version {version} not supported")
109
+
110
+ return self
@@ -0,0 +1,2 @@
1
+ from flowllm.service.mcp_service import MCPService
2
+ from flowllm.service.http_service import HttpService
@@ -0,0 +1,59 @@
1
+ from concurrent.futures import ThreadPoolExecutor
2
+ from typing import Dict
3
+
4
+ from loguru import logger
5
+
6
+ from flowllm.context.flow_context import FlowContext
7
+ from flowllm.context.service_context import C
8
+ from flowllm.flow_engine.base_flow_engine import BaseFlowEngine
9
+ from flowllm.schema.flow_response import FlowResponse
10
+ from flowllm.schema.service_config import ServiceConfig, EmbeddingModelConfig, FlowConfig
11
+
12
+
13
+ class BaseService:
14
+
15
+ def __init__(self, service_config: ServiceConfig):
16
+ self.service_config = service_config
17
+
18
+ C.language = self.service_config.language
19
+ C.thread_pool = ThreadPoolExecutor(max_workers=self.service_config.thread_pool_max_workers)
20
+ for name, config in self.service_config.vector_store.items():
21
+ vector_store_cls = C.resolve_vector_store(config.backend)
22
+ embedding_model_config: EmbeddingModelConfig = self.service_config.embedding_model[config.embedding_model]
23
+ embedding_model_cls = C.resolve_embedding_model(embedding_model_config.backend)
24
+ embedding_model = embedding_model_cls(model_name=embedding_model_config.model_name,
25
+ **embedding_model_config.params)
26
+ C.set_vector_store(name, vector_store_cls(embedding_model=embedding_model, **config.params))
27
+
28
+ self.flow_engine_config = self.service_config.flow_engine
29
+ self.flow_engine_cls = C.resolve_flow_engine(self.flow_engine_config.backend)
30
+ self.flow_config_dict: Dict[str, FlowConfig] = \
31
+ {name: config.set_name(name) for name, config in self.service_config.flow.items()}
32
+
33
+ self.mcp_config = self.service_config.mcp
34
+ self.http_config = self.service_config.http
35
+
36
+ def execute_flow(self, flow_name: str, **kwargs) -> FlowResponse:
37
+ response = FlowResponse()
38
+ try:
39
+ logger.info(f"request.params={kwargs}")
40
+ flow_context = FlowContext(**kwargs,
41
+ response=response,
42
+ service_config=self.service_config.model_copy(deep=True))
43
+
44
+ flow_config = self.flow_config_dict[flow_name]
45
+ flow_engine: BaseFlowEngine = self.flow_engine_cls(flow_name=flow_name,
46
+ flow_content=flow_config.flow_content,
47
+ flow_context=flow_context,
48
+ **self.flow_engine_config.params)
49
+ flow_engine()
50
+
51
+ except Exception as e:
52
+ logger.exception(f"flow_name={flow_name} encounter error={e.args}")
53
+ response.success = False
54
+ response.answer = str(e.args)
55
+
56
+ return response
57
+
58
+ def __call__(self):
59
+ raise NotImplementedError
@@ -0,0 +1,87 @@
1
+ import asyncio
2
+ from functools import partial
3
+ from typing import Dict, Optional
4
+
5
+ import uvicorn
6
+ from fastapi import FastAPI
7
+ from fastapi.middleware.cors import CORSMiddleware
8
+ from loguru import logger
9
+ from pydantic import BaseModel, create_model, Field
10
+
11
+ from flowllm.context.service_context import C
12
+ from flowllm.schema.flow_response import FlowResponse
13
+ from flowllm.schema.tool_call import ParamAttrs
14
+ from flowllm.service.base_service import BaseService
15
+ from flowllm.utils.common_utils import snake_to_camel
16
+
17
+
18
+ @C.register_service("http")
19
+ class HttpService(BaseService):
20
+ TYPE_MAPPING = {
21
+ "str": str,
22
+ "int": int,
23
+ "float": float,
24
+ "bool": bool
25
+ }
26
+
27
+ def __init__(self, *args, **kwargs):
28
+ super().__init__(*args, **kwargs)
29
+ self.app = FastAPI(title="FlowLLM", description="HTTP API for FlowLLM")
30
+
31
+ # Add CORS middleware
32
+ self.app.add_middleware(
33
+ CORSMiddleware,
34
+ allow_origins=["*"],
35
+ allow_credentials=True,
36
+ allow_methods=["*"],
37
+ allow_headers=["*"],
38
+ )
39
+
40
+ # Add health check endpoint
41
+ self.app.get("/health")(self.health_check)
42
+
43
+ @staticmethod
44
+ def health_check():
45
+ return {"status": "healthy"}
46
+
47
+ def _create_pydantic_model(self, flow_name: str, input_schema: Dict[str, ParamAttrs]) -> BaseModel:
48
+ # Create a dynamic Pydantic model based on flow input schema
49
+ fields = {}
50
+
51
+ for param_name, param_config in input_schema.items():
52
+ field_type = self.TYPE_MAPPING.get(param_config.type, str)
53
+
54
+ if not param_config.required:
55
+ fields[param_name] = (Optional[field_type], Field(default=None, description=param_config.description))
56
+ else:
57
+ fields[param_name] = (field_type, Field(default=..., description=param_config.description))
58
+
59
+ return create_model(f"{snake_to_camel(flow_name)}Model", **fields)
60
+
61
+ def register_flow(self, flow_name: str):
62
+ """Register a flow as an HTTP endpoint"""
63
+ flow_config = self.flow_config_dict[flow_name]
64
+ request_model = self._create_pydantic_model(flow_name, flow_config.input_schema)
65
+
66
+ async def execute_flow_endpoint(request: request_model) -> FlowResponse:
67
+ loop = asyncio.get_event_loop()
68
+ response: FlowResponse = await loop.run_in_executor(
69
+ executor=C.thread_pool,
70
+ func=partial(self.execute_flow, flow_name=flow_name, **request.model_dump())) # noqa
71
+
72
+ return response
73
+
74
+ endpoint_path = f"/{flow_name}"
75
+ self.app.post(endpoint_path, response_model=FlowResponse)(execute_flow_endpoint)
76
+ logger.info(f"register flow={flow_name} endpoint={endpoint_path}")
77
+
78
+ def __call__(self):
79
+ for flow_name in self.flow_config_dict:
80
+ self.register_flow(flow_name)
81
+
82
+ # Start the server
83
+ uvicorn.run(self.app,
84
+ host=self.http_config.host,
85
+ port=self.http_config.port,
86
+ timeout_keep_alive=self.http_config.timeout_keep_alive,
87
+ limit_concurrency=self.http_config.limit_concurrency)
@@ -0,0 +1,45 @@
1
+ import asyncio
2
+ from functools import partial
3
+
4
+ from fastmcp import FastMCP
5
+ from fastmcp.tools import FunctionTool
6
+ from loguru import logger
7
+
8
+ from flowllm.context.service_context import C
9
+ from flowllm.service.base_service import BaseService
10
+
11
+
12
+ @C.register_service("mcp")
13
+ class MCPService(BaseService):
14
+
15
+ def __init__(self, *args, **kwargs):
16
+ super().__init__(*args, **kwargs)
17
+ self.mcp = FastMCP("FlowLLM")
18
+
19
+ def register_flow(self, flow_name: str):
20
+ flow_config = self.flow_config_dict[flow_name]
21
+
22
+ async def execute_flow_async(**kwargs) -> str:
23
+ loop = asyncio.get_event_loop()
24
+ response = await loop.run_in_executor(
25
+ executor=C.thread_pool,
26
+ func=partial(self.execute_flow, flow_name=flow_name, **kwargs)) # noqa
27
+ return response.answer
28
+
29
+ tool = FunctionTool(name=flow_name, # noqa
30
+ description=flow_config.description, # noqa
31
+ fn=execute_flow_async,
32
+ parameters=flow_config.input_schema)
33
+ self.mcp.add_tool(tool)
34
+ logger.info(f"register flow={flow_name}")
35
+
36
+ def __call__(self):
37
+ for flow_name in self.flow_config_dict:
38
+ self.register_flow(flow_name)
39
+
40
+ if self.mcp_config.transport == "sse":
41
+ self.mcp.run(transport="sse", host=self.mcp_config.host, port=self.mcp_config.port)
42
+ elif self.mcp_config.transport == "stdio":
43
+ self.mcp.run(transport="stdio")
44
+ else:
45
+ raise ValueError(f"unsupported mcp transport: {self.mcp_config.transport}")
@@ -0,0 +1 @@
1
+ from flowllm.storage import vector_store
@@ -0,0 +1,3 @@
1
+ from flowllm.storage.vector_store.chroma_vector_store import ChromaVectorStore
2
+ from flowllm.storage.vector_store.es_vector_store import EsVectorStore
3
+ from flowllm.storage.vector_store.local_vector_store import LocalVectorStore
@@ -0,0 +1,44 @@
1
+ from abc import ABC
2
+ from pathlib import Path
3
+ from typing import List, Iterable
4
+
5
+ from pydantic import BaseModel, Field
6
+
7
+ from flowllm.embedding_model.base_embedding_model import BaseEmbeddingModel
8
+ from flowllm.schema.vector_node import VectorNode
9
+
10
+
11
+ class BaseVectorStore(BaseModel, ABC):
12
+ embedding_model: BaseEmbeddingModel | None = Field(default=None)
13
+ batch_size: int = Field(default=1024)
14
+
15
+ def exist_workspace(self, workspace_id: str, **kwargs) -> bool:
16
+ raise NotImplementedError
17
+
18
+ def delete_workspace(self, workspace_id: str, **kwargs):
19
+ raise NotImplementedError
20
+
21
+ def create_workspace(self, workspace_id: str, **kwargs):
22
+ raise NotImplementedError
23
+
24
+ def _iter_workspace_nodes(self, workspace_id: str, **kwargs) -> Iterable[VectorNode]:
25
+ raise NotImplementedError
26
+
27
+ def dump_workspace(self, workspace_id: str, path: str | Path = "", callback_fn=None, **kwargs):
28
+ raise NotImplementedError
29
+
30
+ def load_workspace(self, workspace_id: str, path: str | Path = "", nodes: List[VectorNode] = None, callback_fn=None,
31
+ **kwargs):
32
+ raise NotImplementedError
33
+
34
+ def copy_workspace(self, src_workspace_id: str, dest_workspace_id: str, **kwargs):
35
+ raise NotImplementedError
36
+
37
+ def search(self, query: str, workspace_id: str, top_k: int = 1, **kwargs) -> List[VectorNode]:
38
+ raise NotImplementedError
39
+
40
+ def insert(self, nodes: VectorNode | List[VectorNode], workspace_id: str, **kwargs):
41
+ raise NotImplementedError
42
+
43
+ def delete(self, node_ids: str | List[str], workspace_id: str, **kwargs):
44
+ raise NotImplementedError
@@ -6,17 +6,16 @@ from chromadb.config import Settings
6
6
  from loguru import logger
7
7
  from pydantic import Field, PrivateAttr, model_validator
8
8
 
9
- from llmflow.embedding_model.openai_compatible_embedding_model import OpenAICompatibleEmbeddingModel
10
- from llmflow.schema.vector_node import VectorNode
11
- from llmflow.vector_store import VECTOR_STORE_REGISTRY
12
- from llmflow.vector_store.base_vector_store import BaseVectorStore
9
+ from flowllm.context.service_context import C
10
+ from flowllm.schema.vector_node import VectorNode
11
+ from flowllm.storage.vector_store.local_vector_store import LocalVectorStore
13
12
 
14
13
 
15
- @VECTOR_STORE_REGISTRY.register("chroma")
16
- class ChromaVectorStore(BaseVectorStore):
14
+ @C.register_vector_store("chroma")
15
+ class ChromaVectorStore(LocalVectorStore):
17
16
  store_dir: str = Field(default="./chroma_vector_store")
18
17
  collections: dict = Field(default_factory=dict)
19
- _client: chromadb.Client = PrivateAttr()
18
+ _client: chromadb.ClientAPI = PrivateAttr()
20
19
 
21
20
  @model_validator(mode="after")
22
21
  def init_client(self):
@@ -97,8 +96,10 @@ class ChromaVectorStore(BaseVectorStore):
97
96
 
98
97
 
99
98
  def main():
100
- from dotenv import load_dotenv
101
- load_dotenv()
99
+ from flowllm.utils.common_utils import load_env
100
+ from flowllm.embedding_model import OpenAICompatibleEmbeddingModel
101
+
102
+ load_env()
102
103
 
103
104
  embedding_model = OpenAICompatibleEmbeddingModel(dimensions=64, model_name="text-embedding-v4")
104
105
  workspace_id = "chroma_test_index"
@@ -185,4 +186,4 @@ def main():
185
186
 
186
187
  if __name__ == "__main__":
187
188
  main()
188
- # launch with: python -m llmflow.storage.chroma_vector_store
189
+ # launch with: python -m flowllm.storage.chroma_vector_store
@@ -6,14 +6,13 @@ from elasticsearch.helpers import bulk
6
6
  from loguru import logger
7
7
  from pydantic import Field, PrivateAttr, model_validator
8
8
 
9
- from llmflow.embedding_model.openai_compatible_embedding_model import OpenAICompatibleEmbeddingModel
10
- from llmflow.schema.vector_node import VectorNode
11
- from llmflow.vector_store import VECTOR_STORE_REGISTRY
12
- from llmflow.vector_store.base_vector_store import BaseVectorStore
9
+ from flowllm.context.service_context import C
10
+ from flowllm.schema.vector_node import VectorNode
11
+ from flowllm.storage.vector_store.local_vector_store import LocalVectorStore
13
12
 
14
13
 
15
- @VECTOR_STORE_REGISTRY.register("elasticsearch")
16
- class EsVectorStore(BaseVectorStore):
14
+ @C.register_vector_store("elasticsearch")
15
+ class EsVectorStore(LocalVectorStore):
17
16
  hosts: str | List[str] = Field(default_factory=lambda: os.getenv("ES_HOSTS", "http://localhost:9200"))
18
17
  basic_auth: str | Tuple[str, str] | None = Field(default=None)
19
18
  retrieve_filters: List[dict] = []
@@ -24,6 +23,7 @@ class EsVectorStore(BaseVectorStore):
24
23
  if isinstance(self.hosts, str):
25
24
  self.hosts = [self.hosts]
26
25
  self._client = Elasticsearch(hosts=self.hosts, basic_auth=self.basic_auth)
26
+ logger.info(f"Elasticsearch client initialized with hosts: {self.hosts}")
27
27
  return self
28
28
 
29
29
  def exist_workspace(self, workspace_id: str, **kwargs) -> bool:
@@ -162,8 +162,10 @@ class EsVectorStore(BaseVectorStore):
162
162
 
163
163
 
164
164
  def main():
165
- from dotenv import load_dotenv
166
- load_dotenv()
165
+ from flowllm.utils.common_utils import load_env
166
+ from flowllm.embedding_model import OpenAICompatibleEmbeddingModel
167
+
168
+ load_env()
167
169
 
168
170
  embedding_model = OpenAICompatibleEmbeddingModel(dimensions=64, model_name="text-embedding-v4")
169
171
  workspace_id = "rag_nodes_index"
@@ -224,4 +226,3 @@ def main():
224
226
 
225
227
  if __name__ == "__main__":
226
228
  main()
227
- # launch with: python -m llmflow.storage.es_vector_store