vectorwave 0.2.9__tar.gz → 0.3.0__tar.gz
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.
- {vectorwave-0.2.9 → vectorwave-0.3.0}/PKG-INFO +5 -2
- {vectorwave-0.2.9 → vectorwave-0.3.0}/Readme.md +4 -1
- {vectorwave-0.2.9 → vectorwave-0.3.0}/pyproject.toml +1 -1
- {vectorwave-0.2.9 → vectorwave-0.3.0}/src/vectorwave/__init__.py +3 -2
- {vectorwave-0.2.9 → vectorwave-0.3.0}/src/vectorwave/batch/batch.py +23 -5
- {vectorwave-0.2.9 → vectorwave-0.3.0}/src/vectorwave/core/auto_injector.py +1 -1
- {vectorwave-0.2.9 → vectorwave-0.3.0}/src/vectorwave/core/decorator.py +43 -35
- {vectorwave-0.2.9 → vectorwave-0.3.0}/src/vectorwave/core/generator.py +2 -2
- vectorwave-0.3.0/src/vectorwave/core/initializer.py +37 -0
- vectorwave-0.3.0/src/vectorwave/core/llm/factory.py +10 -0
- {vectorwave-0.2.9 → vectorwave-0.3.0}/src/vectorwave/database/dataset.py +10 -2
- {vectorwave-0.2.9 → vectorwave-0.3.0}/src/vectorwave/database/db.py +127 -99
- {vectorwave-0.2.9 → vectorwave-0.3.0}/src/vectorwave/database/db_search.py +4 -4
- {vectorwave-0.2.9 → vectorwave-0.3.0}/src/vectorwave/models/db_config.py +3 -0
- {vectorwave-0.2.9 → vectorwave-0.3.0}/src/vectorwave/monitoring/tracer.py +199 -179
- {vectorwave-0.2.9 → vectorwave-0.3.0}/src/vectorwave/search/execution_search.py +2 -20
- {vectorwave-0.2.9 → vectorwave-0.3.0}/src/vectorwave/search/rag_search.py +2 -2
- {vectorwave-0.2.9 → vectorwave-0.3.0}/src/vectorwave/utils/healer.py +1 -1
- {vectorwave-0.2.9 → vectorwave-0.3.0}/src/vectorwave/utils/replayer.py +73 -51
- vectorwave-0.3.0/src/vectorwave/utils/replayer_semantic.py +130 -0
- {vectorwave-0.2.9 → vectorwave-0.3.0}/src/vectorwave/utils/return_caching_utils.py +2 -1
- vectorwave-0.3.0/src/vectorwave/utils/serialization.py +17 -0
- {vectorwave-0.2.9 → vectorwave-0.3.0}/src/vectorwave/utils/status.py +0 -4
- vectorwave-0.2.9/src/vectorwave/core/llm/factory.py +0 -13
- vectorwave-0.2.9/src/vectorwave/utils/replayer_semantic.py +0 -234
- {vectorwave-0.2.9 → vectorwave-0.3.0}/crates/Cargo.lock +0 -0
- {vectorwave-0.2.9 → vectorwave-0.3.0}/crates/Cargo.toml +0 -0
- {vectorwave-0.2.9 → vectorwave-0.3.0}/crates/src/lib.rs +0 -0
- {vectorwave-0.2.9 → vectorwave-0.3.0}/src/vectorwave/batch/__init__.py +0 -0
- {vectorwave-0.2.9 → vectorwave-0.3.0}/src/vectorwave/core/__init__.py +0 -0
- {vectorwave-0.2.9 → vectorwave-0.3.0}/src/vectorwave/core/core.py +0 -0
- {vectorwave-0.2.9 → vectorwave-0.3.0}/src/vectorwave/core/llm/__init__.py +0 -0
- {vectorwave-0.2.9 → vectorwave-0.3.0}/src/vectorwave/core/llm/base.py +0 -0
- {vectorwave-0.2.9 → vectorwave-0.3.0}/src/vectorwave/core/llm/openai_client.py +0 -0
- {vectorwave-0.2.9 → vectorwave-0.3.0}/src/vectorwave/database/__init__.py +0 -0
- {vectorwave-0.2.9 → vectorwave-0.3.0}/src/vectorwave/database/archiver.py +0 -0
- {vectorwave-0.2.9 → vectorwave-0.3.0}/src/vectorwave/exception/__init__.py +0 -0
- {vectorwave-0.2.9 → vectorwave-0.3.0}/src/vectorwave/exception/exceptions.py +0 -0
- {vectorwave-0.2.9 → vectorwave-0.3.0}/src/vectorwave/models/__init__.py +0 -0
- {vectorwave-0.2.9 → vectorwave-0.3.0}/src/vectorwave/monitoring/__init__.py +0 -0
- {vectorwave-0.2.9 → vectorwave-0.3.0}/src/vectorwave/monitoring/alert/__init__.py +0 -0
- {vectorwave-0.2.9 → vectorwave-0.3.0}/src/vectorwave/monitoring/alert/base.py +0 -0
- {vectorwave-0.2.9 → vectorwave-0.3.0}/src/vectorwave/monitoring/alert/factory.py +0 -0
- {vectorwave-0.2.9 → vectorwave-0.3.0}/src/vectorwave/monitoring/alert/null_alerter.py +0 -0
- {vectorwave-0.2.9 → vectorwave-0.3.0}/src/vectorwave/monitoring/alert/webhook_alerter.py +0 -0
- {vectorwave-0.2.9 → vectorwave-0.3.0}/src/vectorwave/monitoring/monitoring.py +0 -0
- {vectorwave-0.2.9 → vectorwave-0.3.0}/src/vectorwave/prediction/__init__.py +0 -0
- {vectorwave-0.2.9 → vectorwave-0.3.0}/src/vectorwave/prediction/predictor.py +0 -0
- {vectorwave-0.2.9 → vectorwave-0.3.0}/src/vectorwave/search/__init__.py +0 -0
- {vectorwave-0.2.9 → vectorwave-0.3.0}/src/vectorwave/search/extended_search.py +0 -0
- {vectorwave-0.2.9 → vectorwave-0.3.0}/src/vectorwave/utils/__init__.py +0 -0
- {vectorwave-0.2.9 → vectorwave-0.3.0}/src/vectorwave/utils/context.py +0 -0
- {vectorwave-0.2.9 → vectorwave-0.3.0}/src/vectorwave/utils/function_cache.py +0 -0
- {vectorwave-0.2.9 → vectorwave-0.3.0}/src/vectorwave/utils/github_pr.py +0 -0
- {vectorwave-0.2.9 → vectorwave-0.3.0}/src/vectorwave/utils/path_utils.py +0 -0
- {vectorwave-0.2.9 → vectorwave-0.3.0}/src/vectorwave/utils/scheduler.py +0 -0
- {vectorwave-0.2.9 → vectorwave-0.3.0}/src/vectorwave/vectorizer/__init__.py +0 -0
- {vectorwave-0.2.9 → vectorwave-0.3.0}/src/vectorwave/vectorizer/base.py +0 -0
- {vectorwave-0.2.9 → vectorwave-0.3.0}/src/vectorwave/vectorizer/factory.py +0 -0
- {vectorwave-0.2.9 → vectorwave-0.3.0}/src/vectorwave/vectorizer/huggingface_vectorizer.py +0 -0
- {vectorwave-0.2.9 → vectorwave-0.3.0}/src/vectorwave/vectorizer/openai_vectorizer.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: vectorwave
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Classifier: Programming Language :: Python :: 3
|
|
5
5
|
Classifier: Programming Language :: Python :: 3.10
|
|
6
6
|
Classifier: Programming Language :: Python :: 3.11
|
|
@@ -26,7 +26,10 @@ Requires-Python: >=3.10
|
|
|
26
26
|
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
|
|
27
27
|
Project-URL: Repository, https://github.com/cozymori/vectorwave
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
|
|
30
|
+

