mMonika commited on
Commit
a60dec0
·
verified ·
1 Parent(s): af831e8

Rename app.py to main.py

Browse files
Files changed (2) hide show
  1. app.py +0 -585
  2. main.py +22 -0
app.py DELETED
@@ -1,585 +0,0 @@
1
- import sys
2
- import warnings
3
- from datetime import datetime
4
- import time
5
- import json
6
- import gradio as gr
7
- from crewai import Agent, Crew, Process, Task, LLM
8
- from crewai.project import CrewBase, agent, crew, task
9
- from crewai_tools import SerperDevTool, ScrapeWebsiteTool
10
- from crewai.knowledge.source.pdf_knowledge_source import PDFKnowledgeSource
11
- import openai
12
- from crewai import Agent, Task, Crew
13
- import os
14
- import queue
15
- from langchain_openai import ChatOpenAI
16
- from typing import List, Dict, Optional
17
- from pydantic import BaseModel, Field, confloat
18
-
19
- # llm = LLM(model="deepseek/deepseek-r1-distill-qwen-32b")
20
- # from crewai.llms import LiteLLM
21
- from fastapi import FastAPI
22
-
23
- app = FastAPI()
24
-
25
- @app.get("/")
26
- def greet_json():
27
- return {"Hello": "World!"}
28
-
29
- llm = LLM(
30
- model="deepseek-ai/DeepSeek-R1-Distill-Qwen-32B",
31
- api_base="http://localhost:8000" # or DeepSeek API
32
- )
33
- class SkillScore(BaseModel):
34
- skill_name: str = Field(description="Name of the skill being scored")
35
- required: bool = Field(description="Whether this skill is required or nice-to-have")
36
- match_level: confloat(ge=0, le=1) = Field(description="How well the candidate's experience matches (0-1)")
37
- years_experience: Optional[float] = Field(description="Years of experience with this skill", default=None)
38
- context_score: confloat(ge=0, le=1) = Field(
39
- description="How relevant the skill usage context is to the job requirements",
40
- default=0.5
41
- )
42
-
43
- class JobMatchScore(BaseModel):
44
- overall_match: confloat(ge=0, le=100) = Field(
45
- description="Overall match percentage (0-100)"
46
- )
47
- technical_skills_match: confloat(ge=0, le=100) = Field(
48
- description="Technical skills match percentage"
49
- )
50
- soft_skills_match: confloat(ge=0, le=100) = Field(
51
- description="Soft skills match percentage"
52
- )
53
- experience_match: confloat(ge=0, le=100) = Field(
54
- description="Experience level match percentage"
55
- )
56
- education_match: confloat(ge=0, le=100) = Field(
57
- description="Education requirements match percentage"
58
- )
59
- industry_match: confloat(ge=0, le=100) = Field(
60
- description="Industry experience match percentage"
61
- )
62
- skill_details: List[SkillScore] = Field(
63
- description="Detailed scoring for each skill",
64
- default_factory=list
65
- )
66
- strengths: List[str] = Field(
67
- description="List of areas where candidate exceeds requirements",
68
- default_factory=list
69
- )
70
- gaps: List[str] = Field(
71
- description="List of areas needing improvement",
72
- default_factory=list
73
- )
74
- scoring_factors: Dict[str, float] = Field(
75
- description="Weights used for different scoring components",
76
- default_factory=lambda: {
77
- "technical_skills": 0.35,
78
- "soft_skills": 0.20,
79
- "experience": 0.25,
80
- "education": 0.10,
81
- "industry": 0.10
82
- }
83
- )
84
-
85
- class JobRequirements(BaseModel):
86
- technical_skills: List[str] = Field(
87
- description="List of required technical skills",
88
- default_factory=list
89
- )
90
- soft_skills: List[str] = Field(
91
- description="List of required soft skills",
92
- default_factory=list
93
- )
94
- experience_requirements: List[str] = Field(
95
- description="List of experience requirements",
96
- default_factory=list
97
- )
98
- key_responsibilities: List[str] = Field(
99
- description="List of key job responsibilities",
100
- default_factory=list
101
- )
102
- education_requirements: List[str] = Field(
103
- description="List of education requirements",
104
- default_factory=list
105
- )
106
- nice_to_have: List[str] = Field(
107
- description="List of preferred but not required skills",
108
- default_factory=list
109
- )
110
- job_title: str = Field(
111
- description="Official job title",
112
- default=""
113
- )
114
- department: Optional[str] = Field(
115
- description="Department or team within the company",
116
- default=None
117
- )
118
- reporting_structure: Optional[str] = Field(
119
- description="Who this role reports to and any direct reports",
120
- default=None
121
- )
122
- job_level: Optional[str] = Field(
123
- description="Level of the position (e.g., Entry, Senior, Lead)",
124
- default=None
125
- )
126
- location_requirements: Dict[str, str] = Field(
127
- description="Location details including remote/hybrid options",
128
- default_factory=dict
129
- )
130
- work_schedule: Optional[str] = Field(
131
- description="Expected work hours and schedule flexibility",
132
- default=None
133
- )
134
- travel_requirements: Optional[str] = Field(
135
- description="Expected travel frequency and scope",
136
- default=None
137
- )
138
- compensation: Dict[str, str] = Field(
139
- description="Salary range and compensation details if provided",
140
- default_factory=dict
141
- )
142
- benefits: List[str] = Field(
143
- description="List of benefits and perks",
144
- default_factory=list
145
- )
146
- tools_and_technologies: List[str] = Field(
147
- description="Specific tools, software, or technologies used",
148
- default_factory=list
149
- )
150
- industry_knowledge: List[str] = Field(
151
- description="Required industry-specific knowledge",
152
- default_factory=list
153
- )
154
- certifications_required: List[str] = Field(
155
- description="Required certifications or licenses",
156
- default_factory=list
157
- )
158
- security_clearance: Optional[str] = Field(
159
- description="Required security clearance level if any",
160
- default=None
161
- )
162
- team_size: Optional[str] = Field(
163
- description="Size of the immediate team",
164
- default=None
165
- )
166
- key_projects: List[str] = Field(
167
- description="Major projects or initiatives mentioned",
168
- default_factory=list
169
- )
170
- cross_functional_interactions: List[str] = Field(
171
- description="Teams or departments this role interacts with",
172
- default_factory=list
173
- )
174
- career_growth: List[str] = Field(
175
- description="Career development and growth opportunities",
176
- default_factory=list
177
- )
178
- training_provided: List[str] = Field(
179
- description="Training or development programs offered",
180
- default_factory=list
181
- )
182
- diversity_inclusion: Optional[str] = Field(
183
- description="D&I statements or requirements",
184
- default=None
185
- )
186
- company_values: List[str] = Field(
187
- description="Company values mentioned in the job posting",
188
- default_factory=list
189
- )
190
- job_url: str = Field(
191
- description="URL of the job posting",
192
- default=""
193
- )
194
- posting_date: Optional[str] = Field(
195
- description="When the job was posted",
196
- default=None
197
- )
198
- application_deadline: Optional[str] = Field(
199
- description="Application deadline if specified",
200
- default=None
201
- )
202
- special_instructions: List[str] = Field(
203
- description="Any special application instructions or requirements",
204
- default_factory=list
205
- )
206
- match_score: JobMatchScore = Field(
207
- description="Detailed scoring of how well the candidate matches the job requirements",
208
- default_factory=JobMatchScore
209
- )
210
- score_explanation: List[str] = Field(
211
- description="Detailed explanation of how scores were calculated",
212
- default_factory=list
213
- )
214
-
215
- class ResumeOptimization(BaseModel):
216
- content_suggestions: List[Dict[str, str]] = Field(
217
- description="List of content optimization suggestions with 'before' and 'after' examples"
218
- )
219
- skills_to_highlight: List[str] = Field(
220
- description="List of skills that should be emphasized based on job requirements"
221
- )
222
- achievements_to_add: List[str] = Field(
223
- description="List of achievements that should be added or modified"
224
- )
225
- keywords_for_ats: List[str] = Field(
226
- description="List of important keywords for ATS optimization"
227
- )
228
- formatting_suggestions: List[str] = Field(
229
- description="List of formatting improvements"
230
- )
231
-
232
- class CompanyResearch(BaseModel):
233
- recent_developments: List[str] = Field(
234
- description="List of recent company news and developments"
235
- )
236
- culture_and_values: List[str] = Field(
237
- description="Key points about company culture and values"
238
- )
239
- market_position: Dict[str, List[str]] = Field(
240
- description="Information about market position, including competitors and industry standing"
241
- )
242
- growth_trajectory: List[str] = Field(
243
- description="Information about company's growth and future plans"
244
- )
245
- interview_questions: List[str] = Field(
246
- description="Strategic questions to ask during the interview"
247
- )
248
-
249
- resume_analyzer = Agent(
250
- role= "Resume Optimization Expert",
251
- goal= "Analyze resumes and provide structured optimization suggestions",
252
- backstory= """
253
- You are a resume optimization specialist with deep knowledge of ATS systems
254
- and modern resume best practices. You excel at analyzing PDF resumes and
255
- providing actionable suggestions for improvement. Your recommendations always
256
- focus on both human readability and ATS compatibility.""",
257
- verbose=True,
258
- llm = llm,
259
- # knowledge_sources=[pdf_source],
260
- )
261
- job_analyzer = Agent(
262
- role= "Job Requirements Analyst",
263
- goal= "Analyze job descriptions and score candidate fit",
264
- backstory= """
265
- You are an expert in job market analysis and candidate evaluation. Your strength
266
- lies in breaking down job requirements into clear categories and providing
267
- detailed scoring based on candidate qualifications. You understand both technical
268
- and soft skills requirements, and can evaluate experience levels accurately.""",
269
- verbose=True,
270
- tools=[ScrapeWebsiteTool()],
271
- llm = llm,
272
-
273
- # knowledge_sources=[pdf_source],
274
- )
275
- company_researcher = Agent(
276
- role= "Company Intelligence Specialist",
277
- goal= "Research companies and prepare interview insights",
278
- backstory= """
279
- You are a corporate research expert who excels at gathering and analyzing
280
- the latest company information. You know how to find and synthesize data
281
- from various sources to create comprehensive company profiles and prepare
282
- candidates for interviews. """,
283
- tools=[SerperDevTool()],
284
- verbose=True,
285
- llm = llm,
286
-
287
- # knowledge_sources=[pdf_source],
288
-
289
- )
290
- resume_writer = Agent (
291
- role= "Resume Markdown Specialist",
292
- goal= "Create beautifully formatted, ATS-optimized resumes in markdown",
293
- backstory= """
294
- You are a resume writing expert who specializes in creating markdown-formatted
295
- resumes. You know how to transform structured optimization suggestions into
296
- beautifully formatted, ATS-friendly documents that maintain professionalism
297
- while showcasing candidate strengths effectively.""",
298
- verbose=True,
299
- llm = llm,
300
-
301
- )
302
- report_generator = Agent(
303
- role= "Career Report Generator and Markdown Specialist",
304
- goal= "Create comprehensive, visually appealing, and actionable reports from job application analysis",
305
- backstory= """
306
- You are an expert in data visualization, technical writing, and Markdown formatting.
307
- You excel at combining data from multiple JSON sources to create cohesive,
308
- visually appealing reports. Your specialty is transforming structured analysis
309
- into clear, actionable insights with proper markdown formatting, emojis, and
310
- visual elements that make information both appealing and easily digestible.""",
311
- verbose=True,
312
- llm = llm,
313
-
314
- )
315
-
316
- analyze_job_task = Task(
317
- description="""Analyze the {job_url} description and score the candidate's fit based on their resume.
318
- Output will be saved as structured JSON data.
319
- 1. Extract Requirements:
320
- - Technical skills (required vs nice-to-have)
321
- - Soft skills
322
- - Experience levels
323
- - Education requirements
324
- - Industry knowledge
325
- 2. Score Technical Skills (35% of total):
326
- - For each required skill:
327
- * Match Level (0-1): How well does candidate's experience match?
328
- * Years Experience: Compare to required years
329
- * Context Score: How relevant is their usage of the skill?
330
- - Calculate weighted average based on skill importance
331
- 3. Score Soft Skills (20% of total):
332
- - Identify soft skills from resume
333
- - Compare against job requirements
334
- - Consider context and demonstration of skills
335
- 4. Score Experience (25% of total):
336
- - Years of relevant experience
337
- - Role similarity
338
- - Industry relevance
339
- - Project scope and complexity
340
- 5. Score Education (10% of total):
341
- - Degree level match
342
- - Field of study relevance
343
- - Additional certifications
344
- 6. Score Industry Knowledge (10% of total):
345
- - Years in similar industry
346
- - Domain expertise
347
- - Industry-specific achievements
348
- 7. Calculate Overall Score:
349
- - Weighted average of all components
350
- - Identify key strengths and gaps
351
- - Provide detailed scoring explanation""",
352
- expected_output="Structured JSON data containing job analysis and scoring details according to the JobRequirements model schema",
353
- output_file='job_analysis.json',
354
- output_pydantic=JobRequirements,
355
- agent=job_analyzer,
356
- # knowledge_sources=[pdf_source],
357
-
358
- )
359
- optimize_resume_task = Task(
360
- description= """
361
- Review the provided resume against the job analysis and create structured optimization suggestions.
362
- Output will be saved as structured JSON data.
363
- 1. Content Analysis:
364
- - Compare resume content with job requirements
365
- - Identify missing keywords and skills
366
- - Analyze achievement descriptions
367
- - Check for ATS compatibility
368
- 2. Structure Review:
369
- - Evaluate section organization
370
- - Check formatting consistency
371
- - Assess information hierarchy
372
- - Verify contact details
373
- 3. Generate Suggestions:
374
- - Content improvements with before/after examples
375
- - Skills to highlight based on job match
376
- - Achievements to add or modify
377
- - ATS optimization recommendations
378
- 4. Make sure not to add skills that are not there in the candidate but you can extract the relavent skills from candidate""",
379
- expected_output= """
380
- Structured JSON data containing detailed optimization suggestions according to
381
- the ResumeOptimization model schema.""",
382
- agent=resume_analyzer,
383
- context= [analyze_job_task],
384
- output_file='resume_optimization.json',
385
- output_pydantic=ResumeOptimization
386
- )
387
- research_company_task = Task(
388
- description= """
389
- Research the {company_name} and prepare the latest (year 2025) and comprehensive analysis.
390
- Output will be saved as structured JSON data.
391
- 1. Company Overview:
392
- - Recent developments and news
393
- - Culture and values
394
- - Market position
395
- - Growth trajectory
396
- 2. Interview Preparation:
397
- - Common interview questions
398
- - Company-specific topics
399
- - Recent projects or initiatives
400
- - Key challenges and opportunities""",
401
- expected_output="""
402
- Structured JSON data containing company research results according to
403
- the CompanyResearch model schema.""",
404
- agent= company_researcher,
405
- context= [analyze_job_task, optimize_resume_task],
406
- output_file='company_research.json',
407
- output_pydantic=CompanyResearch
408
- )
409
- generate_resume_task = Task(
410
- description= """
411
- Using the optimization suggestions and job analysis from previous steps,
412
- create a polished resume in markdown format.
413
- Do not add markdown code blocks like '```'.
414
- 1. Content Integration:
415
- - Incorporate optimization suggestions
416
- - Add missing keywords and skills
417
- - Enhance achievement descriptions
418
- - Ensure ATS compatibility
419
- 2. Formatting:
420
- - Use proper markdown headers (#, ##, ###)
421
- - Apply consistent styling
422
- - Create clear section hierarchy
423
- - Use bullet points effectively
424
- 3. Documentation:
425
- - Track changes made
426
- - Note preserved elements
427
- - Explain optimization choices""",
428
- expected_output= """
429
- A beautifully formatted markdown resume document that:
430
- - Incorporates all optimization suggestions
431
- - Uses proper markdown formatting
432
- - Is ATS-friendly
433
- - Documents all changes made""",
434
- agent= resume_writer,
435
- context= [optimize_resume_task, analyze_job_task, research_company_task],
436
- output_file='output/optimized_resume.md'
437
- )
438
- generate_report_task = Task(
439
- description="""
440
- Create an executive summary report using data from previous steps.
441
- Format in markdown without code blocks '```'.
442
- 1. Data Integration:
443
- - Job analysis and scores
444
- - Resume optimization details
445
- - Company research insights
446
- - Final resume changes
447
- 2. Report Sections:
448
- ## Executive Summary
449
- - Overall match score and quick wins
450
- - Key strengths and improvement areas
451
- - Action items priority list
452
- ## Job Fit Analysis
453
- - Detailed score breakdown
454
- - Skills match assessment
455
- - Experience alignment
456
- ## Optimization Overview
457
- - Key resume improvements
458
- - ATS optimization results
459
- - Impact metrics
460
- ## Company Insights
461
- - Culture fit analysis
462
- - Interview preparation tips
463
- - Key talking points
464
- ## Next Steps
465
- - Prioritized action items
466
- - Skill development plan
467
- - Application strategy
468
- 3. Formatting:
469
- - Use proper markdown headers
470
- - Include relevant emojis
471
- - Create tables where appropriate
472
- - Use bullet points for scannability""",
473
- expected_output=
474
- """ A comprehensive markdown report that combines all analyses into an
475
- actionable, clear document with concrete next steps.""",
476
- agent= report_generator,
477
- context= [analyze_job_task, optimize_resume_task, research_company_task, generate_resume_task, ],
478
- output_file='output/final_report.md'
479
- )
480
- import os
481
- from crewai import Crew
482
-
483
- # Function to run CrewAI with dynamic inputs
484
- def run_crew(api_key: str, job_url: str, company_name: str, resume_pdf_path: str):
485
- if not api_key:
486
- return "⚠️ Please provide a valid OpenAI API Key."
487
-
488
- os.environ["OPENAI_API_KEY"] = f"{api_key}" # Set API key securely
489
- # Load PDF as knowledge source
490
- # pdf_source = resume_pdf_path
491
- pdf_source = PDFKnowledgeSource(
492
- file_paths=[resume_pdf_path])
493
- # Initialize CrewAI with resume knowledge
494
- print(resume_pdf_path)
495
- crew = Crew(
496
- agents=[resume_analyzer, job_analyzer, company_researcher, resume_writer, report_generator],
497
- tasks=[analyze_job_task, optimize_resume_task, research_company_task, generate_resume_task, generate_report_task ],
498
- verbose=True,
499
- knowledge_sources=[pdf_source],
500
-
501
- )
502
- inputs = {
503
- 'job_url': job_url,
504
- 'company_name': company_name
505
- }
506
-
507
- # Run AI pipeline
508
- result_extractor = crew.kickoff(inputs=inputs)
509
- # Ensure output exists before writing files
510
- # optimized_resume_text = result_extractor.get('optimized_resume') if isinstance(result_extractor, dict) and 'optimized_resume' in result_extractor else "No resume data generated."
511
- # final_report_text = result_extractor.get('final_report') if isinstance(result_extractor, dict) and 'final_report' in result_extractor else "No report generated."
512
-
513
- # # Save outputs as markdown files
514
- # optimized_resume_path = os.path.join(OUTPUT_DIR, "optimized_resume.md")
515
- # final_report_path = os.path.join(OUTPUT_DIR, "final_report.md")
516
-
517
- # with open(optimized_resume_path, "w", encoding="utf-8") as resume_file:
518
- # resume_file.write(f"# Optimized Resume\n\n{optimized_resume_text}\n")
519
-
520
- # with open(final_report_path, "w", encoding="utf-8") as report_file:
521
- # report_file.write(f"# AI Resume Optimization Report\n\n{final_report_text}\n")
522
-
523
- # return "✅ Resume processed successfully! Download the files below.", optimized_resume_path, final_report_path
524
-
525
- return result_extractor
526
-
527
- import gradio as gr
528
- import os
529
- import shutil
530
- import traceback
531
-
532
- UPLOAD_DIR = "knowledge"
533
- os.makedirs(UPLOAD_DIR, exist_ok=True)
534
- OUTPUT_DIR = "output"
535
-
536
- def process_resume(api_key, job_url, company_name, resume_pdf,output_files):
537
- """Handles user input, saves the uploaded resume, and runs CrewAI."""
538
- try:
539
- if not api_key:
540
- return "⚠️ Please enter your OpenAI API Key.", []
541
-
542
- if resume_pdf is None:
543
- return "⚠️ Please upload a PDF resume.", []
544
-
545
- # Get the actual file path from the uploaded file
546
- resume_path_tmp = resume_pdf.name # Extract temp file path
547
- resume_filename = os.path.basename(resume_path_tmp)
548
- resume_path = os.path.join(UPLOAD_DIR, resume_filename)
549
-
550
- # Move the uploaded file to the desired location
551
- shutil.move(resume_path_tmp, resume_path)
552
- print(resume_filename)
553
- # Run CrewAI (assuming `run_crew()` is implemented)
554
- result = run_crew(api_key, job_url, company_name, resume_filename)
555
-
556
- # Get the list of files in the output folder for download
557
- output_files = [os.path.join(OUTPUT_DIR, f) for f in os.listdir(OUTPUT_DIR) if os.path.isfile(os.path.join(OUTPUT_DIR, f))]
558
-
559
- return result, output_files
560
-
561
- except Exception as e:
562
- error_msg = f"❌ An error occurred:\n\n{str(e)}\n\n{traceback.format_exc()}"
563
- return error_msg, []
564
-
565
- # Build Gradio UI
566
- with gr.Blocks(theme=gr.themes.Soft()) as demo:
567
- gr.Markdown("# 🤖 AI Resume Optimizer 🚀")
568
- gr.Markdown("Get Complete analysis of your resume")
569
-
570
- api_key = gr.Textbox(label="🔑 Open AI API Key", placeholder="Enter your OpenAI API Key securely")
571
- job_url = gr.Textbox(label="🔗 Job URL", placeholder="Paste job listing URL here")
572
- company_name = gr.Textbox(label="🏢 Company Name", placeholder="Enter company name")
573
- resume_pdf = gr.File(label="📄 Upload Resume (PDF Only)")
574
- btn = gr.Button("Optimize Resume")
575
-
576
- output = gr.Textbox(label="📝 Agent Output", interactive=True)
577
- gr.Markdown("Get your optimized resume below")
578
-
579
- output_files = gr.File(label="📂 Download Processed Files", interactive=True)
580
-
581
- btn.click(process_resume, inputs=[api_key, job_url, company_name, resume_pdf], outputs=[output, output_files])
582
-
583
- # Launch the UI
584
- if __name__ == "__main__":
585
- demo.launch()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
main.py ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI
2
+ import requests
3
+
4
+ app = FastAPI()
5
+
6
+ OLLAMA_BASE_URL = "http://localhost:11434"
7
+
8
+ @app.get("/")
9
+ def read_root():
10
+ return {"message": "FastAPI with Ollama is running!"}
11
+
12
+ @app.get("/ask_ollama/")
13
+ def ask_ollama(question: str):
14
+ payload = {
15
+ "model": "mistral",
16
+ "messages": [
17
+ {"role": "system", "content": "You are an AI assistant."},
18
+ {"role": "user", "content": question}
19
+ ]
20
+ }
21
+ response = requests.post(f"{OLLAMA_BASE_URL}/api/generate", json=payload)
22
+ return response.json()