admin08077's picture
Update app.py
0189940 verified
# app.py
# Author: James Burvel O'Callaghan III
# Company: CITIBANK DEMO BUSINESS INC
# Description: Self-Sustaining Blockchain-Integrated AI Monetization Ecosystem with Streamlit Interface
import os
import uuid
import hashlib
import json
from datetime import datetime
import streamlit as st
import requests
from sqlalchemy import create_engine, Column, Integer, String, Float, Boolean, DateTime, ForeignKey
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
import openai
# ========================
# Streamlit Configuration UI
# ========================
st.set_page_config(page_title="CITIBANK DEMO BUSINESS INC AI Crypto Ecosystem", layout="wide")
st.title("🌟 CITIBANK DEMO BUSINESS INC AI Crypto Ecosystem 🌟")
st.sidebar.header("πŸ”§ Configuration Settings")
# Database Configuration
st.sidebar.subheader("πŸ“š Database Configuration")
db_type = st.sidebar.selectbox("Select Database Type", ("SQLite", "PostgreSQL"))
if db_type == "SQLite":
sqlite_db_path = st.sidebar.text_input("SQLite Database File Path", value="citibank_demo_business_inc_ai_crypto.db")
DATABASE_URI = f"sqlite:///{sqlite_db_path}"
elif db_type == "PostgreSQL":
pg_host = st.sidebar.text_input("PostgreSQL Host", value="localhost")
pg_port = st.sidebar.number_input("PostgreSQL Port", min_value=1, max_value=65535, value=5432)
pg_user = st.sidebar.text_input("PostgreSQL Username", value="postgres")
pg_password = st.sidebar.text_input("PostgreSQL Password", type="password")
pg_db = st.sidebar.text_input("PostgreSQL Database Name", value="citibank_demo_business_inc_ai_crypto")
DATABASE_URI = f"postgresql://{pg_user}:{pg_password}@{pg_host}:{pg_port}/{pg_db}"
# Blockchain Configuration
st.sidebar.subheader("πŸ”— Blockchain Configuration")
BLOCKCHAIN_NODE_URL = st.sidebar.text_input("Blockchain Node URL", value="https://rpc.buildbear.io/linguistic-doctorstrange-fb0930a4")
# Hardcoded Smart Contract Address
CONTRACT_ADDRESS = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" # USDC Token Address
# OpenAI Configuration (Optional)
st.sidebar.subheader("πŸ€– OpenAI Configuration")
OPENAI_API_KEY = st.sidebar.text_input("OpenAI API Key (Optional)", type="password")
# Blockchain Address Configuration
st.sidebar.subheader("πŸ”— Your Blockchain Address")
default_token_address = st.sidebar.text_input("Your Blockchain Address (0x...)", value="0x7B35A86fa8cE689b6D8111C09217E7466B5c442A") # Example address
# ========================
# Validate Configuration Inputs
# ========================
config_valid = True
config_errors = []
if not BLOCKCHAIN_NODE_URL.startswith("http"):
config_valid = False
config_errors.append("Blockchain Node URL must start with http or https.")
if not (CONTRACT_ADDRESS.startswith("0x") and len(CONTRACT_ADDRESS) == 42):
config_valid = False
config_errors.append("Invalid Smart Contract Address.")
if db_type == "PostgreSQL":
if not all([pg_host, pg_port, pg_user, pg_password, pg_db]):
config_valid = False
config_errors.append("All PostgreSQL configuration fields must be filled.")
if not config_valid:
st.error("⚠️ **Configuration Errors:**")
for error in config_errors:
st.error(f"- {error}")
st.stop()
# Initialize OpenAI API if API key is provided
if OPENAI_API_KEY:
openai.api_key = OPENAI_API_KEY
openai_enabled = True
st.sidebar.success("πŸ”Œ OpenAI Connected")
else:
openai_enabled = False
st.sidebar.info("πŸ€– OpenAI not connected. AI features are disabled.")
# ========================
# Database Setup
# ========================
Base = declarative_base()
class Token(Base):
__tablename__ = 'tokens'
id = Column(String(36), primary_key=True) # UUID
value = Column(Float, nullable=False)
text = Column(String(256), nullable=False) # Text to store on blockchain
recipient_address = Column(String(42), nullable=False) # Address receiving tokens
verified = Column(Boolean, default=False)
verification_hash = Column(String(64))
created_at = Column(DateTime, default=datetime.utcnow)
class Transaction(Base):
__tablename__ = 'transactions'
id = Column(Integer, primary_key=True)
token_id = Column(String(36), ForeignKey('tokens.id'), nullable=True)
action = Column(String(50), nullable=False)
value = Column(Float, nullable=True)
hash = Column(String(64), nullable=True)
timestamp = Column(DateTime, default=datetime.utcnow)
class Stake(Base):
__tablename__ = 'stakes'
id = Column(Integer, primary_key=True)
amount = Column(Float, nullable=False)
timestamp = Column(DateTime, default=datetime.utcnow)
# Create database engine and session
if db_type == "SQLite":
engine = create_engine(DATABASE_URI, connect_args={"check_same_thread": False})
else:
engine = create_engine(DATABASE_URI)
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
session = Session()
# ========================
# Utility Functions
# ========================
def mint_tokens_via_api(address, token, balance):
"""
Mints tokens by calling the external API endpoint.
Returns True if successful, False otherwise.
"""
url = 'https://backend.buildbear.io/node/faucet/erc20/linguistic-doctorstrange-fb0930a4'
headers = {
'accept': '*/*',
'accept-language': 'en-US,en;q=0.9',
'cache-control': 'no-cache',
'content-type': 'application/json',
'dnt': '1',
'origin': 'https://faucet.buildbear.io',
'pragma': 'no-cache',
'priority': 'u=1, i',
'referer': 'https://faucet.buildbear.io/',
'sec-ch-ua': '"Not(A:Brand";v="99", "Google Chrome";v="133", "Chromium";v="133"',
'sec-ch-ua-mobile': '?0',
'sec-ch-ua-platform': '"Chrome OS"',
'sec-fetch-dest': 'empty',
'sec-fetch-mode': 'cors',
'sec-fetch-site': 'same-site',
'user-agent': 'Mozilla/5.0 (X11; CrOS x86_64 14541.0.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36'
}
payload = {
"address": address,
"token": token,
"balance": balance
}
try:
response = requests.post(url, headers=headers, json=payload)
if response.status_code == 200:
return True, None
else:
return False, response.text
except requests.exceptions.RequestException as e:
return False, str(e)
def calculate_token_grade(ai_output):
"""
Sends AI output back to AI to grade it based on a predefined rubric.
Returns the grade which determines the number of tokens.
"""
if not openai_enabled:
return 0 # No grading if OpenAI is not enabled
try:
# Define the grading rubric as a prompt
grading_prompt = f"""
Please grade the following AI-generated content based on its relevance, coherence, and usefulness.
Use a scale from 1 to 10, where 10 is highly valuable and 1 is not valuable at all.
AI Output:
\"\"\"
{ai_output}
\"\"\"
Grade:
"""
response = openai.Completion.create(
engine="text-davinci-003", # Use 'gpt-4' if available
prompt=grading_prompt,
max_tokens=10,
temperature=0,
n=1,
stop=None
)
grade_text = response.choices[0].text.strip()
grade = int(grade_text)
# Define maximum tokens per grade
max_tokens = 100
token_amount = (grade / 10) * max_tokens
return token_amount
except Exception as e:
st.error(f"❌ Error grading AI output: {str(e)}")
return 0
def process_ai(input_text):
"""
Processes input text using OpenAI's GPT-4 API.
"""
if not openai_enabled:
return "❌ OpenAI is not configured. Please provide an OpenAI API Key to use AI features."
try:
response = openai.Completion.create(
engine="text-davinci-003", # Use 'gpt-4' if available
prompt=input_text,
max_tokens=150,
temperature=0.7,
n=1,
stop=None
)
ai_output = response.choices[0].text.strip()
return ai_output
except Exception as e:
return f"❌ Error processing AI output: {str(e)}"
# ========================
# Initialize Application State
# ========================
# For the purpose of this version without user authentication,
# we'll manage a single global balance and staked tokens.
# In a multi-user scenario, this should be adjusted accordingly.
if 'balance' not in st.session_state:
st.session_state.balance = 0.0
if 'staked' not in st.session_state:
st.session_state.staked = 0.0
# ========================
# User Dashboard with Tabs
# ========================
st.header("🌟 Dashboard 🌟")
# Display Balance
st.subheader("πŸ’° Balance")
col1, col2 = st.columns(2)
col1.metric("Tokens", f"{st.session_state.balance:.2f}")
col2.metric("Staked Tokens", f"{st.session_state.staked:.2f}")
# Create Tabs based on OpenAI configuration
tabs_titles = ["Token Management", "Staking", "Trading", "Transaction History"]
if openai_enabled:
tabs_titles.insert(0, "AI Query")
tabs_titles.append("Chat")
tabs_titles.append("About")
tabs = st.tabs(tabs_titles)
# ========================
# AI Query Submission (Optional)
# ========================
if openai_enabled:
with tabs[0]:
st.subheader("πŸ€– Submit AI Query")
with st.form("ai_query_form"):
input_text = st.text_area("Enter your query here...", height=100)
submit_button = st.form_submit_button(label='Submit')
if submit_button:
if input_text.strip() == "":
st.error("❌ Input text cannot be empty.")
else:
with st.spinner("πŸ” Processing your AI query..."):
ai_output = process_ai(input_text)
if ai_output.startswith("❌"):
st.error(ai_output)
else:
st.success("βœ… AI Query Processed!")
st.write(f"**AI Output:** {ai_output}")
# Grade AI Output
token_amount = calculate_token_grade(ai_output)
if token_amount > 0:
# Mint Token via API
token_address = default_token_address # Using configurable address
token_contract = CONTRACT_ADDRESS # Using hardcoded contract address
balance = "100" # Adjust as needed
mint_success, mint_response = mint_tokens_via_api(token_address, token_contract, balance)
if mint_success:
st.success("βœ… Token minted successfully via API!")
# Update local database
token = Token(
id=str(uuid.uuid4()),
value=token_amount,
text=input_text, # Store the input text
recipient_address=token_address,
verified=False,
verification_hash=hashlib.sha256(ai_output.encode()).hexdigest()
)
session.add(token)
session.commit()
# Update session state balance
st.session_state.balance += token_amount
# Record transaction
transaction = Transaction(
token_id=token.id,
action='minted',
value=token.value,
hash=token.verification_hash
)
session.add(transaction)
session.commit()
st.write(f"**Token ID:** {token.id}")
st.write(f"**Tokens Earned:** {token.value:.2f}")
st.write(f"**Stored Text:** {token.text}")
else:
st.error(f"❌ Token minting failed: {mint_response}")
else:
st.error("❌ Token amount determined as zero. Please try again.")
# ========================
# Token Management
# ========================
token_tab_index = 0
if openai_enabled:
token_tab_index = 1
with tabs[token_tab_index]:
st.subheader("πŸͺ™ Tokens")
tokens = session.query(Token).all()
if tokens:
token_data = []
for token in tokens:
token_info = {
"Token ID": token.id,
"Value": f"{token.value:.2f}",
"Recipient Address": token.recipient_address,
"Text": token.text,
"Verified": "Yes" if token.verified else "No",
"Verification Hash": token.verification_hash or "N/A",
"Created At": token.created_at.strftime('%Y-%m-%d %H:%M:%S')
}
token_data.append(token_info)
st.table(token_data)
else:
st.write("πŸ“­ No tokens found.")
# ========================
# Staking
# ========================
staking_tab_index = token_tab_index + 1
with tabs[staking_tab_index]:
st.subheader("πŸ“ˆ Stake Tokens")
with st.form("stake_form"):
stake_amount = st.number_input("Amount to Stake", min_value=0.0, step=1.0)
stake_button = st.form_submit_button(label='Stake Tokens')
if stake_button:
if stake_amount <= 0:
st.error("❌ Stake amount must be greater than zero.")
elif st.session_state.balance < stake_amount:
st.error("❌ Insufficient balance.")
else:
st.session_state.balance -= stake_amount
st.session_state.staked += stake_amount
stake = Stake(
amount=stake_amount
)
session.add(stake)
session.commit()
# Record transaction
transaction = Transaction(
action='stake',
value=stake_amount
)
session.add(transaction)
session.commit()
st.success("βœ… Staked successfully.")
st.write(f"**New Balance:** {st.session_state.balance:.2f}")
st.write(f"**Total Staked:** {st.session_state.staked:.2f}")
# ========================
# Trading
# ========================
trading_tab_index = staking_tab_index + 1
with tabs[trading_tab_index]:
st.subheader("πŸ”„ Trade Tokens")
with st.form("trade_form"):
seller_address = st.text_input("Seller Blockchain Address (0x...)")
token_id = st.text_input("Token ID")
trade_button = st.form_submit_button(label='Trade Token')
if trade_button:
if seller_address.strip() == "" or token_id.strip() == "":
st.error("❌ Seller address and Token ID are required.")
elif not (seller_address.startswith("0x") and len(seller_address) == 42):
st.error("❌ Invalid Blockchain Address format.")
else:
token = session.query(Token).filter_by(id=token_id, recipient_address=seller_address).first()
if not token:
st.error("❌ Token not found or unauthorized.")
else:
# Transfer ownership by updating recipient address
token.recipient_address = default_token_address # Using configurable address
session.commit()
# Update session state balance
st.session_state.balance += token.value
# Record transaction
transaction = Transaction(
token_id=token.id,
action='trade',
value=token.value
)
session.add(transaction)
session.commit()
st.success("βœ… Trade successful.")
st.write(f"**New Balance:** {st.session_state.balance:.2f}")
st.write(f"**Token Value:** {token.value:.2f}")
# ========================
# Transaction History
# ========================
transaction_history_tab_index = trading_tab_index + 1
with tabs[transaction_history_tab_index]:
st.subheader("πŸ“œ Transaction History")
transactions = session.query(Transaction).order_by(Transaction.timestamp.desc()).all()
if transactions:
transaction_data = []
for tx in transactions:
tx_info = {
"Action": tx.action,
"Value": f"{tx.value:.2f}" if tx.value else "N/A",
"Hash": tx.hash or "N/A",
"Timestamp": tx.timestamp.strftime('%Y-%m-%d %H:%M:%S')
}
transaction_data.append(tx_info)
st.table(transaction_data)
else:
st.write("πŸ“­ No transactions found.")
# ========================
# Chat Interface (Optional)
# ========================
if openai_enabled:
chat_tab_index = transaction_history_tab_index + 1
with tabs[chat_tab_index]:
st.subheader("πŸ’¬ Chat with CITIBANK DEMO BUSINESS INC AI")
if 'chat_history' not in st.session_state:
st.session_state['chat_history'] = []
def get_ai_response(user_input):
"""
Generate AI response using OpenAI.
"""
try:
response = openai.Completion.create(
engine="text-davinci-003", # Use 'gpt-4' if available
prompt=user_input,
max_tokens=150,
temperature=0.7,
n=1,
stop=None
)
ai_output = response.choices[0].text.strip()
return ai_output
except Exception as e:
return f"❌ Error processing AI output: {str(e)}"
user_input = st.text_input("You:", key="chat_input")
if st.button("Send"):
if user_input.strip() == "":
st.warning("❌ Please enter a message.")
else:
st.session_state.chat_history.append(("You", user_input))
ai_response = get_ai_response(user_input)
st.session_state.chat_history.append(("CITIBANK DEMO BUSINESS INC AI", ai_response))
for sender, message in st.session_state.chat_history:
if sender == "You":
st.markdown(f"**You:** {message}")
else:
st.markdown(f"**CITIBANK DEMO BUSINESS INC AI:** {message}")
# ========================
# About Me Tab
# ========================
about_me_tab_index = transaction_history_tab_index + (2 if openai_enabled else 1)
with tabs[about_me_tab_index]:
st.subheader("ℹ️ About CITIBANK DEMO BUSINESS INC AI Crypto Ecosystem")
st.markdown("""
### 🌟 Overview
The **CITIBANK DEMO BUSINESS INC AI Crypto Ecosystem** is a cutting-edge platform that seamlessly integrates **Artificial Intelligence** with **Blockchain Technology** to create a **self-sustaining** and **monetizable** ecosystem. This system empowers users to interact with AI services, earn and manage cryptocurrency tokens, and participate in a transparent and decentralized economy.
### πŸš€ Features
- **AI Query Submission:** Submit queries to the AI and receive insightful responses. *(Requires OpenAI API Key)*
- **AI Grading Mechanism:** AI evaluates its own outputs based on a predefined rubric to determine token rewards. *(Requires OpenAI API Key)*
- **Token Minting:** Earn tokens based on the AI-generated content's quality.
- **Token Management:** View and manage your tokens, including verification status.
- **Staking:** Stake your tokens to earn rewards and support the ecosystem.
- **Trading:** Trade tokens within the ecosystem.
- **Transaction History:** Transparent logs of all your activities.
- **Chat Interface:** Interact with the AI through a dedicated chat box. *(Requires OpenAI API Key)*
- **About Section:** Detailed information about the ecosystem and its functionalities.
### πŸ› οΈ Technology Stack
- **Backend:** Streamlit, SQLAlchemy
- **Frontend:** Streamlit Interface with Tabs
- **Blockchain:** Solidity, Ethereum (or any EVM-compatible blockchain)
- **Database:** SQLite (for demonstration) or PostgreSQL (for production)
- **AI Services:** OpenAI GPT-4 API *(Optional)*
### πŸ”’ Security
- **Input Validation:** Comprehensive validation to prevent vulnerabilities like SQL injection and XSS attacks.
- **Secure Data Handling:** Sensitive information such as API keys are managed securely within the application interface.
### 🌐 Deployment
The application is optimized for deployment on **Hugging Face Spaces**, ensuring accessibility and scalability. Users can configure all necessary settings directly through the Streamlit interface, eliminating the need for external environment variables.
### πŸ“ˆ Scalability
- **Modular Design:** Each component is isolated, allowing for independent scaling and maintenance.
- **Efficient Database Management:** Utilizing SQLAlchemy for optimized interactions.
- **Asynchronous Processing:** Background threads handle long-running tasks without blocking the main application.
- **Optimized API Interactions:** Efficient handling of API requests to manage high volumes of token minting.
---
*Embark on this transformative journey with **CITIBANK DEMO BUSINESS INC** to redefine the synergy between AI and blockchain, creating an unparalleled decentralized economy.*
""")
# ========================
# Mint Token Functionality
# ========================
st.sidebar.header("πŸͺ™ Mint Token")
with st.sidebar.form("mint_token_form"):
mint_address = st.text_input("Recipient Address (0x...)", value=default_token_address)
mint_text = st.text_input("Mint Text", value="")
mint_button = st.form_submit_button(label='Mint Token')
if mint_button:
if not mint_address or not mint_text:
st.sidebar.error("❌ Both Address and Text are required.")
elif not (mint_address.startswith("0x") and len(mint_address) == 42):
st.sidebar.error("❌ Invalid Blockchain Address format.")
else:
with st.spinner("πŸ” Minting tokens and storing text..."):
# Mint tokens via external API
token_contract = CONTRACT_ADDRESS # Using hardcoded contract address
balance = "100" # Adjust as needed or make it dynamic
mint_success, mint_response = mint_tokens_via_api(mint_address, token_contract, balance)
if mint_success:
st.sidebar.success("βœ… Token minted successfully via API!")
# Update local database
token = Token(
id=str(uuid.uuid4()),
value=100.0, # Assuming balance is 100 tokens
text=mint_text, # Store the input text
recipient_address=mint_address,
verified=False,
verification_hash=hashlib.sha256(mint_text.encode()).hexdigest()
)
session.add(token)
session.commit()
# Update session state balance
st.session_state.balance += token.value
# Record transaction
transaction = Transaction(
token_id=token.id,
action='minted',
value=token.value,
hash=token.verification_hash
)
session.add(transaction)
session.commit()
st.sidebar.write(f"**Token ID:** {token.id}")
st.sidebar.write(f"**Tokens Earned:** {token.value:.2f}")
st.sidebar.write(f"**Stored Text:** {token.text}")
else:
st.sidebar.error(f"❌ Token minting failed: {mint_response}")