pangxiang commited on
Commit
75e16a1
·
verified ·
1 Parent(s): c10c692

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +89 -158
app.py CHANGED
@@ -1,177 +1,108 @@
1
  #!/usr/bin/env python3
2
  # -*- coding: utf-8 -*-
3
  """
4
- CodeGPS ProDeepSeek AI 补丁修复 & 聊天增强
 
5
  """
6
- import gradio as gr, re, requests, os, json, difflib
7
- from dataclasses import dataclass
8
- from typing import List, Dict
9
 
10
- # ============================================================
11
- # -------------------- 编辑引擎 -------------------------------
12
- # ============================================================
13
- @dataclass
14
- class CodeBlock:
15
- start_line:int; end_line:int; type:str; name:str; content:str
16
-
17
- class CodeGPSEngine:
18
- def __init__(self): self.reset()
19
- def reset(self):
20
- self.lines=[]; self.language="unknown"; self.blocks=[]; self.history_stack=[]
21
- def load(self,code:str)->str:
22
- if not code.strip(): self.reset(); return "⚠️ 代码为空"
23
- self.lines=code.split("\n"); self.language=self._detect_lang(code)
24
- return f"✅ {self.language.upper()} | {len(self.lines)} 行"
25
- def _detect_lang(self,code):
26
- pats={'python':[r'def\s','import\s',r':\s*$'],
27
- 'html':[r'<html',r'<div',r'</\w+>'],
28
- 'javascript':[r'function\s',r'=>',r'const\s+']}
29
- for l,ps in pats.items():
30
- if sum(bool(re.search(p,code)) for p in ps)>=2:return l
31
- return 'plaintext'
32
- def get_code(self): return "\n".join(self.lines)
33
- def replace_range(self,s,e,new)->Dict:
34
- if not(1<=s<=len(self.lines) and 1<=e<=len(self.lines)):
35
- return {'ok':False,'msg':'⚠️ 行号越界'}
36
- self.history_stack.append(self.lines.copy())
37
- old=self.lines[s-1:e]
38
- self.lines[s-1:e]=new.split("\n")
39
- return {'ok':True,'msg':f'✅ 修改 {s}-{e} 行','old':old,'new':new.split("\n"),'s':s,'e':e}
40
  def undo(self):
41
- if not self.history_stack:return{'ok':False,'msg':'无历史记录'}
42
- self.lines=self.history_stack.pop();return{'ok':True,'msg':'✅ 撤销'}
43
- def generate_prompt(self,task=''):
44
- code_lines="\n".join(f"{i+1:4d}|{l}" for i,l in enumerate(self.lines))
45
- return f"语言:{self.language}\n```{self.language}\n{code_lines}\n```\n任务:{task}"
46
-
47
- # ============================================================
48
- # -------------------- DeepSeek API 封装 ----------------------
49
- # ============================================================
50
- CONF=os.path.expanduser("~/.codegps_conf.json")
51
- def load_conf():
52
- if os.path.exists(CONF): return json.load(open(CONF))
53
- return {"api_key":"","model":"deepseek-chat"}
54
- def save_conf(c): json.dump(c,open(CONF,"w"),ensure_ascii=False,indent=2)
55
 
56
- def call_patch_ai(prompt,model,key,start,end):
57
- url="https://api.deepseek.com/chat/completions"
58
- sys_prompt=("你是代码修复助手。请只输出JSON补丁,示例:"
59
- '{"type":"replace","start":行号_int,"end":行号_int,"new_code":"替换内容"},'
60
- "不要包含多余解释。")
61
- task_prompt=f"{prompt}\n用户指定修复范围:{start}-{end}行"
62
- data={"model":model,
63
- "messages":[{"role":"system","content":sys_prompt},
64
- {"role":"user","content":task_prompt}],
65
- "stream":False}
66
- r=requests.post(url,json=data,
67
- headers={"Authorization":f"Bearer {key}",
68
- "Content-Type":"application/json"})
69
- try: return r.json()["choices"][0]["message"]["content"]
70
- except Exception: return f"API 返回异常:{r.text}"
71
 
