update output

This commit is contained in:
2025-11-15 23:02:19 +00:00
parent 4580638cfd
commit e03a92e7ec
+82 -80
View File
@@ -5007,7 +5007,7 @@ def _build_enhanced_result(chunk_text: str, meta: dict, score: float, graph: Opt
def _get_result_graph_context(meta: dict, graph: Optional[LocalGraph] = None) -> dict: def _get_result_graph_context(meta: dict, graph: Optional[LocalGraph] = None) -> dict:
"""Get relevant graph context for a search result with cross-file awareness.""" """Get MOST relevant graph context - optimized for LLM tokens."""
if graph is None or graph.graph.number_of_nodes() == 0: if graph is None or graph.graph.number_of_nodes() == 0:
return {} return {}
@@ -5032,61 +5032,68 @@ def _get_result_graph_context(meta: dict, graph: Optional[LocalGraph] = None) ->
node_id = f"svelte::component::{file_path}::{entity_name}" node_id = f"svelte::component::{file_path}::{entity_name}"
if node_id and node_id in graph.graph: if node_id and node_id in graph.graph:
# Get direct relationships WITH file info # PRIORITY 1: Cross-file dependencies (highest value for LLM)
neighbors = list(graph.neighbors(node_id)) cross_file_rels = []
if neighbors: incoming_cross_file = []
context['relationships'] = []
context['cross_file_deps'] = [] # NEW: Track cross-file dependencies
for neighbor_id, neighbor_data in neighbors[:10]: # Show more neighbors # Outgoing cross-file relationships
for neighbor_id, neighbor_data in graph.neighbors(node_id):
neighbor_file = neighbor_data.get('file', '')
if neighbor_file and neighbor_file != file_path:
edge_data = graph.graph.edges[node_id, neighbor_id] edge_data = graph.graph.edges[node_id, neighbor_id]
rel_type = edge_data.get('type', 'related') rel_type = edge_data.get('type', 'related')
neighbor_name = neighbor_data.get('name', neighbor_id.split('::')[-1]) neighbor_name = neighbor_data.get('name', neighbor_id.split('::')[-1])
neighbor_file = neighbor_data.get('file', '')
neighbor_type = neighbor_data.get('type', '') neighbor_type = neighbor_data.get('type', '')
# Build compact relationship string with file info # Compress representation based on relationship importance
if neighbor_file and neighbor_file != file_path: if rel_type in ['extends', 'implements', 'calls']:
# Cross-file relationship - show file # High-value relationships - keep full info
rel_str = f"{rel_type}:{neighbor_name}@{neighbor_file}" cross_file_rels.append(f"{rel_type}:{neighbor_type}:{neighbor_name}@{neighbor_file}")
context['cross_file_deps'].append(rel_str)
else: else:
# Same-file relationship - omit file for brevity # Medium-value - compress type
rel_str = f"{rel_type}:{neighbor_name}" cross_file_rels.append(f"{rel_type}:{neighbor_name}@{neighbor_file}")
context['relationships'].append(rel_str) # PRIORITY 2: Reverse dependencies (what uses this entity)
# NEW: Find reverse dependencies (what depends on THIS entity)
incoming = []
for predecessor in graph.graph.predecessors(node_id): for predecessor in graph.graph.predecessors(node_id):
pred_data = graph.graph.nodes[predecessor] pred_data = graph.graph.nodes[predecessor]
pred_file = pred_data.get('file', '') pred_file = pred_data.get('file', '')
pred_name = pred_data.get('name', '') pred_name = pred_data.get('name', '')
# Only show cross-file incoming (same-file is less valuable)
if pred_file and pred_file != file_path:
edge_data = graph.graph.edges[predecessor, node_id] edge_data = graph.graph.edges[predecessor, node_id]
rel_type = edge_data.get('type', 'related') rel_type = edge_data.get('type', 'related')
# Only show cross-file incoming dependencies if rel_type in ['calls', 'extends', 'implements']:
if pred_file and pred_file != file_path: incoming_cross_file.append(f"{rel_type}:{pred_name}@{pred_file}")
incoming.append(f"{rel_type}:{pred_name}@{pred_file}")
if incoming: # Apply aggressive limits for token conservation
context['used_by'] = incoming[:10] if cross_file_rels:
# Sort by relationship importance
priority_order = {'extends': 0, 'implements': 1, 'calls': 2}
cross_file_rels.sort(key=lambda x: priority_order.get(x.split(':')[0], 99))
context['xfile'] = cross_file_rels[:6] # Only top 6 cross-file deps
# Get file-level context (same as before) if incoming_cross_file:
context['used_by'] = incoming_cross_file[:4] # Only top 4 reverse deps
# PRIORITY 3: Critical same-file context (only if cross-file is sparse)
if not context.get('xfile') and not context.get('used_by'):
file_node_id = f"file::{file_path}" file_node_id = f"file::{file_path}"
if file_node_id in graph.graph: if file_node_id in graph.graph:
file_neighbors = list(graph.neighbors(file_node_id)) file_entities = []
if file_neighbors: for neighbor_id, neighbor_data in graph.neighbors(file_node_id):
context['file_entities'] = []
for neighbor_id, neighbor_data in file_neighbors[:5]:
neighbor_type = neighbor_data.get('type', '') neighbor_type = neighbor_data.get('type', '')
neighbor_name = neighbor_data.get('name', '') neighbor_name = neighbor_data.get('name', '')
if neighbor_type and neighbor_name and neighbor_name != entity_name: if (neighbor_type in ['class', 'struct', 'interface', 'component'] and
context['file_entities'].append(f"{neighbor_type}:{neighbor_name}") neighbor_name != entity_name):
file_entities.append(f"{neighbor_type}:{neighbor_name}")
if file_entities:
context['file'] = file_entities[:3] # Only top 3 same-file entities
return context return context
def _extract_docstring(chunk_text: str) -> str: def _extract_docstring(chunk_text: str) -> str:
"""Extract docstring or comments from chunk text.""" """Extract docstring or comments from chunk text."""
lines = chunk_text.split('\n') lines = chunk_text.split('\n')
@@ -5125,74 +5132,69 @@ def _extract_docstring(chunk_text: str) -> str:
def _format_enhanced_results(results: List[Dict], query: str, result_type: str) -> str: def _format_enhanced_results(results: List[Dict], query: str, result_type: str) -> str:
"""Format enhanced results with dense LLM-optimized context.""" """Ultra-compact formatting optimized for LLM token usage."""
if not results: if not results:
return f"# {result_type.title()}: {query}\nNo results found.\n" return f"# {result_type.title()}: {query}\nNo results found.\n"
lines = [ lines = [
f"# {result_type.title()}: {query}", f"# {result_type.title()}: {query}",
f"results[{len(results)}]{{file,line,type,name,score,content,context}}:" f"Found {len(results)} results:"
] ]
for result in results: for i, result in enumerate(results, 1):
context_parts = [] # Extract core info
file_path = result.get('file', '')
line_num = result.get('line', '')
entity_type = result.get('type', 'code')
entity_name = result.get('name', '')
score = result.get('score', 0.0)
content = result.get('content', '')[:350] # Strict content limit
# Graph context as dense key:value pairs
graph_context = result.get('graph_context', {}) graph_context = result.get('graph_context', {})
# Cross-file dependencies (highest value) # Build ultra-compact context string
if graph_context.get('cross_file_deps'): context_parts = []
deps = '|'.join(graph_context['cross_file_deps'][:8])
context_parts.append(f"xfile:{deps}")
# All relationships # Cross-file deps (highest priority)
if graph_context.get('relationships'): if graph_context.get('xfile'):
rels = '|'.join(graph_context['relationships'][:12]) # Compress further: remove file paths, keep only key info
context_parts.append(f"rels:{rels}") compressed_deps = []
for dep in graph_context['xfile'][:4]: # Only top 4
parts = dep.split('@')[0] # Remove file path
compressed_deps.append(parts)
context_parts.append(f"deps:{'|'.join(compressed_deps)}")
# Reverse dependencies # Reverse deps
if graph_context.get('used_by'): if graph_context.get('used_by'):
used = '|'.join(graph_context['used_by'][:6]) compressed_used = []
context_parts.append(f"used:{used}") for used in graph_context['used_by'][:3]: # Only top 3
parts = used.split('@')[0] # Remove file path
compressed_used.append(parts)
context_parts.append(f"used:{'|'.join(compressed_used)}")
# File context # Same-file context (lowest priority)
if graph_context.get('file_entities'): if graph_context.get('file') and not context_parts:
entities = '|'.join(graph_context['file_entities'][:10]) context_parts.append(f"file:{'|'.join(graph_context['file'][:2])}")
context_parts.append(f"file:{entities}")
# Docstring (if valuable) context_str = " ".join(context_parts)
# Ultra-compact row format
row = f"{i}. {file_path}:{line_num} {entity_type}:{entity_name} (score:{score:.2f})"
if context_str:
row += f" [{context_str}]"
lines.append(row)
lines.append(f" Content: {content}")
# Add docstring only if highly relevant and short
docstring = result.get('docstring', '') docstring = result.get('docstring', '')
if docstring and len(docstring) > 10: # Only include substantial docs if docstring and len(docstring) < 100 and any(keyword in query.lower() for keyword in ['how', 'what', 'why', 'documentation']):
context_parts.append(f"doc:{docstring[:200]}") lines.append(f" Docs: {docstring}")
context_str = ";".join(context_parts) lines.append("") # Empty line between results
# Minimal row with essential info
row = [
result.get('file', ''),
result.get('line', ''),
result.get('type', 'code'),
result.get('name', ''),
f"{result.get('score', 0.0):.2f}",
result.get('content', '')[:500], # More content tokens
context_str
]
# Efficient escaping
escaped_row = []
for field in row:
field_str = str(field)
if ',' in field_str or ';' in field_str:
escaped = field_str.replace('"', '\\"')
escaped_row.append(f'"{escaped}"')
else:
escaped_row.append(field_str)
lines.append(" " + ",".join(escaped_row))
return "\n".join(lines) return "\n".join(lines)
def _extract_clean_content(chunk_text: str) -> str: def _extract_clean_content(chunk_text: str) -> str:
"""Extract clean content from chunk text by removing duplicate metadata.""" """Extract clean content from chunk text by removing duplicate metadata."""
lines = chunk_text.split('\n') lines = chunk_text.split('\n')