Localize online search results to user country when location available

Get country code to server chat api from i.p location check on clients.
Use country code to get country specific online search results via Serper.dev API
This commit is contained in:
Debanjum Singh Solanky
2024-09-30 01:19:56 -07:00
parent eb86f6fc42
commit 1fed842fcc
9 changed files with 24 additions and 10 deletions

View File

@@ -60,6 +60,7 @@
let region = null; let region = null;
let city = null; let city = null;
let countryName = null; let countryName = null;
let countryCode = null;
let timezone = null; let timezone = null;
let chatMessageState = { let chatMessageState = {
newResponseTextEl: null, newResponseTextEl: null,
@@ -76,6 +77,7 @@
region = data.region; region = data.region;
city = data.city; city = data.city;
countryName = data.country_name; countryName = data.country_name;
countryCode = data.country_code;
timezone = data.timezone; timezone = data.timezone;
}) })
.catch(err => { .catch(err => {
@@ -157,6 +159,7 @@
...(!!city && { city: city }), ...(!!city && { city: city }),
...(!!region && { region: region }), ...(!!region && { region: region }),
...(!!countryName && { country: countryName }), ...(!!countryName && { country: countryName }),
...(!!countryCode && { country_code: countryCode }),
...(!!timezone && { timezone: timezone }), ...(!!timezone && { timezone: timezone }),
}; };

View File

@@ -308,18 +308,19 @@
<script src="./utils.js"></script> <script src="./utils.js"></script>
<script src="./chatutils.js"></script> <script src="./chatutils.js"></script>
<script> <script>
let region = null; let region = null;
let city = null; let city = null;
let countryName = null; let countryName = null;
let countryCode = null;
let timezone = null; let timezone = null;
fetch("https://ipapi.co/json") fetch("https://ipapi.co/json")
.then(response => response.json()) .then(response => response.json())
.then(data => { .then(data => {
region = data.region;
city = data.city; city = data.city;
region = data.region;
countryName = data.country_name; countryName = data.country_name;
countryCode = data.country_code;
timezone = data.timezone; timezone = data.timezone;
}) })
.catch(err => { .catch(err => {
@@ -410,6 +411,7 @@
...(!!city && { city: city }), ...(!!city && { city: city }),
...(!!region && { region: region }), ...(!!region && { region: region }),
...(!!countryName && { country: countryName }), ...(!!countryName && { country: countryName }),
...(!!countryCode && { country_code: countryCode }),
...(!!timezone && { timezone: timezone }), ...(!!timezone && { timezone: timezone }),
}; };

View File

@@ -36,6 +36,7 @@ interface Location {
region: string; region: string;
city: string; city: string;
countryName: string; countryName: string;
countryCode: string;
timezone: string; timezone: string;
} }
@@ -70,6 +71,7 @@ export class KhojChatView extends KhojPaneView {
region: data.region, region: data.region,
city: data.city, city: data.city,
countryName: data.country_name, countryName: data.country_name,
countryCode: data.country_code,
timezone: data.timezone, timezone: data.timezone,
}; };
}) })
@@ -1060,6 +1062,7 @@ export class KhojChatView extends KhojPaneView {
city: this.location.city, city: this.location.city,
region: this.location.region, region: this.location.region,
country: this.location.countryName, country: this.location.countryName,
country_code: this.location.countryCode,
timezone: this.location.timezone, timezone: this.location.timezone,
}), }),
}; };

View File

@@ -241,9 +241,10 @@ export default function Chat() {
conversation_id: conversationId, conversation_id: conversationId,
stream: true, stream: true,
...(locationData && { ...(locationData && {
city: locationData.city,
region: locationData.region, region: locationData.region,
country: locationData.country, country: locationData.country,
city: locationData.city, country_code: locationData.countryCode,
timezone: locationData.timezone, timezone: locationData.timezone,
}), }),
...(image64 && { image: image64 }), ...(image64 && { image: image64 }),

View File

@@ -6,6 +6,7 @@ export interface LocationData {
city: string; city: string;
region: string; region: string;
country: string; country: string;
countryCode: string;
postal: string; postal: string;
latitude: number; latitude: number;
longitude: number; longitude: number;

View File

@@ -231,6 +231,7 @@ export default function SharedChat() {
region: locationData.region, region: locationData.region,
country: locationData.country, country: locationData.country,
city: locationData.city, city: locationData.city,
country_code: locationData.countryCode,
timezone: locationData.timezone, timezone: locationData.timezone,
}), }),
...(image64 && { image: image64 }), ...(image64 && { image: image64 }),

