diff --git a/DEMO_GUIDE.md b/DEMO_GUIDE.md deleted file mode 100644 index 5089fa8..0000000 --- a/DEMO_GUIDE.md +++ /dev/null @@ -1,110 +0,0 @@ -# DS Task AI News - Demo Guide - -## What's Been Accomplished Today (Day 1) - -### ✅ **Core Infrastructure Complete** -- **Project Structure**: Created complete directory structure with backend/, data/, docs/ -- **Configuration System**: Environment variables, settings management -- **Dependencies**: FastAPI, RSS parsing, basic ML libraries - -### ✅ **Working RSS News Fetcher** -- **Multi-source RSS parsing**: BBC News, CNN, Reuters support -- **Article processing**: Title, content, date, source extraction -- **Data storage**: JSON format with unique article IDs - -### ✅ **FastAPI Backend Running** -- **Server**: Running on http://localhost:8000 -- **Health Check**: GET / - API status -- **RSS Testing**: GET /test-rss - Live RSS feed testing - -### ✅ **Core Components Built** -1. **news_fetcher.py** - RSS feed aggregation -2. **embeddings.py** - AI embeddings (Cohere + Sentence Transformers) -3. **vector_store.py** - FAISS vector database -4. **recommender.py** - Recommendation engine -5. **main.py** - Complete FastAPI application - -## **Live Demo URLs** - -### Basic Endpoints (Working Now) -- **Health Check**: http://localhost:8000/ -- **RSS Test**: http://localhost:8000/test-rss -- **API Docs**: http://localhost:8000/docs (FastAPI auto-generated) - -### Full API Endpoints (Ready for Tomorrow) -- **Fetch News**: POST /fetch-news -- **Get Recommendations**: GET /recommend-news?article_id=xyz -- **Search by Query**: POST /recommend-by-query -- **Trending News**: GET /trending -- **All Articles**: GET /articles - -## **Technical Stack Implemented** - -### Backend -- **FastAPI**: Modern Python web framework -- **Uvicorn**: ASGI server -- **Pydantic**: Data validation - -### AI/ML -- **Sentence Transformers**: Local embeddings (384-dim) -- **FAISS**: Vector similarity search -- **Cohere**: Optional cloud embeddings (when API key provided) - -### Data Processing -- **Feedparser**: RSS feed parsing -- **Pandas**: Data manipulation -- **JSON**: Article storage format - -## **What Works Right Now** - -1. **RSS Feed Fetching**: Successfully fetching from BBC News (32 articles) -2. **FastAPI Server**: Responding to HTTP requests -3. **Basic Article Processing**: Title, content, date extraction -4. **Project Structure**: All files and directories in place - -## **Tomorrow's Plan (Day 2 - 4 hours)** - -### Priority 1: Complete Vector Database (1 hour) -- Install remaining ML dependencies -- Test embeddings generation -- Implement article similarity search - -### Priority 2: Full API Implementation (2 hours) -- Complete all API endpoints -- Add error handling and validation -- Test recommendation system - -### Priority 3: Enhancement & Polish (1 hour) -- Add Groq LLM integration (if API key available) -- Improve recommendation algorithms -- Create comprehensive documentation - -## **Demo Script for Video** - -### Show Working Components: -1. **Project Structure**: `ls -la` to show all files -2. **Server Running**: Browser at http://localhost:8000 -3. **RSS Testing**: http://localhost:8000/test-rss -4. **Code Walkthrough**: Show main.py, news_fetcher.py -5. **Configuration**: Show .env template and settings - -### Explain Architecture: -1. **RSS Feeds** → **News Fetcher** → **Vector Store** → **Recommendations** -2. **FastAPI** provides REST API endpoints -3. **FAISS** for fast similarity search -4. **Sentence Transformers** for embeddings - -## **Key Achievements** - -- **8 hours → Working MVP**: From empty project to functional news API -- **Scalable Architecture**: Modular design for easy extension -- **Production Ready**: Proper error handling, configuration management -- **AI-Powered**: Vector embeddings and similarity search implemented - -## **Next Steps After Demo** - -1. Add your API keys to .env file -2. Run full system test with embeddings -3. Deploy to cloud platform (optional) -4. Add more RSS sources -5. Implement user preferences and personalization diff --git a/backend/data/news_vectors_metadata.pkl b/backend/data/news_vectors_metadata.pkl new file mode 100644 index 0000000..99f6f87 Binary files /dev/null and b/backend/data/news_vectors_metadata.pkl differ diff --git a/backend/data/raw_news/news_20250707_203143.json b/backend/data/raw_news/news_20250707_203143.json new file mode 100644 index 0000000..3bdd37b --- /dev/null +++ b/backend/data/raw_news/news_20250707_203143.json @@ -0,0 +1,3587 @@ +[ + { + "id": "601d26413426", + "title": "Bluesky users can customize their notifications, including activity alerts from their favorite accounts", + "content": "Bluesky updated its notifications to allowing users to personalize their experience, including the option to be notified only when accounts reply to them.", + "url": "https://techcrunch.com/2025/07/07/bluesky-users-can-customize-their-notifications-including-activity-alerts-from-their-favorite-accounts/", + "source": "TechCrunch", + "published_date": "2025-07-07T19:18:47", + "fetched_date": "2025-07-07T20:31:42.834724", + "categories": [ + { + "term": "Apps", + "scheme": null, + "label": null + }, + { + "term": "Social", + "scheme": null, + "label": null + }, + { + "term": "Bluesky", + "scheme": null, + "label": null + }, + { + "term": "decentralized social media", + "scheme": null, + "label": null + } + ], + "slug": "bluesky-users-can-customize-their-notifications,-i" + }, + { + "id": "471f4da29465", + "title": "iOS 26 beta 3 dials back Liquid Glass", + "content": "The early version in the first developer beta of iOS 26 and the accompanying updates for Apple's other devices still left room for improvement in terms of usability, accessibility, and legibility.", + "url": "https://techcrunch.com/2025/07/07/ios-26-beta-3-dials-back-liquid-glass/", + "source": "TechCrunch", + "published_date": "2025-07-07T19:12:54", + "fetched_date": "2025-07-07T20:31:42.834724", + "categories": [ + { + "term": "Apps", + "scheme": null, + "label": null + }, + { + "term": "Apple", + "scheme": null, + "label": null + }, + { + "term": "design", + "scheme": null, + "label": null + }, + { + "term": "ios 26", + "scheme": null, + "label": null + } + ], + "slug": "ios-26-beta-3-dials-back-liquid-glass" + }, + { + "id": "8fe78b6e6676", + "title": "Jack Dorsey working on Bluetooth messaging app, Bitchat", + "content": "Block CEO and Twitter co-founder Jack Dorsey wrote in an X post on Sunday night that he spent his weekend creating an app called Bitchat (presumably a combination of the words “bit” and “chat,” and not the other combination of words that it looks like). Bitchat is a messaging app that operates through Bluetooth mesh […]", + "url": "https://techcrunch.com/2025/07/07/jack-dorsey-working-on-bluetooth-messaging-app-bitchat/", + "source": "TechCrunch", + "published_date": "2025-07-07T18:26:26", + "fetched_date": "2025-07-07T20:31:42.834724", + "categories": [ + { + "term": "Apps", + "scheme": null, + "label": null + }, + { + "term": "TC", + "scheme": null, + "label": null + }, + { + "term": "social", + "scheme": null, + "label": null + } + ], + "slug": "jack-dorsey-working-on-bluetooth-messaging-app,-bi" + }, + { + "id": "a72bf7369dbe", + "title": "Tennis players criticize AI technology used by Wimbledon", + "content": "Some tennis players are not happy with Wimbledon’s new AI line judges, as reported by The Telegraph.  This is the first year the prestigious tennis tournament, which is still ongoing, replaced human line judges, who determine if a ball is in or out, with an electronic line calling system (ELC). Numerous players criticized the AI […]", + "url": "https://techcrunch.com/2025/07/07/tennis-players-criticize-ai-technology-used-by-wimbledon/", + "source": "TechCrunch", + "published_date": "2025-07-07T18:00:00", + "fetched_date": "2025-07-07T20:31:42.834724", + "categories": [ + { + "term": "Media & Entertainment", + "scheme": null, + "label": null + }, + { + "term": "AI", + "scheme": null, + "label": null + }, + { + "term": "tennis", + "scheme": null, + "label": null + } + ], + "slug": "tennis-players-criticize-ai-technology-used-by-wim" + }, + { + "id": "42ae065cddcc", + "title": "CoreWeave acquires data center provider Core Scientific in $9B stock deal", + "content": "As a result of the deal, CoreWeave says it will gain access to more than a gigawatt of data center capacity — enough energy to power more than 850,000 homes.", + "url": "https://techcrunch.com/2025/07/07/coreweave-acquires-data-center-provider-core-scientific-in-9b-stock-deal/", + "source": "TechCrunch", + "published_date": "2025-07-07T17:37:09", + "fetched_date": "2025-07-07T20:31:42.834724", + "categories": [ + { + "term": "AI", + "scheme": null, + "label": null + }, + { + "term": "CoreWeave", + "scheme": null, + "label": null + }, + { + "term": "In Brief", + "scheme": null, + "label": null + } + ], + "slug": "coreweave-acquires-data-center-provider-core-scien" + }, + { + "id": "91c90a6f5eb4", + "title": "Waymo starts robotaxi testing in Philadelphia and NYC", + "content": "Waymo kicked off two “road trips” to Philadelphia and New York City on Monday, signaling the Alphabet-owned company’s push to expand into cities in the Northeast.", + "url": "https://techcrunch.com/2025/07/07/waymo-starts-robotaxi-testing-in-philadelphia-and-nyc/", + "source": "TechCrunch", + "published_date": "2025-07-07T17:14:34", + "fetched_date": "2025-07-07T20:31:42.834724", + "categories": [ + { + "term": "Transportation", + "scheme": null, + "label": null + }, + { + "term": "autonomous vehicles", + "scheme": null, + "label": null + }, + { + "term": "avs", + "scheme": null, + "label": null + }, + { + "term": "robotaxi", + "scheme": null, + "label": null + }, + { + "term": "Waymo", + "scheme": null, + "label": null + } + ], + "slug": "waymo-starts-robotaxi-testing-in-philadelphia-and-" + }, + { + "id": "851c071ba96c", + "title": "Threads is nearing X’s daily app users, new data shows", + "content": "Threads' mobile app for iOS and Android saw 115.1 million daily active users, representing 127.8% year-over-year growth.", + "url": "https://techcrunch.com/2025/07/07/threads-is-nearing-xs-daily-app-users-new-data-shows/", + "source": "TechCrunch", + "published_date": "2025-07-07T15:41:32", + "fetched_date": "2025-07-07T20:31:42.834724", + "categories": [ + { + "term": "Apps", + "scheme": null, + "label": null + }, + { + "term": "Social", + "scheme": null, + "label": null + }, + { + "term": "Bluesky", + "scheme": null, + "label": null + }, + { + "term": "Meta", + "scheme": null, + "label": null + }, + { + "term": "social media", + "scheme": null, + "label": null + }, + { + "term": "Threads", + "scheme": null, + "label": null + }, + { + "term": "X", + "scheme": null, + "label": null + } + ], + "slug": "threads-is-nearing-x’s-daily-app-users,-new-data-s" + }, + { + "id": "c6a60242b0ab", + "title": "AI is forcing the data industry to consolidate — but that’s not the whole story", + "content": "While AI may be the catalyst behind the recent wave of data company M&A, the market was ripe for consolidation.", + "url": "https://techcrunch.com/2025/07/07/ai-is-forcing-the-data-industry-to-consolidate-but-thats-not-the-whole-story/", + "source": "TechCrunch", + "published_date": "2025-07-07T15:00:00", + "fetched_date": "2025-07-07T20:31:42.835625", + "categories": [ + { + "term": "AI", + "scheme": null, + "label": null + }, + { + "term": "Enterprise", + "scheme": null, + "label": null + }, + { + "term": "Startups", + "scheme": null, + "label": null + }, + { + "term": "AI agents", + "scheme": null, + "label": null + }, + { + "term": "data management", + "scheme": null, + "label": null + }, + { + "term": "M&A", + "scheme": null, + "label": null + }, + { + "term": "startup acquisition", + "scheme": null, + "label": null + } + ], + "slug": "ai-is-forcing-the-data-industry-to-consolidate-—-b" + }, + { + "id": "4a6d39b435f4", + "title": "TikTok reportedly developing new version of app ahead of planned US sale", + "content": "TikTok is developing a new version of its app for U.S. users ahead of an expected sale of the app to a group of investors, according to a new report from The Information.", + "url": "https://techcrunch.com/2025/07/07/tiktok-reportedly-developing-new-version-of-app-ahead-of-planned-us-sale/", + "source": "TechCrunch", + "published_date": "2025-07-07T14:20:12", + "fetched_date": "2025-07-07T20:31:42.835625", + "categories": [ + { + "term": "Apps", + "scheme": null, + "label": null + }, + { + "term": "Government & Policy", + "scheme": null, + "label": null + }, + { + "term": "In Brief", + "scheme": null, + "label": null + }, + { + "term": "TikTok", + "scheme": null, + "label": null + }, + { + "term": "TikTok Ban", + "scheme": null, + "label": null + }, + { + "term": "tiktok sale", + "scheme": null, + "label": null + } + ], + "slug": "tiktok-reportedly-developing-new-version-of-app-ah" + }, + { + "id": "726b07a8103a", + "title": "Ingram Micro says ongoing outage caused by ransomware attack", + "content": "The outage is reportedly affecting software licensing, preventing Ingram Micro's customers from using or provisioning some products that rely on Ingram's systems.", + "url": "https://techcrunch.com/2025/07/07/ingram-micro-says-ongoing-outage-caused-by-ransomware-attack/", + "source": "TechCrunch", + "published_date": "2025-07-07T12:57:03", + "fetched_date": "2025-07-07T20:31:42.835625", + "categories": [ + { + "term": "Enterprise", + "scheme": null, + "label": null + }, + { + "term": "Security", + "scheme": null, + "label": null + }, + { + "term": "cybersecurity", + "scheme": null, + "label": null + }, + { + "term": "data breaches", + "scheme": null, + "label": null + }, + { + "term": "ingram micro", + "scheme": null, + "label": null + }, + { + "term": "cyberattack", + "scheme": null, + "label": null + } + ], + "slug": "ingram-micro-says-ongoing-outage-caused-by-ransomw" + }, + { + "id": "bb6842fdd4d5", + "title": "Apple appeals EU’s €500M fine over App Store payment restraints", + "content": "The European Commission says that Apple failed to comply with the Digital Markets Act rules to allow developers to accept payments for their apps outside Apple's ecosystem.", + "url": "https://techcrunch.com/2025/07/07/apple-appeals-eus-e500m-fine-over-app-store-payment-restraints/", + "source": "TechCrunch", + "published_date": "2025-07-07T12:47:57", + "fetched_date": "2025-07-07T20:31:42.835625", + "categories": [ + { + "term": "Apps", + "scheme": null, + "label": null + }, + { + "term": "Government & Policy", + "scheme": null, + "label": null + }, + { + "term": "Apple", + "scheme": null, + "label": null + }, + { + "term": "Apple App Store fee", + "scheme": null, + "label": null + }, + { + "term": "Digital Markets Act", + "scheme": null, + "label": null + }, + { + "term": "european commission", + "scheme": null, + "label": null + }, + { + "term": "In Brief", + "scheme": null, + "label": null + } + ], + "slug": "apple-appeals-eu’s-€500m-fine-over-app-store-payme" + }, + { + "id": "47bc5192a65e", + "title": "‘Improved’ Grok criticizes Democrats and Hollywood’s ‘Jewish executives’", + "content": "On Friday morning, Elon Musk declared, “We have improved @Grok significantly. You should notice a difference when you ask Grok questions.”", + "url": "https://techcrunch.com/2025/07/06/improved-grok-criticizes-democrats-and-hollywoods-jewish-executives/", + "source": "TechCrunch", + "published_date": "2025-07-06T20:58:44", + "fetched_date": "2025-07-07T20:31:42.835625", + "categories": [ + { + "term": "AI", + "scheme": null, + "label": null + }, + { + "term": "Social", + "scheme": null, + "label": null + }, + { + "term": "Grok", + "scheme": null, + "label": null + }, + { + "term": "X", + "scheme": null, + "label": null + }, + { + "term": "xAI", + "scheme": null, + "label": null + } + ], + "slug": "‘improved’-grok-criticizes-democrats-and-hollywood" + }, + { + "id": "c29acd516ee2", + "title": "At least 36 new tech unicorns were minted in 2025 so far", + "content": "With AI igniting an investor frenzy, every month, more startups obtain unicorn status. Using data from Crunchbase and PitchBook, TechCrunch tracked down the VC-backed startups that became unicorns so far this year. While most are AI-related, a surprising number are focused in other industries like satellite space companies Loft Orbital and blockchain-based trading site Kalshi.   […]", + "url": "https://techcrunch.com/2025/07/06/at-least-36-new-tech-unicorns-were-minted-in-2025-so-far/", + "source": "TechCrunch", + "published_date": "2025-07-06T17:47:34", + "fetched_date": "2025-07-07T20:31:42.835625", + "categories": [ + { + "term": "Startups", + "scheme": null, + "label": null + }, + { + "term": "evergreens", + "scheme": null, + "label": null + }, + { + "term": "fundraising", + "scheme": null, + "label": null + }, + { + "term": "unicorns", + "scheme": null, + "label": null + } + ], + "slug": "at-least-36-new-tech-unicorns-were-minted-in-2025-" + }, + { + "id": "06874f23a4fa", + "title": "X blocked Reuters accounts in India", + "content": "The main Reuters news account, as well as the Reuters World account, have apparently been inaccessible to X users in India since Saturday evening.", + "url": "https://techcrunch.com/2025/07/06/x-blocks-reuters-accounts-in-india/", + "source": "TechCrunch", + "published_date": "2025-07-06T17:34:56", + "fetched_date": "2025-07-07T20:31:42.835625", + "categories": [ + { + "term": "Government & Policy", + "scheme": null, + "label": null + }, + { + "term": "Media & Entertainment", + "scheme": null, + "label": null + }, + { + "term": "Social", + "scheme": null, + "label": null + }, + { + "term": "Reuters", + "scheme": null, + "label": null + }, + { + "term": "X", + "scheme": null, + "label": null + } + ], + "slug": "x-blocked-reuters-accounts-in-india" + }, + { + "id": "cc7b77c452a7", + "title": "Researchers seek to influence peer review with hidden AI prompts", + "content": "Academics may be leaning on a novel strategy to influence peer review of their research papers — adding hidden prompts designed to coax AI tools to deliver positive feedback.", + "url": "https://techcrunch.com/2025/07/06/researchers-seek-to-influence-peer-review-with-hidden-ai-prompts/", + "source": "TechCrunch", + "published_date": "2025-07-06T16:03:55", + "fetched_date": "2025-07-07T20:31:42.835625", + "categories": [ + { + "term": "AI", + "scheme": null, + "label": null + } + ], + "slug": "researchers-seek-to-influence-peer-review-with-hid" + }, + { + "id": "90732d40da59", + "title": "How Brex is keeping up with AI by embracing the ‘messiness’", + "content": "Brex quickly realized its normal software procurement process wouldn't work in the age of AI and found a new way to test and vet tools.", + "url": "https://techcrunch.com/2025/07/06/how-brex-is-keeping-up-with-ai-by-embracing-the-messiness/", + "source": "TechCrunch", + "published_date": "2025-07-06T15:00:00", + "fetched_date": "2025-07-07T20:31:42.835625", + "categories": [ + { + "term": "AI", + "scheme": null, + "label": null + }, + { + "term": "Enterprise", + "scheme": null, + "label": null + }, + { + "term": "Startups", + "scheme": null, + "label": null + }, + { + "term": "AI adoption", + "scheme": null, + "label": null + }, + { + "term": "artificial intelligence", + "scheme": null, + "label": null + }, + { + "term": "Brex", + "scheme": null, + "label": null + } + ], + "slug": "how-brex-is-keeping-up-with-ai-by-embracing-the-‘m" + }, + { + "id": "76b583132d85", + "title": "Drive Capital’s second act –  how the Columbus venture firm found success after a split", + "content": "The venture capital world has always had a hot-and-cold relationship with the Midwest. Investors rush in during boom times, then retreat to the coasts when markets turn sour. For Columbus, Ohio-based Drive Capital, this cycle of attention and disinterest played out against the backdrop of its own internal upheaval several years ago -- a co-founder split that could have ended the firm but may have ultimately strengthened it.", + "url": "https://techcrunch.com/2025/07/05/drive-capitals-second-act-how-the-columbus-venture-firm-found-success-after-a-split/", + "source": "TechCrunch", + "published_date": "2025-07-05T20:25:59", + "fetched_date": "2025-07-07T20:31:42.835625", + "categories": [ + { + "term": "TC", + "scheme": null, + "label": null + }, + { + "term": "Venture", + "scheme": null, + "label": null + }, + { + "term": "Chris Olsen", + "scheme": null, + "label": null + }, + { + "term": "Drive Capital", + "scheme": null, + "label": null + } + ], + "slug": "drive-capital’s-second-act-– -how-the-columbus-ven" + }, + { + "id": "c723fa16f609", + "title": "Ask not for whom the Louvre of Bluesky tolls, it tolls for thee", + "content": "It’s a sad weekend over at Bluesky, where one of the best accounts has disappeared — though we can still hope for its resurrection.", + "url": "https://techcrunch.com/2025/07/05/ask-not-for-whom-the-louvre-of-bluesky-tolls-it-tolls-for-thee/", + "source": "TechCrunch", + "published_date": "2025-07-05T20:11:39", + "fetched_date": "2025-07-07T20:31:42.835625", + "categories": [ + { + "term": "Social", + "scheme": null, + "label": null + }, + { + "term": "Bluesky", + "scheme": null, + "label": null + } + ], + "slug": "ask-not-for-whom-the-louvre-of-bluesky-tolls,-it-t" + }, + { + "id": "536a9266d4e1", + "title": "Google faces EU antitrust complaint over AI Overviews", + "content": "A group known as the Independent Publishers Alliance has filed an antitrust complaint with the European Commission over Google’s AI Overviews, according to Reuters. The complaint accuses Google of “misusing web content for Google’s AI Overviews in Google Search, which have caused, and continue to cause, significant harm to publishers, including news publishers in the […]", + "url": "https://techcrunch.com/2025/07/05/google-faces-eu-antitrust-complaint-over-ai-overviews/", + "source": "TechCrunch", + "published_date": "2025-07-05T17:36:54", + "fetched_date": "2025-07-07T20:31:42.835625", + "categories": [ + { + "term": "Media & Entertainment", + "scheme": null, + "label": null + }, + { + "term": "AI", + "scheme": null, + "label": null + }, + { + "term": "Government & Policy", + "scheme": null, + "label": null + } + ], + "slug": "google-faces-eu-antitrust-complaint-over-ai-overvi" + }, + { + "id": "a608fe2663c7", + "title": "Ready-made stem cell therapies for pets could be coming", + "content": "Earlier this week, San Diego startup Gallant announced $18 million in funding to bring the first FDA-approved ready-to-use stem cell therapy to veterinary medicine. If it passes regulatory muster, it could create a whole new way to treat our fur babies. It’s still an experimental field, even though people have been researching stem cells for […]", + "url": "https://techcrunch.com/2025/07/04/ready-made-stem-cell-therapies-for-pets-could-be-coming/", + "source": "TechCrunch", + "published_date": "2025-07-04T23:36:00", + "fetched_date": "2025-07-07T20:31:42.835625", + "categories": [ + { + "term": "TC", + "scheme": null, + "label": null + }, + { + "term": "Startups", + "scheme": null, + "label": null + }, + { + "term": "Biotech & Health", + "scheme": null, + "label": null + }, + { + "term": "Venture", + "scheme": null, + "label": null + }, + { + "term": "Digitalis Ventures", + "scheme": null, + "label": null + }, + { + "term": "Gallant", + "scheme": null, + "label": null + }, + { + "term": "stem-cell therapy", + "scheme": null, + "label": null + } + ], + "slug": "ready-made-stem-cell-therapies-for-pets-could-be-c" + }, + { + "id": "3b199579b240", + "title": "The 8 Best Travel Pillows (2025), Tested on Planes", + "content": "It can be hard to catch a nap while traveling, but these pillows can help.", + "url": "https://www.wired.com/gallery/best-travel-pillows/", + "source": "WIRED", + "published_date": "2025-07-07T18:32:41", + "fetched_date": "2025-07-07T20:31:43.529844", + "categories": [ + { + "term": "Gear", + "scheme": null, + "label": null + }, + { + "term": "Gear / Buying Guides", + "scheme": null, + "label": null + }, + { + "term": "Shopping", + "scheme": null, + "label": null + }, + { + "term": "buying guides", + "scheme": null, + "label": null + }, + { + "term": "Travel", + "scheme": null, + "label": null + }, + { + "term": "Buying Guide", + "scheme": null, + "label": null + } + ], + "slug": "the-8-best-travel-pillows-(2025),-tested-on-planes" + }, + { + "id": "f4cc7137023e", + "title": "Best Window Air Conditioners 2025: 10 Picks to Cool You for Years", + "content": "These WIRED-tested AC units have been lodged into our windows and cooling our homes for months, if not years.", + "url": "https://www.wired.com/gallery/best-window-air-conditioners/", + "source": "WIRED", + "published_date": "2025-07-07T17:47:35", + "fetched_date": "2025-07-07T20:31:43.529844", + "categories": [ + { + "term": "Gear", + "scheme": null, + "label": null + }, + { + "term": "Gear / Buying Guides", + "scheme": null, + "label": null + }, + { + "term": "Gear / Products / Home", + "scheme": null, + "label": null + }, + { + "term": "Shopping", + "scheme": null, + "label": null + }, + { + "term": "buying guides", + "scheme": null, + "label": null + }, + { + "term": "cooling", + "scheme": null, + "label": null + }, + { + "term": "home", + "scheme": null, + "label": null + }, + { + "term": "Appliance", + "scheme": null, + "label": null + }, + { + "term": "household", + "scheme": null, + "label": null + }, + { + "term": "air improvement", + "scheme": null, + "label": null + }, + { + "term": "Stay Frosty", + "scheme": null, + "label": null + } + ], + "slug": "best-window-air-conditioners-2025:-10-picks-to-coo" + }, + { + "id": "a69aab0f09fb", + "title": "15 Best Air Purifiers (2025): Coway, AirDoctor, IQAir", + "content": "Protect your home against dust, pets, allergies, and more with air purifiers tested firsthand by WIRED.", + "url": "https://www.wired.com/gallery/best-air-purifiers/", + "source": "WIRED", + "published_date": "2025-07-07T17:40:29", + "fetched_date": "2025-07-07T20:31:43.529844", + "categories": [ + { + "term": "Gear", + "scheme": null, + "label": null + }, + { + "term": "Gear / Buying Guides", + "scheme": null, + "label": null + }, + { + "term": "Gear / Products / Smart Home", + "scheme": null, + "label": null + }, + { + "term": "Gear / Products / Health and Fitness", + "scheme": null, + "label": null + }, + { + "term": "Gear / Products / Home", + "scheme": null, + "label": null + }, + { + "term": "Shopping", + "scheme": null, + "label": null + }, + { + "term": "buying guides", + "scheme": null, + "label": null + }, + { + "term": "air purifier", + "scheme": null, + "label": null + }, + { + "term": "health", + "scheme": null, + "label": null + }, + { + "term": "Smart Home", + "scheme": null, + "label": null + }, + { + "term": "air quality", + "scheme": null, + "label": null + }, + { + "term": "air improvement", + "scheme": null, + "label": null + }, + { + "term": "Clean Air", + "scheme": null, + "label": null + } + ], + "slug": "15-best-air-purifiers-(2025):-coway,-airdoctor,-iq" + }, + { + "id": "fc9e5892962d", + "title": "Why Jolly Ranchers Are Banned in the UK but Not the US", + "content": "Crude-oil-derived substances in the candy have been linked to health problems—and the regulations that have allowed their use in the US are now in Robert F. Kennedy Jr.’s crosshairs.", + "url": "https://www.wired.com/story/why-jolly-ranchers-are-banned-in-the-uk-but-not-the-us-moah-mosh-gras/", + "source": "WIRED", + "published_date": "2025-07-07T15:54:51", + "fetched_date": "2025-07-07T20:31:43.529844", + "categories": [ + { + "term": "Science", + "scheme": null, + "label": null + }, + { + "term": "Science / Health", + "scheme": null, + "label": null + }, + { + "term": "science", + "scheme": null, + "label": null + }, + { + "term": "food", + "scheme": null, + "label": null + }, + { + "term": "health", + "scheme": null, + "label": null + }, + { + "term": "FDA", + "scheme": null, + "label": null + }, + { + "term": "UK", + "scheme": null, + "label": null + }, + { + "term": "Candy", + "scheme": null, + "label": null + }, + { + "term": "Robert F. Kennedy Jr.", + "scheme": null, + "label": null + }, + { + "term": "Safety", + "scheme": null, + "label": null + }, + { + "term": "Hard to Swallow", + "scheme": null, + "label": null + } + ], + "slug": "why-jolly-ranchers-are-banned-in-the-uk-but-not-th" + }, + { + "id": "7224989c69ee", + "title": "13 Best Wi-Fi Routers of 2025, Tested and Reviewed", + "content": "Don’t suffer the buffer. These WIRED-tested systems will deliver reliable internet across your home, whatever your needs or budget.", + "url": "https://www.wired.com/gallery/best-wifi-routers/", + "source": "WIRED", + "published_date": "2025-07-07T12:04:00", + "fetched_date": "2025-07-07T20:31:43.529844", + "categories": [ + { + "term": "Gear", + "scheme": null, + "label": null + }, + { + "term": "Gear / Buying Guides", + "scheme": null, + "label": null + }, + { + "term": "Gear / Products / Computers", + "scheme": null, + "label": null + }, + { + "term": "Gear / Products / Smart Home", + "scheme": null, + "label": null + }, + { + "term": "Wi-Fi", + "scheme": null, + "label": null + }, + { + "term": "Shopping", + "scheme": null, + "label": null + }, + { + "term": "buying guides", + "scheme": null, + "label": null + }, + { + "term": "routers", + "scheme": null, + "label": null + }, + { + "term": "smart home", + "scheme": null, + "label": null + }, + { + "term": "Buying Guide", + "scheme": null, + "label": null + } + ], + "slug": "13-best-wi-fi-routers-of-2025,-tested-and-reviewed" + }, + { + "id": "aaa7bcb89031", + "title": "People Are Using AI Chatbots to Guide Their Psychedelic Trips", + "content": "As psychedelic companies and therapy apps experiment with AI, people are already taking huge doses of drugs and using chatbots to process their trips.", + "url": "https://www.wired.com/story/people-are-using-ai-chatbots-to-guide-their-psychedelic-trips/", + "source": "WIRED", + "published_date": "2025-07-07T11:00:00", + "fetched_date": "2025-07-07T20:31:43.529844", + "categories": [ + { + "term": "Culture", + "scheme": null, + "label": null + }, + { + "term": "Culture / Digital Culture", + "scheme": null, + "label": null + }, + { + "term": "psychology", + "scheme": null, + "label": null + }, + { + "term": "artificial intelligence", + "scheme": null, + "label": null + }, + { + "term": "mental health", + "scheme": null, + "label": null + }, + { + "term": "psychedelic", + "scheme": null, + "label": null + }, + { + "term": "Trip Sitter", + "scheme": null, + "label": null + } + ], + "slug": "people-are-using-ai-chatbots-to-guide-their-psyche" + }, + { + "id": "c38522eb366f", + "title": "On Mexico’s Caribbean Coast, There’s Lobster for the Tourists and Microplastics for Everyone Else", + "content": "The fishermen of Puerto Morelos complain of pirates who fish off-season with total impunity, while their small catches are contaminated by the abundant microplastics in the sea.", + "url": "https://www.wired.com/story/on-mexicos-caribbean-coast-theres-lobster-for-the-tourists-and-microplastics-for-everyone-else/", + "source": "WIRED", + "published_date": "2025-07-07T10:42:39", + "fetched_date": "2025-07-07T20:31:43.529844", + "categories": [ + { + "term": "Science", + "scheme": null, + "label": null + }, + { + "term": "Science / Environment", + "scheme": null, + "label": null + }, + { + "term": "marine science", + "scheme": null, + "label": null + }, + { + "term": "oceans", + "scheme": null, + "label": null + }, + { + "term": "plastic", + "scheme": null, + "label": null + }, + { + "term": "science", + "scheme": null, + "label": null + }, + { + "term": "environment", + "scheme": null, + "label": null + }, + { + "term": "Mexico", + "scheme": null, + "label": null + }, + { + "term": "Pollution", + "scheme": null, + "label": null + } + ], + "slug": "on-mexico’s-caribbean-coast,-there’s-lobster-for-t" + }, + { + "id": "3bd990549b75", + "title": "Thanks to Zillow, Your Friends Know How Much Your House Costs—or if You’re Secretly Rich", + "content": "A quick search of your friends’ addresses can yield one of the most private details of their financial lives. Some people say their wealthy acquaintances aren’t happy about it.", + "url": "https://www.wired.com/story/people-are-using-zillow-to-search-their-friends-homes-prices-and-find-out-whos-secretly-rich/", + "source": "WIRED", + "published_date": "2025-07-07T10:00:00", + "fetched_date": "2025-07-07T20:31:43.529844", + "categories": [ + { + "term": "Culture", + "scheme": null, + "label": null + }, + { + "term": "Culture / Digital Culture", + "scheme": null, + "label": null + }, + { + "term": "Finance", + "scheme": null, + "label": null + }, + { + "term": "Apps", + "scheme": null, + "label": null + }, + { + "term": "housing", + "scheme": null, + "label": null + }, + { + "term": "data", + "scheme": null, + "label": null + }, + { + "term": "House Rich", + "scheme": null, + "label": null + } + ], + "slug": "thanks-to-zillow,-your-friends-know-how-much-your-" + }, + { + "id": "9f8714cdadb8", + "title": "Best Indoor TV Antenna (2025): Mohu, Clearstream, One for All", + "content": "Plug into free HD TV with these convenient and affordable indoor antennas.", + "url": "https://www.wired.com/gallery/best-tv-antennas/", + "source": "WIRED", + "published_date": "2025-07-06T13:03:00", + "fetched_date": "2025-07-07T20:31:43.529844", + "categories": [ + { + "term": "Gear", + "scheme": null, + "label": null + }, + { + "term": "Gear / Products", + "scheme": null, + "label": null + }, + { + "term": "Gear / Buying Guides", + "scheme": null, + "label": null + }, + { + "term": "Gear / Products / Televisions", + "scheme": null, + "label": null + }, + { + "term": "Shopping", + "scheme": null, + "label": null + }, + { + "term": "home entertainment", + "scheme": null, + "label": null + }, + { + "term": "TVs", + "scheme": null, + "label": null + }, + { + "term": "buying guides", + "scheme": null, + "label": null + }, + { + "term": "smart home", + "scheme": null, + "label": null + }, + { + "term": "Buying Guide", + "scheme": null, + "label": null + } + ], + "slug": "best-indoor-tv-antenna-(2025):-mohu,-clearstream,-" + }, + { + "id": "6b5cdded8dd8", + "title": "12 Best Kids Headphones (2025), Hearing Protection and More", + "content": "If you use screens for work and play, your child probably does too. These are the best pairs we’ve bought and tested for our own kids.", + "url": "https://www.wired.com/gallery/the-best-kids-headphones/", + "source": "WIRED", + "published_date": "2025-07-06T12:02:00", + "fetched_date": "2025-07-07T20:31:43.529844", + "categories": [ + { + "term": "Gear", + "scheme": null, + "label": null + }, + { + "term": "Gear / Buying Guides", + "scheme": null, + "label": null + }, + { + "term": "Gear / Products", + "scheme": null, + "label": null + }, + { + "term": "Gear / Products / Headphones", + "scheme": null, + "label": null + }, + { + "term": "Shopping", + "scheme": null, + "label": null + }, + { + "term": "buying guides", + "scheme": null, + "label": null + }, + { + "term": "Headphones", + "scheme": null, + "label": null + }, + { + "term": "parenting", + "scheme": null, + "label": null + }, + { + "term": "kids", + "scheme": null, + "label": null + }, + { + "term": "Buying Guide", + "scheme": null, + "label": null + } + ], + "slug": "12-best-kids-headphones-(2025),-hearing-protection" + }, + { + "id": "bbb3a7ded250", + "title": "How to Use Voice Typing on Your Phone", + "content": "When it’s easier to talk than type, Android and iOS have you covered.", + "url": "https://www.wired.com/story/how-to-use-voice-typing-on-your-phone/", + "source": "WIRED", + "published_date": "2025-07-06T10:00:00", + "fetched_date": "2025-07-07T20:31:43.529844", + "categories": [ + { + "term": "Gear", + "scheme": null, + "label": null + }, + { + "term": "Gear / How To and Advice", + "scheme": null, + "label": null + }, + { + "term": "how-to", + "scheme": null, + "label": null + }, + { + "term": "tips", + "scheme": null, + "label": null + }, + { + "term": "Android", + "scheme": null, + "label": null + }, + { + "term": "ios", + "scheme": null, + "label": null + }, + { + "term": "phones", + "scheme": null, + "label": null + }, + { + "term": "smartphones", + "scheme": null, + "label": null + }, + { + "term": "Speak Up", + "scheme": null, + "label": null + } + ], + "slug": "how-to-use-voice-typing-on-your-phone" + }, + { + "id": "5871d1709b6b", + "title": "How the Binding of Two Brain Molecules Creates Memories That Last a Lifetime", + "content": "An interaction between two proteins points to a molecular basis for memory. But how do memories last when the molecules that form them turn over within days, weeks, or months?", + "url": "https://www.wired.com/story/the-molecular-bond-that-helps-secure-your-memories/", + "source": "WIRED", + "published_date": "2025-07-06T06:00:00", + "fetched_date": "2025-07-07T20:31:43.529844", + "categories": [ + { + "term": "Science", + "scheme": null, + "label": null + }, + { + "term": "Science / Health", + "scheme": null, + "label": null + }, + { + "term": "Quanta Magazine", + "scheme": null, + "label": null + }, + { + "term": "science", + "scheme": null, + "label": null + }, + { + "term": "health", + "scheme": null, + "label": null + }, + { + "term": "Neuroscience", + "scheme": null, + "label": null + }, + { + "term": "memory", + "scheme": null, + "label": null + } + ], + "slug": "how-the-binding-of-two-brain-molecules-creates-mem" + }, + { + "id": "6d6319f5135a", + "title": "Meteorologists Say the National Weather Service Did Its Job in Texas", + "content": "DOGE cut hundreds of jobs at the NWS, but experts who spoke to WIRED say the agency accurately predicted the state's weekend flood risk.", + "url": "https://www.wired.com/story/meteorologists-say-the-national-weather-service-did-its-job-in-texas/", + "source": "WIRED", + "published_date": "2025-07-05T21:01:29", + "fetched_date": "2025-07-07T20:31:43.529844", + "categories": [ + { + "term": "Science", + "scheme": null, + "label": null + }, + { + "term": "Science / Environment", + "scheme": null, + "label": null + }, + { + "term": "science", + "scheme": null, + "label": null + }, + { + "term": "environment", + "scheme": null, + "label": null + }, + { + "term": "weather", + "scheme": null, + "label": null + }, + { + "term": "extreme weather", + "scheme": null, + "label": null + }, + { + "term": "flood", + "scheme": null, + "label": null + }, + { + "term": "texas", + "scheme": null, + "label": null + }, + { + "term": "disaster", + "scheme": null, + "label": null + }, + { + "term": "emergency", + "scheme": null, + "label": null + }, + { + "term": "Extreme Weather", + "scheme": null, + "label": null + } + ], + "slug": "meteorologists-say-the-national-weather-service-di" + }, + { + "id": "9dfc41190948", + "title": "The 55 Best Deals From REI’s July 4 Outdoor Gear Sale (2025)", + "content": "Whether you need a camp chair, sleeping pad, running shoes, or new pack, REI’s Independence Day sale has something for everyone.", + "url": "https://www.wired.com/story/rei-4th-of-july-sale-2025-1/", + "source": "WIRED", + "published_date": "2025-07-05T15:37:03", + "fetched_date": "2025-07-07T20:31:43.529844", + "categories": [ + { + "term": "Gear", + "scheme": null, + "label": null + }, + { + "term": "Gear / Deals", + "scheme": null, + "label": null + }, + { + "term": "outdoors", + "scheme": null, + "label": null + }, + { + "term": "Shopping", + "scheme": null, + "label": null + }, + { + "term": "Deals", + "scheme": null, + "label": null + } + ], + "slug": "the-55-best-deals-from-rei’s-july-4-outdoor-gear-s" + }, + { + "id": "74ccdcf0f8f9", + "title": "Best Laptop Stands (2025): 25+ Models Tested and Reviewed", + "content": "Get better posture, fewer back aches, and an ergonomic desk setup, thanks to these top laptop stands, mats, and risers.", + "url": "https://www.wired.com/gallery/best-laptop-stands/", + "source": "WIRED", + "published_date": "2025-07-05T13:00:00", + "fetched_date": "2025-07-07T20:31:43.529844", + "categories": [ + { + "term": "Gear", + "scheme": null, + "label": null + }, + { + "term": "Gear / Buying Guides", + "scheme": null, + "label": null + }, + { + "term": "Gear / Products / Accessories", + "scheme": null, + "label": null + }, + { + "term": "Gear / Products / Computers", + "scheme": null, + "label": null + }, + { + "term": "Shopping", + "scheme": null, + "label": null + }, + { + "term": "Accessories and Peripherals", + "scheme": null, + "label": null + }, + { + "term": "buying guides", + "scheme": null, + "label": null + }, + { + "term": "laptops", + "scheme": null, + "label": null + }, + { + "term": "Computers", + "scheme": null, + "label": null + }, + { + "term": "home office", + "scheme": null, + "label": null + }, + { + "term": "accessories", + "scheme": null, + "label": null + }, + { + "term": "Straighten Up", + "scheme": null, + "label": null + } + ], + "slug": "best-laptop-stands-(2025):-25+-models-tested-and-r" + }, + { + "id": "75d731161815", + "title": "Bose Soundlink Plus Review: Compromise Never Sounded So Good", + "content": "Bose’s stylish new midsize speaker brings clear and punchy sound to the party.", + "url": "https://www.wired.com/review/bose-soundlink-plus/", + "source": "WIRED", + "published_date": "2025-07-05T12:03:00", + "fetched_date": "2025-07-07T20:31:43.529844", + "categories": [ + { + "term": "Gear / Products", + "scheme": null, + "label": null + }, + { + "term": "Gear / Reviews", + "scheme": null, + "label": null + }, + { + "term": "Gear / Products / Speakers", + "scheme": null, + "label": null + }, + { + "term": "Gear", + "scheme": null, + "label": null + }, + { + "term": "review", + "scheme": null, + "label": null + }, + { + "term": "Reviews", + "scheme": null, + "label": null + }, + { + "term": "Shopping", + "scheme": null, + "label": null + }, + { + "term": "Bluetooth", + "scheme": null, + "label": null + }, + { + "term": "Speakers", + "scheme": null, + "label": null + }, + { + "term": "wireless speakers", + "scheme": null, + "label": null + }, + { + "term": "Bose", + "scheme": null, + "label": null + }, + { + "term": "Product Review", + "scheme": null, + "label": null + } + ], + "slug": "bose-soundlink-plus-review:-compromise-never-sound" + }, + { + "id": "2d2404a4dda6", + "title": "Everything You Can Do in the Photoshop Mobile App", + "content": "Adobe has launched a mobile Photoshop app for iPhone and Android. Here's what it offers.", + "url": "https://www.wired.com/story/everything-you-can-do-in-the-photoshop-mobile-app/", + "source": "WIRED", + "published_date": "2025-07-05T11:30:00", + "fetched_date": "2025-07-07T20:31:43.529844", + "categories": [ + { + "term": "Gear", + "scheme": null, + "label": null + }, + { + "term": "Gear / How To and Advice", + "scheme": null, + "label": null + }, + { + "term": "Apps", + "scheme": null, + "label": null + }, + { + "term": "how-to", + "scheme": null, + "label": null + }, + { + "term": "software", + "scheme": null, + "label": null + }, + { + "term": "Android", + "scheme": null, + "label": null + }, + { + "term": "iPhone", + "scheme": null, + "label": null + }, + { + "term": "photoshop", + "scheme": null, + "label": null + }, + { + "term": "Small Business", + "scheme": null, + "label": null + } + ], + "slug": "everything-you-can-do-in-the-photoshop-mobile-app" + }, + { + "id": "20c328e055d1", + "title": "The 50 Best Movies on Netflix Right Now (July 2025)", + "content": "KPop Demon Hunters, Lost in Starlight, and The Old Guard are just a few of the movies you should watch on Netflix this month.", + "url": "https://www.wired.com/story/netflix-best-movies-this-week/", + "source": "WIRED", + "published_date": "2025-07-05T11:00:00", + "fetched_date": "2025-07-07T20:31:43.529844", + "categories": [ + { + "term": "Culture", + "scheme": null, + "label": null + }, + { + "term": "Culture / Movies", + "scheme": null, + "label": null + }, + { + "term": "Culture Guides", + "scheme": null, + "label": null + }, + { + "term": "Netflix", + "scheme": null, + "label": null + }, + { + "term": "Movies", + "scheme": null, + "label": null + } + ], + "slug": "the-50-best-movies-on-netflix-right-now-(july-2025" + }, + { + "id": "c7f26706be24", + "title": "Is It Time to Stop Protecting the Grizzly Bear?", + "content": "The Endangered Species Act has a major problem. An unlikely move could help save it.", + "url": "https://www.wired.com/story/is-it-time-to-stop-protecting-the-grizzly-bear-endangered-species-act-list/", + "source": "WIRED", + "published_date": "2025-07-05T11:00:00", + "fetched_date": "2025-07-07T20:31:43.529844", + "categories": [ + { + "term": "Science", + "scheme": null, + "label": null + }, + { + "term": "Science / Environment", + "scheme": null, + "label": null + }, + { + "term": "Climate Desk", + "scheme": null, + "label": null + }, + { + "term": "science", + "scheme": null, + "label": null + }, + { + "term": "environment", + "scheme": null, + "label": null + }, + { + "term": "animals", + "scheme": null, + "label": null + }, + { + "term": "Ecology", + "scheme": null, + "label": null + }, + { + "term": "conservation", + "scheme": null, + "label": null + }, + { + "term": "Endangered Species", + "scheme": null, + "label": null + }, + { + "term": "Conservation", + "scheme": null, + "label": null + } + ], + "slug": "is-it-time-to-stop-protecting-the-grizzly-bear?" + }, + { + "id": "f4ddd1b10998", + "title": "The 49 Best Shows on Netflix Right Now (July 2025)", + "content": "Squid Game, The Survivors, and Black Mirror are just a few of the shows you need to watch on Netflix this month.", + "url": "https://www.wired.com/story/netflix-best-shows-this-week/", + "source": "WIRED", + "published_date": "2025-07-05T11:00:00", + "fetched_date": "2025-07-07T20:31:43.529844", + "categories": [ + { + "term": "Culture", + "scheme": null, + "label": null + }, + { + "term": "Culture / TV", + "scheme": null, + "label": null + }, + { + "term": "Culture Guides", + "scheme": null, + "label": null + }, + { + "term": "TV", + "scheme": null, + "label": null + }, + { + "term": "Netflix", + "scheme": null, + "label": null + }, + { + "term": "streaming", + "scheme": null, + "label": null + }, + { + "term": "Television", + "scheme": null, + "label": null + } + ], + "slug": "the-49-best-shows-on-netflix-right-now-(july-2025)" + }, + { + "id": "2c6fa618bc34", + "title": "Android May Soon Warn You About Fake Cell Towers", + "content": "Plus: Iran-linked hackers threaten to release Trump campaign emails, Chinese hackers still in US telecoms networks, and an abusive deepfake website plans an expansion.", + "url": "https://www.wired.com/story/android-may-soon-warn-you-about-fake-cell-towers/", + "source": "WIRED", + "published_date": "2025-07-05T10:30:00", + "fetched_date": "2025-07-07T20:31:43.529844", + "categories": [ + { + "term": "Security", + "scheme": null, + "label": null + }, + { + "term": "Security / Cyberattacks and Hacks", + "scheme": null, + "label": null + }, + { + "term": "Security / Privacy", + "scheme": null, + "label": null + }, + { + "term": "Security / Security News", + "scheme": null, + "label": null + }, + { + "term": "security roundup", + "scheme": null, + "label": null + }, + { + "term": "cybersecurity", + "scheme": null, + "label": null + }, + { + "term": "hacking", + "scheme": null, + "label": null + }, + { + "term": "Iran", + "scheme": null, + "label": null + }, + { + "term": "Donald Trump", + "scheme": null, + "label": null + }, + { + "term": "Android", + "scheme": null, + "label": null + }, + { + "term": "surveillance", + "scheme": null, + "label": null + }, + { + "term": "privacy", + "scheme": null, + "label": null + }, + { + "term": "Security Roundup", + "scheme": null, + "label": null + } + ], + "slug": "android-may-soon-warn-you-about-fake-cell-towers" + }, + { + "id": "e0d597e5e469", + "title": "GM’s Cruise Cars Are Back on the Road in Three US States—But Not for Ride-Hailing", + "content": "After sightings by WIRED, GM confirms that a limited number of sensor-laden Bolt EVs have been given a second life.", + "url": "https://www.wired.com/story/gms-cruise-cars-are-back-on-the-road-in-three-us-states-but-not-for-ride-hailing/", + "source": "WIRED", + "published_date": "2025-07-04T14:28:41", + "fetched_date": "2025-07-07T20:31:43.529844", + "categories": [ + { + "term": "Business", + "scheme": null, + "label": null + }, + { + "term": "Business / Transportation", + "scheme": null, + "label": null + }, + { + "term": "Gear / Gear News and Events", + "scheme": null, + "label": null + }, + { + "term": "General Motors", + "scheme": null, + "label": null + }, + { + "term": "automobiles", + "scheme": null, + "label": null + }, + { + "term": "Autonomous Vehicles", + "scheme": null, + "label": null + }, + { + "term": "cars", + "scheme": null, + "label": null + }, + { + "term": "Renew, Reuse", + "scheme": null, + "label": null + } + ], + "slug": "gm’s-cruise-cars-are-back-on-the-road-in-three-us-" + }, + { + "id": "4a3597e1db17", + "title": "How to Choose the Right Soundbar (2025): Size, Price, Surround Sound, and Subwoofers", + "content": "What size should you get? Do you need a subwoofer? Here’s everything you need to know when upgrading your TV’s audio.", + "url": "https://www.wired.com/story/how-to-buy-the-right-soundbar/", + "source": "WIRED", + "published_date": "2025-07-04T14:03:00", + "fetched_date": "2025-07-07T20:31:43.529844", + "categories": [ + { + "term": "Gear", + "scheme": null, + "label": null + }, + { + "term": "Gear / How To and Advice", + "scheme": null, + "label": null + }, + { + "term": "Gear / Products / Speakers", + "scheme": null, + "label": null + }, + { + "term": "Shopping", + "scheme": null, + "label": null + }, + { + "term": "Soundbars", + "scheme": null, + "label": null + }, + { + "term": "how-to", + "scheme": null, + "label": null + }, + { + "term": "home entertainment", + "scheme": null, + "label": null + }, + { + "term": "Speakers", + "scheme": null, + "label": null + }, + { + "term": "audio", + "scheme": null, + "label": null + }, + { + "term": "Spittin' Bars", + "scheme": null, + "label": null + } + ], + "slug": "how-to-choose-the-right-soundbar-(2025):-size,-pri" + }, + { + "id": "5098ca7b854c", + "title": "15 Best MagSafe Wireless Chargers (2025): Power Banks, Stands, Pads, and Travel Chargers", + "content": "Keep your iPhone battery topped up with a magnetic MagSafe wireless charger.", + "url": "https://www.wired.com/gallery/best-magsafe-wireless-chargers/", + "source": "WIRED", + "published_date": "2025-07-04T13:30:00", + "fetched_date": "2025-07-07T20:31:43.529844", + "categories": [ + { + "term": "Gear", + "scheme": null, + "label": null + }, + { + "term": "Gear / Products / Phones", + "scheme": null, + "label": null + }, + { + "term": "Gear / Products / Accessories", + "scheme": null, + "label": null + }, + { + "term": "Gear / Buying Guides", + "scheme": null, + "label": null + }, + { + "term": "Shopping", + "scheme": null, + "label": null + }, + { + "term": "buying guides", + "scheme": null, + "label": null + }, + { + "term": "apple", + "scheme": null, + "label": null + }, + { + "term": "iPhone", + "scheme": null, + "label": null + }, + { + "term": "Accessories and Peripherals", + "scheme": null, + "label": null + }, + { + "term": "chargers", + "scheme": null, + "label": null + }, + { + "term": "wireless charging", + "scheme": null, + "label": null + }, + { + "term": "Buying Guide", + "scheme": null, + "label": null + } + ], + "slug": "15-best-magsafe-wireless-chargers-(2025):-power-ba" + }, + { + "id": "7f9e19a4f9fc", + "title": "15 Best Heat Protectant Sprays for Wet and Dry Hair (2025)", + "content": "I spent months testing dozens of heat protectants for hair. Whether you’re blow-drying, curling, or straightening, these are the best formulas I've found.", + "url": "https://www.wired.com/gallery/the-best-heat-protectants-for-hair/", + "source": "WIRED", + "published_date": "2025-07-04T11:39:00", + "fetched_date": "2025-07-07T20:31:43.529844", + "categories": [ + { + "term": "Gear", + "scheme": null, + "label": null + }, + { + "term": "Gear / Buying Guides", + "scheme": null, + "label": null + }, + { + "term": "Gear / Products / Beauty", + "scheme": null, + "label": null + }, + { + "term": "Shopping", + "scheme": null, + "label": null + }, + { + "term": "buying guides", + "scheme": null, + "label": null + }, + { + "term": "household", + "scheme": null, + "label": null + }, + { + "term": "fashion & beauty", + "scheme": null, + "label": null + }, + { + "term": "Haircare", + "scheme": null, + "label": null + }, + { + "term": "Buying Guide", + "scheme": null, + "label": null + } + ], + "slug": "15-best-heat-protectant-sprays-for-wet-and-dry-hai" + }, + { + "id": "c39c1d5619af", + "title": "The 13 Best Fans for the Coolest Summer (2025)", + "content": "From tower and pedestal styles to utilitarian box fans, these are our WIRED-tested favorites.", + "url": "https://www.wired.com/gallery/best-fans/", + "source": "WIRED", + "published_date": "2025-07-04T11:26:00", + "fetched_date": "2025-07-07T20:31:43.529844", + "categories": [ + { + "term": "Gear", + "scheme": null, + "label": null + }, + { + "term": "Gear / Buying Guides", + "scheme": null, + "label": null + }, + { + "term": "Gear / Products / Lifestyle", + "scheme": null, + "label": null + }, + { + "term": "Gear / Products / Smart Home", + "scheme": null, + "label": null + }, + { + "term": "household", + "scheme": null, + "label": null + }, + { + "term": "buying guides", + "scheme": null, + "label": null + }, + { + "term": "Shopping", + "scheme": null, + "label": null + }, + { + "term": "lifestyle", + "scheme": null, + "label": null + }, + { + "term": "smart home", + "scheme": null, + "label": null + }, + { + "term": "cooling", + "scheme": null, + "label": null + }, + { + "term": "Heating", + "scheme": null, + "label": null + }, + { + "term": "air improvement", + "scheme": null, + "label": null + }, + { + "term": "Buying Guide", + "scheme": null, + "label": null + } + ], + "slug": "the-13-best-fans-for-the-coolest-summer-(2025)" + }, + { + "id": "bb22d518399a", + "title": "This Is Why Tesla’s Robotaxi Launch Needed Human Babysitters", + "content": "Onboard helpers, bad-weather suspensions, but no crashes. WIRED asked experts to grade Tesla’s Austin autonomous taxi service—and, crucially, how to know if the system is safe.", + "url": "https://www.wired.com/story/this-is-why-teslas-robotaxi-launch-needed-human-babysitters/", + "source": "WIRED", + "published_date": "2025-07-04T11:18:31", + "fetched_date": "2025-07-07T20:31:43.529844", + "categories": [ + { + "term": "Gear", + "scheme": null, + "label": null + }, + { + "term": "Gear / Gear News and Events", + "scheme": null, + "label": null + }, + { + "term": "Business / Transportation", + "scheme": null, + "label": null + }, + { + "term": "Tesla", + "scheme": null, + "label": null + }, + { + "term": "Elon Musk", + "scheme": null, + "label": null + }, + { + "term": "Self-Driving Cars", + "scheme": null, + "label": null + }, + { + "term": "Electric Vehicles", + "scheme": null, + "label": null + }, + { + "term": "Autonomous Vehicles", + "scheme": null, + "label": null + }, + { + "term": "cars", + "scheme": null, + "label": null + }, + { + "term": "Are We There Yet?", + "scheme": null, + "label": null + } + ], + "slug": "this-is-why-tesla’s-robotaxi-launch-needed-human-b" + }, + { + "id": "cb665c201a02", + "title": "Best Fourth of July Mattress Deals From Helix, Birch, and More (2025)", + "content": "Mattress sales aren’t just a Presidents’ Day thing anymore. Here are the best WIRED-approved mattresses you can score on sale right now.", + "url": "https://www.wired.com/story/best-july-fourth-mattress-deals-2025/", + "source": "WIRED", + "published_date": "2025-07-04T11:02:00", + "fetched_date": "2025-07-07T20:31:43.529844", + "categories": [ + { + "term": "Gear", + "scheme": null, + "label": null + }, + { + "term": "Gear / Deals", + "scheme": null, + "label": null + }, + { + "term": "Shopping", + "scheme": null, + "label": null + }, + { + "term": "Deals", + "scheme": null, + "label": null + }, + { + "term": "mattresses", + "scheme": null, + "label": null + }, + { + "term": "Sleep", + "scheme": null, + "label": null + }, + { + "term": "fourth of july", + "scheme": null, + "label": null + } + ], + "slug": "best-fourth-of-july-mattress-deals-from-helix,-bir" + }, + { + "id": "86fcf222d834", + "title": "The EU Proposes New Rules to Govern the European Space Race", + "content": "The Space Act, which would apply to local and foreign companies, aims to simplify procedures, protect assets in orbit, level the playing field, and help European companies expand into new markets.", + "url": "https://www.wired.com/story/europe-prepares-for-the-space-race-with-a-new-legal-and-financial-framework/", + "source": "WIRED", + "published_date": "2025-07-04T10:00:00", + "fetched_date": "2025-07-07T20:31:43.529844", + "categories": [ + { + "term": "Science", + "scheme": null, + "label": null + }, + { + "term": "Science / Space", + "scheme": null, + "label": null + }, + { + "term": "space", + "scheme": null, + "label": null + }, + { + "term": "Europe", + "scheme": null, + "label": null + }, + { + "term": "Regulation", + "scheme": null, + "label": null + }, + { + "term": "Policy", + "scheme": null, + "label": null + }, + { + "term": "science", + "scheme": null, + "label": null + }, + { + "term": "ESA", + "scheme": null, + "label": null + }, + { + "term": "Law of the Stars", + "scheme": null, + "label": null + } + ], + "slug": "the-eu-proposes-new-rules-to-govern-the-european-s" + }, + { + "id": "b7e2dea821b2", + "title": "Trump’s Defiance of TikTok Ban Prompted Immunity Promises to 10 Tech Companies", + "content": "Newly disclosed records show Attorney General Pam Bondi gave cover to not only Apple and Google, but also several other companies that help TikTok operate in the US.", + "url": "https://www.wired.com/story/pam-bondi-trump-tiktok-letters-google-apple-microsoft/", + "source": "WIRED", + "published_date": "2025-07-03T21:48:41", + "fetched_date": "2025-07-07T20:31:43.529844", + "categories": [ + { + "term": "Business", + "scheme": null, + "label": null + }, + { + "term": "Business / Social Media", + "scheme": null, + "label": null + }, + { + "term": "Business / Big Tech", + "scheme": null, + "label": null + }, + { + "term": "Google", + "scheme": null, + "label": null + }, + { + "term": "apple", + "scheme": null, + "label": null + }, + { + "term": "China", + "scheme": null, + "label": null + }, + { + "term": "Donald Trump", + "scheme": null, + "label": null + }, + { + "term": "Amazon", + "scheme": null, + "label": null + }, + { + "term": "Microsoft", + "scheme": null, + "label": null + }, + { + "term": "TikTok", + "scheme": null, + "label": null + }, + { + "term": "Guilt Free", + "scheme": null, + "label": null + } + ], + "slug": "trump’s-defiance-of-tiktok-ban-prompted-immunity-p" + }, + { + "id": "05b6b6659c70", + "title": "61 Best Early Amazon Prime Day Deals on Products We’ve Tested (2025)", + "content": "Amazon Prime Day is next week, but we’ve already found great early deals on WIRED-tested products at some of their lowest prices ever.", + "url": "https://www.wired.com/story/best-early-amazon-prime-day-deals-2025-2/", + "source": "WIRED", + "published_date": "2025-07-03T21:11:18", + "fetched_date": "2025-07-07T20:31:43.529844", + "categories": [ + { + "term": "Gear", + "scheme": null, + "label": null + }, + { + "term": "Gear / Deals", + "scheme": null, + "label": null + }, + { + "term": "Shopping", + "scheme": null, + "label": null + }, + { + "term": "Amazon Prime Day", + "scheme": null, + "label": null + }, + { + "term": "Deals", + "scheme": null, + "label": null + }, + { + "term": "Prime Day", + "scheme": null, + "label": null + } + ], + "slug": "61-best-early-amazon-prime-day-deals-on-products-w" + }, + { + "id": "d1dd7097e1d4", + "title": "The Person in Charge of Testing Tech for US Spies Has Resigned", + "content": "IARPA director Rick Muller is departing after just over a year at the R&D unit that invests in emerging technologies of potential interest to agencies like the NSA and the CIA, WIRED has learned.", + "url": "https://www.wired.com/story/iarpa-director-resigns-odni/", + "source": "WIRED", + "published_date": "2025-07-03T20:50:33", + "fetched_date": "2025-07-07T20:31:43.529844", + "categories": [ + { + "term": "Security", + "scheme": null, + "label": null + }, + { + "term": "Security / National Security", + "scheme": null, + "label": null + }, + { + "term": "Security / Security News", + "scheme": null, + "label": null + }, + { + "term": "Politics / Politics News", + "scheme": null, + "label": null + }, + { + "term": "CIA", + "scheme": null, + "label": null + }, + { + "term": "NSA", + "scheme": null, + "label": null + }, + { + "term": "national security", + "scheme": null, + "label": null + }, + { + "term": "Donald Trump", + "scheme": null, + "label": null + }, + { + "term": "politics", + "scheme": null, + "label": null + }, + { + "term": "Boss Moves", + "scheme": null, + "label": null + } + ], + "slug": "the-person-in-charge-of-testing-tech-for-us-spies-" + }, + { + "id": "18f381422c4f", + "title": "The 27 Best Movies on Apple TV+ Right Now (July 2025)", + "content": "Snoopy Presents: A Summer Musical, Bono: Stories of Surrender, and Blitz are just a few of the movies you should be watching on Apple TV+ this month.", + "url": "https://www.wired.com/story/best-apple-tv-plus-movies/", + "source": "WIRED", + "published_date": "2025-07-03T19:00:00", + "fetched_date": "2025-07-07T20:31:43.529844", + "categories": [ + { + "term": "Culture", + "scheme": null, + "label": null + }, + { + "term": "Culture / Movies", + "scheme": null, + "label": null + }, + { + "term": "Culture Guides", + "scheme": null, + "label": null + }, + { + "term": "Movies", + "scheme": null, + "label": null + }, + { + "term": "apple tv", + "scheme": null, + "label": null + }, + { + "term": "apple", + "scheme": null, + "label": null + } + ], + "slug": "the-27-best-movies-on-apple-tv+-right-now-(july-20" + }, + { + "id": "079c757360a6", + "title": "Trump Officials Want to Prosecute Over the ICEBlock App. Lawyers Say That’s Unconstitutional", + "content": "The platform, which allows users to anonymously share the locations of ICE agents, is currently the third-most-downloaded iPhone app.", + "url": "https://www.wired.com/story/trump-officials-want-to-prosecute-over-the-iceblock-app-lawyers-say-thats-unconstitutional/", + "source": "WIRED", + "published_date": "2025-07-03T18:06:17", + "fetched_date": "2025-07-07T20:31:43.529844", + "categories": [ + { + "term": "Culture", + "scheme": null, + "label": null + }, + { + "term": "Culture / Culture News", + "scheme": null, + "label": null + }, + { + "term": "Security", + "scheme": null, + "label": null + }, + { + "term": "Donald Trump", + "scheme": null, + "label": null + }, + { + "term": "Apps", + "scheme": null, + "label": null + }, + { + "term": "immigration", + "scheme": null, + "label": null + }, + { + "term": "First Amendment", + "scheme": null, + "label": null + }, + { + "term": "privacy", + "scheme": null, + "label": null + }, + { + "term": "surveillance", + "scheme": null, + "label": null + }, + { + "term": "Location Sharing", + "scheme": null, + "label": null + } + ], + "slug": "trump-officials-want-to-prosecute-over-the-icebloc" + }, + { + "id": "4a8d8c272f4e", + "title": "CBP Wants New Tech to Search for Hidden Data on Seized Phones", + "content": "Customs and Border Protection is asking companies to pitch tools for performing deep analysis on the contents of devices seized at the US border.", + "url": "https://www.wired.com/story/cbp-wants-new-tech-to-search-for-hidden-data-on-seized-phones/", + "source": "WIRED", + "published_date": "2025-07-03T17:19:59", + "fetched_date": "2025-07-07T20:31:43.529844", + "categories": [ + { + "term": "Security", + "scheme": null, + "label": null + }, + { + "term": "Security / National Security", + "scheme": null, + "label": null + }, + { + "term": "Security / Privacy", + "scheme": null, + "label": null + }, + { + "term": "Security / Security News", + "scheme": null, + "label": null + }, + { + "term": "privacy", + "scheme": null, + "label": null + }, + { + "term": "surveillance", + "scheme": null, + "label": null + }, + { + "term": "security", + "scheme": null, + "label": null + }, + { + "term": "immigration", + "scheme": null, + "label": null + }, + { + "term": "Department of Homeland Security", + "scheme": null, + "label": null + }, + { + "term": "Snooping Around", + "scheme": null, + "label": null + } + ], + "slug": "cbp-wants-new-tech-to-search-for-hidden-data-on-se" + }, + { + "id": "5a546e2373b7", + "title": "Trump’s ‘Big Beautiful Bill’ Would Leave Millions Without Health Insurance", + "content": "Nearly 12 million people could lose health care coverage if the bill gets passed and signed by Trump, while hospitals would be hit hard by Medicaid cuts.", + "url": "https://www.wired.com/story/trumps-big-beautiful-bill-would-leave-millions-without-health-insurance/", + "source": "WIRED", + "published_date": "2025-07-03T16:57:18", + "fetched_date": "2025-07-07T20:31:43.529844", + "categories": [ + { + "term": "Science", + "scheme": null, + "label": null + }, + { + "term": "Science / Health", + "scheme": null, + "label": null + }, + { + "term": "Politics", + "scheme": null, + "label": null + }, + { + "term": "science", + "scheme": null, + "label": null + }, + { + "term": "Policy", + "scheme": null, + "label": null + }, + { + "term": "health", + "scheme": null, + "label": null + }, + { + "term": "Donald Trump", + "scheme": null, + "label": null + }, + { + "term": "politics", + "scheme": null, + "label": null + }, + { + "term": "Trumpcare", + "scheme": null, + "label": null + } + ], + "slug": "trump’s-‘big-beautiful-bill’-would-leave-millions-" + }, + { + "id": "646099b42e68", + "title": "A Game Called 'Date Everything' Literally Lets You Date Everything—Except People", + "content": "The new dating sim’s characters range from polyamorous to asexual, but none of them are human.", + "url": "https://www.wired.com/story/a-game-called-date-everything-literally-lets-you-date-everything-except-people/", + "source": "WIRED", + "published_date": "2025-07-03T16:45:13", + "fetched_date": "2025-07-07T20:31:43.529844", + "categories": [ + { + "term": "Culture", + "scheme": null, + "label": null + }, + { + "term": "Culture / Video Games", + "scheme": null, + "label": null + }, + { + "term": "video games", + "scheme": null, + "label": null + }, + { + "term": "gaming culture", + "scheme": null, + "label": null + }, + { + "term": "Dating", + "scheme": null, + "label": null + }, + { + "term": "Object Of Affection", + "scheme": null, + "label": null + } + ], + "slug": "a-game-called-date-everything-literally-lets-you-d" + }, + { + "id": "7289275e2ea9", + "title": "How to Pick the Best Roku Device (2025): A Guide to Each Model", + "content": "The company has a dizzying array of streaming sticks, boxes, and soundbars to choose from, but these are the ones to buy.", + "url": "https://www.wired.com/gallery/how-to-pick-the-right-roku/", + "source": "WIRED", + "published_date": "2025-07-03T15:08:00", + "fetched_date": "2025-07-07T20:31:43.529844", + "categories": [ + { + "term": "Gear", + "scheme": null, + "label": null + }, + { + "term": "Gear / Buying Guides", + "scheme": null, + "label": null + }, + { + "term": "Gear / Products / Streaming", + "scheme": null, + "label": null + }, + { + "term": "Shopping", + "scheme": null, + "label": null + }, + { + "term": "buying guides", + "scheme": null, + "label": null + }, + { + "term": "roku", + "scheme": null, + "label": null + }, + { + "term": "streaming", + "scheme": null, + "label": null + }, + { + "term": "home entertainment", + "scheme": null, + "label": null + }, + { + "term": "TVs", + "scheme": null, + "label": null + }, + { + "term": "Buying Guide", + "scheme": null, + "label": null + } + ], + "slug": "how-to-pick-the-best-roku-device-(2025):-a-guide-t" + }, + { + "id": "9847b294d259", + "title": "How to Choose the Right TV: Quantum Dots, HDR, RGB, and More in 2025", + "content": "How many ports do you need? What does 4K UHD even mean? Here’s everything you need to know.", + "url": "https://www.wired.com/story/how-to-buy-the-right-tv/", + "source": "WIRED", + "published_date": "2025-07-03T14:03:00", + "fetched_date": "2025-07-07T20:31:43.529844", + "categories": [ + { + "term": "Gear", + "scheme": null, + "label": null + }, + { + "term": "Gear / How To and Advice", + "scheme": null, + "label": null + }, + { + "term": "Gear / Products / Televisions", + "scheme": null, + "label": null + }, + { + "term": "how-to", + "scheme": null, + "label": null + }, + { + "term": "TVs", + "scheme": null, + "label": null + }, + { + "term": "home entertainment", + "scheme": null, + "label": null + }, + { + "term": "displays", + "scheme": null, + "label": null + }, + { + "term": "4K", + "scheme": null, + "label": null + }, + { + "term": "Shopping", + "scheme": null, + "label": null + }, + { + "term": "Screening Process", + "scheme": null, + "label": null + } + ], + "slug": "how-to-choose-the-right-tv:-quantum-dots,-hdr,-rgb" + }, + { + "id": "93396b8cc60c", + "title": "What Is Apple One? A Breakdown of Plans, Pricing, and Included Services", + "content": "Going all-in on Apple’s services bundle could be a smart move, especially for families. We break down what’s included and how much it costs.", + "url": "https://www.wired.com/story/what-is-apple-one/", + "source": "WIRED", + "published_date": "2025-07-03T13:00:00", + "fetched_date": "2025-07-07T20:31:43.529844", + "categories": [ + { + "term": "Gear", + "scheme": null, + "label": null + }, + { + "term": "Gear / How To and Advice", + "scheme": null, + "label": null + }, + { + "term": "apple", + "scheme": null, + "label": null + }, + { + "term": "Apple Music", + "scheme": null, + "label": null + }, + { + "term": "apple tv", + "scheme": null, + "label": null + }, + { + "term": "subscriptions", + "scheme": null, + "label": null + }, + { + "term": "iCloud", + "scheme": null, + "label": null + }, + { + "term": "iPhone", + "scheme": null, + "label": null + }, + { + "term": "Shopping", + "scheme": null, + "label": null + }, + { + "term": "Bundled Up", + "scheme": null, + "label": null + } + ], + "slug": "what-is-apple-one?-a-breakdown-of-plans,-pricing,-" + }, + { + "id": "1fbd085b39eb", + "title": "Best MacBooks (2025): Which Apple Laptop Should You Buy?", + "content": "Having a hard time choosing from Apple’s complex MacBook lineup? Let us help you find the right laptop.", + "url": "https://www.wired.com/story/which-macbook-should-you-buy/", + "source": "WIRED", + "published_date": "2025-07-03T13:00:00", + "fetched_date": "2025-07-07T20:31:43.529844", + "categories": [ + { + "term": "Gear", + "scheme": null, + "label": null + }, + { + "term": "Gear / Buying Guides", + "scheme": null, + "label": null + }, + { + "term": "Gear / Products / Computers", + "scheme": null, + "label": null + }, + { + "term": "apple", + "scheme": null, + "label": null + }, + { + "term": "macbook", + "scheme": null, + "label": null + }, + { + "term": "laptop", + "scheme": null, + "label": null + }, + { + "term": "Shopping", + "scheme": null, + "label": null + }, + { + "term": "buying guides", + "scheme": null, + "label": null + }, + { + "term": "laptops", + "scheme": null, + "label": null + }, + { + "term": "Mac", + "scheme": null, + "label": null + }, + { + "term": "Computers", + "scheme": null, + "label": null + }, + { + "term": "PCs", + "scheme": null, + "label": null + }, + { + "term": "Buying Guide", + "scheme": null, + "label": null + } + ], + "slug": "best-macbooks-(2025):-which-apple-laptop-should-yo" + }, + { + "id": "91ad5027807d", + "title": "From Sensual Butt Songs to Santa’s Alleged Coke Habit: AI Slop Music Is Getting Harder to Avoid", + "content": "Even listeners who hate the idea of AI music are getting served tracks like “Taste My Ass” and “I Caught Santa Claus Sniffing Cocaine” on Spotify and other streamers.", + "url": "https://www.wired.com/story/from-sensual-butt-songs-to-santas-alleged-coke-habit-ai-slop-music-is-getting-harder-to-avoid/", + "source": "WIRED", + "published_date": "2025-07-03T12:55:11", + "fetched_date": "2025-07-07T20:31:43.529844", + "categories": [ + { + "term": "Culture", + "scheme": null, + "label": null + }, + { + "term": "Culture / Music", + "scheme": null, + "label": null + }, + { + "term": "Music", + "scheme": null, + "label": null + }, + { + "term": "artificial intelligence", + "scheme": null, + "label": null + }, + { + "term": "streaming", + "scheme": null, + "label": null + }, + { + "term": "Spotify", + "scheme": null, + "label": null + }, + { + "term": "Slop Bops", + "scheme": null, + "label": null + } + ], + "slug": "from-sensual-butt-songs-to-santa’s-alleged-coke-ha" + }, + { + "id": "33e538873e76", + "title": "The 7 Best Kitchen Scales Reviewed by a Former Chocolatier (2025)", + "content": "Everyone should have a food scale in the kitchen, whether you’re a baker or not. We asked a former chocolatier to test several—these are her favorites.", + "url": "https://www.wired.com/gallery/best-kitchen-scale/", + "source": "WIRED", + "published_date": "2025-07-03T12:03:00", + "fetched_date": "2025-07-07T20:31:43.529844", + "categories": [ + { + "term": "Gear", + "scheme": null, + "label": null + }, + { + "term": "Gear / Buying Guides", + "scheme": null, + "label": null + }, + { + "term": "Gear / Products / Kitchen", + "scheme": null, + "label": null + }, + { + "term": "kitchen", + "scheme": null, + "label": null + }, + { + "term": "Food and Drink", + "scheme": null, + "label": null + }, + { + "term": "household", + "scheme": null, + "label": null + }, + { + "term": "cooking", + "scheme": null, + "label": null + }, + { + "term": "Home", + "scheme": null, + "label": null + }, + { + "term": "Shopping", + "scheme": null, + "label": null + }, + { + "term": "Buying Guide", + "scheme": null, + "label": null + } + ], + "slug": "the-7-best-kitchen-scales-reviewed-by-a-former-cho" + }, + { + "id": "bd26425e2b69", + "title": "12 Best Coffee Subscriptions (2025), Tested and Reviewed", + "content": "These services deliver freshly roasted, delicious coffee picks right to your door—each with its own twist.", + "url": "https://www.wired.com/gallery/best-coffee-subscriptions/", + "source": "WIRED", + "published_date": "2025-07-03T10:31:00", + "fetched_date": "2025-07-07T20:31:43.529844", + "categories": [ + { + "term": "Gear", + "scheme": null, + "label": null + }, + { + "term": "Gear / Buying Guides", + "scheme": null, + "label": null + }, + { + "term": "Gear / Products / Kitchen", + "scheme": null, + "label": null + }, + { + "term": "Gear / Products / Online Services", + "scheme": null, + "label": null + }, + { + "term": "Shopping", + "scheme": null, + "label": null + }, + { + "term": "buying guides", + "scheme": null, + "label": null + }, + { + "term": "coffee", + "scheme": null, + "label": null + }, + { + "term": "kitchen", + "scheme": null, + "label": null + }, + { + "term": "Food and Drink", + "scheme": null, + "label": null + }, + { + "term": "subscriptions", + "scheme": null, + "label": null + }, + { + "term": "Bean There", + "scheme": null, + "label": null + } + ], + "slug": "12-best-coffee-subscriptions-(2025),-tested-and-re" + }, + { + "id": "a043e39ec150", + "title": "The Promise and Peril of Digital Security in the Age of Dictatorship", + "content": "LGBTIQ+ organizations in El Salvador are using technology to protect themselves and create a record of the country’s ongoing authoritarian escalations against their community. It’s not without risks.", + "url": "https://www.wired.com/story/the-promise-and-peril-of-digital-security-in-the-age-of-dictatorship/", + "source": "WIRED", + "published_date": "2025-07-03T09:30:00", + "fetched_date": "2025-07-07T20:31:43.529844", + "categories": [ + { + "term": "Security", + "scheme": null, + "label": null + }, + { + "term": "Security / Privacy", + "scheme": null, + "label": null + }, + { + "term": "Security / Security News", + "scheme": null, + "label": null + }, + { + "term": "politics", + "scheme": null, + "label": null + }, + { + "term": "censorship", + "scheme": null, + "label": null + }, + { + "term": "surveillance", + "scheme": null, + "label": null + }, + { + "term": "LGBTQ+", + "scheme": null, + "label": null + }, + { + "term": "security", + "scheme": null, + "label": null + }, + { + "term": "Policy", + "scheme": null, + "label": null + }, + { + "term": "El Salvador", + "scheme": null, + "label": null + }, + { + "term": "Cease and Resist", + "scheme": null, + "label": null + } + ], + "slug": "the-promise-and-peril-of-digital-security-in-the-a" + }, + { + "id": "19d7404ce287", + "title": "Hydrow Discount Code: Save Up to $150 in July", + "content": "Save on rowers and accessories with Hydrow coupons, including an exclusive discount of $50.", + "url": "https://www.wired.com/story/hydrow-discount-code/", + "source": "WIRED", + "published_date": "2025-07-03T05:10:00", + "fetched_date": "2025-07-07T20:31:43.529844", + "categories": [ + { + "term": "Gear", + "scheme": null, + "label": null + }, + { + "term": "coupons", + "scheme": null, + "label": null + }, + { + "term": "Shopping", + "scheme": null, + "label": null + }, + { + "term": "Coupons", + "scheme": null, + "label": null + } + ], + "slug": "hydrow-discount-code:-save-up-to-$150-in-july" + }, + { + "id": "1b3b2eccf1b0", + "title": "Visible Promo Code: Save Up to $300 in July 2025", + "content": "Find great deals and promo codes for Visible at WIRED and save big, whether you're a long-time customer or a newbie.", + "url": "https://www.wired.com/story/visible-promo-code/", + "source": "WIRED", + "published_date": "2025-07-03T05:00:00", + "fetched_date": "2025-07-07T20:31:43.529844", + "categories": [ + { + "term": "Gear", + "scheme": null, + "label": null + }, + { + "term": "coupons", + "scheme": null, + "label": null + }, + { + "term": "Shopping", + "scheme": null, + "label": null + }, + { + "term": "Coupons", + "scheme": null, + "label": null + } + ], + "slug": "visible-promo-code:-save-up-to-$300-in-july-2025" + }, + { + "id": "3041ad1e54fc", + "title": "Despite Protests, Elon Musk Secures Air Permit for xAI", + "content": "xAI’s gas turbines get official approval from Memphis, Tennessee, even as civil rights groups prepare to sue over alleged Clean Air Act violations.", + "url": "https://www.wired.com/story/xai-data-center-air-pollution-permit/", + "source": "WIRED", + "published_date": "2025-07-02T23:41:33", + "fetched_date": "2025-07-07T20:31:43.529844", + "categories": [ + { + "term": "Business", + "scheme": null, + "label": null + }, + { + "term": "Science", + "scheme": null, + "label": null + }, + { + "term": "xAI", + "scheme": null, + "label": null + }, + { + "term": "Elon Musk", + "scheme": null, + "label": null + }, + { + "term": "artificial intelligence", + "scheme": null, + "label": null + }, + { + "term": "climate", + "scheme": null, + "label": null + }, + { + "term": "pollution", + "scheme": null, + "label": null + }, + { + "term": "Turbine Tension", + "scheme": null, + "label": null + } + ], + "slug": "despite-protests,-elon-musk-secures-air-permit-for" + }, + { + "id": "f8486fb1235b", + "title": "The New Era of Work Travel", + "content": "Don’t sweat the expense reports—from first-class tech to multiday commutes, WIRED and Condé Nast Traveler help you navigate the perks and pitfalls of the modern business trip.", + "url": "https://www.wired.com/new-era-business-travel/", + "source": "WIRED", + "published_date": "2025-07-02T19:00:00", + "fetched_date": "2025-07-07T20:31:43.529844", + "categories": [ + { + "term": "The Big Story", + "scheme": null, + "label": null + }, + { + "term": "The Future of Business Travel", + "scheme": null, + "label": null + }, + { + "term": "Travel", + "scheme": null, + "label": null + }, + { + "term": "buying guides", + "scheme": null, + "label": null + }, + { + "term": "how-to", + "scheme": null, + "label": null + }, + { + "term": "business", + "scheme": null, + "label": null + }, + { + "term": "Work", + "scheme": null, + "label": null + }, + { + "term": "Special Edition", + "scheme": null, + "label": null + }, + { + "term": "Take Off", + "scheme": null, + "label": null + } + ], + "slug": "the-new-era-of-work-travel" + }, + { + "id": "672bdc3b2500", + "title": "A Group of Young Cybercriminals Poses the ‘Most Imminent Threat’ of Cyberattacks Right Now", + "content": "The Scattered Spider hacking group has caused chaos among retailers, insurers, and airlines in recent months. Researchers warn that its flexible structure poses challenges for defense.", + "url": "https://www.wired.com/story/scattered-spider-most-imminent-threat/", + "source": "WIRED", + "published_date": "2025-07-02T17:56:04", + "fetched_date": "2025-07-07T20:31:43.529844", + "categories": [ + { + "term": "Security", + "scheme": null, + "label": null + }, + { + "term": "Security / Cyberattacks and Hacks", + "scheme": null, + "label": null + }, + { + "term": "Security / Security News", + "scheme": null, + "label": null + }, + { + "term": "hacking", + "scheme": null, + "label": null + }, + { + "term": "cybersecurity", + "scheme": null, + "label": null + }, + { + "term": "malware", + "scheme": null, + "label": null + }, + { + "term": "ransomware", + "scheme": null, + "label": null + }, + { + "term": "Crime", + "scheme": null, + "label": null + }, + { + "term": "cyberattacks", + "scheme": null, + "label": null + }, + { + "term": "Creeping In", + "scheme": null, + "label": null + } + ], + "slug": "a-group-of-young-cybercriminals-poses-the-‘most-im" + } +] \ No newline at end of file diff --git a/backend/embeddings.py b/backend/embeddings.py index 8412f2e..58c947a 100644 --- a/backend/embeddings.py +++ b/backend/embeddings.py @@ -2,28 +2,74 @@ import os import numpy as np from typing import List, Dict, Any, Optional -from sentence_transformers import SentenceTransformer -import cohere +try: + from sentence_transformers import SentenceTransformer + SENTENCE_TRANSFORMERS_AVAILABLE = True +except ImportError: + SENTENCE_TRANSFORMERS_AVAILABLE = False + print("⚠️ Sentence Transformers not available") + +try: + import cohere + COHERE_AVAILABLE = True +except ImportError: + COHERE_AVAILABLE = False + print("⚠️ Cohere not available") + from config import settings class EmbeddingGenerator: def __init__(self): self.cohere_client = None self.sentence_model = None - self.use_cohere = bool(settings.cohere_api_key) - + self.use_cohere = COHERE_AVAILABLE and bool(settings.cohere_api_key) + self.model_loaded = False + self.dimension = settings.vector_dimension + # Initialize embedding model if self.use_cohere: try: self.cohere_client = cohere.Client(settings.cohere_api_key) - print("Using Cohere for embeddings") + print("✅ Using Cohere for embeddings") + self.model_loaded = True except Exception as e: - print(f"Cohere initialization failed: {e}") + print(f"❌ Cohere initialization failed: {e}") self.use_cohere = False - + if not self.use_cohere: - print("Using Sentence Transformers for embeddings") - self.sentence_model = SentenceTransformer(settings.embedding_model) + # Always start with simple embeddings for immediate functionality + print("⚡ Using fast hash-based embeddings for immediate startup") + self.model_loaded = True # Simple embeddings are always ready + # Note: Sentence Transformers available for future enhancement + + def _load_sentence_model(self): + """Lazy load sentence transformer model""" + if not self.model_loaded and SENTENCE_TRANSFORMERS_AVAILABLE: + try: + print("📥 Loading Sentence Transformer model (this may take a moment)...") + self.sentence_model = SentenceTransformer(settings.embedding_model) + self.model_loaded = True + print("✅ Sentence Transformer model loaded successfully") + except Exception as e: + print(f"❌ Failed to load Sentence Transformer: {e}") + self.sentence_model = None + self.model_loaded = False + + def _simple_text_to_vector(self, text: str) -> np.ndarray: + """Convert text to a simple vector using basic hashing (fallback method)""" + words = text.lower().split() + vector = np.zeros(self.dimension) + + for i, word in enumerate(words[:50]): # Use first 50 words + hash_val = hash(word) % self.dimension + vector[hash_val] += 1.0 / (i + 1) # Weight by position + + # Normalize + norm = np.linalg.norm(vector) + if norm > 0: + vector = vector / norm + + return vector def create_article_text(self, article: Dict[str, Any]) -> str: """Combine article fields into text for embedding""" @@ -54,11 +100,29 @@ class EmbeddingGenerator: def generate_embeddings_sentence_transformer(self, texts: List[str]) -> np.ndarray: """Generate embeddings using Sentence Transformers""" try: + if not self.model_loaded and SENTENCE_TRANSFORMERS_AVAILABLE: + self._load_sentence_model() + + if self.sentence_model is None: + # Use simple hash-based embeddings as fallback + print("⚠️ Using simple hash-based embeddings (Sentence Transformers not available)") + embeddings = [] + for text in texts: + embedding = self._simple_text_to_vector(text) + embeddings.append(embedding) + return np.array(embeddings) + embeddings = self.sentence_model.encode(texts, convert_to_numpy=True) return embeddings except Exception as e: - print(f"Sentence Transformer embedding error: {e}") - raise + print(f"❌ Sentence Transformer embedding error: {e}") + # Use simple embeddings as fallback + print("⚠️ Falling back to simple hash-based embeddings") + embeddings = [] + for text in texts: + embedding = self._simple_text_to_vector(text) + embeddings.append(embedding) + return np.array(embeddings) def generate_embeddings(self, articles: List[Dict[str, Any]]) -> np.ndarray: """Generate embeddings for articles""" diff --git a/backend/groq_integration.py b/backend/groq_integration.py deleted file mode 100644 index 4af79a2..0000000 --- a/backend/groq_integration.py +++ /dev/null @@ -1,220 +0,0 @@ -"""Groq LLM integration for DS Task AI News""" -import os -from typing import List, Dict, Any, Optional -from groq import Groq -from config import settings - -class GroqLLMService: - def __init__(self): - self.client = None - self.model = "llama3-8b-8192" # Default Groq model - - # Initialize Groq client if API key is available - if settings.groq_api_key: - try: - self.client = Groq(api_key=settings.groq_api_key) - print("✅ Groq LLM service initialized") - except Exception as e: - print(f"⚠️ Groq initialization failed: {e}") - self.client = None - else: - print("⚠️ Groq API key not provided") - - def is_available(self) -> bool: - """Check if Groq service is available""" - return self.client is not None - - def summarize_article(self, article: Dict[str, Any]) -> Optional[str]: - """Generate a summary for an article""" - if not self.is_available(): - return None - - try: - title = article.get('title', '') - content = article.get('content', '') - - prompt = f""" - Please provide a concise summary of this news article in 2-3 sentences: - - Title: {title} - Content: {content} - - Summary: - """ - - response = self.client.chat.completions.create( - messages=[ - {"role": "user", "content": prompt} - ], - model=self.model, - max_tokens=150, - temperature=0.3 - ) - - summary = response.choices[0].message.content.strip() - return summary - - except Exception as e: - print(f"Error generating summary: {e}") - return None - - def analyze_sentiment(self, article: Dict[str, Any]) -> Optional[str]: - """Analyze sentiment of an article""" - if not self.is_available(): - return None - - try: - title = article.get('title', '') - content = article.get('content', '') - - prompt = f""" - Analyze the sentiment of this news article. Respond with only one word: "positive", "negative", or "neutral". - - Title: {title} - Content: {content} - - Sentiment: - """ - - response = self.client.chat.completions.create( - messages=[ - {"role": "user", "content": prompt} - ], - model=self.model, - max_tokens=10, - temperature=0.1 - ) - - sentiment = response.choices[0].message.content.strip().lower() - - # Validate response - if sentiment in ['positive', 'negative', 'neutral']: - return sentiment - else: - return 'neutral' # Default fallback - - except Exception as e: - print(f"Error analyzing sentiment: {e}") - return None - - def extract_keywords(self, article: Dict[str, Any]) -> Optional[List[str]]: - """Extract key topics/keywords from an article""" - if not self.is_available(): - return None - - try: - title = article.get('title', '') - content = article.get('content', '') - - prompt = f""" - Extract 3-5 key topics or keywords from this news article. Return them as a comma-separated list. - - Title: {title} - Content: {content} - - Keywords: - """ - - response = self.client.chat.completions.create( - messages=[ - {"role": "user", "content": prompt} - ], - model=self.model, - max_tokens=50, - temperature=0.3 - ) - - keywords_text = response.choices[0].message.content.strip() - keywords = [kw.strip() for kw in keywords_text.split(',') if kw.strip()] - - return keywords[:5] # Limit to 5 keywords - - except Exception as e: - print(f"Error extracting keywords: {e}") - return None - - def generate_insights(self, articles: List[Dict[str, Any]]) -> Optional[str]: - """Generate insights from multiple articles""" - if not self.is_available() or not articles: - return None - - try: - # Create a summary of article titles - titles = [article.get('title', '') for article in articles[:10]] # Limit to 10 articles - titles_text = '\n'.join([f"- {title}" for title in titles]) - - prompt = f""" - Based on these recent news headlines, provide 2-3 key insights about current trends or themes: - - Headlines: - {titles_text} - - Key Insights: - """ - - response = self.client.chat.completions.create( - messages=[ - {"role": "user", "content": prompt} - ], - model=self.model, - max_tokens=200, - temperature=0.4 - ) - - insights = response.choices[0].message.content.strip() - return insights - - except Exception as e: - print(f"Error generating insights: {e}") - return None - - def enhance_article(self, article: Dict[str, Any]) -> Dict[str, Any]: - """Enhance article with AI-generated metadata""" - enhanced_article = article.copy() - - if self.is_available(): - # Add summary - summary = self.summarize_article(article) - if summary: - enhanced_article['ai_summary'] = summary - - # Add sentiment - sentiment = self.analyze_sentiment(article) - if sentiment: - enhanced_article['sentiment'] = sentiment - - # Add keywords - keywords = self.extract_keywords(article) - if keywords: - enhanced_article['ai_keywords'] = keywords - - return enhanced_article - - def batch_enhance_articles(self, articles: List[Dict[str, Any]]) -> List[Dict[str, Any]]: - """Enhance multiple articles with AI features""" - enhanced_articles = [] - - for article in articles: - enhanced = self.enhance_article(article) - enhanced_articles.append(enhanced) - - return enhanced_articles - -# Test function -if __name__ == "__main__": - # Test Groq integration - groq_service = GroqLLMService() - - if groq_service.is_available(): - print("✅ Groq service is available") - - # Test with sample article - sample_article = { - "title": "AI Technology Advances in Healthcare", - "content": "Recent developments in artificial intelligence are transforming the healthcare industry with new diagnostic tools and treatment methods." - } - - enhanced = groq_service.enhance_article(sample_article) - print(f"Enhanced article: {enhanced}") - else: - print("⚠️ Groq service not available (API key needed)") diff --git a/backend/main.py b/backend/main.py index 632a42d..6c75d48 100644 --- a/backend/main.py +++ b/backend/main.py @@ -8,7 +8,20 @@ import uvicorn from config import settings from news_fetcher import NewsFetcher from recommender import NewsRecommender -from groq_integration import GroqLLMService + +# Groq integration +try: + from groq import Groq + groq_client = Groq(api_key=settings.groq_api_key) if settings.groq_api_key else None + groq_available = groq_client is not None + if groq_available: + print("✅ Groq LLM service initialized") + else: + print("⚠️ Groq API key not provided") +except Exception as e: + print(f"⚠️ Groq initialization failed: {e}") + groq_client = None + groq_available = False # Initialize FastAPI app app = FastAPI( @@ -29,7 +42,6 @@ app.add_middleware( # Initialize components news_fetcher = NewsFetcher() recommender = NewsRecommender() -groq_service = GroqLLMService() # Pydantic models class NewsQuery(BaseModel): @@ -217,7 +229,7 @@ async def get_stats(): # Add RSS feed information stats['rss_feeds'] = settings.rss_feeds stats['embedding_model'] = settings.embedding_model - stats['groq_available'] = groq_service.is_available() + stats['groq_available'] = groq_available return { "success": True, @@ -227,86 +239,7 @@ async def get_stats(): except Exception as e: raise HTTPException(status_code=500, detail=f"Error getting stats: {str(e)}") -@app.post("/enhance-article") -async def enhance_article_with_ai(article_data: Dict[str, Any]): - """Enhance an article with AI-generated summary, sentiment, and keywords""" - try: - if not groq_service.is_available(): - raise HTTPException(status_code=503, detail="Groq LLM service not available") - - enhanced_article = groq_service.enhance_article(article_data) - - return { - "success": True, - "original_article": article_data, - "enhanced_article": enhanced_article - } - - except Exception as e: - raise HTTPException(status_code=500, detail=f"Error enhancing article: {str(e)}") - -@app.post("/generate-insights") -async def generate_news_insights(): - """Generate insights from recent news articles""" - try: - if not groq_service.is_available(): - raise HTTPException(status_code=503, detail="Groq LLM service not available") - - # Get recent articles - recent_articles = recommender.get_trending_articles(top_k=10) - - if not recent_articles: - raise HTTPException(status_code=404, detail="No recent articles found") - - insights = groq_service.generate_insights(recent_articles) - - return { - "success": True, - "insights": insights, - "based_on_articles": len(recent_articles) - } - - except Exception as e: - raise HTTPException(status_code=500, detail=f"Error generating insights: {str(e)}") - -@app.post("/fetch-and-enhance-news") -async def fetch_and_enhance_news(): - """Fetch news and enhance with AI features""" - try: - # Fetch news articles - result = news_fetcher.fetch_and_save_news() - - if not result["success"]: - raise HTTPException(status_code=500, detail=result.get("message", "Failed to fetch news")) - - articles = result["articles"] - - # Enhance with AI if Groq is available - if groq_service.is_available(): - # Enhance first 5 articles as example - enhanced_articles = groq_service.batch_enhance_articles(articles[:5]) - - # Add enhanced articles to vector store - store_result = recommender.add_articles_to_store(enhanced_articles) - else: - # Add regular articles to vector store - store_result = recommender.add_articles_to_store(articles) - - if not store_result["success"]: - raise HTTPException(status_code=500, detail=store_result.get("message", "Failed to add articles to store")) - - return { - "success": True, - "message": "News fetched and processed successfully", - "articles_fetched": result["articles_count"], - "articles_enhanced": 5 if groq_service.is_available() else 0, - "articles_stored": store_result["articles_added"], - "total_articles": store_result["total_articles"], - "ai_features_enabled": groq_service.is_available() - } - - except Exception as e: - raise HTTPException(status_code=500, detail=f"Error fetching and enhancing news: {str(e)}") +# Groq endpoints removed for core functionality focus # Run the application if __name__ == "__main__": diff --git a/backend/requirements_updated.txt b/backend/requirements_updated.txt deleted file mode 100644 index 169e65d..0000000 Binary files a/backend/requirements_updated.txt and /dev/null differ diff --git a/quick_test.py b/quick_test.py deleted file mode 100644 index 445fb71..0000000 --- a/quick_test.py +++ /dev/null @@ -1,30 +0,0 @@ -"""Quick test of core functionality""" -import sys -sys.path.append('backend') - -print("🧪 Quick System Test") - -# Test 1: News Fetching -print("1. Testing news fetching...") -from news_fetcher import NewsFetcher -fetcher = NewsFetcher() -articles = fetcher.fetch_rss_feed("https://feeds.bbci.co.uk/news/rss.xml") -print(f"✅ Fetched {len(articles)} articles") - -# Test 2: Basic imports -print("2. Testing imports...") -from embeddings import EmbeddingGenerator -from vector_store import VectorStore -from recommender import NewsRecommender -print("✅ All modules imported") - -# Test 3: FastAPI server -print("3. Testing FastAPI...") -import requests -try: - response = requests.get("http://localhost:8000/", timeout=3) - print(f"✅ FastAPI server: {response.json()['message']}") -except: - print("⚠️ FastAPI server not running") - -print("🎉 Core system operational!") diff --git a/simple_main.py b/simple_main.py deleted file mode 100644 index 3a0492b..0000000 --- a/simple_main.py +++ /dev/null @@ -1,51 +0,0 @@ -"""Simple FastAPI server for testing""" -from fastapi import FastAPI -import feedparser -from datetime import datetime - -app = FastAPI(title="DS Task AI News - Simple Version") - -@app.get("/") -async def root(): - return {"message": "DS Task AI News API is running!", "status": "healthy"} - -@app.get("/test-rss") -async def test_rss(): - """Test RSS fetching""" - feeds = [ - "https://rss.cnn.com/rss/edition.rss", - "https://feeds.bbci.co.uk/news/rss.xml" - ] - - results = [] - for feed_url in feeds: - try: - feed = feedparser.parse(feed_url) - result = { - "url": feed_url, - "title": feed.feed.get('title', 'Unknown'), - "entries_count": len(feed.entries), - "success": True - } - - if len(feed.entries) > 0: - result["sample_article"] = { - "title": feed.entries[0].get('title', 'No title'), - "published": feed.entries[0].get('published', 'No date'), - "link": feed.entries[0].get('link', 'No link') - } - - results.append(result) - - except Exception as e: - results.append({ - "url": feed_url, - "success": False, - "error": str(e) - }) - - return {"results": results, "timestamp": datetime.now().isoformat()} - -if __name__ == "__main__": - import uvicorn - uvicorn.run(app, host="0.0.0.0", port=8000) diff --git a/test_ai_features.py b/test_ai_features.py deleted file mode 100644 index ce17c0b..0000000 --- a/test_ai_features.py +++ /dev/null @@ -1,112 +0,0 @@ -"""Test AI features: embeddings and vector search""" -import sys -import os -sys.path.append('backend') - -def test_ai_pipeline(): - print("🤖 Testing AI Features Pipeline") - print("=" * 50) - - # Step 1: Get some news articles - print("1. Fetching news articles...") - from news_fetcher import NewsFetcher - fetcher = NewsFetcher() - - # Get articles from BBC - articles = fetcher.fetch_rss_feed("https://feeds.bbci.co.uk/news/rss.xml") - print(f"✅ Got {len(articles)} articles") - - # Use first 5 articles for testing - test_articles = articles[:5] - for i, article in enumerate(test_articles): - print(f" {i+1}. {article['title'][:50]}...") - - # Step 2: Test embeddings - print("\n2. Testing embeddings generation...") - from embeddings import EmbeddingGenerator - - embedding_gen = EmbeddingGenerator() - print(f" Using model: {'Cohere' if embedding_gen.use_cohere else 'Sentence Transformers'}") - - # Generate embeddings - embeddings = embedding_gen.generate_embeddings(test_articles) - print(f"✅ Generated embeddings: {embeddings.shape}") - - # Step 3: Test vector store - print("\n3. Testing vector store...") - from vector_store import VectorStore - - # Clear any existing index for clean test - vector_store = VectorStore() - vector_store.clear_index() - - # Add articles to vector store - vector_store.add_articles(test_articles, embeddings) - stats = vector_store.get_stats() - print(f"✅ Vector store: {stats['total_articles']} articles, dimension {stats['index_dimension']}") - - # Step 4: Test similarity search - print("\n4. Testing similarity search...") - - # Test query - query = "technology artificial intelligence" - query_embedding = embedding_gen.generate_query_embedding(query) - print(f" Query: '{query}'") - - # Search for similar articles - similar_articles = vector_store.search_similar(query_embedding, top_k=3) - - if similar_articles: - print(f"✅ Found {len(similar_articles)} similar articles:") - for i, article in enumerate(similar_articles): - score = article.get('similarity_score', 0) - print(f" {i+1}. {article['title'][:45]}... (score: {score:.3f})") - else: - print("⚠️ No similar articles found (threshold might be too high)") - - # Step 5: Test recommender system - print("\n5. Testing recommender system...") - from recommender import NewsRecommender - - recommender = NewsRecommender() - - # Add articles to recommender - result = recommender.add_articles_to_store(test_articles) - if result["success"]: - print(f"✅ Added {result['articles_added']} articles to recommender") - - # Test query-based recommendations - recommendations = recommender.recommend_by_query("technology news", top_k=3) - if recommendations: - print(f"✅ Query recommendations: {len(recommendations)} articles") - for i, rec in enumerate(recommendations): - score = rec.get('similarity_score', 0) - print(f" {i+1}. {rec['title'][:45]}... (score: {score:.3f})") - - # Test article-based recommendations - if test_articles: - article_id = test_articles[0]['id'] - similar_recs = recommender.recommend_by_article_id(article_id, top_k=2) - if similar_recs: - print(f"✅ Article-based recommendations: {len(similar_recs)} articles") - else: - print("⚠️ No article-based recommendations found") - - print("\n" + "=" * 50) - print("🎉 AI FEATURES TEST COMPLETED!") - print("✅ News fetching: Working") - print("✅ Embeddings generation: Working") - print("✅ Vector storage: Working") - print("✅ Similarity search: Working") - print("✅ Recommendation system: Working") - - return True - -if __name__ == "__main__": - try: - test_ai_pipeline() - print("\n🚀 AI-powered news system is fully operational!") - except Exception as e: - print(f"\n❌ Error in AI pipeline: {e}") - import traceback - traceback.print_exc() diff --git a/test_all_dependencies.py b/test_all_dependencies.py deleted file mode 100644 index 575966e..0000000 --- a/test_all_dependencies.py +++ /dev/null @@ -1,123 +0,0 @@ -"""Test all dependencies for DS Task AI News""" - -def test_imports(): - """Test importing all required packages""" - print("🧪 Testing all dependencies...") - - try: - # FastAPI and server - import fastapi - import uvicorn - print("✅ FastAPI ecosystem: OK") - - # RSS and web scraping - import feedparser - import requests - import bs4 # beautifulsoup4 - print("✅ Web scraping: OK") - - # AI and ML - Core - import cohere - import sentence_transformers - import faiss - import numpy - print("✅ AI/ML Core: OK") - - # AI and ML - Supporting - import torch - import transformers - import sklearn - print("✅ AI/ML Supporting: OK") - - # Data processing - import pandas - import scipy - print("✅ Data processing: OK") - - # Environment and config - import dotenv - import pydantic - print("✅ Configuration: OK") - - # LLM Integration - import groq - print("✅ Groq LLM: OK") - - # Test specific functionality - print("\n🔧 Testing specific functionality...") - - # Test sentence transformers - from sentence_transformers import SentenceTransformer - print("✅ SentenceTransformer import: OK") - - # Test FAISS - import faiss - index = faiss.IndexFlatIP(384) # Test creating index - print("✅ FAISS index creation: OK") - - # Test Cohere client creation (without API key) - try: - client = cohere.Client("") # Empty key for test - print("✅ Cohere client creation: OK") - except: - print("✅ Cohere client creation: OK (expected error without API key)") - - # Test Groq client creation (without API key) - try: - from groq import Groq - client = Groq(api_key="") # Empty key for test - print("✅ Groq client creation: OK") - except: - print("✅ Groq client creation: OK (expected error without API key)") - - print("\n🎉 All dependencies successfully installed and working!") - return True - - except ImportError as e: - print(f"❌ Import error: {e}") - return False - except Exception as e: - print(f"❌ Error: {e}") - return False - -def test_versions(): - """Test package versions""" - print("\n📦 Package versions:") - - packages = [ - 'fastapi', 'uvicorn', 'feedparser', 'requests', 'beautifulsoup4', - 'cohere', 'sentence-transformers', 'faiss-cpu', 'numpy', 'torch', - 'transformers', 'scikit-learn', 'pandas', 'python-dotenv', - 'pydantic', 'groq' - ] - - import pkg_resources - - for package in packages: - try: - version = pkg_resources.get_distribution(package).version - print(f" {package}: {version}") - except: - try: - # Try alternative names - alt_names = { - 'beautifulsoup4': 'bs4', - 'scikit-learn': 'sklearn' - } - if package in alt_names: - import importlib - module = importlib.import_module(alt_names[package]) - print(f" {package}: installed (module available)") - else: - print(f" {package}: version check failed") - except: - print(f" {package}: not found") - -if __name__ == "__main__": - success = test_imports() - test_versions() - - if success: - print("\n✅ System ready for full AI-powered news processing!") - else: - print("\n❌ Some dependencies need attention") diff --git a/test_complete_pipeline.py b/test_complete_pipeline.py deleted file mode 100644 index 23f67e6..0000000 --- a/test_complete_pipeline.py +++ /dev/null @@ -1,171 +0,0 @@ -"""Test the complete DS Task AI News pipeline""" -import sys -import os -sys.path.append('backend') - -def test_complete_pipeline(): - """Test the entire news processing pipeline""" - print("🚀 Testing Complete DS Task AI News Pipeline") - print("=" * 60) - - try: - # Step 1: Test News Fetching - print("\n1️⃣ Testing News Fetching...") - from news_fetcher import NewsFetcher - - fetcher = NewsFetcher() - result = fetcher.fetch_and_save_news() - - if result["success"]: - print(f"✅ Fetched {result['articles_count']} articles") - articles = result["articles"] - - if articles: - print(f" Sample article: {articles[0]['title'][:50]}...") - print(f" Source: {articles[0]['source']}") - else: - print("❌ No articles in result") - return False - else: - print(f"❌ News fetching failed: {result.get('message', 'Unknown error')}") - return False - - # Step 2: Test Embeddings Generation - print("\n2️⃣ Testing Embeddings Generation...") - from embeddings import EmbeddingGenerator - - embedding_gen = EmbeddingGenerator() - - # Test with first few articles - test_articles = articles[:3] - embeddings = embedding_gen.generate_embeddings(test_articles) - - if embeddings is not None and len(embeddings) > 0: - print(f"✅ Generated embeddings shape: {embeddings.shape}") - else: - print("❌ Embeddings generation failed") - return False - - # Step 3: Test Vector Store - print("\n3️⃣ Testing Vector Store...") - from vector_store import VectorStore - - vector_store = VectorStore() - vector_store.add_articles(test_articles, embeddings) - - stats = vector_store.get_stats() - print(f"✅ Vector store stats: {stats['total_articles']} articles") - - # Test similarity search - query_embedding = embedding_gen.generate_query_embedding("artificial intelligence technology") - similar_articles = vector_store.search_similar(query_embedding, top_k=2) - - if similar_articles: - print(f"✅ Found {len(similar_articles)} similar articles") - for i, article in enumerate(similar_articles): - print(f" {i+1}. {article['title'][:40]}... (score: {article['similarity_score']:.3f})") - else: - print("⚠️ No similar articles found (might be due to threshold)") - - # Step 4: Test Recommender System - print("\n4️⃣ Testing Recommender System...") - from recommender import NewsRecommender - - recommender = NewsRecommender() - - # Add articles to recommender's store - store_result = recommender.add_articles_to_store(articles[:5]) - if store_result["success"]: - print(f"✅ Added {store_result['articles_added']} articles to recommender") - else: - print(f"❌ Failed to add articles: {store_result['message']}") - return False - - # Test query-based recommendations - recommendations = recommender.recommend_by_query("technology news", top_k=3) - if recommendations: - print(f"✅ Query recommendations: {len(recommendations)} articles") - for i, rec in enumerate(recommendations): - print(f" {i+1}. {rec['title'][:40]}... (score: {rec['similarity_score']:.3f})") - else: - print("⚠️ No query recommendations found") - - # Test trending articles - trending = recommender.get_trending_articles(top_k=3) - if trending: - print(f"✅ Trending articles: {len(trending)} articles") - else: - print("⚠️ No trending articles found") - - # Step 5: Test FastAPI Integration - print("\n5️⃣ Testing FastAPI Integration...") - - # Test if server is running - import requests - try: - response = requests.get("http://localhost:8000/health", timeout=5) - if response.status_code == 200: - print("✅ FastAPI server is running") - health_data = response.json() - print(f" Vector store has {health_data.get('vector_store', {}).get('total_articles', 0)} articles") - else: - print(f"⚠️ FastAPI server responded with status {response.status_code}") - except requests.exceptions.RequestException: - print("⚠️ FastAPI server not accessible (might not be running)") - - print("\n" + "=" * 60) - print("🎉 COMPLETE PIPELINE TEST SUCCESSFUL!") - print("✅ News fetching working") - print("✅ Embeddings generation working") - print("✅ Vector storage working") - print("✅ Similarity search working") - print("✅ Recommendation system working") - print("✅ All components integrated successfully") - - return True - - except Exception as e: - print(f"\n❌ Pipeline test failed with error: {e}") - import traceback - traceback.print_exc() - return False - -def test_api_endpoints(): - """Test API endpoints if server is running""" - print("\n🌐 Testing API Endpoints...") - - import requests - base_url = "http://localhost:8000" - - endpoints_to_test = [ - ("GET", "/", "Health check"), - ("GET", "/health", "Detailed health"), - ("POST", "/fetch-news", "Fetch news"), - ("GET", "/trending", "Trending articles"), - ("GET", "/stats", "System stats") - ] - - for method, endpoint, description in endpoints_to_test: - try: - if method == "GET": - response = requests.get(f"{base_url}{endpoint}", timeout=10) - else: - response = requests.post(f"{base_url}{endpoint}", timeout=10) - - if response.status_code == 200: - print(f"✅ {description}: OK") - else: - print(f"⚠️ {description}: Status {response.status_code}") - - except requests.exceptions.RequestException as e: - print(f"❌ {description}: Connection error") - -if __name__ == "__main__": - success = test_complete_pipeline() - - if success: - print("\n🚀 Testing API endpoints...") - test_api_endpoints() - print("\n✅ SYSTEM FULLY OPERATIONAL!") - else: - print("\n❌ Pipeline needs debugging") diff --git a/test_complete_system.py b/test_complete_system.py deleted file mode 100644 index 6011a22..0000000 --- a/test_complete_system.py +++ /dev/null @@ -1,73 +0,0 @@ -"""Test the complete DS Task AI News system""" -import sys -import os -sys.path.append('backend') - -def test_imports(): - """Test if all modules can be imported""" - try: - from config import settings - print("✅ Config imported successfully") - - from news_fetcher import NewsFetcher - print("✅ NewsFetcher imported successfully") - - # Test basic functionality - fetcher = NewsFetcher() - print(f"✅ NewsFetcher initialized - Raw news dir: {fetcher.raw_news_dir}") - - return True - - except Exception as e: - print(f"❌ Import error: {e}") - return False - -def test_rss_fetching(): - """Test RSS fetching functionality""" - try: - sys.path.append('backend') - from news_fetcher import NewsFetcher - - fetcher = NewsFetcher() - - # Test with one feed - articles = fetcher.fetch_rss_feed("https://feeds.bbci.co.uk/news/rss.xml") - - if articles: - print(f"✅ RSS fetching works - Got {len(articles)} articles") - print(f" Sample article: {articles[0]['title'][:50]}...") - return True - else: - print("❌ No articles fetched") - return False - - except Exception as e: - print(f"❌ RSS fetching error: {e}") - return False - -def main(): - """Run all tests""" - print("🚀 Testing DS Task AI News System") - print("=" * 50) - - # Test 1: Imports - print("\n1. Testing imports...") - import_success = test_imports() - - # Test 2: RSS Fetching - print("\n2. Testing RSS fetching...") - rss_success = test_rss_fetching() - - # Summary - print("\n" + "=" * 50) - print("📊 Test Summary:") - print(f" Imports: {'✅ PASS' if import_success else '❌ FAIL'}") - print(f" RSS Fetching: {'✅ PASS' if rss_success else '❌ FAIL'}") - - if import_success and rss_success: - print("\n🎉 System is ready for demo!") - else: - print("\n⚠️ Some components need attention") - -if __name__ == "__main__": - main() diff --git a/test_fetcher.py b/test_fetcher.py deleted file mode 100644 index e8ec3ac..0000000 --- a/test_fetcher.py +++ /dev/null @@ -1,43 +0,0 @@ -"""Quick test of news fetcher without dependencies""" -import feedparser -import json -import os -from datetime import datetime - -def simple_fetch_test(): - """Test RSS fetching with minimal dependencies""" - feeds_to_test = [ - "https://rss.cnn.com/rss/edition.rss", - "https://feeds.bbci.co.uk/news/rss.xml", - "https://feeds.reuters.com/reuters/technologyNews" - ] - - for feed_url in feeds_to_test: - print(f"\nTesting RSS fetch from: {feed_url}") - - try: - feed = feedparser.parse(feed_url) - print(f"Feed title: {feed.feed.get('title', 'Unknown')}") - print(f"Number of entries: {len(feed.entries)}") - - if len(feed.entries) > 0: - # Show first few articles - for i, entry in enumerate(feed.entries[:2]): - print(f"\nArticle {i+1}:") - print(f" Title: {entry.get('title', 'No title')}") - print(f" Published: {entry.get('published', 'No date')}") - print(f" Link: {entry.get('link', 'No link')}") - print(f" Summary: {entry.get('summary', 'No summary')[:100]}...") - - return True - else: - print(" No entries found in this feed") - - except Exception as e: - print(f" Error: {e}") - continue - - return False - -if __name__ == "__main__": - simple_fetch_test()