72
- def chat_ai(message,model,key,context):
73
- url="https://api.deepseek.com/chat/completions"
74
- msgs=[{"role":"system","content":"你是编码助手,可连续对话。"}]+context+[{"role":"user","content":message}]
75
- r=requests.post(url,json={"model":model,"messages":msgs},
76
- headers={"Authorization":f"Bearer {key}","Content-Type":"application/json"})
77
- if r.status_code!=200:return f"错误:{r.status_code}:{r.text}"
78
- return r.json()["choices"][0]["message"]["content"]
 
79
 
80
- # ============================================================
81
- # -------------------- diff 生成 ------------------------------
82
- # ============================================================
83
- def make_diff(old,new,s,e):
84
- diff=list(difflib.unified_diff(old,new,fromfile=f"旧({s}-{e})",tofile=f"新({s}-{e})",lineterm=""))
85
- html=["<pre style='background:#fff;color:#000;padding:10px;height:400px;overflow:auto;border:1px solid #ccc;border-radius:6px;'>"]
86
- for line in diff:
87
- color="red" if line.startswith('-') else "green" if line.startswith('+') else "black"
88
- html.append(f"<span style='color:{color}'>{line}</span>")
89
- html.append("</pre>")
90
- return "".join(html)
 
91
 
92
- # ============================================================
93
- # -------------------- Gradio UI ------------------------------
94
- # ============================================================
95
- def create_ui():
96
- eng=CodeGPSEngine(); conf=load_conf()
97
- messages=[]
98
- with gr.Blocks(title="CodeGPS Pro — DeepSeek AI 补丁修复",theme=gr.themes.Soft()) as app:
99
- gr.Markdown("## 🎯 CodeGPS Pro — DeepSeek AI 补丁修复 & 聊天版")
100
 
101
- # API 配置
102
- with gr.Accordion("⚙️ DeepSeek 配置",open=False):
103
- api=gr.Textbox(label="API KEY",value=conf['api_key'],type="password")
104
- model=gr.Textbox(label="模型名",value=conf['model'])
105
- save_btn=gr.Button("保存配置"); status=gr.Textbox(label="状态",interactive=False)
106
- def save_conf_ui(k,m): save_conf({"api_key":k,"model":m}); return "✅ 已保存"
107
- save_btn.click(save_conf_ui,[api,model],[status])
108
 
109
  with gr.Row():
110
- # 编辑
111
- with gr.Column(scale=2):
112
- code=gr.Code(label="📝 编辑器",language="html",lines=25)
113
- info=gr.Textbox(label="状态",interactive=False)
114
- with gr.Row():
115
- loadb=gr.Button("加载")
116
- undob=gr.Button("撤销")
117
- loadb.click(lambda c:eng.load(c),[code],[info])
118
- undob.click(lambda :[eng.undo()['msg'],eng.get_code()],[],[info,code])
119
- # 指定行输入
120
- with gr.Row():
121
- start_line=gr.Number(label="起始行",value=1,precision=0)
122
- end_line=gr.Number(label="结束行",value=1,precision=0)
123
- # 运行html
124
- run_html=gr.Button("▶️ 运行 HTML",variant="primary")
125
- html_out=gr.HTML(value="<div style='color:#999'>HTML 预览区</div>")
126
- def run_html_fn(c):
127
- if "<html" not in c.lower(): return "<div style='color:red'>非 HTML 无法预览</div>"
128
- path="/tmp/preview.html"; open(path,"w",encoding="utf-8").write(c)
129
- return f"<iframe src='file://{path}' style='width:100%;height:90vh;border:none;'></iframe>"
130
- run_html.click(run_html_fn,[code],[html_out])
131
 
