forked from GomezDerek/tedai-llm-gen
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmain.py
304 lines (253 loc) · 11.9 KB
/
main.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
# File: main.py
from fastapi import FastAPI, HTTPException # Original line
from pydantic import BaseModel
import requests
import json
import os
from pydantic import BaseModel
from typing import List, Dict, Any
from fpdf import FPDF
from fastapi.responses import FileResponse
import io
from dotenv import load_dotenv
load_dotenv()
from fastapi.middleware.cors import CORSMiddleware
from biz_roadmap_generation.gemini_roadmap import gemini_roadmap
app = FastAPI()
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], # Allows all origins
allow_credentials=True,
allow_methods=["*"], # Allows all methods
allow_headers=["*"], # Allows all headers
)
from reportlab.lib.pagesizes import letter
from reportlab.platypus import SimpleDocTemplate, Paragraph
from reportlab.lib.styles import getSampleStyleSheet
from io import BytesIO
from fastapi import FastAPI, HTTPException, Response
import requests
# *** Modified Import Statement ***
from duckduckgo_search import DDGS # Updated import for compatibility
def text_to_pdf(text):
buffer = BytesIO()
doc = SimpleDocTemplate(buffer, pagesize=letter)
styles = getSampleStyleSheet()
flowables = []
for line in text.split('\n'):
para = Paragraph(line, styles['Normal'])
flowables.append(para)
doc.build(flowables)
buffer.seek(0)
return buffer.getvalue()
OPENROUTER_API_KEY = os.getenv("OPENROUTER_API_KEY")
# OPENROUTER_API_KEY="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"
class IdeaModel(BaseModel):
name: str
mission: str
goals: List[str]
targetMarket: Dict[str, Any]
primaryProduct: str
sdgs: List[str]
class ChatRequest(BaseModel):
# name: str
idea: IdeaModel
# class ChatRequest(BaseModel):
# message: str
# *** New Additions Start Here ***
# Added: Function to integrate DuckDuckGo search and format citations
def integrate_duckduckgo(query: str, max_results: int = 3) -> str:
"""Fetches DuckDuckGo search results and formats them as citations."""
try:
results = duckduckgo_search(query, max_results=max_results)
if not results:
return "\n\nCitations: No relevant citations found."
citations = "\n".join([f"[{i+1}] {res['title']}: {res['link']}" for i, res in enumerate(results)])
return f"\n\nCitations:\n{citations}"
except Exception as e:
return f"\n\nCitations: DuckDuckGo search error: {str(e)}"
# *** New Additions End Here ***
@app.post("/investors")
async def getInvestors(request: ChatRequest):
try:
request_json = request.json()
response = requests.post(
url="https://openrouter.ai/api/v1/chat/completions",
headers={
"Authorization": f"Bearer {OPENROUTER_API_KEY}",
},
json={
"model": "meta-llama/llama-3.2-3b-instruct:free",
"messages": [
{
"role": "system",
"content": "You are a helpful assistant, expert in starting non profits. Provide concise and accurate responses."
},
{
"role": "user",
# "content": "Considering this particular idea, Please provide steps on how I can connect with investors and list the investors I can potentially connect with, steps to take, and things to keep in mind during this."
"content": "The JSON file I provided contains the content of my non-profit idea. Use this to identify potential investors for my non-profit. Create a list of what categories of entities would be interested in investing in non-profits with a mission like mine. Examples of entity categories can be corporations, celebrities, or charities. Create a list of names for each category of entities. Each list should include at least 2 names. Your output should be in markdown format"
},
{
"role": "user",
"content": request_json
}
]
}
)
response.raise_for_status()
result = response.json()
if "choices" in result and len(result["choices"]) > 0:
main_content = response.json()["choices"][0]["message"]["content"]
else:
raise HTTPException(status_code=500, detail="Unexpected response format from OpenRouter API")
# *** New Additions Start Here ***
# Added: Append DuckDuckGo citations
query = f"Investors for {request.idea.mission}"
citations = integrate_duckduckgo(query)
return main_content + citations
# *** New Additions End Here ***
except requests.RequestException as e:
raise HTTPException(status_code=500, detail=f"Error calling OpenRouter API: {str(e)}")
@app.post("/grantInfo")
async def getGrantInfo(request: ChatRequest):
try:
request_json = request.json()
response = requests.post(
url="https://openrouter.ai/api/v1/chat/completions",
headers={
"Authorization": f"Bearer {OPENROUTER_API_KEY}",
},
json={
"model": "meta-llama/llama-3.2-3b-instruct:free",
"messages": [
{
"role": "system",
"content": "You are a helpful assistant, expert in starting non profits. Provide concise and accurate responses."
},
{
"role": "user",
# "content": "Considering this particular idea, Please provide steps on how I can connect with investors and list the investors I can potentially connect with, steps to take, and things to keep in mind during this."
"content": "The JSON file I provided contains the content of my non-profit idea. Use this to identify potential grants I can apply to, for my non-profit. Create a list of entities that would be interested in providing grants to non-profits with a mission like mine. Your output should be in markdown format"
},
{
"role": "user",
"content": request_json
}
]
}
)
response.raise_for_status()
result = response.json()
if "choices" in result and len(result["choices"]) > 0:
main_content = response.json()["choices"][0]["message"]["content"]
else:
raise HTTPException(status_code=500, detail="Unexpected response format from OpenRouter API")
# *** New Additions Start Here ***
# Added: Append DuckDuckGo citations
query = f"Grants for {request.idea.mission}"
citations = integrate_duckduckgo(query)
return main_content + citations
# *** New Additions End Here ***
except requests.RequestException as e:
raise HTTPException(status_code=500, detail=f"Error calling OpenRouter API: {str(e)}")
@app.post("/getGrantProposal")
async def getGrantProposal(request: ChatRequest):
try:
# request_json = request.json()
idea_description = request.json()
prompt = f"""Write a persuasive grant proposal for a non-profit organization based on this {idea_description}. Include:
1. A captivating executive summary that highlights the problem, your solution, and potential impact
2. A clear problem statement with supporting data and real-world examples
3. Your organization's unique approach and proposed solution
4. Specific, measurable goals and objectives
5. A detailed implementation plan with timeline and milestones
6. Expected outcomes and how you'll measure success
7. A realistic budget breakdown
8. Your team's qualifications and relevant experience
9. Sustainability plan for long-term impact
10. Compelling conclusion that reinforces the urgency and importance of your project
Use a conversational yet professional tone, incorporate storytelling elements, and emphasize the human impact of your work. Provide concrete examples and data to support your claims. Tailor the proposal to align with the goals and values of potential funders."""
response = requests.post(
url="https://openrouter.ai/api/v1/chat/completions",
headers={
"Authorization": f"Bearer {OPENROUTER_API_KEY}",
},
json={
"model": "meta-llama/llama-3.2-3b-instruct:free",
"messages": [
{
"role": "system",
"content": "You are a helpful assistant, expert in writing grant proposals for non-profits. Provide compelling, concise and accurate responses."
},
{
"role": "user",
"content": prompt
}
]
}
)
response.raise_for_status()
result = response.json()
if "choices" in result and len(result["choices"]) > 0:
propContent = response.json()["choices"][0]["message"]["content"]
# *** New Additions Start Here ***
# Added: Append DuckDuckGo citations
query = f"Grant proposal examples for {request.idea.mission}"
citations = integrate_duckduckgo(query)
combined_content = propContent + citations
# *** New Additions End Here ***
pdf_bytes = text_to_pdf(combined_content)
# Return the PDF as a downloadable file
return Response(
content=pdf_bytes,
media_type="application/pdf",
headers={"Content-Disposition": "attachment; filename=grant_proposal.pdf"}
)
# return FileResponse(
# pdf_buffer,
# media_type="application/pdf",
# headers={"Content-Disposition": "attachment; filename=grant_proposal.pdf"}
# )
else:
raise HTTPException(status_code=500, detail="Unexpected response format from OpenRouter API")
except requests.RequestException as e:
raise HTTPException(status_code=500, detail=f"Error calling OpenRouter API: {str(e)}")
GEMINI_API_KEY = os.getenv("GEMINI_API_KEY")
@app.post("/business_plan_roadmap")
async def getPlanning(request: ChatRequest):
# *** New Additions Start Here ***
# Added: Try-except block and append DuckDuckGo citations
try:
response_content = gemini_roadmap()
# Append DuckDuckGo citations
query = f"Business plan roadmap for {request.idea.mission}"
citations = integrate_duckduckgo(query)
combined_response = response_content + citations
return combined_response
except Exception as e:
raise HTTPException(status_code=500, detail=f"Roadmap generation error: {str(e)}")
# *** New Additions End Here ***
# *** New Fixes Start Here ***
# Added: Function to perform DuckDuckGo search
def ddg_search(query: str, max_results: int = 3) -> list:
"""Performs DuckDuckGo search and returns results"""
try:
with DDGS() as ddgs:
results = list(ddgs.text(query, max_results=max_results))
return results
except Exception as e:
print(f"DuckDuckGo search error: {e}")
return []
# Added: Corrected integrate_duckduckgo function to use 'href' instead of 'link'
def integrate_duckduckgo(query: str, max_results: int = 3) -> str:
"""Fetches DuckDuckGo search results and formats them as citations."""
try:
results = ddg_search(query, max_results=max_results)
if not results:
return "\n\nCitations: No relevant citations found."
citations = "\n".join([f"[{i+1}] {res['title']}: {res['href']}" for i, res in enumerate(results)])
return f"\n\nCitations:\n{citations}"
except Exception as e:
return f"\n\nCitations: DuckDuckGo search error: {str(e)}"
# *** New Fixes End Here ***