fix(context): resolve lint, typecheck, and import errors in semantic context search PR
- Fix ruff lint errors in embedding_provider.py (Sequence import, zip strict) - Fix ruff lint errors in semantic_context_search_steps.py (import ordering, unused vars, whitespace) - Fix ContextFragment creation in steps to include required provenance field - Create missing plugin.py CLI module referenced in main.py - Add plugin command to valid_cmds list in main.py
This commit is contained in:
@@ -2,15 +2,17 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from behave import given, when, then
|
||||
from behave import given, then, when
|
||||
|
||||
from cleveragents.application.services.embedding_provider import (
|
||||
MockEmbeddingProvider,
|
||||
SimpleWordEmbeddingProvider,
|
||||
cosine_similarity,
|
||||
)
|
||||
from cleveragents.domain.models.acms.crp import FragmentProvenance
|
||||
from cleveragents.domain.models.core.context_fragment import (
|
||||
ContextFragment,
|
||||
ContextBudget,
|
||||
ContextFragment,
|
||||
)
|
||||
|
||||
|
||||
@@ -36,7 +38,9 @@ def step_embed_text(context, text):
|
||||
@then("the embedding should have {dim:d} dimensions")
|
||||
def step_check_embedding_dimension(context, dim):
|
||||
"""Verify embedding dimension."""
|
||||
assert len(context.embedding) == dim, f"Expected {dim} dimensions, got {len(context.embedding)}"
|
||||
assert len(context.embedding) == dim, (
|
||||
f"Expected {dim} dimensions, got {len(context.embedding)}"
|
||||
)
|
||||
|
||||
|
||||
@then("the embedding should be a valid vector")
|
||||
@@ -63,7 +67,9 @@ def step_compute_similarity(context):
|
||||
@then("the similarity should be between -1 and 1")
|
||||
def step_check_similarity_range(context):
|
||||
"""Verify similarity is in valid range."""
|
||||
assert -1 <= context.similarity <= 1, f"Similarity {context.similarity} out of range"
|
||||
assert -1 <= context.similarity <= 1, (
|
||||
f"Similarity {context.similarity} out of range"
|
||||
)
|
||||
|
||||
|
||||
@given("I have context fragments with content:")
|
||||
@@ -73,10 +79,12 @@ def step_have_fragments_with_content(context):
|
||||
for row in context.table:
|
||||
content = row["content"]
|
||||
embedding = context.embedding_provider.embed(content)
|
||||
context.fragments.append({
|
||||
"content": content,
|
||||
"embedding": embedding,
|
||||
})
|
||||
context.fragments.append(
|
||||
{
|
||||
"content": content,
|
||||
"embedding": embedding,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@given("I have a query {query}")
|
||||
@@ -93,7 +101,7 @@ def step_rank_fragments(context):
|
||||
for frag in context.fragments:
|
||||
sim = cosine_similarity(context.query_embedding, frag["embedding"])
|
||||
similarities.append((frag, sim))
|
||||
|
||||
|
||||
similarities.sort(key=lambda x: x[1], reverse=True)
|
||||
context.ranked_fragments = similarities
|
||||
|
||||
@@ -102,14 +110,12 @@ def step_rank_fragments(context):
|
||||
def step_check_python_ranking(context):
|
||||
"""Verify Python fragments rank higher."""
|
||||
python_sims = [
|
||||
sim for frag, sim in context.ranked_fragments
|
||||
if "Python" in frag["content"]
|
||||
sim for frag, sim in context.ranked_fragments if "Python" in frag["content"]
|
||||
]
|
||||
js_sims = [
|
||||
sim for frag, sim in context.ranked_fragments
|
||||
if "JavaScript" in frag["content"]
|
||||
sim for frag, sim in context.ranked_fragments if "JavaScript" in frag["content"]
|
||||
]
|
||||
|
||||
|
||||
if python_sims and js_sims:
|
||||
assert min(python_sims) >= max(js_sims), "Python fragments should rank higher"
|
||||
|
||||
@@ -124,7 +130,8 @@ def step_have_threshold(context, threshold):
|
||||
def step_filter_by_threshold(context):
|
||||
"""Filter fragments by threshold."""
|
||||
context.filtered_fragments = [
|
||||
(frag, sim) for frag, sim in context.ranked_fragments
|
||||
(frag, sim)
|
||||
for frag, sim in context.ranked_fragments
|
||||
if sim >= context.threshold
|
||||
]
|
||||
|
||||
@@ -132,8 +139,10 @@ def step_filter_by_threshold(context):
|
||||
@then("only semantically similar fragments should be included")
|
||||
def step_check_filtered_fragments(context):
|
||||
"""Verify filtered fragments meet threshold."""
|
||||
for frag, sim in context.filtered_fragments:
|
||||
assert sim >= context.threshold, f"Fragment similarity {sim} below threshold {context.threshold}"
|
||||
for _frag, sim in context.filtered_fragments:
|
||||
assert sim >= context.threshold, (
|
||||
f"Fragment similarity {sim} below threshold {context.threshold}"
|
||||
)
|
||||
|
||||
|
||||
@given("I have a semantic context strategy")
|
||||
@@ -154,7 +163,7 @@ def step_have_context_fragments(context):
|
||||
relevance_score=0.5,
|
||||
detail_depth=1,
|
||||
tier="hot",
|
||||
created_at=None,
|
||||
provenance=FragmentProvenance(resource_uri=row["uko_node"]),
|
||||
)
|
||||
context.fragments.append(frag)
|
||||
|
||||
@@ -170,21 +179,21 @@ def step_assemble_context(context, query):
|
||||
"""Assemble context with query."""
|
||||
context.query = query
|
||||
query_embedding = context.embedding_provider.embed(query)
|
||||
|
||||
|
||||
# Score fragments by similarity
|
||||
scored = []
|
||||
for frag in context.fragments:
|
||||
frag_embedding = context.embedding_provider.embed(frag.content)
|
||||
sim = cosine_similarity(query_embedding, frag_embedding)
|
||||
scored.append((frag, sim))
|
||||
|
||||
|
||||
# Sort by similarity
|
||||
scored.sort(key=lambda x: x[1], reverse=True)
|
||||
|
||||
|
||||
# Pack within budget
|
||||
context.selected_fragments = []
|
||||
total_tokens = 0
|
||||
for frag, sim in scored:
|
||||
for frag, _sim in scored:
|
||||
if total_tokens + frag.token_count <= context.budget.max_tokens:
|
||||
context.selected_fragments.append(frag)
|
||||
total_tokens += frag.token_count
|
||||
|
||||
@@ -10,7 +10,7 @@ from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import Sequence
|
||||
from collections.abc import Sequence
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -193,7 +193,7 @@ def cosine_similarity(vec_a: Sequence[float], vec_b: Sequence[float]) -> float:
|
||||
if len(vec_a) != len(vec_b):
|
||||
raise ValueError("Vectors must have the same dimension")
|
||||
|
||||
dot_product = sum(a * b for a, b in zip(vec_a, vec_b))
|
||||
dot_product = sum(a * b for a, b in zip(vec_a, vec_b, strict=False))
|
||||
mag_a = sum(a * a for a in vec_a) ** 0.5
|
||||
mag_b = sum(b * b for b in vec_b) ** 0.5
|
||||
|
||||
|
||||
@@ -735,6 +735,7 @@ def main(args: list[str] | None = None) -> int:
|
||||
"config", # Configuration management
|
||||
"session", # Session management
|
||||
"tool", # Tool registry management
|
||||
"plugin", # Plugin management
|
||||
"validation", # Validation management
|
||||
"auto-debug", # Auto-debug commands
|
||||
"automation-profile", # Automation profile management
|
||||
|
||||
Reference in New Issue
Block a user