132
- # AI 区域
133
- with gr.Column(scale=1):
134
- gr.Markdown("### 🤖 DeepSeek AI 补丁系统")
135
- task=gr.Textbox(label="任务说明",lines=4,placeholder="示例: 优化第 行循环性能")
136
- gen_btn=gr.Button("🩹 生成补丁")
137
- diff_card=gr.HTML(visible=False)
138
- with gr.Row(visible=False) as confirm_row:
139
- confirm_btn=gr.Button("✅ 应用补丁")
140
- cancel_btn=gr.Button("❌ 取消")
141
- def gen_patch(tasktxt,start,end):
142
- cf=load_conf()
143
- resp=call_patch_ai(eng.generate_prompt(tasktxt),cf['model'],cf['api_key'],start,end)
144
- try: patch=json.loads(resp)
145
- except Exception:
146
- return gr.update(value=f"<pre style='color:red'>{resp}</pre>",visible=True),gr.update(visible=False)
147
- s,e=int(patch.get("start",start)),int(patch.get("end",end))
148
- new=patch.get("new_code","")
149
- eng.pending_patch={'s':s,'e':e,'new':new}
150
- html=make_diff(eng.lines[s-1:e],new.split("\n"),s,e)
151
- return gr.update(value=html,visible=True),gr.update(visible=True)
152
- gen_btn.click(gen_patch,[task,start_line,end_line],[diff_card,confirm_row])
153
- def apply_patch():
154
- p=eng.pending_patch; r=eng.replace_range(p['s'],p['e'],p['new']); eng.pending_patch=None
155
- return gr.update(value=eng.get_code()),gr.update(value="<div style='color:green'>✅ 已应用</div>",visible=False),gr.update(visible=False)
156
- confirm_btn.click(apply_patch,[],[code,diff_card,confirm_row])
157
- cancel_btn.click(lambda :[gr.update(visible=False),gr.update(visible=False)],[ ],[diff_card,confirm_row])
158
 
159
- # 聊天区
160
- gr.Markdown("### 💬 与 DeepSeek AI 对话")
161
- chatbot=gr.Chatbot(label="DeepSeek 对话区")
162
- msg_box=gr.Textbox(label="输入",placeholder="DeepSeekAI 交谈…")
163
- send_btn=gr.Button("发送")
164
- def chat_fn(msg,history):
165
- cf=load_conf()
166
- messages.append({"role":"user","content":msg})
167
- ai_reply=chat_ai(msg,cf['model'],cf['api_key'],messages)
168
- messages.append({"role":"assistant","content":ai_reply})
169
- history.append((msg,ai_reply))
170
- return history,""
171
- send_btn.click(chat_fn,[msg_box,chatbot],[chatbot,msg_box])
 
 
 
 
 
 
172
 
 
 
173
  return app
174
 
175
  if __name__=="__main__":
176
- app=create_ui()
177
- app.launch(server_name="0.0.0.0",server_port=7860,share=True)
 
1
  #!/usr/bin/env python3
2
  # -*- coding: utf-8 -*-
3
  """
4
+ CodeGPS Pro DeepSeek AI 测试安全
5
+ 不在磁盘保存任何凭证;关闭或点击“清除凭证”即忘记。
6
  """
7
+ import gradio as gr, json, re, difflib
 
 
8
 
9
+ # ------------------------------------------------------------
10
+ # 极简代码引擎
11
+ # ------------------------------------------------------------
12
+ class Engine:
13
+ def __init__(self): self.lines=[]; self.history=[]
14
+ def load(self,code):
15
+ self.lines=code.split('\n');return f"✅ 载入 {len(self.lines)} 行"
16
+ def replace_range(self,s,e,new):
17
+ self.history.append(self.lines.copy())
18
+ old=self.lines[s-1:e]; self.lines[s-1:e]=new.split('\n')
19
+ return old
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  def undo(self):
21
+ if not self.history:return"无历史"
22
+ self.lines=self.history.pop();return"✅ 撤销"
23
+ def get_code(self): return '\n'.join(self.lines)
 
 
 
 
 
 
 
 
 
 
 
24
 
25
+ eng=Engine()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
 
27
+ # ------------------------------------------------------------
28
+ # 虚拟 AI 调用:你这替换为真实 DeepSeek API 请求
29
+ # ------------------------------------------------------------
30
+ def call_ai_patch(api_key, model, code, task):
31
+ """这里应调用真实接口;返回 JSON patch 字符串"""
32
+ # mock:演示只改前两行
33
+ fake=[{"start":1,"end":2,"new_code":"print('AI已修复')"}]
34
+ return json.dumps(fake,ensure_ascii=False)
35
 
