hashan-7 commited on
Commit
e34f3d2
·
verified ·
1 Parent(s): 97d9169

Deploy code agent from GitHub Actions

Browse files
Files changed (4) hide show
  1. Dockerfile +12 -0
  2. README.md +8 -7
  3. app.py +236 -0
  4. requirements.txt +7 -0
Dockerfile ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.11-slim
2
+
3
+ WORKDIR /app
4
+
5
+ COPY requirements.txt .
6
+ RUN pip install --no-cache-dir -r requirements.txt
7
+
8
+ COPY app.py .
9
+
10
+ EXPOSE 7860
11
+
12
+ CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
README.md CHANGED
@@ -1,12 +1,13 @@
1
  ---
2
- title: Stitch Qa Code Agent
3
- emoji: 🌍
4
- colorFrom: green
5
- colorTo: red
6
  sdk: docker
7
- pinned: false
8
  license: mit
9
- short_description: Generates code-level repair suggestions and patch guidance
10
  ---
11
 
12
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
1
  ---
2
+ title: Stitch QA Code Agent
3
+ emoji: 🧠
4
+ colorFrom: purple
5
+ colorTo: blue
6
  sdk: docker
7
+ app_port: 7860
8
  license: mit
 
9
  ---
10
 
11
+ # Stitch QA Code Agent
12
+
13
+ Generates code-level repair suggestions and patch guidance for Stitch QA using a code-focused model.
app.py ADDED
@@ -0,0 +1,236 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI
2
+ from pydantic import BaseModel
3
+ from transformers import AutoTokenizer, AutoModelForCausalLM
4
+ import os
5
+ import torch
6
+ import re
7
+
8
+ HF_MODEL = os.getenv("HF_MODEL", "Qwen/Qwen2.5-0.5B-Instruct")
9
+
10
+ tokenizer = None
11
+ model = None
12
+
13
+ app = FastAPI(title="Stitch QA Code Agent")
14
+
15
+
16
+ class CodeRepairRequest(BaseModel):
17
+ project_type: str
18
+ file_path: str | None = None
19
+ code_snippet: str | None = None
20
+ error_log: str | None = None
21
+ root_cause: str | None = None
22
+ repair_summary: str | None = None
23
+
24
+
25
+ @app.get("/")
26
+ def health_check():
27
+ return {
28
+ "service": "stitch-qa-code-agent",
29
+ "status": "running",
30
+ "llm_enabled": True,
31
+ "llm_mode": "local-transformers",
32
+ "model": HF_MODEL
33
+ }
34
+
35
+
36
+ def load_model():
37
+ global tokenizer, model
38
+
39
+ if tokenizer is None or model is None:
40
+ tokenizer = AutoTokenizer.from_pretrained(HF_MODEL)
41
+ model = AutoModelForCausalLM.from_pretrained(
42
+ HF_MODEL,
43
+ torch_dtype=torch.float32,
44
+ low_cpu_mem_usage=True
45
+ )
46
+
47
+ return tokenizer, model
48
+
49
+
50
+ def build_prompt(request: CodeRepairRequest):
51
+ code = request.code_snippet or "No code snippet provided."
52
+ error = request.error_log or "No error log provided."
53
+ root_cause = request.root_cause or "No root cause provided."
54
+ repair_summary = request.repair_summary or "No repair summary provided."
55
+ file_path = request.file_path or "Unknown file"
56
+
57
+ return f"""
58
+ Analyze the following code repair context and provide safe code-level guidance.
59
+
60
+ Project type:
61
+ {request.project_type}
62
+
63
+ File path:
64
+ {file_path}
65
+
66
+ Root cause:
67
+ {root_cause}
68
+
69
+ Repair summary:
70
+ {repair_summary}
71
+
72
+ Error log:
73
+ {error}
74
+
75
+ Code snippet:
76
+ {code}
77
+
78
+ Return only these sections:
79
+ 1. Problem
80
+ 2. Safe fix approach
81
+ 3. Suggested code change
82
+ 4. Verification step
83
+
84
+ Do not include system/user/assistant labels.
85
+ Do not repeat the prompt.
86
+ Do not invent files that are not shown.
87
+ Do not apply changes automatically.
88
+ Keep the answer concise.
89
+ """
90
+
91
+
92
+ def call_llm(prompt: str):
93
+ active_tokenizer, active_model = load_model()
94
+
95
+ messages = [
96
+ {
97
+ "role": "system",
98
+ "content": "You are a careful code repair assistant. Return only the final repair guidance."
99
+ },
100
+ {
101
+ "role": "user",
102
+ "content": prompt
103
+ }
104
+ ]
105
+
106
+ if hasattr(active_tokenizer, "apply_chat_template"):
107
+ formatted_prompt = active_tokenizer.apply_chat_template(
108
+ messages,
109
+ tokenize=False,
110
+ add_generation_prompt=True
111
+ )
112
+ else:
113
+ formatted_prompt = prompt
114
+
115
+ inputs = active_tokenizer(
116
+ formatted_prompt,
117
+ return_tensors="pt",
118
+ truncation=True,
119
+ max_length=1024
120
+ )
121
+
122
+ outputs = active_model.generate(
123
+ **inputs,
124
+ max_new_tokens=256,
125
+ do_sample=False,
126
+ pad_token_id=active_tokenizer.eos_token_id
127
+ )
128
+
129
+ generated_text = active_tokenizer.decode(outputs[0], skip_special_tokens=True)
130
+
131
+ return generated_text.strip()
132
+
133
+
134
+ def fallback_code_guidance(request: CodeRepairRequest):
135
+ if request.error_log:
136
+ summary = (
137
+ "A code-level issue may exist based on the provided error log. "
138
+ "Review the affected file, identify the failing line, apply the smallest safe change, "
139
+ "and rerun the project tests."
140
+ )
141
+ else:
142
+ summary = (
143
+ "No specific error log was provided. Review the code snippet manually and run the project tests "
144
+ "after applying any change."
145
+ )
146
+
147
+ return {
148
+ "agent": "code-agent",
149
+ "mode": "fallback",
150
+ "summary": summary,
151
+ "risk_level": "MEDIUM",
152
+ "auto_apply": False,
153
+ "suggested_patch": None,
154
+ "verification": "Rerun Stitch QA after applying any manual code changes."
155
+ }
156
+
157
+
158
+ def remove_prompt_leak(text: str):
159
+ cleaned = text.strip()
160
+
161
+ marker_patterns = [
162
+ r"assistant\s*###",
163
+ r"assistant\s*1\.",
164
+ r"assistant\s*Problem",
165
+ r"###\s*1\.\s*Problem",
166
+ r"1\.\s*Problem"
167
+ ]
168
+
169
+ for pattern in marker_patterns:
170
+ match = re.search(pattern, cleaned, flags=re.IGNORECASE | re.DOTALL)
171
+ if match:
172
+ cleaned = cleaned[match.start():]
173
+ break
174
+
175
+ cleaned = re.sub(r"^\s*assistant\s*", "", cleaned, flags=re.IGNORECASE)
176
+ cleaned = re.sub(r"^\s*system\s+.*?\s+user\s+", "", cleaned, flags=re.IGNORECASE | re.DOTALL)
177
+
178
+ bad_prefixes = [
179
+ "system You are",
180
+ "user You are",
181
+ "Analyze the following code repair context"
182
+ ]
183
+
184
+ for prefix in bad_prefixes:
185
+ index = cleaned.lower().find(prefix.lower())
186
+ if index == 0:
187
+ return None
188
+
189
+ return cleaned.strip()
190
+
191
+
192
+ def clean_output(text: str):
193
+ cleaned = remove_prompt_leak(text)
194
+ if not cleaned:
195
+ return None
196
+
197
+ cleaned = re.sub(r"\n{3,}", "\n\n", cleaned)
198
+ cleaned = cleaned.strip()
199
+
200
+ if not cleaned:
201
+ return None
202
+
203
+ if len(cleaned) < 30:
204
+ return None
205
+
206
+ if "system You are" in cleaned or "user You are" in cleaned:
207
+ return None
208
+
209
+ return cleaned
210
+
211
+
212
+ @app.post("/suggest-code-fix")
213
+ def suggest_code_fix(request: CodeRepairRequest):
214
+ fallback_result = fallback_code_guidance(request)
215
+
216
+ try:
217
+ prompt = build_prompt(request)
218
+ llm_text = call_llm(prompt)
219
+ cleaned_text = clean_output(llm_text)
220
+
221
+ if not cleaned_text:
222
+ return fallback_result
223
+
224
+ return {
225
+ "agent": "code-agent",
226
+ "mode": "llm",
227
+ "summary": cleaned_text,
228
+ "risk_level": "MEDIUM",
229
+ "auto_apply": False,
230
+ "suggested_patch": None,
231
+ "verification": "Apply the suggested change manually, then rerun Stitch QA verification."
232
+ }
233
+
234
+ except Exception as error:
235
+ fallback_result["llm_error"] = repr(error)
236
+ return fallback_result
requirements.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ fastapi
2
+ uvicorn
3
+ pydantic
4
+ transformers
5
+ torch
6
+ sentencepiece
7
+ accelerate