airabbitX commited on
Commit
ec32ae2
·
verified ·
1 Parent(s): 85db553

Upload models.py

Browse files
Files changed (1) hide show
  1. models.py +232 -0
models.py ADDED
@@ -0,0 +1,232 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from openai import OpenAI
2
+ import json
3
+ import time
4
+ from datetime import datetime
5
+ from utils import log_step, SYSTEM_PROMPT, logger
6
+
7
+ class LSP:
8
+ def __init__(self, api_key: str):
9
+ if not api_key or api_key.strip() == "":
10
+ raise ValueError("API key cannot be empty")
11
+ self.client = OpenAI(api_key=api_key)
12
+
13
+ def get_section_map(self, content: str) -> tuple[dict, float]:
14
+ """Get map of sections without loading full content"""
15
+ start_time = time.time()
16
+ log_step("SECTION_MAP", "Starting section map generation")
17
+
18
+ sections = {}
19
+ in_code_block = False
20
+ current_section = None
21
+ section_start = 0
22
+
23
+ lines = content.split('\n')
24
+ for i, line in enumerate(lines):
25
+ if line.strip().startswith('```'):
26
+ in_code_block = not in_code_block
27
+ continue
28
+
29
+ if not in_code_block and line.strip().startswith('#'):
30
+ if current_section:
31
+ sections[current_section] = (section_start, i-1)
32
+ current_section = line.strip()
33
+ section_start = i
34
+
35
+ if current_section:
36
+ sections[current_section] = (section_start, len(lines)-1)
37
+
38
+ elapsed = time.time() - start_time
39
+ log_step("SECTION_MAP", f"Section map generated in {elapsed:.2f}s", sections)
40
+ return sections, elapsed
41
+
42
+ def extract_section(self, content: str, start: int, end: int) -> tuple[str, float]:
43
+ """Get just the content of target section"""
44
+ start_time = time.time()
45
+ log_step("EXTRACT", f"Extracting section from line {start} to {end}")
46
+
47
+ lines = content.split('\n')
48
+ section = '\n'.join(lines[start:end+1])
49
+
50
+ elapsed = time.time() - start_time
51
+ log_step("EXTRACT", f"Section extracted in {elapsed:.2f}s", {"length": len(section)})
52
+ return section, elapsed
53
+
54
+ def replace_section(self, content: str, start: int, end: int, new_content: str) -> tuple[str, float]:
55
+ """Replace section and return full content"""
56
+ start_time = time.time()
57
+ log_step("REPLACE", f"Replacing section from line {start} to {end}")
58
+
59
+ lines = content.split('\n')
60
+ lines[start:end+1] = new_content.split('\n')
61
+ result = '\n'.join(lines)
62
+
63
+ elapsed = time.time() - start_time
64
+ log_step("REPLACE", f"Section replaced in {elapsed:.2f}s", {"new_length": len(result)})
65
+ return result, elapsed
66
+
67
+ def tools(self):
68
+ return [
69
+ {
70
+ "type": "function",
71
+ "function": {
72
+ "name": "identify_section",
73
+ "description": "Identify which section needs to be modified based on headers map",
74
+ "parameters": {
75
+ "type": "object",
76
+ "properties": {
77
+ "section_name": {
78
+ "type": "string",
79
+ "description": "Name of section to edit"
80
+ },
81
+ "reason": {
82
+ "type": "string",
83
+ "description": "Why this section was chosen"
84
+ }
85
+ },
86
+ "required": ["section_name", "reason"]
87
+ }
88
+ }
89
+ },
90
+ {
91
+ "type": "function",
92
+ "function": {
93
+ "name": "modify_section",
94
+ "description": "Make changes to the section content",
95
+ "parameters": {
96
+ "type": "object",
97
+ "properties": {
98
+ "modified_content": {
99
+ "type": "string",
100
+ "description": "New content for the section"
101
+ },
102
+ "changes_made": {
103
+ "type": "string",
104
+ "description": "Description of changes"
105
+ }
106
+ },
107
+ "required": ["modified_content", "changes_made"]
108
+ }
109
+ }
110
+ }
111
+ ]
112
+
113
+ async def edit_smart(self, content: str, instruction: str) -> tuple[str, list[str], float]:
114
+ """Smart editing with section targeting"""
115
+ total_start = time.time()
116
+ timings = {}
117
+ traces = []
118
+
119
+ try:
120
+ # Phase 1: Get section map
121
+ section_map, map_time = self.get_section_map(content)
122
+ timings['section_map'] = map_time
123
+ traces.append(f"[{map_time:.2f}s] Found sections: {json.dumps(section_map, indent=2)}")
124
+
125
+ # Phase 2: Identify section
126
+ messages = [
127
+ {"role": "system", "content": SYSTEM_PROMPT},
128
+ {"role": "user", "content": f"Section map: {json.dumps(section_map)}\nInstruction: {instruction}"}
129
+ ]
130
+
131
+ identify_start = time.time()
132
+ response = self.client.chat.completions.create(
133
+ model="gpt-4o-mini",
134
+ messages=messages,
135
+ tools=self.tools()
136
+ )
137
+ identify_time = time.time() - identify_start
138
+ timings['identify_section'] = identify_time
139
+
140
+ tool_call = response.choices[0].message.tool_calls[0]
141
+ args = json.loads(tool_call.function.arguments)
142
+ target_section = args["section_name"]
143
+ start, end = section_map[target_section]
144
+
145
+ traces.append(f"[{identify_time:.2f}s] Selected section: {target_section} (lines {start}-{end})")
146
+
147
+ # Phase 3: Extract section
148
+ section_content, extract_time = self.extract_section(content, start, end)
149
+ timings['extract_section'] = extract_time
150
+ traces.append(f"[{extract_time:.2f}s] Extracted content:\n{section_content}")
151
+
152
+ # Phase 4: Modify section
153
+ modify_start = time.time()
154
+ messages.extend([
155
+ response.choices[0].message,
156
+ {
157
+ "role": "tool",
158
+ "content": json.dumps({"success": True, "section": target_section}),
159
+ "tool_call_id": tool_call.id
160
+ },
161
+ {
162
+ "role": "user",
163
+ "content": f"Here's the section to modify:\n{section_content}"
164
+ }
165
+ ])
166
+
167
+ response = self.client.chat.completions.create(
168
+ model="gpt-4o-mini",
169
+ messages=messages,
170
+ tools=self.tools()
171
+ )
172
+ modify_time = time.time() - modify_start
173
+ timings['modify_section'] = modify_time
174
+
175
+ tool_call = response.choices[0].message.tool_calls[0]
176
+ args = json.loads(tool_call.function.arguments)
177
+ traces.append(f"[{modify_time:.2f}s] Modified content:\n{args['modified_content']}")
178
+
179
+ # Phase 5: Replace section
180
+ result, replace_time = self.replace_section(content, start, end, args["modified_content"])
181
+ timings['replace_section'] = replace_time
182
+
183
+ total_time = time.time() - total_start
184
+ timings['total'] = total_time
185
+
186
+ # Add timing summary
187
+ timing_summary = "\nTiming Summary:\n" + "\n".join([
188
+ f"- {step}: {time:.2f}s" for step, time in timings.items()
189
+ ])
190
+ traces.append(timing_summary)
191
+
192
+ return result, traces, total_time
193
+
194
+ except Exception as e:
195
+ total_time = time.time() - total_start
196
+ error_msg = str(e)
197
+ traces.append(f"Error after {total_time:.2f}s: {error_msg}")
198
+ return error_msg, traces, total_time
199
+
200
+ async def edit_naive(self, content: str, instruction: str) -> tuple[str, list[str], float]:
201
+ """Naive approach - give everything to AI"""
202
+ total_start = time.time()
203
+ traces = [f"[0.00s] Starting naive edit (sending entire document)"]
204
+
205
+ try:
206
+ messages = [
207
+ {"role": "system", "content": "You are a document editor. Edit the provided document according to instructions."},
208
+ {"role": "user", "content": f"Edit this document according to this instruction: {instruction}\n\nDocument:\n{content}"}
209
+ ]
210
+
211
+ api_start = time.time()
212
+ response = self.client.chat.completions.create(
213
+ model="gpt-4o-mini",
214
+ messages=messages
215
+ )
216
+ api_time = time.time() - api_start
217
+
218
+ result = response.choices[0].message.content
219
+ total_time = time.time() - total_start
220
+
221
+ traces.extend([
222
+ f"[{api_time:.2f}s] OpenAI API call completed",
223
+ f"[{total_time:.2f}s] Total processing completed"
224
+ ])
225
+
226
+ return result, traces, total_time
227
+
228
+ except Exception as e:
229
+ total_time = time.time() - total_start
230
+ error_msg = str(e)
231
+ traces.append(f"Error after {total_time:.2f}s: {error_msg}")
232
+ return error_msg, traces, total_time