36
+ # ------------------------------------------------------------
37
+ # diff 生成
38
+ # ------------------------------------------------------------
39
+ def diff_html(old,new,s,e):
40
+ out=['<pre style="background:#fff;border:1px solid #ccc;'
41
+ 'padding:8px;height:300px;overflow:auto;">']
42
+ for l in difflib.unified_diff(old,new,fromfile=f"旧({s}-{e})",
43
+ tofile="",lineterm=""):
44
+ c='red'if l.startswith('-')else'green'if l.startswith('+')else'#000'
45
+ out.append(f'<span style="color:{c}">{l}</span>')
46
+ out.append('</pre>')
47
+ return ''.join(out)
48
 
49
+ # ------------------------------------------------------------
50
+ # UI
51
+ # ------------------------------------------------------------
52
+ def make_ui():
53
+ with gr.Blocks(title="CodeGPS Pro — 安全测试版") as app:
54
+ gr.Markdown("## 👁 CodeGPS Pro — DeepSeek AI 视觉补丁安全版")
 
 
55
 
56
+ # 仅内存保存的 Key / Model
57
+ creds = gr.State({"api_key":"","model":""})
 
 
 
 
 
58
 
59
  with gr.Row():
60
+ code=gr.Code(label="编辑器",language="python",lines=25)
61
+ chat=gr.Chatbot(label="AI 日志")
62
+
63
+ with gr.Accordion("⚙️ 临时凭证设置",open=False):
64
+ api_in=gr.Textbox(label="API Key",type="password")
65
+ model_in=gr.Textbox(label="模型名",value="deepseek-chat")
66
+ save_btn=gr.Button("保存临时凭证")
67
+ clear_btn=gr.Button("🔐 清除凭证")
68
+ out_info=gr.Textbox(label="状态",interactive=False)
69
+
70
+ # 存入内存状态
71
+ def save_creds(api,model):
72
+ return {"api_key":api,"model":model},f"✅ 凭证加载于内存(退出即清除)"
73
+ def clear_creds():
74
+ return {"api_key":"","model":""},"🔐 已清除内存凭证"
75
+ save_btn.click(save_creds,[api_in,model_in],[creds,out_info])
76
+ clear_btn.click(clear_creds,[],[creds,out_info])
 
 
 
 
77
 
78
+ task=gr.Textbox(label="任务描述",placeholder="讲清要修的部分",lines=2)
79
+ load_btn=gr.Button("🚀 加载并自动修复")
80
+ diffview=gr.HTML()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81
 
82
+ def auto_fix(code_text,task_text,cred,chat_hist):
83
+ status=eng.load(code_text)
84
+ if not cred["api_key"]:
85
+ chat_hist.append(("系统","⚠️未设置APIKey"))
86
+ return code_text,chat_hist,"未设置Key",""
87
+ resp=call_ai_patch(cred["api_key"],cred["model"],code_text,task_text)
88
+ try:
89
+ patches=json.loads(resp)
90
+ for p in sorted(patches,key=lambda x:x["start"],reverse=True):
91
+ old=eng.replace_range(p["start"],p["end"],p["new_code"])
92
+ html=diff_html(old,p["new_code"].split("\n"),p["start"],p["end"])
93
+ chat_hist.append(("AI",f"🩹 已自动修复 {len(patches)} 处"))
94
+ return eng.get_code(),chat_hist,f"{status}|AI 修复完成",html
95
+ except Exception as e:
96
+ chat_hist.append(("系统",f"⚠️ AI输出错误 {e}\n{resp}"))
97
+ return code_text,chat_hist,"出错",""
98
+ load_btn.click(auto_fix,
99
+ inputs=[code,task,creds,chat],
100
+ outputs=[code,chat,out_info,diffview])
101
 
102
+ undo=gr.Button("↩️ 撤销")
103
+ undo.click(lambda:[eng.undo(),eng.get_code()],[ ],[out_info,code])
104
  return app
105
 
106
  if __name__=="__main__":
107
+ ui=make_ui()
108
+ ui.launch(server_port=7860)