Spaces:
Sleeping
Sleeping
Download api.py from Punnawat01/Brook-api: direct link, hf CLI and curl.
- Browser
- Download file 6.37 kB
-
https://huggingface.co/spaces/Punnawat01/Brook-api/resolve/main/api.py
- Command line
-
hf download hf://spaces/Punnawat01/Brook-api/api.py
-
curl -L -o api.py https://huggingface.co/spaces/Punnawat01/Brook-api/resolve/main/api.py
6.37 kB
| #uvicorn bytext:app --reload | |
| from pydantic import BaseModel | |
| from fastapi import FastAPI,Query | |
| from typing import List | |
| import difflib | |
| import csv | |
| from fastapi.middleware.cors import CORSMiddleware | |
| import random | |
| from fooddata import csv_data | |
| from io import StringIO | |
| app = FastAPI() | |
| async def read_main(): | |
| return {"msg": "Hello World"} | |
| # Enable CORS | |
| app.add_middleware( | |
| CORSMiddleware, | |
| allow_origins=["*"], | |
| allow_credentials=True, | |
| allow_methods=["*"], | |
| allow_headers=["*"], | |
| ) | |
| # Parse CSV data (assuming 'csv_data' is defined somewhere) | |
| csv_lines = csv_data.strip().split('\n') | |
| csv_reader = csv.DictReader(csv_lines) | |
| foods = list(csv_reader) | |
| def calculate_similarity(user_input, food): | |
| # Compare user input directly with the "foodname" field | |
| food_name_lower = food['foodname'].lower() | |
| similarity_score = difflib.SequenceMatcher(None, user_input, food_name_lower).ratio() | |
| return similarity_score | |
| async def find_food( | |
| keyword: str = Query(None, title="General Search Keyword", min_length=1), | |
| avoid_preference: str = Query(None, title="Avoid Preference"), | |
| ): | |
| # Split avoid_preference into a list of individual preferences | |
| avoid_preferences_list = avoid_preference.lower().split(",") if avoid_preference else [] | |
| # If there's no input for keyword, return 5 random foods without the specified avoid preferences | |
| if not keyword and avoid_preferences_list: | |
| foods_without_avoid = [food for food in foods if not any(avoid_pref in food['avoid'].lower() for avoid_pref in avoid_preferences_list)] | |
| random_foods = random.sample(foods_without_avoid, min(5, len(foods_without_avoid))) | |
| result = [{"foodname": food['foodname'], "type": food['type'], "price": food['price'], "country": food['country'], "images": food['images']} for food in random_foods] | |
| return result | |
| # Filter out foods to avoid | |
| foods_to_consider = [food for food in foods if not any(avoid_pref in food['avoid'].lower() for avoid_pref in avoid_preferences_list)] if avoid_preference else foods | |
| # If there's no input for both keyword and avoid_preference, return random 5 foods | |
| if not keyword and not avoid_preference: | |
| random_foods = random.sample(foods, 5) | |
| result = [{"foodname": food['foodname'], "type": food['type'], "price": food['price'], "country": food['country'], "images": food['images']} for food in random_foods] | |
| return result | |
| # Convert user input to lowercase | |
| user_input = keyword.lower() | |
| # Calculate similarity using a more flexible approach | |
| similarity_scores = [ | |
| ( | |
| food['foodname'], | |
| food['type'], | |
| food['price'], | |
| food['country'], | |
| food['images'], # Add 'images' here | |
| calculate_similarity(user_input, food) | |
| ) | |
| for food in foods_to_consider | |
| ] | |
| # Find the top 5 foods with the highest similarity scores | |
| top_matches = sorted(similarity_scores, key=lambda x: x[5], reverse=True)[:5] | |
| # Format the results | |
| result = [{"foodname": foodname, "type": foodtype, "price": foodprice, "country": foodcountry, "images": images} | |
| for foodname, foodtype, foodprice, foodcountry, images, _ in top_matches] | |
| return result | |
| def filter_food_by_criteria(data, criteria, header_mapping): | |
| filtered_food = [food for i, food in enumerate(csv.reader(data.strip().split("\n"))) if i > 0] | |
| for criterion, value in criteria.items(): | |
| if value and criterion != 'price': | |
| if criterion == 'avoid': | |
| avoid_values = [av.lower() for av in value.split(',')] | |
| filtered_food = [food for food in filtered_food if not any(any(av.lower() in tag.lower() for tag in food[header_mapping['avoid']].split(',')) for av in avoid_values)] | |
| elif criterion == 'country': | |
| # Improved handling of 'country' criterion (case-insensitive and stripping whitespace) | |
| filtered_food = [food for food in filtered_food if isinstance(food, list) and value.lower().strip() in food[header_mapping[criterion]].lower().strip()] | |
| else: | |
| filtered_food = [food for food in filtered_food if isinstance(food, list) and any(val.lower() in food[header_mapping[criterion]].lower() for val in value.split(','))] | |
| if value and criterion == 'price': | |
| min_price, max_price = map(int, value.split('-')) | |
| if isinstance(filtered_food[0][header_mapping[criterion]], list): | |
| # Case when it's a list | |
| filtered_food = [food for food in filtered_food if min_price < int(food[header_mapping[criterion]][0].split('-')[0]) < max_price] | |
| else: | |
| # Case when it's not a list | |
| filtered_food = [food for food in filtered_food if min_price < int(food[header_mapping[criterion]].split('-')[0]) < max_price] | |
| return filtered_food | |
| # รหัสหัวข้อ | |
| header_mapping = { | |
| 'foodname': 0, | |
| 'country': 1, | |
| 'taste': 2, | |
| 'type': 3, | |
| 'price': 4, | |
| 'avoid': 5, | |
| 'images': 6, | |
| } | |
| def recommend_food( | |
| avoid: str = Query(None, description="Foods to avoid, use comma as separator"), | |
| country: str = Query(None, description="Preferred country"), | |
| taste: str = Query(None, description="Preferred taste"), | |
| price: str = Query(None, description="Preferred price range"), | |
| food_type: str = Query(None, description="Preferred food type") | |
| ): | |
| try: | |
| user_criteria = { | |
| 'avoid': avoid, | |
| 'country': country, | |
| 'taste': taste, | |
| 'price': price, | |
| 'type': food_type, | |
| } | |
| # Filter food based on user criteria | |
| recommended_food = filter_food_by_criteria(csv_data, user_criteria, header_mapping) | |
| # Extract relevant information for the response | |
| response_data = [ | |
| { | |
| "foodname": food[header_mapping['foodname']], | |
| "price": food[header_mapping['price']], | |
| "type": food[header_mapping['type']], | |
| "country": food[header_mapping['country']], | |
| "images": food[header_mapping['images']], | |
| } for food in recommended_food | |
| ] | |
| return response_data | |
| except Exception as e: | |
| return {"error": str(e)} |