Spaces:
Sleeping
Sleeping
apparently works
Browse files
app.py
CHANGED
|
@@ -816,84 +816,131 @@ async def generate_piclet(image, hf_token: str) -> dict:
|
|
| 816 |
# Get user profile (creates if doesn't exist)
|
| 817 |
user_profile = PicletDiscoveryService.get_or_create_user_profile(user_info)
|
| 818 |
|
| 819 |
-
# Extract image from Gradio input
|
| 820 |
-
# Gradio cleans up temp files, so we
|
| 821 |
from PIL import Image as PILImage
|
|
|
|
|
|
|
| 822 |
image_path = image if isinstance(image, str) else image.name if hasattr(image, 'name') else str(image)
|
| 823 |
-
image_data = PILImage.open(image_path)
|
| 824 |
-
|
| 825 |
-
# Step 1: Generate caption
|
| 826 |
-
print("Step 1/5: Generating image caption...")
|
| 827 |
-
caption = await PicletGeneratorService.generate_enhanced_caption(image_data, hf_token)
|
| 828 |
-
|
| 829 |
-
# Step 2: Generate concept
|
| 830 |
-
print("Step 2/5: Generating Piclet concept...")
|
| 831 |
-
concept_data = await PicletGeneratorService.generate_piclet_concept(caption, hf_token)
|
| 832 |
-
|
| 833 |
-
object_name = concept_data['objectName']
|
| 834 |
-
attributes = concept_data['attributes']
|
| 835 |
-
stats = concept_data['stats']
|
| 836 |
-
image_prompt = concept_data['imagePrompt']
|
| 837 |
-
concept_text = concept_data['concept']
|
| 838 |
-
|
| 839 |
-
# Step 3: Generate image
|
| 840 |
-
print("Step 3/5: Generating Piclet image...")
|
| 841 |
-
image_result = await PicletGeneratorService.generate_piclet_image(
|
| 842 |
-
image_prompt,
|
| 843 |
-
stats['tier'],
|
| 844 |
-
hf_token
|
| 845 |
-
)
|
| 846 |
|
| 847 |
-
#
|
| 848 |
-
|
| 849 |
-
|
|
|
|
|
|
|
| 850 |
|
| 851 |
-
|
| 852 |
-
|
| 853 |
-
|
| 854 |
-
|
| 855 |
-
|
| 856 |
-
#
|
| 857 |
-
|
| 858 |
-
|
| 859 |
-
|
| 860 |
-
|
| 861 |
-
|
| 862 |
-
|
| 863 |
-
|
| 864 |
-
|
| 865 |
-
|
| 866 |
-
|
| 867 |
-
|
| 868 |
-
|
| 869 |
-
|
| 870 |
-
|
| 871 |
-
|
| 872 |
-
|
| 873 |
-
|
| 874 |
-
|
| 875 |
-
|
| 876 |
-
|
| 877 |
-
|
| 878 |
-
|
| 879 |
-
|
| 880 |
-
|
| 881 |
-
|
| 882 |
-
|
| 883 |
-
|
| 884 |
-
if not
|
| 885 |
-
discovery_status = '
|
| 886 |
canonical_id = existing_data['canonical']['typeId']
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 887 |
|
| 888 |
-
|
| 889 |
-
|
| 890 |
-
|
| 891 |
-
|
| 892 |
-
|
| 893 |
-
|
| 894 |
-
|
| 895 |
-
|
| 896 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 897 |
"discoveredBy": user_info['preferred_username'],
|
| 898 |
"discovererSub": user_info['sub'],
|
| 899 |
"discovererUsername": user_info['preferred_username'],
|
|
@@ -902,7 +949,7 @@ async def generate_piclet(image, hf_token: str) -> dict:
|
|
| 902 |
"discoveredAt": datetime.now().isoformat(),
|
| 903 |
"scanCount": scan_count,
|
| 904 |
"picletData": {
|
| 905 |
-
"typeId":
|
| 906 |
"nickname": stats['name'],
|
| 907 |
"stats": stats,
|
| 908 |
"imageUrl": image_result['imageUrl'],
|
|
@@ -911,90 +958,65 @@ async def generate_piclet(image, hf_token: str) -> dict:
|
|
| 911 |
"imagePrompt": image_prompt,
|
| 912 |
"createdAt": datetime.now().isoformat()
|
| 913 |
}
|
| 914 |
-
}
|
| 915 |
-
"variations": []
|
| 916 |
-
}
|
| 917 |
-
canonical_id = type_id
|
| 918 |
-
|
| 919 |
-
PicletDiscoveryService.save_piclet_data(object_name, canonical_data)
|
| 920 |
-
|
| 921 |
-
# Update user profile
|
| 922 |
-
user_profile["discoveries"].append(type_id)
|
| 923 |
-
user_profile["uniqueFinds"] = user_profile.get("uniqueFinds", 0) + 1
|
| 924 |
-
user_profile["totalFinds"] = user_profile.get("totalFinds", 0) + 1
|
| 925 |
-
user_profile["rarityScore"] = user_profile.get("rarityScore", 0) + 100
|
| 926 |
-
PicletDiscoveryService.save_user_data(user_info['sub'], user_profile)
|
| 927 |
|
| 928 |
-
|
| 929 |
-
|
| 930 |
-
existing_data = PicletDiscoveryService.load_piclet_data(object_name)
|
| 931 |
-
variation_id = f"{PicletDiscoveryService.normalize_object_name(object_name)}_{len(existing_data['variations']) + 1:03d}"
|
| 932 |
|
| 933 |
-
|
| 934 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 935 |
"attributes": attributes,
|
| 936 |
-
"
|
| 937 |
-
"discovererSub": user_info['sub'],
|
| 938 |
-
"discovererUsername": user_info['preferred_username'],
|
| 939 |
-
"discovererName": user_info.get('name'),
|
| 940 |
-
"discovererPicture": user_info.get('picture'),
|
| 941 |
-
"discoveredAt": datetime.now().isoformat(),
|
| 942 |
"scanCount": scan_count,
|
| 943 |
-
"
|
| 944 |
-
"typeId": variation_id,
|
| 945 |
-
"nickname": stats['name'],
|
| 946 |
-
"stats": stats,
|
| 947 |
-
"imageUrl": image_result['imageUrl'],
|
| 948 |
-
"imageCaption": caption,
|
| 949 |
-
"concept": concept_text,
|
| 950 |
-
"imagePrompt": image_prompt,
|
| 951 |
-
"createdAt": datetime.now().isoformat()
|
| 952 |
-
}
|
| 953 |
}
|
| 954 |
|
| 955 |
-
|
| 956 |
-
|
| 957 |
-
|
| 958 |
-
|
| 959 |
-
|
| 960 |
-
user_profile["totalFinds"] = user_profile.get("totalFinds", 0) + 1
|
| 961 |
-
user_profile["rarityScore"] = user_profile.get("rarityScore", 0) + 50
|
| 962 |
-
PicletDiscoveryService.save_user_data(user_info['sub'], user_profile)
|
| 963 |
-
|
| 964 |
-
# Build complete response
|
| 965 |
-
piclet_data = {
|
| 966 |
-
"typeId": canonical_id,
|
| 967 |
-
"nickname": stats['name'],
|
| 968 |
-
"stats": stats,
|
| 969 |
-
"imageUrl": image_result['imageUrl'],
|
| 970 |
-
"imageCaption": caption,
|
| 971 |
-
"concept": concept_text,
|
| 972 |
-
"imagePrompt": image_prompt,
|
| 973 |
-
"objectName": object_name,
|
| 974 |
-
"attributes": attributes,
|
| 975 |
-
"discoveryStatus": discovery_status,
|
| 976 |
-
"scanCount": scan_count,
|
| 977 |
-
"createdAt": datetime.now().isoformat()
|
| 978 |
-
}
|
| 979 |
|
| 980 |
-
|
| 981 |
-
|
| 982 |
-
|
| 983 |
-
|
| 984 |
-
|
|
|
|
|
|
|
| 985 |
|
| 986 |
-
|
| 987 |
-
"
|
| 988 |
-
|
| 989 |
-
|
| 990 |
-
|
| 991 |
-
|
| 992 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 993 |
|
| 994 |
except Exception as e:
|
| 995 |
-
print(f"Failed to
|
| 996 |
-
import traceback
|
| 997 |
-
traceback.print_exc()
|
| 998 |
return {
|
| 999 |
"success": False,
|
| 1000 |
"error": str(e)
|
|
|
|
| 816 |
# Get user profile (creates if doesn't exist)
|
| 817 |
user_profile = PicletDiscoveryService.get_or_create_user_profile(user_info)
|
| 818 |
|
| 819 |
+
# Extract image from Gradio input - save to temp file to pass to API calls
|
| 820 |
+
# Gradio cleans up temp files, so we save to our own temp file
|
| 821 |
from PIL import Image as PILImage
|
| 822 |
+
import shutil
|
| 823 |
+
|
| 824 |
image_path = image if isinstance(image, str) else image.name if hasattr(image, 'name') else str(image)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 825 |
|
| 826 |
+
# Save to a temporary file that we control
|
| 827 |
+
with tempfile.NamedTemporaryFile(mode='wb', suffix='.jpg', delete=False) as f:
|
| 828 |
+
temp_image_path = f.name
|
| 829 |
+
img = PILImage.open(image_path)
|
| 830 |
+
img.save(temp_image_path, format='JPEG')
|
| 831 |
|
| 832 |
+
try:
|
| 833 |
+
# Step 1: Generate caption
|
| 834 |
+
print("Step 1/5: Generating image caption...")
|
| 835 |
+
caption = await PicletGeneratorService.generate_enhanced_caption(temp_image_path, hf_token)
|
| 836 |
+
|
| 837 |
+
# Step 2: Generate concept
|
| 838 |
+
print("Step 2/5: Generating Piclet concept...")
|
| 839 |
+
concept_data = await PicletGeneratorService.generate_piclet_concept(caption, hf_token)
|
| 840 |
+
|
| 841 |
+
object_name = concept_data['objectName']
|
| 842 |
+
attributes = concept_data['attributes']
|
| 843 |
+
stats = concept_data['stats']
|
| 844 |
+
image_prompt = concept_data['imagePrompt']
|
| 845 |
+
concept_text = concept_data['concept']
|
| 846 |
+
|
| 847 |
+
# Step 3: Generate image
|
| 848 |
+
print("Step 3/5: Generating Piclet image...")
|
| 849 |
+
image_result = await PicletGeneratorService.generate_piclet_image(
|
| 850 |
+
image_prompt,
|
| 851 |
+
stats['tier'],
|
| 852 |
+
hf_token
|
| 853 |
+
)
|
| 854 |
+
|
| 855 |
+
# Step 4: Check for canonical/variation
|
| 856 |
+
print("Step 4/5: Checking for existing canonical...")
|
| 857 |
+
existing_data = PicletDiscoveryService.load_piclet_data(object_name)
|
| 858 |
+
|
| 859 |
+
discovery_status = 'new'
|
| 860 |
+
canonical_id = None
|
| 861 |
+
scan_count = 1
|
| 862 |
+
|
| 863 |
+
if existing_data:
|
| 864 |
+
# Check if this is an exact canonical match (no attributes)
|
| 865 |
+
if not attributes or len(attributes) == 0:
|
| 866 |
+
discovery_status = 'existing'
|
| 867 |
canonical_id = existing_data['canonical']['typeId']
|
| 868 |
+
# Increment scan count
|
| 869 |
+
existing_data['canonical']['scanCount'] = existing_data['canonical'].get('scanCount', 0) + 1
|
| 870 |
+
scan_count = existing_data['canonical']['scanCount']
|
| 871 |
+
PicletDiscoveryService.save_piclet_data(object_name, existing_data)
|
| 872 |
+
else:
|
| 873 |
+
# Check for matching variation
|
| 874 |
+
variations = existing_data.get('variations', [])
|
| 875 |
+
matched_variation = None
|
| 876 |
+
|
| 877 |
+
for variation in variations:
|
| 878 |
+
var_attrs = set(variation.get('attributes', []))
|
| 879 |
+
search_attrs = set(attributes)
|
| 880 |
+
overlap = len(var_attrs.intersection(search_attrs))
|
| 881 |
+
|
| 882 |
+
if overlap >= len(search_attrs) * 0.5:
|
| 883 |
+
matched_variation = variation
|
| 884 |
+
discovery_status = 'existing'
|
| 885 |
+
canonical_id = existing_data['canonical']['typeId']
|
| 886 |
+
# Increment variation scan count
|
| 887 |
+
variation['scanCount'] = variation.get('scanCount', 0) + 1
|
| 888 |
+
scan_count = variation['scanCount']
|
| 889 |
+
PicletDiscoveryService.save_piclet_data(object_name, existing_data)
|
| 890 |
+
break
|
| 891 |
+
|
| 892 |
+
if not matched_variation:
|
| 893 |
+
discovery_status = 'variation'
|
| 894 |
+
canonical_id = existing_data['canonical']['typeId']
|
| 895 |
|
| 896 |
+
# Step 5: Save new discovery if needed
|
| 897 |
+
print("Step 5/5: Saving to dataset...")
|
| 898 |
+
if discovery_status == 'new':
|
| 899 |
+
# Create new canonical
|
| 900 |
+
type_id = f"{PicletDiscoveryService.normalize_object_name(object_name)}_canonical"
|
| 901 |
+
canonical_data = {
|
| 902 |
+
"canonical": {
|
| 903 |
+
"objectName": object_name,
|
| 904 |
+
"typeId": type_id,
|
| 905 |
+
"discoveredBy": user_info['preferred_username'],
|
| 906 |
+
"discovererSub": user_info['sub'],
|
| 907 |
+
"discovererUsername": user_info['preferred_username'],
|
| 908 |
+
"discovererName": user_info.get('name'),
|
| 909 |
+
"discovererPicture": user_info.get('picture'),
|
| 910 |
+
"discoveredAt": datetime.now().isoformat(),
|
| 911 |
+
"scanCount": scan_count,
|
| 912 |
+
"picletData": {
|
| 913 |
+
"typeId": type_id,
|
| 914 |
+
"nickname": stats['name'],
|
| 915 |
+
"stats": stats,
|
| 916 |
+
"imageUrl": image_result['imageUrl'],
|
| 917 |
+
"imageCaption": caption,
|
| 918 |
+
"concept": concept_text,
|
| 919 |
+
"imagePrompt": image_prompt,
|
| 920 |
+
"createdAt": datetime.now().isoformat()
|
| 921 |
+
}
|
| 922 |
+
},
|
| 923 |
+
"variations": []
|
| 924 |
+
}
|
| 925 |
+
canonical_id = type_id
|
| 926 |
+
|
| 927 |
+
PicletDiscoveryService.save_piclet_data(object_name, canonical_data)
|
| 928 |
+
|
| 929 |
+
# Update user profile
|
| 930 |
+
user_profile["discoveries"].append(type_id)
|
| 931 |
+
user_profile["uniqueFinds"] = user_profile.get("uniqueFinds", 0) + 1
|
| 932 |
+
user_profile["totalFinds"] = user_profile.get("totalFinds", 0) + 1
|
| 933 |
+
user_profile["rarityScore"] = user_profile.get("rarityScore", 0) + 100
|
| 934 |
+
PicletDiscoveryService.save_user_data(user_info['sub'], user_profile)
|
| 935 |
+
|
| 936 |
+
elif discovery_status == 'variation':
|
| 937 |
+
# Create new variation
|
| 938 |
+
existing_data = PicletDiscoveryService.load_piclet_data(object_name)
|
| 939 |
+
variation_id = f"{PicletDiscoveryService.normalize_object_name(object_name)}_{len(existing_data['variations']) + 1:03d}"
|
| 940 |
+
|
| 941 |
+
variation_data = {
|
| 942 |
+
"typeId": variation_id,
|
| 943 |
+
"attributes": attributes,
|
| 944 |
"discoveredBy": user_info['preferred_username'],
|
| 945 |
"discovererSub": user_info['sub'],
|
| 946 |
"discovererUsername": user_info['preferred_username'],
|
|
|
|
| 949 |
"discoveredAt": datetime.now().isoformat(),
|
| 950 |
"scanCount": scan_count,
|
| 951 |
"picletData": {
|
| 952 |
+
"typeId": variation_id,
|
| 953 |
"nickname": stats['name'],
|
| 954 |
"stats": stats,
|
| 955 |
"imageUrl": image_result['imageUrl'],
|
|
|
|
| 958 |
"imagePrompt": image_prompt,
|
| 959 |
"createdAt": datetime.now().isoformat()
|
| 960 |
}
|
| 961 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 962 |
|
| 963 |
+
existing_data['variations'].append(variation_data)
|
| 964 |
+
PicletDiscoveryService.save_piclet_data(object_name, existing_data)
|
|
|
|
|
|
|
| 965 |
|
| 966 |
+
# Update user profile
|
| 967 |
+
user_profile["discoveries"].append(variation_id)
|
| 968 |
+
user_profile["totalFinds"] = user_profile.get("totalFinds", 0) + 1
|
| 969 |
+
user_profile["rarityScore"] = user_profile.get("rarityScore", 0) + 50
|
| 970 |
+
PicletDiscoveryService.save_user_data(user_info['sub'], user_profile)
|
| 971 |
+
|
| 972 |
+
# Build complete response
|
| 973 |
+
piclet_data = {
|
| 974 |
+
"typeId": canonical_id,
|
| 975 |
+
"nickname": stats['name'],
|
| 976 |
+
"stats": stats,
|
| 977 |
+
"imageUrl": image_result['imageUrl'],
|
| 978 |
+
"imageCaption": caption,
|
| 979 |
+
"concept": concept_text,
|
| 980 |
+
"imagePrompt": image_prompt,
|
| 981 |
+
"objectName": object_name,
|
| 982 |
"attributes": attributes,
|
| 983 |
+
"discoveryStatus": discovery_status,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 984 |
"scanCount": scan_count,
|
| 985 |
+
"createdAt": datetime.now().isoformat()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 986 |
}
|
| 987 |
|
| 988 |
+
messages = {
|
| 989 |
+
'new': f"Congratulations! You discovered the first {object_name} Piclet!",
|
| 990 |
+
'variation': f"You found a new variation of {object_name}!",
|
| 991 |
+
'existing': f"You encountered a known {object_name} Piclet."
|
| 992 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 993 |
|
| 994 |
+
return {
|
| 995 |
+
"success": True,
|
| 996 |
+
"piclet": piclet_data,
|
| 997 |
+
"discoveryStatus": discovery_status,
|
| 998 |
+
"canonicalId": canonical_id,
|
| 999 |
+
"message": messages.get(discovery_status, "Piclet generated!")
|
| 1000 |
+
}
|
| 1001 |
|
| 1002 |
+
except Exception as e:
|
| 1003 |
+
print(f"Failed to generate Piclet: {e}")
|
| 1004 |
+
import traceback
|
| 1005 |
+
traceback.print_exc()
|
| 1006 |
+
return {
|
| 1007 |
+
"success": False,
|
| 1008 |
+
"error": str(e)
|
| 1009 |
+
}
|
| 1010 |
+
finally:
|
| 1011 |
+
# Clean up temporary image file
|
| 1012 |
+
if os.path.exists(temp_image_path):
|
| 1013 |
+
try:
|
| 1014 |
+
os.unlink(temp_image_path)
|
| 1015 |
+
except:
|
| 1016 |
+
pass
|
| 1017 |
|
| 1018 |
except Exception as e:
|
| 1019 |
+
print(f"Failed to process image: {e}")
|
|
|
|
|
|
|
| 1020 |
return {
|
| 1021 |
"success": False,
|
| 1022 |
"error": str(e)
|