Merge pull request #680 from srbmisc/week2_day4_srb
Week 2, Day 4 - OpenAI + Gradio + Tools Project
This commit is contained in:
@@ -0,0 +1,245 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "2a8071da",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Week 2, Day 4 - Use of Tools with openAI - Saurabh Gupta. For any feedback, please mail it to srbmisc@gmail.com, I would love connecting with you to discuss more on this, potentially improving it. Thank you for your read.\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "08f50ff5",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# 🔍 LinkedIn Job Search Conversationally with OpenAI and JobSpy\n",
|
||||
"\n",
|
||||
"Looking for a job on LinkedIn but tired of manually scrolling through endless listings? This Python project simplifies your job hunt by automating the process of searching LinkedIn job postings based on your **desired role** and **location**.\n",
|
||||
"\n",
|
||||
"## 🚀 What It Does\n",
|
||||
"\n",
|
||||
"Using the powerful Python scraping library **`jobspy`** [Github Link](https://github.com/speedyapply/JobSpy), this tool fetches **real-time job listings from LinkedIn** tailored to your input. Just provide:\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"- 🧑💻 **Job Title** (e.g., *Data Scientist*, *Frontend Developer*)\n",
|
||||
"- 📍 **Location** (e.g., *New York*, *Remote*, *Berlin*)\n",
|
||||
"\n",
|
||||
"…and the script will return up to **3 curated job listings** matching your criteria — complete with **direct links to the job posts** on LinkedIn.\n",
|
||||
"\n",
|
||||
"## ✅ Key Features\n",
|
||||
"\n",
|
||||
"- 🔎 Real-time LinkedIn job scraping \n",
|
||||
"- ⚡ Fast and minimalistic – only the top 3 results \n",
|
||||
"- 🔗 Includes clickable links to the job listings \n",
|
||||
"- 💬 Simple CLI input — no setup hassles\n",
|
||||
"\n",
|
||||
"## 📌 Use Case\n",
|
||||
"\n",
|
||||
"Whether you're actively job hunting or just exploring opportunities in your field, this tool helps you **stay updated** with fresh job listings — without opening a browser.\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "af6d6650",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"try:\n",
|
||||
" from jobspy import scrape_jobs\n",
|
||||
"except:\n",
|
||||
" %pip install -U python-jobspy\n",
|
||||
" from jobspy import scrape_jobs"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "a08eb7af",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# imports\n",
|
||||
"\n",
|
||||
"import os\n",
|
||||
"import json\n",
|
||||
"from dotenv import load_dotenv\n",
|
||||
"from openai import OpenAI\n",
|
||||
"import gradio as gr\n",
|
||||
"import pandas as pd"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "11a280b1",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"load_dotenv(override=True)\n",
|
||||
"\n",
|
||||
"openai_api_key = os.getenv('OPENAI_API_KEY')\n",
|
||||
"if openai_api_key:\n",
|
||||
" print(f\"OpenAI API Key exists and begins {openai_api_key[:8]}\")\n",
|
||||
"else:\n",
|
||||
" print(\"OpenAI API Key not set\")\n",
|
||||
" \n",
|
||||
"MODEL = \"gpt-4.1-mini\"\n",
|
||||
"openai = OpenAI()\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "dbac4cb6",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def callExternalAPI(title, location) -> str:\n",
|
||||
" jobs = pd.DataFrame(scrape_jobs(\n",
|
||||
" site_name=[\"linkedin\"],\n",
|
||||
" search_term=title,\n",
|
||||
" location=location,\n",
|
||||
" results_wanted=3,\n",
|
||||
" hours_old=48\n",
|
||||
" ))\n",
|
||||
" print(f\"Found {len(jobs)} jobs\")\n",
|
||||
" if len(jobs) > 0:\n",
|
||||
" df = pd.DataFrame(jobs.loc[:,['title','company','location','date_posted','job_url']])\n",
|
||||
" df = df.fillna('N/A')\n",
|
||||
" return df.to_json()\n",
|
||||
" return 'No results found'"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "b44a92f6",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"system_message = ''' You are a helpful assistant for a Jobs Agency who helps users with job listings available.\n",
|
||||
"Give short, courteous answers to the users. Tell the user you can bring max 3 job listings at once. Present the job listings to the user in nice Markdown.\n",
|
||||
"Always be accurate. If you don't know the answer, say so.'''"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "339ac21b",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"getData_function = {\n",
|
||||
" \"name\": \"callExternalAPI\",\n",
|
||||
" \"description\": '''Get the Job listings for the provided job title and/or location. Call this whenever the user needs specific job listings data for the title or location that they provide. Following are few examples - \n",
|
||||
" 1. Give me the jobs available for Software Engineer at Gurugram, India. - In such case, you can call this function by passing the job_title as Software Engineer and job_location as Gurugram, India.\n",
|
||||
" 2. Give me the jobs available for Software Engineer. - In such case, you can call this function by passing the job_title as Software Engineer and job_location as blank string.\n",
|
||||
" 3. Give me the jobs available at Gurugram, India. - In such case, you can call this function by passing the job_title as blank string and job_location as Gurugram, India.\n",
|
||||
" ''',\n",
|
||||
" \"parameters\": {\n",
|
||||
" \"type\": \"object\",\n",
|
||||
" \"properties\": {\n",
|
||||
" \"job_title\": {\n",
|
||||
" \"type\": \"string\",\n",
|
||||
" \"description\": \"The title or position or designation of the job the user is interested in\",\n",
|
||||
" },\n",
|
||||
" \"job_location\": {\n",
|
||||
" \"type\": \"string\",\n",
|
||||
" \"description\": \"The location of the job the user is interested in\",\n",
|
||||
" }\n",
|
||||
" },\n",
|
||||
" \"required\": [\"job_title\",\"job_location\"],\n",
|
||||
" \"additionalProperties\": False\n",
|
||||
" }\n",
|
||||
"}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "892250a4",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"tools = [{\"type\": \"function\", \"function\": getData_function}]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "4be6fd80",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# We have to write that function handle_tool_call:\n",
|
||||
"\n",
|
||||
"def handle_tool_call(message):\n",
|
||||
" tool_call = message.tool_calls[0]\n",
|
||||
" arguments = json.loads(tool_call.function.arguments)\n",
|
||||
" job_title = arguments.get('job_title')\n",
|
||||
" job_location = arguments.get('job_location')\n",
|
||||
" jobs = callExternalAPI(job_title,job_location)\n",
|
||||
" response = {\n",
|
||||
" \"role\": \"tool\",\n",
|
||||
" \"content\": json.dumps({\"job_title\": job_title,\"job_location\": job_location,\"job_listings\": jobs}),\n",
|
||||
" \"tool_call_id\": tool_call.id\n",
|
||||
" }\n",
|
||||
" return response"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "9d0b5b08",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def chat(message, history):\n",
|
||||
" messages = [{\"role\": \"system\", \"content\": system_message}] + history + [{\"role\": \"user\", \"content\": message}]\n",
|
||||
" response = openai.chat.completions.create(model=MODEL, messages=messages, tools=tools)\n",
|
||||
"\n",
|
||||
" if response.choices[0].finish_reason==\"tool_calls\":\n",
|
||||
" message = response.choices[0].message\n",
|
||||
" response = handle_tool_call(message)\n",
|
||||
" messages.append(message)\n",
|
||||
" messages.append(response)\n",
|
||||
" response = openai.chat.completions.create(model=MODEL, messages=messages)\n",
|
||||
" \n",
|
||||
" return response.choices[0].message.content"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "085b4aae",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"gr.ChatInterface(fn=chat, type=\"messages\").launch()"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "venv",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.12.11"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
Reference in New Issue
Block a user