coreinsight-cli 0.1.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.
- coreinsight_cli-0.1.0/LICENSE +21 -0
- coreinsight_cli-0.1.0/PKG-INFO +115 -0
- coreinsight_cli-0.1.0/README.md +78 -0
- coreinsight_cli-0.1.0/coreinsight/Dockerfile.cpp-sandbox +2 -0
- coreinsight_cli-0.1.0/coreinsight/Dockerfile.python-sandbox +3 -0
- coreinsight_cli-0.1.0/coreinsight/__init__.py +0 -0
- coreinsight_cli-0.1.0/coreinsight/analyzer.py +374 -0
- coreinsight_cli-0.1.0/coreinsight/config.py +51 -0
- coreinsight_cli-0.1.0/coreinsight/hardware.py +45 -0
- coreinsight_cli-0.1.0/coreinsight/indexer.py +97 -0
- coreinsight_cli-0.1.0/coreinsight/main.py +366 -0
- coreinsight_cli-0.1.0/coreinsight/parser.py +95 -0
- coreinsight_cli-0.1.0/coreinsight/prompts.py +50 -0
- coreinsight_cli-0.1.0/coreinsight/sandbox.py +566 -0
- coreinsight_cli-0.1.0/coreinsight/scanner.py +103 -0
- coreinsight_cli-0.1.0/coreinsight_cli.egg-info/PKG-INFO +115 -0
- coreinsight_cli-0.1.0/coreinsight_cli.egg-info/SOURCES.txt +21 -0
- coreinsight_cli-0.1.0/coreinsight_cli.egg-info/dependency_links.txt +1 -0
- coreinsight_cli-0.1.0/coreinsight_cli.egg-info/entry_points.txt +2 -0
- coreinsight_cli-0.1.0/coreinsight_cli.egg-info/requires.txt +14 -0
- coreinsight_cli-0.1.0/coreinsight_cli.egg-info/top_level.txt +1 -0
- coreinsight_cli-0.1.0/pyproject.toml +56 -0
- coreinsight_cli-0.1.0/setup.cfg +4 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Varun Jani
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: coreinsight-cli
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Local-first AI performance profiler that mathematically verifies optimizations for Python, C++, and CUDA
|
|
5
|
+
Author: Varun Jani
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/Prais3/coreinsight_cli
|
|
8
|
+
Project-URL: Bug Tracker, https://github.com/Prais3/coreinsight_cli/issues
|
|
9
|
+
Keywords: performance,profiling,optimization,llm,cuda,cpp,python,hpc,benchmarking
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Topic :: Software Development :: Debuggers
|
|
18
|
+
Classifier: Topic :: System :: Hardware
|
|
19
|
+
Requires-Python: >=3.9
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
License-File: LICENSE
|
|
22
|
+
Requires-Dist: rich>=13.0
|
|
23
|
+
Requires-Dist: docker>=6.0
|
|
24
|
+
Requires-Dist: tree-sitter==0.21.3
|
|
25
|
+
Requires-Dist: tree-sitter-languages
|
|
26
|
+
Requires-Dist: langchain>=0.2.0
|
|
27
|
+
Requires-Dist: langchain-core>=0.2.0
|
|
28
|
+
Requires-Dist: langchain-ollama>=0.1.0
|
|
29
|
+
Requires-Dist: langchain-google-genai>=1.0.0
|
|
30
|
+
Requires-Dist: langchain-openai>=0.1.0
|
|
31
|
+
Requires-Dist: langchain-anthropic>=0.1.0
|
|
32
|
+
Requires-Dist: pydantic>=2.0
|
|
33
|
+
Requires-Dist: chromadb>=0.5.0
|
|
34
|
+
Requires-Dist: sentence-transformers>=3.0.0
|
|
35
|
+
Requires-Dist: psutil>=5.9
|
|
36
|
+
Dynamic: license-file
|
|
37
|
+
|
|
38
|
+
# CoreInsight CLI
|
|
39
|
+
|
|
40
|
+
CoreInsight is a local-first, hardware-aware AI performance profiler. It shifts performance engineering "left" by parsing your Python, C++, and CUDA code, identifying hardware bottlenecks (like CPU cache thrashing or CUDA warp divergence), and mathematically verifying AI-generated optimizations inside secure Docker sandboxes.
|
|
41
|
+
|
|
42
|
+
## Prerequisites
|
|
43
|
+
|
|
44
|
+
* **Python 3.9+**
|
|
45
|
+
* **Docker Desktop / Docker Engine** (Must be running for the sandbox verification)
|
|
46
|
+
* **Ollama** (Optional, if using local models) or API keys for cloud models.
|
|
47
|
+
|
|
48
|
+
## Installation & Usage
|
|
49
|
+
|
|
50
|
+
**Required: Install Docker: https://docs.docker.com/engine/install/**
|
|
51
|
+
|
|
52
|
+
**Optional (Suggested): Setup OpenAI/Anthropic/Google API keys to load their models**
|
|
53
|
+
|
|
54
|
+
**1. Build locally:**
|
|
55
|
+
Clone this repository and install it in editable mode:
|
|
56
|
+
```bash
|
|
57
|
+
pip install -e .
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
**2. Configure CoreInsight CLI:**
|
|
61
|
+
Set up your preferred AI provider (Ollama, local vLLM, OpenAI, Anthropic, or Gemini):
|
|
62
|
+
```bash
|
|
63
|
+
coreinsight configure
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
**3. Build Global Context (Recommended for multiple files):**
|
|
67
|
+
Index your repository so the AI understands your custom structs, classes, and dependencies across files:
|
|
68
|
+
```bash
|
|
69
|
+
coreinsight index
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
**4. Test on a file:**
|
|
73
|
+
Analyze a specific file. The CLI will extract hot loops, process them in parallel, verify optimizations in Docker, and output a live Markdown report.
|
|
74
|
+
```bash
|
|
75
|
+
coreinsight analyze <file_name>
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
**5. Project-Wide Hotspot Scanning:**
|
|
79
|
+
Instead of guessing which files are slow, scan your entire repository. CoreInsight will use static AST analysis to rank the most complex, deeply-nested loops in your project.
|
|
80
|
+
```bash
|
|
81
|
+
coreinsight scan
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Build the Project
|
|
85
|
+
|
|
86
|
+
Download build:
|
|
87
|
+
```bash
|
|
88
|
+
pip install build
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Run the build command to generate wheel file:
|
|
92
|
+
```bash
|
|
93
|
+
python -m build --wheel
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
To build project elsewhere using wheel file:
|
|
97
|
+
```bash
|
|
98
|
+
pip install dist/coreinsight_cli-*.whl
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
To build project using source code:
|
|
102
|
+
```bash
|
|
103
|
+
pip install -e .
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Architecture Notes
|
|
107
|
+
CoreInsight runs 100% locally. Code is only transmitted to the AI provider you configure. If you use Ollama or a local server, your proprietary code never leaves your machine.
|
|
108
|
+
|
|
109
|
+
## Current/Future Features In Progess:
|
|
110
|
+
|
|
111
|
+
- Improve AST parsing
|
|
112
|
+
- Extract and integrate hardware information for the LLM
|
|
113
|
+
- Improve CLI interface
|
|
114
|
+
- Parallel execution
|
|
115
|
+
- Improve RAG
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# CoreInsight CLI
|
|
2
|
+
|
|
3
|
+
CoreInsight is a local-first, hardware-aware AI performance profiler. It shifts performance engineering "left" by parsing your Python, C++, and CUDA code, identifying hardware bottlenecks (like CPU cache thrashing or CUDA warp divergence), and mathematically verifying AI-generated optimizations inside secure Docker sandboxes.
|
|
4
|
+
|
|
5
|
+
## Prerequisites
|
|
6
|
+
|
|
7
|
+
* **Python 3.9+**
|
|
8
|
+
* **Docker Desktop / Docker Engine** (Must be running for the sandbox verification)
|
|
9
|
+
* **Ollama** (Optional, if using local models) or API keys for cloud models.
|
|
10
|
+
|
|
11
|
+
## Installation & Usage
|
|
12
|
+
|
|
13
|
+
**Required: Install Docker: https://docs.docker.com/engine/install/**
|
|
14
|
+
|
|
15
|
+
**Optional (Suggested): Setup OpenAI/Anthropic/Google API keys to load their models**
|
|
16
|
+
|
|
17
|
+
**1. Build locally:**
|
|
18
|
+
Clone this repository and install it in editable mode:
|
|
19
|
+
```bash
|
|
20
|
+
pip install -e .
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
**2. Configure CoreInsight CLI:**
|
|
24
|
+
Set up your preferred AI provider (Ollama, local vLLM, OpenAI, Anthropic, or Gemini):
|
|
25
|
+
```bash
|
|
26
|
+
coreinsight configure
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
**3. Build Global Context (Recommended for multiple files):**
|
|
30
|
+
Index your repository so the AI understands your custom structs, classes, and dependencies across files:
|
|
31
|
+
```bash
|
|
32
|
+
coreinsight index
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
**4. Test on a file:**
|
|
36
|
+
Analyze a specific file. The CLI will extract hot loops, process them in parallel, verify optimizations in Docker, and output a live Markdown report.
|
|
37
|
+
```bash
|
|
38
|
+
coreinsight analyze <file_name>
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
**5. Project-Wide Hotspot Scanning:**
|
|
42
|
+
Instead of guessing which files are slow, scan your entire repository. CoreInsight will use static AST analysis to rank the most complex, deeply-nested loops in your project.
|
|
43
|
+
```bash
|
|
44
|
+
coreinsight scan
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Build the Project
|
|
48
|
+
|
|
49
|
+
Download build:
|
|
50
|
+
```bash
|
|
51
|
+
pip install build
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Run the build command to generate wheel file:
|
|
55
|
+
```bash
|
|
56
|
+
python -m build --wheel
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
To build project elsewhere using wheel file:
|
|
60
|
+
```bash
|
|
61
|
+
pip install dist/coreinsight_cli-*.whl
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
To build project using source code:
|
|
65
|
+
```bash
|
|
66
|
+
pip install -e .
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Architecture Notes
|
|
70
|
+
CoreInsight runs 100% locally. Code is only transmitted to the AI provider you configure. If you use Ollama or a local server, your proprietary code never leaves your machine.
|
|
71
|
+
|
|
72
|
+
## Current/Future Features In Progess:
|
|
73
|
+
|
|
74
|
+
- Improve AST parsing
|
|
75
|
+
- Extract and integrate hardware information for the LLM
|
|
76
|
+
- Improve CLI interface
|
|
77
|
+
- Parallel execution
|
|
78
|
+
- Improve RAG
|
|
File without changes
|
|
@@ -0,0 +1,374 @@
|
|
|
1
|
+
import re
|
|
2
|
+
import logging
|
|
3
|
+
from typing import Optional, List
|
|
4
|
+
from pydantic import BaseModel, Field
|
|
5
|
+
|
|
6
|
+
from langchain_core.output_parsers import JsonOutputParser
|
|
7
|
+
from langchain_core.prompts import PromptTemplate
|
|
8
|
+
from langchain_core.exceptions import OutputParserException
|
|
9
|
+
|
|
10
|
+
from langchain_ollama import ChatOllama
|
|
11
|
+
from langchain_google_genai import ChatGoogleGenerativeAI
|
|
12
|
+
from langchain_openai import ChatOpenAI
|
|
13
|
+
from langchain_anthropic import ChatAnthropic
|
|
14
|
+
|
|
15
|
+
from coreinsight.prompts import SYSTEM_PROMPT, ANALYSIS_TEMPLATE
|
|
16
|
+
|
|
17
|
+
logger = logging.getLogger(__name__)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class Bottleneck(BaseModel):
|
|
21
|
+
line: int = Field(description="The approximate line number of the issue in the original code")
|
|
22
|
+
severity: str = Field(description="Critical, High, Medium, Low")
|
|
23
|
+
message: str = Field(description="Specific hardware or algorithmic bottleneck at this line")
|
|
24
|
+
suggestion: str = Field(description="How to fix this specific line")
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class AuditResult(BaseModel):
|
|
28
|
+
severity: str = Field(description="Overall severity: Critical, High, Medium, Low")
|
|
29
|
+
issue: str = Field(description="Brief overall description of the bottleneck")
|
|
30
|
+
reasoning: str = Field(description="Step-by-step hardware-level reasoning for the proposed changes")
|
|
31
|
+
suggestion: str = Field(description="Overall specific fix strategy")
|
|
32
|
+
bottlenecks: List[Bottleneck] = Field(description="List of specific line-level bottlenecks", default_factory=list)
|
|
33
|
+
optimized_code: Optional[str] = Field(description="The entirely rewritten optimized code, ready to drop in", default=None)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
_HARNESS_TEMPLATE = """
|
|
37
|
+
You are a strict QA engineer writing a standalone asymptotic scaling benchmark script in {language}.
|
|
38
|
+
|
|
39
|
+
ORIGINAL FUNCTION (Name: {func_name}):
|
|
40
|
+
{original}
|
|
41
|
+
|
|
42
|
+
OPTIMIZED FUNCTION:
|
|
43
|
+
{optimized}
|
|
44
|
+
|
|
45
|
+
GLOBAL DEPENDENCIES (Helper functions/structs required to run the code):
|
|
46
|
+
{context}
|
|
47
|
+
|
|
48
|
+
Write the complete executable script (e.g., `int main()` or `if __name__ == "__main__":`) that:
|
|
49
|
+
1. Includes necessary imports/headers.
|
|
50
|
+
2. Includes ALL required helper functions or structs from GLOBAL DEPENDENCIES so the script is fully standalone.
|
|
51
|
+
3. Defines BOTH the original and optimized functions exactly as provided above.
|
|
52
|
+
4. Tests multiple data sizes (e.g., N=10, 100, 1000, 5000).
|
|
53
|
+
5. Target Hardware: {hardware_target}. The largest N MUST cross cache boundaries but MUST NOT exceed 20% of available RAM to prevent OOM crashes.
|
|
54
|
+
6. Initializes realistic dummy data for each size N.
|
|
55
|
+
7. Times execution of original vs optimized using high-resolution timers.
|
|
56
|
+
|
|
57
|
+
CRITICAL TIMING:
|
|
58
|
+
- Python: use `time.perf_counter()`. C++: use `std::chrono::high_resolution_clock`.
|
|
59
|
+
- Clamp: `orig_time = max(end - start, 1e-9)` to prevent zero-division.
|
|
60
|
+
- Speedup: `speedup = orig_time / opt_time`.
|
|
61
|
+
|
|
62
|
+
ISOLATION RULES (CRITICAL):
|
|
63
|
+
- This runs in an empty Docker container. NO local files exist.
|
|
64
|
+
- DO NOT use local imports. Define everything inline.
|
|
65
|
+
- DO NOT rename the original function — call it exactly `{func_name}`.
|
|
66
|
+
|
|
67
|
+
OUTPUT FORMAT (CRITICAL):
|
|
68
|
+
Print ONLY this exact CSV to stdout, no other text:
|
|
69
|
+
N,Original_Time,Optimized_Time,Speedup
|
|
70
|
+
10,0.002,0.001,2.00
|
|
71
|
+
|
|
72
|
+
[PYTHON ONLY]: Also import matplotlib, plot results, and save as `benchmark_plot.png`.
|
|
73
|
+
|
|
74
|
+
FORMATTING RULE: Wrap your ENTIRE script in a single markdown code block. No text before or after.
|
|
75
|
+
"""
|
|
76
|
+
|
|
77
|
+
_FIX_TEMPLATE = """
|
|
78
|
+
You are an expert {language} developer. Your previous benchmark script FAILED in an isolated sandbox.
|
|
79
|
+
|
|
80
|
+
ORIGINAL FUNCTION (Name: {func_name}):
|
|
81
|
+
{original}
|
|
82
|
+
|
|
83
|
+
GLOBAL DEPENDENCIES:
|
|
84
|
+
{context}
|
|
85
|
+
|
|
86
|
+
YOUR FAILED SCRIPT:
|
|
87
|
+
{bad_harness}
|
|
88
|
+
|
|
89
|
+
EXECUTION ERROR LOGS:
|
|
90
|
+
{error_logs}
|
|
91
|
+
|
|
92
|
+
ISOLATION CONSTRAINTS (CRITICAL):
|
|
93
|
+
- Empty Docker container. No local files. NO local imports.
|
|
94
|
+
- Define `{func_name}` and all GLOBAL DEPENDENCIES inline.
|
|
95
|
+
|
|
96
|
+
FIX INSTRUCTIONS:
|
|
97
|
+
1. Diagnose the failure from the error logs above.
|
|
98
|
+
2. Fix imports, NameErrors, type mismatches, infinite loops, or OOM issues.
|
|
99
|
+
3. Maintain the CSV stdout format exactly: N,Original_Time,Optimized_Time,Speedup
|
|
100
|
+
4. Use high-resolution timers and clamp with `max(t, 1e-9)`.
|
|
101
|
+
5. [PYTHON ONLY]: Save benchmark plot as `benchmark_plot.png`.
|
|
102
|
+
|
|
103
|
+
FORMATTING RULE: Wrap your ENTIRE fixed script in a single markdown code block. No text before or after.
|
|
104
|
+
"""
|
|
105
|
+
|
|
106
|
+
_TEST_CASES_TEMPLATE = """
|
|
107
|
+
You are a QA engineer writing correctness test cases for a function.
|
|
108
|
+
|
|
109
|
+
FUNCTION NAME: {func_name}
|
|
110
|
+
LANGUAGE: {language}
|
|
111
|
+
|
|
112
|
+
FUNCTION SIGNATURE AND BODY:
|
|
113
|
+
{original}
|
|
114
|
+
|
|
115
|
+
GLOBAL DEPENDENCIES (helper functions / structs this function relies on):
|
|
116
|
+
{context}
|
|
117
|
+
|
|
118
|
+
Your task: generate {num_cases} diverse test cases that call `{func_name}` with different
|
|
119
|
+
arguments. The cases must cover:
|
|
120
|
+
- Small inputs (N ~ 10)
|
|
121
|
+
- Medium inputs (N ~ 100-500)
|
|
122
|
+
- Edge cases: empty collections, single-element, all-zeros, negative values (where applicable)
|
|
123
|
+
- Boundary conditions specific to this function's logic
|
|
124
|
+
|
|
125
|
+
OUTPUT FORMAT — respond with ONLY a valid JSON array, nothing else. No markdown fences,
|
|
126
|
+
no explanation. Each element must be a JSON object with exactly two keys:
|
|
127
|
+
"args" : a JSON array of positional arguments (use only JSON-serialisable types:
|
|
128
|
+
numbers, strings, booleans, arrays, objects — NO numpy, NO bytes)
|
|
129
|
+
"kwargs": a JSON object of keyword arguments (may be empty {{}})
|
|
130
|
+
|
|
131
|
+
Example (do NOT copy this — generate cases specific to {func_name}):
|
|
132
|
+
[
|
|
133
|
+
{{"args": [[1, 2, 3]], "kwargs": {{}}}},
|
|
134
|
+
{{"args": [[]], "kwargs": {{}}}},
|
|
135
|
+
{{"args": [[9, -1, 4, 0, 7]], "kwargs": {{"reverse": true}}}}
|
|
136
|
+
]
|
|
137
|
+
|
|
138
|
+
CONSTRAINTS:
|
|
139
|
+
- All values must be plain JSON types — no numpy arrays, no custom objects.
|
|
140
|
+
- If the function operates on a matrix, represent it as a list-of-lists.
|
|
141
|
+
- If the function takes a size integer N, generate concrete data of that size inline.
|
|
142
|
+
- Do NOT include function calls or expressions — only literal values.
|
|
143
|
+
- Produce exactly {num_cases} test cases.
|
|
144
|
+
"""
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
class AnalyzerAgent:
|
|
148
|
+
def __init__(self, provider="ollama", model_name="llama3.2", api_keys=None):
|
|
149
|
+
self.parser = JsonOutputParser(pydantic_object=AuditResult)
|
|
150
|
+
self.provider = provider
|
|
151
|
+
api_keys = api_keys or {}
|
|
152
|
+
|
|
153
|
+
if provider == "openai":
|
|
154
|
+
if not api_keys.get("openai"):
|
|
155
|
+
raise ValueError("OpenAI API Key required.")
|
|
156
|
+
self.base_llm = ChatOpenAI(
|
|
157
|
+
model=model_name,
|
|
158
|
+
api_key=api_keys["openai"],
|
|
159
|
+
temperature=0.1,
|
|
160
|
+
model_kwargs={"response_format": {"type": "json_object"}},
|
|
161
|
+
)
|
|
162
|
+
self.json_llm = self.base_llm
|
|
163
|
+
|
|
164
|
+
elif provider == "local_server":
|
|
165
|
+
base_url = api_keys.get("local_url", "http://localhost:1234/v1")
|
|
166
|
+
self.base_llm = ChatOpenAI(
|
|
167
|
+
model=model_name,
|
|
168
|
+
api_key="not-needed",
|
|
169
|
+
base_url=base_url,
|
|
170
|
+
temperature=0.1,
|
|
171
|
+
model_kwargs={"response_format": {"type": "json_object"}},
|
|
172
|
+
)
|
|
173
|
+
self.json_llm = self.base_llm
|
|
174
|
+
|
|
175
|
+
elif provider == "anthropic":
|
|
176
|
+
if not api_keys.get("anthropic"):
|
|
177
|
+
raise ValueError("Anthropic API Key required.")
|
|
178
|
+
self.base_llm = ChatAnthropic(
|
|
179
|
+
model=model_name,
|
|
180
|
+
api_key=api_keys["anthropic"],
|
|
181
|
+
temperature=0.1,
|
|
182
|
+
)
|
|
183
|
+
# Anthropic doesn't support response_format; JSON is enforced via prompt only
|
|
184
|
+
self.json_llm = self.base_llm
|
|
185
|
+
|
|
186
|
+
elif provider == "google":
|
|
187
|
+
if not api_keys.get("google"):
|
|
188
|
+
raise ValueError("Google Gemini API Key required.")
|
|
189
|
+
self.base_llm = ChatGoogleGenerativeAI(
|
|
190
|
+
model=model_name,
|
|
191
|
+
google_api_key=api_keys["google"],
|
|
192
|
+
temperature=0.1,
|
|
193
|
+
convert_system_message_to_human=True,
|
|
194
|
+
)
|
|
195
|
+
self.json_llm = self.base_llm
|
|
196
|
+
|
|
197
|
+
else: # Ollama default
|
|
198
|
+
self.base_llm = ChatOllama(
|
|
199
|
+
model=model_name,
|
|
200
|
+
temperature=0.1,
|
|
201
|
+
num_predict=4096,
|
|
202
|
+
num_ctx=8192,
|
|
203
|
+
)
|
|
204
|
+
self.json_llm = self.base_llm.bind(format="json")
|
|
205
|
+
|
|
206
|
+
self.prompt = PromptTemplate(
|
|
207
|
+
template=ANALYSIS_TEMPLATE + "\n\n{format_instructions}",
|
|
208
|
+
input_variables=["language", "code_content", "context", "hardware_target"],
|
|
209
|
+
partial_variables={
|
|
210
|
+
"system_prompt": SYSTEM_PROMPT,
|
|
211
|
+
"format_instructions": self.parser.get_format_instructions(),
|
|
212
|
+
},
|
|
213
|
+
)
|
|
214
|
+
self.chain = self.prompt | self.json_llm | self.parser
|
|
215
|
+
|
|
216
|
+
def analyze(self, code: str, language: str, context: str = "", hardware_target: str = "Generic CPU"):
|
|
217
|
+
try:
|
|
218
|
+
return self.chain.invoke({
|
|
219
|
+
"language": language,
|
|
220
|
+
"code_content": code,
|
|
221
|
+
"context": context,
|
|
222
|
+
"hardware_target": hardware_target,
|
|
223
|
+
})
|
|
224
|
+
except OutputParserException:
|
|
225
|
+
return {
|
|
226
|
+
"severity": "Error",
|
|
227
|
+
"issue": "AI Output Parsing Failed",
|
|
228
|
+
"reasoning": "The model failed to return valid JSON.",
|
|
229
|
+
"suggestion": "Try running the analysis again or use a larger parameter model.",
|
|
230
|
+
"bottlenecks": [],
|
|
231
|
+
"optimized_code": None,
|
|
232
|
+
}
|
|
233
|
+
except Exception as e:
|
|
234
|
+
return {
|
|
235
|
+
"severity": "Error",
|
|
236
|
+
"issue": str(e),
|
|
237
|
+
"reasoning": "System error during analysis pipeline.",
|
|
238
|
+
"suggestion": "Check LLM API keys and connectivity.",
|
|
239
|
+
"bottlenecks": [],
|
|
240
|
+
"optimized_code": None,
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
def _extract_executable_code(self, response_text: str) -> str:
|
|
244
|
+
"""Extract the first/longest fenced code block from model output."""
|
|
245
|
+
blocks = re.findall(r"```[a-zA-Z+#]*\s*\n(.*?)```", response_text, re.DOTALL)
|
|
246
|
+
if blocks:
|
|
247
|
+
return max(blocks, key=len).strip()
|
|
248
|
+
|
|
249
|
+
# Fallback: strip fence markers line by line to avoid corrupting code
|
|
250
|
+
lines = response_text.strip().split("\n")
|
|
251
|
+
lines = [l for l in lines if not re.match(r"^```", l)]
|
|
252
|
+
while lines and lines[0].lower().startswith(("here is", "sure", "certainly", "output:")) \
|
|
253
|
+
and not lines[0].strip().startswith(("#", "//")):
|
|
254
|
+
lines.pop(0)
|
|
255
|
+
return "\n".join(lines).strip()
|
|
256
|
+
|
|
257
|
+
def _invoke_code_chain(self, template: str, variables: dict, language: str) -> str:
|
|
258
|
+
"""Shared invocation + extraction logic for harness and fix chains."""
|
|
259
|
+
chain = PromptTemplate.from_template(template) | self.base_llm
|
|
260
|
+
result = chain.invoke(variables)
|
|
261
|
+
raw = result.content if hasattr(result, "content") else str(result)
|
|
262
|
+
# Handle Anthropic returning a list of content blocks
|
|
263
|
+
if isinstance(raw, list):
|
|
264
|
+
raw = "\n".join(
|
|
265
|
+
item["text"] if isinstance(item, dict) and "text" in item else str(item)
|
|
266
|
+
for item in raw
|
|
267
|
+
)
|
|
268
|
+
return self._extract_executable_code(raw)
|
|
269
|
+
|
|
270
|
+
def generate_harness(
|
|
271
|
+
self,
|
|
272
|
+
func_name: str,
|
|
273
|
+
original_code: str,
|
|
274
|
+
optimized_code: str,
|
|
275
|
+
language: str,
|
|
276
|
+
context: str = "",
|
|
277
|
+
hardware_target: str = "Generic CPU",
|
|
278
|
+
) -> str:
|
|
279
|
+
try:
|
|
280
|
+
return self._invoke_code_chain(
|
|
281
|
+
_HARNESS_TEMPLATE,
|
|
282
|
+
{
|
|
283
|
+
"language": language,
|
|
284
|
+
"func_name": func_name,
|
|
285
|
+
"original": original_code,
|
|
286
|
+
"optimized": optimized_code,
|
|
287
|
+
"context": context,
|
|
288
|
+
"hardware_target": hardware_target,
|
|
289
|
+
},
|
|
290
|
+
language,
|
|
291
|
+
)
|
|
292
|
+
except Exception as e:
|
|
293
|
+
is_python = language.lower() == "python"
|
|
294
|
+
opener = "#" if is_python else "//"
|
|
295
|
+
entry = 'if __name__ == "__main__":' if is_python else "int main() {"
|
|
296
|
+
stub = " pass" if is_python else " return 1;\n}"
|
|
297
|
+
return f"{opener} Failed to generate harness: {e}\n{entry}\n{stub}"
|
|
298
|
+
|
|
299
|
+
def fix_harness(
|
|
300
|
+
self,
|
|
301
|
+
func_name: str,
|
|
302
|
+
original_code: str,
|
|
303
|
+
bad_harness: str,
|
|
304
|
+
error_logs: str,
|
|
305
|
+
language: str,
|
|
306
|
+
context: str = "",
|
|
307
|
+
) -> str:
|
|
308
|
+
try:
|
|
309
|
+
return self._invoke_code_chain(
|
|
310
|
+
_FIX_TEMPLATE,
|
|
311
|
+
{
|
|
312
|
+
"language": language,
|
|
313
|
+
"func_name": func_name,
|
|
314
|
+
"original": original_code,
|
|
315
|
+
"bad_harness": bad_harness,
|
|
316
|
+
"error_logs": error_logs,
|
|
317
|
+
"context": context,
|
|
318
|
+
},
|
|
319
|
+
language,
|
|
320
|
+
)
|
|
321
|
+
except Exception as e:
|
|
322
|
+
is_python = language.lower() == "python"
|
|
323
|
+
opener = "#" if is_python else "//"
|
|
324
|
+
return f"{opener} Failed to fix harness: {e}"
|
|
325
|
+
|
|
326
|
+
def generate_test_cases(
|
|
327
|
+
self,
|
|
328
|
+
func_name: str,
|
|
329
|
+
original_code: str,
|
|
330
|
+
language: str,
|
|
331
|
+
context: str = "",
|
|
332
|
+
num_cases: int = 8,
|
|
333
|
+
) -> list:
|
|
334
|
+
"""
|
|
335
|
+
Ask the LLM to generate diverse, JSON-serialisable test cases for
|
|
336
|
+
`func_name` so the sandbox can run correctness verification.
|
|
337
|
+
|
|
338
|
+
Returns a list of {"args": [...], "kwargs": {...}} dicts, or an
|
|
339
|
+
empty list if generation or parsing fails (sandbox skips gracefully).
|
|
340
|
+
"""
|
|
341
|
+
import json
|
|
342
|
+
|
|
343
|
+
chain = PromptTemplate.from_template(_TEST_CASES_TEMPLATE) | self.base_llm
|
|
344
|
+
try:
|
|
345
|
+
result = chain.invoke({
|
|
346
|
+
"func_name": func_name,
|
|
347
|
+
"language": language,
|
|
348
|
+
"original": original_code,
|
|
349
|
+
"context": context or "None",
|
|
350
|
+
"num_cases": num_cases,
|
|
351
|
+
})
|
|
352
|
+
raw = result.content if hasattr(result, "content") else str(result)
|
|
353
|
+
if isinstance(raw, list):
|
|
354
|
+
raw = "\n".join(
|
|
355
|
+
item["text"] if isinstance(item, dict) and "text" in item else str(item)
|
|
356
|
+
for item in raw
|
|
357
|
+
)
|
|
358
|
+
|
|
359
|
+
# Strip markdown fences if the model wrapped anyway
|
|
360
|
+
raw = re.sub(r"```[a-zA-Z]*\s*", "", raw).strip()
|
|
361
|
+
|
|
362
|
+
cases = json.loads(raw)
|
|
363
|
+
|
|
364
|
+
# Validate structure — drop malformed entries silently
|
|
365
|
+
return [
|
|
366
|
+
case for case in cases
|
|
367
|
+
if isinstance(case, dict)
|
|
368
|
+
and isinstance(case.get("args"), list)
|
|
369
|
+
and isinstance(case.get("kwargs"), dict)
|
|
370
|
+
]
|
|
371
|
+
|
|
372
|
+
except Exception as e:
|
|
373
|
+
logger.warning(f"generate_test_cases failed for '{func_name}': {e}")
|
|
374
|
+
return []
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from rich.console import Console
|
|
4
|
+
from rich.prompt import Prompt, Confirm
|
|
5
|
+
|
|
6
|
+
console = Console()
|
|
7
|
+
CONFIG_FILE = Path.home() / ".coreinsight" / "config.json"
|
|
8
|
+
|
|
9
|
+
def load_config():
|
|
10
|
+
if not CONFIG_FILE.exists():
|
|
11
|
+
return {"provider": "ollama", "model_name": "llama3.2", "api_keys": {}}
|
|
12
|
+
with open(CONFIG_FILE, "r") as f:
|
|
13
|
+
return json.load(f)
|
|
14
|
+
|
|
15
|
+
def save_config(config_data):
|
|
16
|
+
CONFIG_FILE.parent.mkdir(parents=True, exist_ok=True)
|
|
17
|
+
with open(CONFIG_FILE, "w") as f:
|
|
18
|
+
json.dump(config_data, f, indent=4)
|
|
19
|
+
|
|
20
|
+
def run_configure():
|
|
21
|
+
"""Interactive CLI to set up models and API keys."""
|
|
22
|
+
console.print("[bold cyan]⚙️ CoreInsight Configuration[/bold cyan]")
|
|
23
|
+
|
|
24
|
+
config = load_config()
|
|
25
|
+
|
|
26
|
+
provider = Prompt.ask(
|
|
27
|
+
"Which AI provider do you want to use?",
|
|
28
|
+
choices=["ollama", "local_server", "openai", "anthropic", "google"],
|
|
29
|
+
default=config.get("provider", "ollama")
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
config["provider"] = provider
|
|
33
|
+
|
|
34
|
+
if provider == "ollama":
|
|
35
|
+
config["model_name"] = Prompt.ask("Ollama model name", default=config.get("model_name", "llama3.2"))
|
|
36
|
+
elif provider == "local_server":
|
|
37
|
+
config["model_name"] = Prompt.ask("Local model name (optional)", default=config.get("model_name", "local-model"))
|
|
38
|
+
config["api_keys"]["local_url"] = Prompt.ask("Local Server Base URL", default="http://localhost:1234/v1")
|
|
39
|
+
elif provider == "openai":
|
|
40
|
+
config["model_name"] = Prompt.ask("OpenAI model name", default="gpt-4o")
|
|
41
|
+
config["api_keys"]["openai"] = Prompt.ask("OpenAI API Key (hidden)", password=True)
|
|
42
|
+
elif provider == "anthropic":
|
|
43
|
+
config["model_name"] = Prompt.ask("Claude model name", default="claude-3-5-sonnet-latest")
|
|
44
|
+
config["api_keys"]["anthropic"] = Prompt.ask("Anthropic API Key (hidden)", password=True)
|
|
45
|
+
elif provider == "google":
|
|
46
|
+
config["model_name"] = Prompt.ask("Gemini model name", default="gemini-1.5-pro")
|
|
47
|
+
config["api_keys"]["google"] = Prompt.ask("Google Gemini API Key (hidden)", password=True)
|
|
48
|
+
|
|
49
|
+
save_config(config)
|
|
50
|
+
console.print("\n[bold green]✅ Configuration saved successfully![/bold green]")
|
|
51
|
+
console.print(f"CoreInsight is now using [bold]{provider}[/bold] ({config['model_name']}).")
|