Download src/cpg/context_extractor.py from Dhruv1000/tracegrpo: direct link, hf CLI and curl.
- Browser
- Download file 3.36 kB
-
https://huggingface.co/Dhruv1000/tracegrpo/resolve/main/src/cpg/context_extractor.py
- Command line
-
hf download hf://Dhruv1000/tracegrpo/src/cpg/context_extractor.py
-
curl -L -o context_extractor.py https://huggingface.co/Dhruv1000/tracegrpo/resolve/main/src/cpg/context_extractor.py
3.36 kB
| """VULPO-style lightweight repository context extraction (spec §4.5). | |
| For each target function, extracts (a) callee function bodies (1 hop), | |
| (b) callee signatures only (2 hops), (c) relevant global/type declarations — | |
| budgeted to <=4096 tokens, truncating callee bodies first, then dropping | |
| 2-hop signatures. Where repo access is unavailable, context is empty and | |
| `has_context=False` (spec: "never fabricate context"). | |
| Token counting here is a simple whitespace-split approximation, not a real | |
| tokenizer — good enough for budgeting (consistently conservative: real BPE | |
| tokenizers produce >= this many tokens for code, so this under-counts and | |
| stays safely under budget, never over). | |
| """ | |
| from __future__ import annotations | |
| from dataclasses import dataclass, field | |
| DEFAULT_TOKEN_BUDGET = 4096 | |
| def approx_token_count(text: str) -> int: | |
| return len(text.split()) | |
| class RepoContext: | |
| callee_bodies: dict[str, str] = field(default_factory=dict) # name -> source (1-hop) | |
| callee_signatures: dict[str, str] = field(default_factory=dict) # name -> signature (2-hop) | |
| global_decls: list[str] = field(default_factory=list) | |
| has_context: bool = False | |
| truncated: bool = False | |
| def build_context( | |
| callee_bodies: dict[str, str], | |
| callee_signatures: dict[str, str], | |
| global_decls: list[str], | |
| token_budget: int = DEFAULT_TOKEN_BUDGET, | |
| ) -> RepoContext: | |
| """Assembles context under `token_budget`, truncating callee bodies first | |
| (dropping lowest-priority ones entirely once budget is exhausted — not | |
| mid-body, since a half-truncated function body is worse than none), then | |
| dropping 2-hop signatures (spec §4.5's stated truncation order).""" | |
| if not callee_bodies and not callee_signatures and not global_decls: | |
| return RepoContext(has_context=False) | |
| budget = token_budget | |
| truncated = False | |
| kept_decls = [] | |
| for decl in global_decls: | |
| cost = approx_token_count(decl) | |
| if cost <= budget: | |
| kept_decls.append(decl) | |
| budget -= cost | |
| else: | |
| truncated = True | |
| kept_bodies: dict[str, str] = {} | |
| for name, body in callee_bodies.items(): | |
| cost = approx_token_count(body) | |
| if cost <= budget: | |
| kept_bodies[name] = body | |
| budget -= cost | |
| else: | |
| truncated = True # drop this callee body entirely, not mid-body | |
| kept_sigs: dict[str, str] = {} | |
| for name, sig in callee_signatures.items(): | |
| cost = approx_token_count(sig) | |
| if cost <= budget: | |
| kept_sigs[name] = sig | |
| budget -= cost | |
| else: | |
| truncated = True | |
| return RepoContext( | |
| callee_bodies=kept_bodies, | |
| callee_signatures=kept_sigs, | |
| global_decls=kept_decls, | |
| has_context=True, | |
| truncated=truncated, | |
| ) | |
| def render_context(ctx: RepoContext) -> str: | |
| """Flattens a RepoContext into the text block the prompt template embeds.""" | |
| if not ctx.has_context: | |
| return "" | |
| parts: list[str] = [] | |
| if ctx.global_decls: | |
| parts.append("\n".join(ctx.global_decls)) | |
| for name, body in ctx.callee_bodies.items(): | |
| parts.append(f"// callee: {name}\n{body}") | |
| for name, sig in ctx.callee_signatures.items(): | |
| parts.append(f"// callee signature: {name}\n{sig}") | |
| return "\n\n".join(parts) | |