View File

@@ -7,7 +7,6 @@ from collections import defaultdict
from typing import Callable, Dict, List, Optional, Tuple, Union from typing import Callable, Dict, List, Optional, Tuple, Union
import aiohttp import aiohttp
import requests
from bs4 import BeautifulSoup from bs4 import BeautifulSoup
from markdownify import markdownify from markdownify import markdownify
@@ -80,7 +79,7 @@ async def search_online(
with timer(f"Internet searches for {list(subqueries)} took", logger): with timer(f"Internet searches for {list(subqueries)} took", logger):
search_func = search_with_google if SERPER_DEV_API_KEY else search_with_jina search_func = search_with_google if SERPER_DEV_API_KEY else search_with_jina
search_tasks = [search_func(subquery) for subquery in subqueries] search_tasks = [search_func(subquery, location) for subquery in subqueries]
search_results = await asyncio.gather(*search_tasks) search_results = await asyncio.gather(*search_tasks)
response_dict = {subquery: search_result for subquery, search_result in search_results} response_dict = {subquery: search_result for subquery, search_result in search_results}
@@ -115,8 +114,9 @@ async def search_online(
yield response_dict yield response_dict
async def search_with_google(query: str) -> Tuple[str, Dict[str, List[Dict]]]: async def search_with_google(query: str, location: LocationData) -> Tuple[str, Dict[str, List[Dict]]]:
payload = json.dumps({"q": query}) country_code = location.country_code.lower() if location and location.country_code else "us"
payload = json.dumps({"q": query, "gl": country_code})
headers = {"X-API-KEY": SERPER_DEV_API_KEY, "Content-Type": "application/json"} headers = {"X-API-KEY": SERPER_DEV_API_KEY, "Content-Type": "application/json"}
async with aiohttp.ClientSession() as session: async with aiohttp.ClientSession() as session:
@@ -220,7 +220,7 @@ async def read_webpage_with_jina(web_url: str) -> str:
return response_json["data"]["content"] return response_json["data"]["content"]
async def search_with_jina(query: str) -> Tuple[str, Dict[str, List[Dict]]]: async def search_with_jina(query: str, location: LocationData) -> Tuple[str, Dict[str, List[Dict]]]:
encoded_query = urllib.parse.quote(query) encoded_query = urllib.parse.quote(query)
jina_search_api_url = f"{JINA_SEARCH_API_URL}/{encoded_query}" jina_search_api_url = f"{JINA_SEARCH_API_URL}/{encoded_query}"
headers = {"Accept": "application/json"} headers = {"Accept": "application/json"}

View File

@@ -529,6 +529,7 @@ class ChatRequestBody(BaseModel):
city: Optional[str] = None city: Optional[str] = None
region: Optional[str] = None region: Optional[str] = None
country: Optional[str] = None country: Optional[str] = None
country_code: Optional[str] = None
timezone: Optional[str] = None timezone: Optional[str] = None
image: Optional[str] = None image: Optional[str] = None
@@ -556,6 +557,7 @@ async def chat(
city = body.city city = body.city
region = body.region region = body.region
country = body.country country = body.country
country_code = body.country_code
timezone = body.timezone timezone = body.timezone
image = body.image image = body.image
@@ -653,8 +655,8 @@ async def chat(
user_name = await aget_user_name(user) user_name = await aget_user_name(user)
location = None location = None
if city or region or country: if city or region or country or country_code:
location = LocationData(city=city, region=region, country=country) location = LocationData(city=city, region=region, country=country, country_code=country_code)
if is_query_empty(q): if is_query_empty(q):
async for result in send_llm_response("Please ask your query to get started."): async for result in send_llm_response("Please ask your query to get started."):

View File

@@ -25,6 +25,7 @@ class LocationData(BaseModel):
city: Optional[str] city: Optional[str]
region: Optional[str] region: Optional[str]
country: Optional[str] country: Optional[str]
country_code: Optional[str]
def __str__(self): def __str__(self):
parts = [] parts = []