Skip to content

Commit 1dee3f1

Browse files
ahmedkhaleel2004#33 temporarily move to o1-mini
1 parent 3a2391d commit 1dee3f1

File tree

7 files changed

+210
-197
lines changed

7 files changed

+210
-197
lines changed

.env.example

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
POSTGRES_URL="postgresql://postgres:password@localhost:5432/gitdiagram"
22
NEXT_PUBLIC_API_DEV_URL=http://localhost:8000
33

4-
# backend
5-
ANTHROPIC_API_KEY=
6-
OPENROUTER_API_KEY=
7-
# could probably also add OPENAI_API_KEY since its an easy swap
4+
OPENAI_API_KEY=
85

96
# OPTIONAL: providing your own GitHub PAT increases rate limits from 60/hr to 5000/hr to the GitHub API
10-
GITHUB_PAT=
7+
GITHUB_PAT=
8+
9+
# old implementation
10+
# OPENROUTER_API_KEY=
11+
# ANTHROPIC_API_KEY=

backend/app/routers/generate.py

Lines changed: 14 additions & 174 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from fastapi.responses import StreamingResponse
33
from dotenv import load_dotenv
44
from app.services.github_service import GitHubService
5-
from app.services.o3_mini_openrouter_service import OpenRouterO3Service
5+
from app.services.o1_mini_openai_service import OpenAIO1Service
66
from app.prompts import (
77
SYSTEM_FIRST_PROMPT,
88
SYSTEM_SECOND_PROMPT,
@@ -25,7 +25,7 @@
2525

2626
# Initialize services
2727
# claude_service = ClaudeService()
28-
o3_service = OpenRouterO3Service()
28+
o1_service = OpenAIO1Service()
2929

3030

3131
# cache github data to avoid double API calls from cost and generate
@@ -52,163 +52,6 @@ class ApiRequest(BaseModel):
5252
github_pat: str | None = None
5353

5454

55-
# OLD NON STREAMING VERSION
56-
@router.post("")
57-
# @limiter.limit("1/minute;5/day") # TEMP: disable rate limit for growth??
58-
async def generate(request: Request, body: ApiRequest):
59-
try:
60-
# Check instructions length
61-
if len(body.instructions) > 1000:
62-
return {"error": "Instructions exceed maximum length of 1000 characters"}
63-
64-
if body.repo in [
65-
"fastapi",
66-
"streamlit",
67-
"flask",
68-
"api-analytics",
69-
"monkeytype",
70-
]:
71-
return {"error": "Example repos cannot be regenerated"}
72-
73-
# Get cached github data with PAT if provided
74-
github_data = get_cached_github_data(body.username, body.repo, body.github_pat)
75-
76-
# Get default branch first
77-
default_branch = github_data["default_branch"]
78-
file_tree = github_data["file_tree"]
79-
readme = github_data["readme"]
80-
81-
# Check combined token count
82-
combined_content = f"{file_tree}\n{readme}"
83-
# token_count = claude_service.count_tokens(combined_content)
84-
token_count = o3_service.count_tokens(combined_content)
85-
86-
# CLAUDE: Modified token limit check
87-
# if 50000 < token_count < 190000 and not body.api_key:
88-
# return {
89-
# "error": f"File tree and README combined exceeds token limit (50,000). Current size: {token_count} tokens. This GitHub repository is too large for my wallet, but you can continue by providing your own Anthropic API key.",
90-
# "token_count": token_count,
91-
# "requires_api_key": True,
92-
# }
93-
# elif token_count > 200000:
94-
# return {
95-
# "error": f"Repository is too large (>200k tokens) for analysis. Claude 3.5 Sonnet's max context length is 200k tokens. Current size: {token_count} tokens."
96-
# }
97-
98-
# O3: Modified token limit check
99-
if 50000 < token_count < 195000 and not body.api_key:
100-
return {
101-
"error": f"File tree and README combined exceeds token limit (50,000). Current size: {token_count} tokens. This GitHub repository is too large for my wallet, but you can continue by providing your own OpenRouter API key.",
102-
"token_count": token_count,
103-
"requires_api_key": True,
104-
}
105-
elif token_count > 195000:
106-
return {
107-
"error": f"Repository is too large (>195k tokens) for analysis. OpenAI o3-mini's max context length is 200k tokens. Current size: {token_count} tokens."
108-
}
109-
110-
# Prepare system prompts with instructions if provided
111-
first_system_prompt = SYSTEM_FIRST_PROMPT
112-
third_system_prompt = SYSTEM_THIRD_PROMPT
113-
if body.instructions:
114-
first_system_prompt = (
115-
first_system_prompt + "\n" + ADDITIONAL_SYSTEM_INSTRUCTIONS_PROMPT
116-
)
117-
third_system_prompt = (
118-
third_system_prompt + "\n" + ADDITIONAL_SYSTEM_INSTRUCTIONS_PROMPT
119-
)
120-
121-
# get the explanation for sysdesign from claude
122-
# explanation = claude_service.call_claude_api(
123-
# system_prompt=first_system_prompt,
124-
# data={
125-
# "file_tree": file_tree,
126-
# "readme": readme,
127-
# "instructions": body.instructions,
128-
# },
129-
# api_key=body.api_key,
130-
# )
131-
132-
# get the explanation for sysdesign from o3
133-
explanation = o3_service.call_o3_api(
134-
system_prompt=first_system_prompt,
135-
data={
136-
"file_tree": file_tree,
137-
"readme": readme,
138-
"instructions": body.instructions,
139-
},
140-
api_key=body.api_key,
141-
reasoning_effort="medium",
142-
)
143-
144-
# Check for BAD_INSTRUCTIONS response
145-
if "BAD_INSTRUCTIONS" in explanation:
146-
return {"error": "Invalid or unclear instructions provided"}
147-
148-
# full_second_response = claude_service.call_claude_api(
149-
# system_prompt=SYSTEM_SECOND_PROMPT,
150-
# data={"explanation": explanation, "file_tree": file_tree},
151-
# api_key=body.api_key,
152-
# )
153-
154-
full_second_response = o3_service.call_o3_api(
155-
system_prompt=SYSTEM_SECOND_PROMPT,
156-
data={"explanation": explanation, "file_tree": file_tree},
157-
api_key=body.api_key,
158-
)
159-
160-
# Extract component mapping from the response
161-
start_tag = "<component_mapping>"
162-
end_tag = "</component_mapping>"
163-
component_mapping_text = full_second_response[
164-
full_second_response.find(start_tag) : full_second_response.find(end_tag)
165-
]
166-
167-
# get mermaid.js code from claude
168-
# mermaid_code = claude_service.call_claude_api(
169-
# system_prompt=third_system_prompt,
170-
# data={
171-
# "explanation": explanation,
172-
# "component_mapping": component_mapping_text,
173-
# "instructions": body.instructions,
174-
# },
175-
# api_key=body.api_key,
176-
# )
177-
178-
# get mermaid.js code from o3
179-
mermaid_code = o3_service.call_o3_api(
180-
system_prompt=third_system_prompt,
181-
data={
182-
"explanation": explanation,
183-
"component_mapping": component_mapping_text,
184-
"instructions": body.instructions,
185-
},
186-
api_key=body.api_key,
187-
reasoning_effort="medium",
188-
)
189-
190-
# check for and remove code block tags
191-
mermaid_code = mermaid_code.replace("```mermaid", "").replace("```", "")
192-
193-
# Check for BAD_INSTRUCTIONS response
194-
if "BAD_INSTRUCTIONS" in mermaid_code:
195-
return {"error": "Invalid or unclear instructions provided"}
196-
197-
# Process click events to include full GitHub URLs
198-
processed_diagram = process_click_events(
199-
mermaid_code, body.username, body.repo, default_branch
200-
)
201-
202-
return {"diagram": processed_diagram, "explanation": explanation}
203-
except RateLimitError as e:
204-
raise HTTPException(
205-
status_code=429,
206-
detail="Service is currently experiencing high demand. Please try again in a few minutes.",
207-
)
208-
except Exception as e:
209-
return {"error": str(e)}
210-
211-
21255
@router.post("/cost")
21356
# @limiter.limit("5/minute") # TEMP: disable rate limit for growth??
21457
async def get_generation_cost(request: Request, body: ApiRequest):
@@ -222,8 +65,8 @@ async def get_generation_cost(request: Request, body: ApiRequest):
22265
# file_tree_tokens = claude_service.count_tokens(file_tree)
22366
# readme_tokens = claude_service.count_tokens(readme)
22467

225-
file_tree_tokens = o3_service.count_tokens(file_tree)
226-
readme_tokens = o3_service.count_tokens(readme)
68+
file_tree_tokens = o1_service.count_tokens(file_tree)
69+
readme_tokens = o1_service.count_tokens(readme)
22770

22871
# CLAUDE: Calculate approximate cost
22972
# Input cost: $3 per 1M tokens ($0.000003 per token)
@@ -232,7 +75,7 @@ async def get_generation_cost(request: Request, body: ApiRequest):
23275
# output_cost = 3500 * 0.000015
23376
# estimated_cost = input_cost + output_cost
23477

235-
# O3: Calculate approximate cost
78+
# O3: Calculate approximate cost temp: o1-mini, same price as o3-mini
23679
# Input cost: $1.1 per 1M tokens ($0.0000011 per token)
23780
# Output cost: $4.4 per 1M tokens ($0.0000044 per token)
23881
input_cost = ((file_tree_tokens * 2 + readme_tokens) + 3000) * 0.0000011
@@ -306,13 +149,13 @@ async def event_generator():
306149

307150
# Token count check
308151
combined_content = f"{file_tree}\n{readme}"
309-
token_count = o3_service.count_tokens(combined_content)
152+
token_count = o1_service.count_tokens(combined_content)
310153

311154
if 50000 < token_count < 195000 and not body.api_key:
312-
yield f"data: {json.dumps({'error': f'File tree and README combined exceeds token limit (50,000). Current size: {token_count} tokens. This GitHub repository is too large for my wallet, but you can continue by providing your own OpenRouter API key.'})}\n\n"
155+
yield f"data: {json.dumps({'error': f'File tree and README combined exceeds token limit (50,000). Current size: {token_count} tokens. This GitHub repository is too large for my wallet, but you can continue by providing your own OpenAI API key.'})}\n\n"
313156
return
314157
elif token_count > 195000:
315-
yield f"data: {json.dumps({'error': f'Repository is too large (>195k tokens) for analysis. OpenAI o3-mini\'s max context length is 200k tokens. Current size: {token_count} tokens.'})}\n\n"
158+
yield f"data: {json.dumps({'error': f'Repository is too large (>195k tokens) for analysis. OpenAI o1-mini\'s max context length is 200k tokens. Current size: {token_count} tokens.'})}\n\n"
316159
return
317160

318161
# Prepare prompts
@@ -331,19 +174,18 @@ async def event_generator():
331174
)
332175

