Spaces:
Sleeping
Sleeping
File size: 9,960 Bytes
3a743e5 b9a5c5a 227c7ac b9a5c5a 227c7ac b9a5c5a 227c7ac b9a5c5a 227c7ac b9a5c5a 227c7ac 3a743e5 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 |
"""
International Trade Flow Predictor - Full Application for Hugging Face Spaces
"""
from flask import Flask, render_template, request, jsonify
import os
import json
import requests
import pandas as pd
import numpy as np
import time
from dotenv import load_dotenv
import sys
import logging
# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
# Load environment variables from .env file if it exists
load_dotenv()
# Log environment for debugging
logger.info(f"Environment variables: HUGGINGFACE_API_TOKEN exists: {'HUGGINGFACE_API_TOKEN' in os.environ}")
logger.info(f"Python version: {sys.version}")
logger.info(f"Working directory: {os.getcwd()}")
logger.info(f"Directory contents: {os.listdir('.')}")
# Initialize Flask app
app = Flask(__name__)
# Import the llm_assistant module
try:
from llm_assistant import TradeAssistant
logger.info("Successfully imported TradeAssistant")
except Exception as e:
logger.error(f"Error importing TradeAssistant: {str(e)}")
# Create a fallback class if import fails
class TradeAssistant:
def __init__(self, api_token=None):
self.api_token = api_token
def query(self, user_question, chat_history=None, include_app_context=True):
return {
"success": False,
"response": "The AI assistant is temporarily unavailable. Please check the application logs for details.",
"message": "Import error"
}
def format_chat_history(self, chat_history_raw):
return []
def enhance_query_with_context(self, query):
return query
def explain_hs_code(self, code):
return {
"success": False,
"response": "HS code explanation is temporarily unavailable.",
"message": "Import error"
}
def get_trade_recommendation(self, country=None, product=None, year=None):
return {
"success": False,
"response": "Trade recommendations are temporarily unavailable.",
"message": "Import error"
}
# Initialize the AI Assistant
trade_assistant = TradeAssistant(api_token=os.environ.get("HUGGINGFACE_API_TOKEN"))
# Import comtradeapicall module for data access
try:
import comtradeapicall
logger.info("Successfully imported comtradeapicall module")
data_api_available = True
except Exception as e:
logger.error(f"Error importing comtradeapicall module: {str(e)}")
data_api_available = False
# Set up API access functions with proper error handling
def get_countries():
"""Get list of countries for the UI"""
try:
if data_api_available:
return comtradeapicall.get_country_list()
else:
# Fallback data if API module is not available
return [
{"code": "842", "name": "United States"},
{"code": "156", "name": "China"},
{"code": "276", "name": "Germany"},
{"code": "392", "name": "Japan"},
{"code": "250", "name": "France"}
]
except Exception as e:
logger.error(f"Error getting country list: {str(e)}")
return [{"code": "842", "name": "United States"}] # Minimal fallback
def get_product_codes():
"""Get list of product codes for the UI"""
try:
if data_api_available:
return comtradeapicall.get_commodity_list()
else:
# Fallback data if API module is not available
return [
{"code": "TOTAL", "description": "All Commodities"},
{"code": "01", "description": "Live animals"},
{"code": "85", "description": "Electrical machinery and equipment"}
]
except Exception as e:
logger.error(f"Error getting product codes: {str(e)}")
return [{"code": "TOTAL", "description": "All Commodities"}] # Minimal fallback
def query_comtrade(params):
"""Query the COMTRADE API with the given parameters"""
try:
if not data_api_available:
logger.warning("COMTRADE API module not available, using fallback data")
return {"data": [], "status": "error", "message": "COMTRADE API module not available"}
# Extract parameters
period = params.get('period', '2022')
reporter_code = params.get('reporter', '842') # Default to USA
partner_code = params.get('partner', '156') # Default to China
cmd_code = params.get('commodity', 'TOTAL') # Default to all commodities
flow_code = params.get('flow') # Can be 'X', 'M', or None for both
# Query the API
logger.info(f"Querying COMTRADE API with params: {params}")
df = comtradeapicall.previewFinalData(
typeCode='C',
freqCode='A',
clCode='HS',
period=period,
reporterCode=reporter_code,
partnerCode=partner_code,
cmdCode=cmd_code,
flowCode=flow_code,
maxRecords=500,
format_output='JSON',
includeDesc=True
)
# Check if we got valid data
if 'message' in df.columns and df.shape[0] > 0 and 'error' in df.iloc[0]['message'].lower():
logger.warning(f"COMTRADE API returned an error: {df.iloc[0]['message']}")
return {"data": [], "status": "error", "message": df.iloc[0]['message']}
# Process the data
return {"data": df.to_dict('records'), "status": "success"}
except Exception as e:
logger.error(f"Error querying COMTRADE API: {str(e)}")
return {"data": [], "status": "error", "message": str(e)}
def clean_comtrade_data(data):
"""Clean and process data from the COMTRADE API"""
try:
if isinstance(data, dict) and "data" in data:
df = pd.DataFrame(data["data"])
elif isinstance(data, list):
df = pd.DataFrame(data)
else:
df = pd.DataFrame(data)
# Handle empty data
if df.empty:
return df
# Standardize column names
cols_to_keep = [
'rtCode', 'rtTitle', 'ptCode', 'ptTitle', 'yr', 'rgCode', 'rgDesc',
'cmdCode', 'cmdDesc', 'TradeValue', 'NetWeight', 'Quantity'
]
# Keep only columns that exist in the data
existing_cols = [col for col in cols_to_keep if col in df.columns]
df = df[existing_cols]
return df
except Exception as e:
logger.error(f"Error cleaning COMTRADE data: {str(e)}")
return pd.DataFrame() # Return empty DataFrame on error
def predict_trade(data, model_type):
return {"predictions": [], "status": "placeholder"}
def export_data(data, format_type):
return "placeholder_data"
def get_ml_models():
return ["Linear Regression", "Random Forest"]
def train_ml_model(data, model_type):
return {"status": "success", "message": "Model trained successfully"}
def get_cached_data():
return {"status": "success", "data": {}}
def get_trade_rankings():
return {"status": "success", "rankings": []}
def get_top_trade_partners(country_code):
return {"status": "success", "partners": []}
# Home page
@app.route('/')
def index():
return render_template('index.html')
# AI Assistant endpoints
@app.route('/api/assistant/query', methods=['POST'])
def assistant_query():
data = request.json
# Get the user question from request
user_question = data.get('question', '')
# Validate input
if not user_question:
return jsonify({
'success': False,
'response': '',
'message': 'No question provided'
})
# Get chat history if provided
chat_history_raw = data.get('chatHistory', [])
# Format chat history for the LLM
chat_history = trade_assistant.format_chat_history(chat_history_raw)
# Enhance query with additional context if applicable
enhanced_question = trade_assistant.enhance_query_with_context(user_question)
# Send query to the LLM
response = trade_assistant.query(enhanced_question, chat_history)
# Return the response
return jsonify(response)
# API endpoint for HS code explanation
@app.route('/api/assistant/explain-hs-code', methods=['POST'])
def explain_hs_code():
data = request.json
# Get the HS code from request
hs_code = data.get('code', '')
# Validate input
if not hs_code:
return jsonify({
'success': False,
'response': '',
'message': 'No HS code provided'
})
# Send to specific HS code explanation function
response = trade_assistant.explain_hs_code(hs_code)
# Return the response
return jsonify(response)
# API endpoint for trade recommendations
@app.route('/api/assistant/get-recommendation', methods=['POST'])
def get_recommendation():
data = request.json
# Get parameters
country = data.get('country', None)
product = data.get('product', None)
year = data.get('year', None)
# At least one parameter should be provided
if not country and not product and not year:
return jsonify({
'success': False,
'response': '',
'message': 'Please provide at least one parameter (country, product, or year)'
})
# Get recommendation
response = trade_assistant.get_trade_recommendation(country, product, year)
# Return the response
return jsonify(response)
if __name__ == "__main__":
# Hugging Face Spaces uses port 7860 by default
port = int(os.environ.get("PORT", 7860))
app.run(host="0.0.0.0", port=port)
|