|
|
31
|
+
|
|
32
|
+
Need more information? Visit [here](https://www.cozymori.net/vectorwave)
|
|
30
33
|
|
|
31
34
|
# VectorWave
|
|
32
35
|

|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
|
|
2
|
+

|
|
3
|
+
|
|
4
|
+
Need more information? Visit [here](https://www.cozymori.net/vectorwave)
|
|
2
5
|
|
|
3
6
|
# VectorWave
|
|
4
7
|

|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from .core.decorator import vectorize
|
|
2
|
-
from .database.db import initialize_database
|
|
2
|
+
from .database.db import initialize_database, update_database_schema
|
|
3
3
|
from .database.db_search import search_functions, search_executions, search_errors_by_message, search_functions_hybrid
|
|
4
4
|
from .monitoring.tracer import trace_span
|
|
5
5
|
from .search.rag_search import search_and_answer, analyze_trace_log
|
|
@@ -25,5 +25,6 @@ __all__ = [
|
|
|
25
25
|
'VectorWaveReplayer',
|
|
26
26
|
'SemanticReplayer',
|
|
27
27
|
'VectorWaveDatasetManager',
|
|
28
|
-
'VectorWaveAutoInjector'
|
|
28
|
+
'VectorWaveAutoInjector',
|
|
29
|
+
'update_database_schema'
|
|
29
30
|
]
|
|
@@ -27,11 +27,18 @@ class WeaviateBatchManager:
|
|
|
27
27
|
Uses High-Performance Rust Core if available, otherwise falls back to Python.
|
|
28
28
|
"""
|
|
29
29
|
|
|
30
|
-
def __init__(self
|
|
30
|
+
def __init__(self, host: Optional[str] = None, port: Optional[int] = None,
|
|
31
|
+
grpc_port: Optional[int] = None, api_key: Optional[str] = None):
|
|
31
32
|
self._initialized = False
|
|
32
33
|
self.settings: WeaviateSettings = get_weaviate_settings()
|
|
33
34
|
self.client: Optional[weaviate.WeaviateClient] = None
|
|
34
35
|
|
|
36
|
+
# Store dynamic connection params
|
|
37
|
+
self._host = host
|
|
38
|
+
self._port = port
|
|
39
|
+
self._grpc_port = grpc_port
|
|
40
|
+
self._api_key = api_key
|
|
41
|
+
|
|
35
42
|
# Batch Configuration
|
|
36
43
|
self.batch_threshold = self.settings.BATCH_THRESHOLD
|
|
37
44
|
self.flush_interval = self.settings.FLUSH_INTERVAL_SECONDS
|
|
@@ -60,7 +67,13 @@ class WeaviateBatchManager:
|
|
|
60
67
|
def _connect_client(self):
|
|
61
68
|
"""Attempts to connect to Weaviate."""
|
|
62
69
|
try:
|
|
63
|
-
self.
|
|
70
|
+
if self._host is not None:
|
|
71
|
+
self.client = get_weaviate_client(
|
|
72
|
+
host=self._host, port=self._port,
|
|
73
|
+
grpc_port=self._grpc_port, api_key=self._api_key
|
|
74
|
+
)
|
|
75
|
+
else:
|
|
76
|
+
self.client = get_weaviate_client(self.settings)
|
|
64
77
|
if self.client:
|
|
65
78
|
self._initialized = True
|
|
66
79
|
except Exception as e:
|
|
@@ -171,6 +184,11 @@ class WeaviateBatchManager:
|
|
|
171
184
|
except:
|
|
172
185
|
pass
|
|
173
186
|
|
|
174
|
-
@lru_cache(
|
|
175
|
-
def get_batch_manager(
|
|
176
|
-
|
|
187
|
+
@lru_cache()
|
|
188
|
+
def get_batch_manager(
|
|
189
|
+
host: Optional[str] = None,
|
|
190
|
+
port: Optional[int] = None,
|
|
191
|
+
grpc_port: Optional[int] = None,
|
|
192
|
+
api_key: Optional[str] = None
|
|
193
|
+
) -> WeaviateBatchManager:
|
|
194
|
+
return WeaviateBatchManager(host=host, port=port, grpc_port=grpc_port, api_key=api_key)
|
|
@@ -23,7 +23,7 @@ def create_smart_wrapper(original_func, root_wrapper):
|
|
|
23
23
|
# Check for existing tracer at runtime
|
|
24
24
|
tracer = current_tracer_var.get()
|
|
25
25
|
|
|
26
|
-
if tracer:
|
|
26
|
+
if tracer is not None:
|
|
27
27
|
# [Case A] Parent trace exists -> Act as Child Span
|
|
28
28
|
# (Wrap original function with trace_span and execute)
|
|
29
29
|
return trace_span(original_func, capture_return_value=True)(*args, **kwargs)
|
|
@@ -13,7 +13,7 @@ from ..utils.function_cache import function_cache_manager
|
|
|
13
13
|
from ..utils.return_caching_utils import _check_and_return_cached_result
|
|
14
14
|
from ..vectorizer.factory import get_vectorizer
|
|
15
15
|
from ..utils.context import execution_source_context
|
|
16
|
-
from ..utils.path_utils import get_repo_root_and_relative_path
|
|
16
|
+
from ..utils.path_utils import get_repo_root_and_relative_path
|
|
17
17
|
|
|
18
18
|
logger = logging.getLogger(__name__)
|
|
19
19
|
|
|
@@ -31,6 +31,7 @@ def vectorize(search_description: Optional[str] = None,
|
|
|
31
31
|
capture_inputs: bool = False,
|
|
32
32
|
semantic_cache_filters: Optional[Dict[str, Any]] = None,
|
|
33
33
|
semantic_cache_scope: Optional[List[str]] = None,
|
|
34
|
+
enable_alert: bool = True,
|
|
34
35
|
**execution_tags):
|
|
35
36
|
"""
|
|
36
37
|
VectorWave Decorator with Auto-Generation support.
|
|
@@ -65,7 +66,7 @@ def vectorize(search_description: Optional[str] = None,
|
|
|
65
66
|
if attr not in final_attributes:
|
|
66
67
|
final_attributes.append(attr)
|
|
67
68
|
|
|
68
|
-
if capture_inputs:
|
|
69
|
+
if capture_inputs or replay:
|
|
69
70
|
try:
|
|
70
71
|
sig = inspect.signature(func)
|
|
71
72
|
for param_name in sig.parameters:
|
|
@@ -74,15 +75,6 @@ def vectorize(search_description: Optional[str] = None,
|
|
|
74
75
|
except Exception as e:
|
|
75
76
|
logger.warning(f"Failed to inspect signature for auto-capture in '{function_name}': {e}")
|
|
76
77
|
|
|
77
|
-
if replay:
|
|
78
|
-
try:
|
|
79
|
-
sig = inspect.signature(func)
|
|
80
|
-
for param_name in sig.parameters:
|
|
81
|
-
if param_name not in ('self', 'cls') and param_name not in final_attributes:
|
|
82
|
-
final_attributes.append(param_name)
|
|
83
|
-
except Exception as e:
|
|
84
|
-
logger.warning(f"Failed to inspect signature for replay auto-capture in '{function_name}': {e}")
|
|
85
|
-
|
|
86
78
|
# Extract Execution Tags
|
|
87
79
|
valid_execution_tags = {}
|
|
88
80
|
settings = get_weaviate_settings()
|
|
@@ -110,7 +102,7 @@ def vectorize(search_description: Optional[str] = None,
|
|
|
110
102
|
if relative_file_path:
|
|
111
103
|
file_path = relative_file_path
|
|
112
104
|
else:
|
|
113
|
-
file_path = abs_file_path
|
|
105
|
+
file_path = abs_file_path
|
|
114
106
|
logger.warning(f"Function '{function_name}' is not in a Git repository. "
|
|
115
107
|
f"PR creation might fail for absolute path: {file_path}")
|
|
116
108
|
except Exception as e:
|
|
@@ -147,7 +139,7 @@ def vectorize(search_description: Optional[str] = None,
|
|
|
147
139
|
vectorizer = get_vectorizer()
|
|
148
140
|
vector_to_add = None
|
|
149
141
|
|
|
150
|
-
if vectorizer and search_description:
|
|
142
|
+
if vectorizer is not None and search_description:
|
|
151
143
|
try:
|
|
152
144
|
vector_to_add = vectorizer.embed(search_description)
|
|
153
145
|
except Exception as e:
|
|
@@ -185,9 +177,32 @@ def vectorize(search_description: Optional[str] = None,
|
|
|
185
177
|
|
|
186
178
|
# --- Wrapper Logic ---
|
|
187
179
|
|
|
180
|
+
def _try_cache(args, kwargs):
|
|
181
|
+
"""Check semantic cache. Returns cached result or None."""
|
|
182
|
+
if not semantic_cache:
|
|
183
|
+
return None
|
|
184
|
+
filters = resolve_semantic_filters(args, kwargs)
|
|
185
|
+
return _check_and_return_cached_result(
|
|
186
|
+
func, args, kwargs, function_name, cache_threshold,
|
|
187
|
+
is_async_func, filters=filters
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
def _build_full_kwargs(kwargs):
|
|
191
|
+
"""Build kwargs with execution tags and metadata."""
|
|
192
|
+
full_kwargs = kwargs.copy()
|
|
193
|
+
full_kwargs.update(valid_execution_tags)
|
|
194
|
+
full_kwargs['function_uuid'] = func_uuid
|
|
195
|
+
full_kwargs['exec_source'] = execution_source_context.get()
|
|
196
|
+
return full_kwargs
|
|
197
|
+
|
|
188
198
|
if is_async_func:
|
|
189
199
|
@trace_root()
|
|
190
|
-
@trace_span(
|
|
200
|
+
@trace_span(
|
|
201
|
+
attributes_to_capture=final_attributes,
|
|
202
|
+
capture_return_value=capture_return_value,
|
|
203
|
+
force_sync=semantic_cache,
|
|
204
|
+
enable_alert=enable_alert
|
|
205
|
+
)
|
|
191
206
|
@wraps(func)
|
|
192
207
|
async def inner_wrapper(*args, **kwargs):
|
|
193
208
|
clean_kwargs = {k: v for k, v in kwargs.items() if
|
|
@@ -196,23 +211,22 @@ def vectorize(search_description: Optional[str] = None,
|
|
|
196
211
|
|
|
197
212
|
@wraps(func)
|
|
198
213
|
async def outer_wrapper(*args, **kwargs):
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
cached
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
full_kwargs = kwargs.copy()
|
|
205
|
-
full_kwargs.update(valid_execution_tags)
|
|
206
|
-
full_kwargs['function_uuid'] = func_uuid
|
|
207
|
-
full_kwargs['exec_source'] = execution_source_context.get()
|
|
208
|
-
return await inner_wrapper(*args, **full_kwargs)
|
|
214
|
+
cached = _try_cache(args, kwargs)
|
|
215
|
+
if cached is not None:
|
|
216
|
+
return cached
|
|
217
|
+
return await inner_wrapper(*args, **_build_full_kwargs(kwargs))
|
|
209
218
|
|
|
210
219
|
outer_wrapper._is_vectorized = True
|
|
211
220
|
return outer_wrapper
|
|
212
221
|
|
|
213
222
|
else: # Sync wrapper
|
|
214
223
|
@trace_root()
|
|
215
|
-
@trace_span(
|
|
224
|
+
@trace_span(
|
|
225
|
+
attributes_to_capture=final_attributes,
|
|
226
|
+
capture_return_value=capture_return_value,
|
|
227
|
+
force_sync=semantic_cache,
|
|
228
|
+
enable_alert=enable_alert
|
|
229
|
+
)
|
|
216
230
|
@wraps(func)
|
|
217
231
|
def inner_wrapper(*args, **kwargs):
|
|
218
232
|
clean_kwargs = {k: v for k, v in kwargs.items() if
|
|
@@ -221,16 +235,10 @@ def vectorize(search_description: Optional[str] = None,
|
|
|
221
235
|
|
|
222
236
|
@wraps(func)
|
|
223
237
|
def outer_wrapper(*args, **kwargs):
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
cached
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
full_kwargs = kwargs.copy()
|
|
230
|
-
full_kwargs.update(valid_execution_tags)
|
|
231
|
-
full_kwargs['function_uuid'] = func_uuid
|
|
232
|
-
full_kwargs['exec_source'] = execution_source_context.get()
|
|
233
|
-
return inner_wrapper(*args, **full_kwargs)
|
|
238
|
+
cached = _try_cache(args, kwargs)
|
|
239
|
+
if cached is not None:
|
|
240
|
+
return cached
|
|
241
|
+
return inner_wrapper(*args, **_build_full_kwargs(kwargs))
|
|
234
242
|
|
|
235
243
|
outer_wrapper._is_vectorized = True
|
|
236
244
|
return outer_wrapper
|
|
@@ -21,7 +21,7 @@ def generate_metadata_via_llm(source_code: str, func_name: str) -> Optional[Dict
|
|
|
21
21
|
"""Call LLM to generate description and narrative from source code."""
|
|
22
22
|
settings = get_weaviate_settings()
|
|
23
23
|
client = get_llm_client()
|
|
24
|
-
if
|
|
24
|
+
if client is None:
|
|
25
25
|
return None
|
|
26
26
|
|
|
27
27
|
prompt = f"""
|
|
@@ -121,7 +121,7 @@ def generate_and_register_metadata():
|
|
|
121
121
|
|
|
122
122
|
# 4. Vectorize the Description
|
|
123
123
|
vector_to_add = None
|
|
124
|
-
if vectorizer and final_desc:
|
|
124
|
+
if vectorizer is not None and final_desc:
|
|
125
125
|
try:
|
|
126
126
|
vector_to_add = vectorizer.embed(final_desc)
|
|
127
127
|
except Exception as e:
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import threading
|
|
2
|
+
import logging
|
|
3
|
+
from ..models.db_config import get_weaviate_settings
|
|
4
|
+
from ..utils.scheduler import start_scheduler
|
|
5
|
+
|
|
6
|
+
logger = logging.getLogger(__name__)
|
|
7
|
+
|
|
8
|
+
_HEALER_STARTED = False
|
|
9
|
+
|
|
10
|
+
def initialize_vectorwave():
|
|
11
|
+
"""
|
|
12
|
+
Initialize vectorwave system.
|
|
13
|
+
Refer to config automatically run Auto Healer System.
|
|
14
|
+
"""
|
|
15
|
+
global _HEALER_STARTED
|
|
16
|
+
try:
|
|
17
|
+
settings = get_weaviate_settings()
|
|
18
|
+
except Exception as e:
|
|
19
|
+
logger.warning(f"⚠️ Failed to load settings during initialization: {e}")
|
|
20
|
+
return
|
|
21
|
+
|
|
22
|
+
if _HEALER_STARTED:
|
|
23
|
+
return
|
|
24
|
+
|
|
25
|
+
if settings.ENABLE_AUTO_HEALER:
|
|
26
|
+
logger.info("🔧 AutoHealer is enabled. Starting background scheduler...")
|
|
27
|
+
|
|
28
|
+
healer_thread = threading.Thread(
|
|
29
|
+
target=start_scheduler,
|
|
30
|
+
kwargs={'interval_minutes': settings.HEALER_CHECK_INTERVAL_MINUTES},
|
|
31
|
+
daemon=True,
|
|
32
|
+
name="VectorWave-AutoHealer"
|
|
33
|
+
)
|
|
34
|
+
healer_thread.start()
|
|
35
|
+
_HEALER_STARTED = True
|
|
36
|
+
else:
|
|
37
|
+
logger.debug("🔧 AutoHealer is disabled (ENABLE_AUTO_HEALER=False).")
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
from functools import lru_cache
|
|
2
|
+
|
|
3
|
+
from .base import BaseLLMClient
|
|
4
|
+
from .openai_client import VectorWaveOpenAIClient
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@lru_cache()
|
|
8
|
+
def get_llm_client() -> BaseLLMClient:
|
|
9
|
+
"""Returns the singleton LLM client instance."""
|
|
10
|
+
return VectorWaveOpenAIClient()
|
|
@@ -37,7 +37,7 @@ class VectorWaveDatasetManager:
|
|
|
37
37
|
include_vector=True
|
|
38
38
|
)
|
|
39
39
|
|
|
40
|
-
if
|
|
40
|
+
if log_obj is None:
|
|
41
41
|
logger.error(f"Log UUID '{log_uuid}' not found.")
|
|
42
42
|
return False
|
|
43
43
|
|
|
@@ -55,9 +55,17 @@ class VectorWaveDatasetManager:
|
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
# 3. Save (reuse original vector)
|
|
58
|
+
vector = (log_obj.vector or {}).get("default")
|
|
59
|
+
if vector is None:
|
|
60
|
+
logger.error(
|
|
61
|
+
f"Log '{log_uuid}' has no stored vector. "
|
|
62
|
+
"The source function must have capture_return_value=True for vector storage."
|
|
63
|
+
)
|
|
64
|
+
return False
|
|
65
|
+
|
|
58
66
|
self.golden_col.data.insert(
|
|
59
67
|
properties=golden_props,
|
|
60
|
-
vector=
|
|
68
|
+
vector=vector,
|
|
61
69
|
uuid=generate_uuid5(log_uuid) # Regenerate to avoid UUID collision, or maintain relation with original
|
|
62
70
|
)
|
|
63
71
|
logger.info(f"✅ Registered log {log_uuid} as Golden Data.")
|