Spaces:
Build error
Build error
| import streamlit as st | |
| import requests | |
| import re | |
| from pypdf import PdfReader | |
| from transformers import T5Tokenizer, T5ForConditionalGeneration | |
| # Digi-Key API and credentials | |
| TOKEN_URL = "https://api.digikey.com/v1/oauth2/token" | |
| API_URL = "https://api.digikey.com/products/v4/search/keyword" | |
| CLIENT_ID = "K9d4a2AaGwQcoAvdNDZVYEOB3sqL4bMg" # Replace with your Digi-Key Client ID | |
| CLIENT_SECRET = "NxzuxY67eJssGDkA" # Replace with your Digi-Key Client Secret | |
| # Function to fetch access token | |
| def fetch_access_token() -> str: | |
| headers = { | |
| "Content-Type": "application/x-www-form-urlencoded", | |
| } | |
| data = { | |
| "client_id": CLIENT_ID, | |
| "client_secret": CLIENT_SECRET, | |
| "grant_type": "client_credentials", | |
| } | |
| response = requests.post(TOKEN_URL, headers=headers, data=data) | |
| if response.status_code == 200: | |
| token_data = response.json() | |
| return token_data["access_token"] | |
| else: | |
| st.error(f"Failed to retrieve access token: {response.status_code} - {response.text}") | |
| st.stop() | |
| # Function to make API requests to Digi-Key | |
| def search_digikey_components(keywords: str) -> dict: | |
| access_token = fetch_access_token() | |
| headers = { | |
| "Authorization": f"Bearer {access_token}", | |
| "Content-Type": "application/json", | |
| "X-DIGIKEY-Client-Id": CLIENT_ID, | |
| } | |
| payload = { | |
| "Keywords": keywords, | |
| "Limit": 50, | |
| "Offset": 0, | |
| "FilterOptionsRequest": { | |
| "MarketPlaceFilter": "NoFilter", | |
| }, | |
| "SortOptions": { | |
| "Field": "None", | |
| "SortOrder": "Ascending", | |
| }, | |
| } | |
| response = requests.post(API_URL, headers=headers, json=payload) | |
| if response.status_code == 200: | |
| return response.json() | |
| else: | |
| st.error(f"API request failed: {response.status_code} - {response.text}") | |
| return {} | |
| # Function to extract key specifications from a PDF datasheet | |
| def extract_specifications_from_pdf(pdf_url: str) -> str: | |
| try: | |
| response = requests.get(pdf_url) | |
| if response.status_code == 200: | |
| with open("datasheet.pdf", "wb") as file: | |
| file.write(response.content) | |
| # Extract text from the PDF | |
| reader = PdfReader("datasheet.pdf") | |
| text = "" | |
| for page in reader.pages: | |
| text += page.extract_text() | |
| # Use regex to find key specifications like voltage, resistance, power, etc. | |
| voltage = re.findall(r"(\d+\.?\d*)\s?(V|Volts)", text) # Voltage (e.g., "5V", "12 Volts") | |
| current = re.findall(r"(\d+\.?\d*)\s?(A|Amps)", text) # Current (e.g., "2A", "0.5 Amps") | |
| resistance = re.findall(r"(\d+\.?\d*)\s?(Ω|ohm)", text) # Resistance (e.g., "10Ω") | |
| power = re.findall(r"(\d+\.?\d*)\s?(W|Watts)", text) # Power (e.g., "5W", "100 Watts") | |
| # Format the specifications | |
| specs = "Specifications:\n" | |
| if voltage: | |
| specs += f"Voltage: {', '.join([f'{v} {unit}' for v, unit in voltage])}\n" | |
| if current: | |
| specs += f"Current: {', '.join([f'{c} {unit}' for c, unit in current])}\n" | |
| if resistance: | |
| specs += f"Resistance: {', '.join([f'{r} {unit}' for r, unit in resistance])}\n" | |
| if power: | |
| specs += f"Power: {', '.join([f'{p} {unit}' for p, unit in power])}\n" | |
| return specs if specs != "Specifications:\n" else "No key specifications found." | |
| else: | |
| return "Unable to fetch datasheet." | |
| except Exception as e: | |
| return f"Error extracting text: {str(e)}" | |
| # Load T5 model and tokenizer | |
| def load_t5_model(): | |
| tokenizer = T5Tokenizer.from_pretrained("t5-small") | |
| model = T5ForConditionalGeneration.from_pretrained("t5-small") | |
| return tokenizer, model | |
| # Generate advice for a component based on specifications | |
| def generate_advice(product: dict, tokenizer, model) -> str: | |
| # Fetch datasheet URL | |
| datasheet_url = product.get("DatasheetUrl") | |
| datasheet_text = "" | |
| if datasheet_url: | |
| datasheet_text = extract_specifications_from_pdf(datasheet_url) | |
| description = product.get("Description", {}).get("DetailedDescription", "No description available.") | |
| category = product.get("Category", {}).get("Name", "Unknown Category") | |
| manufacturer = product.get("Manufacturer", {}).get("Name", "Unknown Manufacturer") | |
| # Improved prompt: Focus only on specifications and product details | |
| prompt = f"Given the following specifications for the component: {datasheet_text}. Provide advice regarding its usage and key considerations based on its specifications. Description: {description}. Category: {category}. Manufacturer: {manufacturer}." | |
| inputs = tokenizer.encode(prompt, return_tensors="pt", max_length=512, truncation=True) | |
| outputs = model.generate(inputs, max_length=150, num_beams=4, temperature=1.5, top_k=50, early_stopping=True) | |
| advice = tokenizer.decode(outputs[0], skip_special_tokens=True) | |
| return advice | |
| # Streamlit app interface | |
| st.title("Component Selection Advisor") | |
| st.write( | |
| """ | |
| This app is an advanced tool for circuit designers, enabling efficient searches for electronic components | |
| using the Digi-Key API. It features AI-powered advice generated with a pretrained T5 model, providing | |
| insightful recommendations. Additionally, the app can extract key specifications from datasheets, ensuring | |
| users have all the critical details for their component selection process. Experience a seamless and | |
| intelligent way to streamline your circuit design workflows. | |
| """ | |
| ) | |
| # Input for the user | |
| keywords = st.text_input("Enter the name or keyword of the component:", "") | |
| if keywords: | |
| st.write(f"Searching for components matching: `{keywords}`...") | |
| data = search_digikey_components(keywords) | |
| if "Products" in data and data["Products"]: | |
| st.header("Search Results") | |
| tokenizer, model = load_t5_model() | |
| for product in data["Products"]: | |
| st.subheader(product["Description"]["ProductDescription"]) | |
| st.write(f"**Manufacturer**: {product['Manufacturer']['Name']}") | |
| st.write(f"**Product Number**: {product['ManufacturerProductNumber']}") | |
| st.write(f"**Unit Price**: ${product['UnitPrice']}") | |
| st.write(f"[Datasheet]({product['DatasheetUrl']})") | |
| st.write(f"[Product Link]({product['ProductUrl']})") | |
| # Check if PhotoUrl exists and is not None | |
| if product.get("PhotoUrl"): | |
| st.image(product["PhotoUrl"], width=200) | |
| else: | |
| st.write("_Image not available_") | |
| # Generate advice based on specifications extracted from the datasheet | |
| advice = generate_advice(product, tokenizer, model) | |
| st.write(f"**AI Advice:** {advice}") | |
| st.write("---") | |
| else: | |
| st.warning("No components found. Try using different keywords.") | |