333176
# Phase 1: Get explanation
334-
yield f"data: {json.dumps({'status': 'explanation_sent', 'message': 'Sending explanation request to o3-mini...'})}\n\n"
177+
yield f"data: {json.dumps({'status': 'explanation_sent', 'message': 'Sending explanation request to o1-mini...'})}\n\n"
335178
await asyncio.sleep(0.1)
336179
yield f"data: {json.dumps({'status': 'explanation', 'message': 'Analyzing repository structure...'})}\n\n"
337180
explanation = ""
338-
async for chunk in o3_service.call_o3_api_stream(
181+
async for chunk in o1_service.call_o1_api_stream(
339182
system_prompt=first_system_prompt,
340183
data={
341184
"file_tree": file_tree,
342185
"readme": readme,
343186
"instructions": body.instructions,
344187
},
345188
api_key=body.api_key,
346-
reasoning_effort="medium",
347189
):
348190
explanation += chunk
349191
yield f"data: {json.dumps({'status': 'explanation_chunk', 'chunk': chunk})}\n\n"
@@ -353,15 +195,14 @@ async def event_generator():
353195
return
354196

355197
# Phase 2: Get component mapping
356-
yield f"data: {json.dumps({'status': 'mapping_sent', 'message': 'Sending component mapping request to o3-mini...'})}\n\n"
198+
yield f"data: {json.dumps({'status': 'mapping_sent', 'message': 'Sending component mapping request to o1-mini...'})}\n\n"
357199
await asyncio.sleep(0.1)
358200
yield f"data: {json.dumps({'status': 'mapping', 'message': 'Creating component mapping...'})}\n\n"
359201
full_second_response = ""
360-
async for chunk in o3_service.call_o3_api_stream(
202+
async for chunk in o1_service.call_o1_api_stream(
361203
system_prompt=SYSTEM_SECOND_PROMPT,
362204
data={"explanation": explanation, "file_tree": file_tree},
363205
api_key=body.api_key,
364-
reasoning_effort="medium",
365206
):
366207
full_second_response += chunk
367208
yield f"data: {json.dumps({'status': 'mapping_chunk', 'chunk': chunk})}\n\n"
@@ -377,19 +218,18 @@ async def event_generator():
377218
]
378219

379220
# Phase 3: Generate Mermaid diagram
380-
yield f"data: {json.dumps({'status': 'diagram_sent', 'message': 'Sending diagram generation request to o3-mini...'})}\n\n"
221+
yield f"data: {json.dumps({'status': 'diagram_sent', 'message': 'Sending diagram generation request to o1-mini...'})}\n\n"
381222
await asyncio.sleep(0.1)
382223
yield f"data: {json.dumps({'status': 'diagram', 'message': 'Generating diagram...'})}\n\n"
383224
mermaid_code = ""
384-
async for chunk in o3_service.call_o3_api_stream(
225+
async for chunk in o1_service.call_o1_api_stream(
385226
system_prompt=third_system_prompt,
386227
data={
387228
"explanation": explanation,
388229
"component_mapping": component_mapping_text,
389230
"instructions": body.instructions,
390231
},
391232
api_key=body.api_key,
392-
reasoning_effort="medium",
393233
):
394234
mermaid_code += chunk
395235
yield f"data: {json.dumps({'status': 'diagram_chunk', 'chunk': chunk})}\n\n"

backend/app/routers/modify.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from anthropic._exceptions import RateLimitError
77
from app.prompts import SYSTEM_MODIFY_PROMPT
88
from pydantic import BaseModel
9-
from app.services.o3_mini_openrouter_service import OpenRouterO3Service
9+
from app.services.o1_mini_openai_service import OpenAIO1Service
1010

1111

1212
load_dotenv()
@@ -15,7 +15,7 @@
1515

1616
# Initialize services
1717
# claude_service = ClaudeService()
18-
o3_service = OpenRouterO3Service()
18+
o1_service = OpenAIO1Service()
1919

2020

2121
# Define the request body model
@@ -59,7 +59,7 @@ async def modify(request: Request, body: ModifyRequest):
5959
# },
6060
# )
6161

62-
modified_mermaid_code = o3_service.call_o3_api(
62+
modified_mermaid_code = o1_service.call_o1_api(
6363
system_prompt=SYSTEM_MODIFY_PROMPT,
6464
data={
6565
"instructions": body.instructions,

0 commit comments

Comments
 (0)