发布于 2026-01-06 0 阅读
0

NewsHub - 人工智能新闻聚合平台

NewsHub——人工智能驱动的新闻聚合平台

NewsHub——人工智能驱动的新闻聚合平台

这是参加Redis AI 挑战赛:实时 AI 创新者的参赛作品。

我建造的

NewsHub是一个智能新闻聚合平台,它彻底改变了用户发现和消费新闻内容的方式。NewsHub 以 Redis 8 作为核心实时数据层,结合了人工智能的强大功能和 Redis 的先进特性,提供个性化、情境相关的新闻体验。

这是我第一次使用 Redis,学习曲线虽然陡峭,但收获颇丰。我发现 Redis 远不止是一个缓存——它是一个功能强大的多模型平台,能够处理复杂的 AI 工作负载。构建 NewsHub 让我明白了 Redis 如何集主数据库、向量搜索引擎和实时分析平台于一体。

主要特点

人工智能驱动的内容智能

  • 利用谷歌 Gemini AI 进行智能摘要,生成简洁、有意义的文章摘要
  • 具备实时情绪检测(正面、负面、中性)的高级情感分析
  • 动态关键词提取和人工智能驱动的主题识别
  • 面向上下文感知内容分析的语义理解

高级搜索与发现

  • 基于 Redis 的相似性匹配的向量语义搜索,使用 768 维嵌入
  • 按主题、情感、来源、关键词和日期范围进行多方面筛选
  • 使用余弦相似度算法的相似文章引擎
  • 模糊搜索,支持拼写错误容错和智能建议

智能个性化

  • 智能信息流管理,可自动从个性化信息流中移除已查看的文章
  • 行为分析追踪阅读模式和参与度指标
  • 基于用户交互模式的实时推荐

实时分析与洞察

  • 通过缓存命中率、响应时间和系统健康状况进行性能监控
  • 全面的用户旅程分析

性能与可扩展性

  • 采用智能请求、查询和结果缓存策略的多层缓存
  • 通过优化的 Redis 操作,响应时间低于 50 毫秒
  • 利用实时新闻摄取和人工智能分析流程进行实时处理

建筑设计

NewsHub 采用现代微服务架构,以 Redis 8 作为核心智能层。该系统旨在实现高性能、可扩展性和实时 AI 处理。

高级系统架构

系统架构

Redis 8 多模型平台架构

Redis架构

数据流与处理管道

数据流图

演示

在线应用

  • Web 应用NewsHub 在线演示
  • API后端NewsHub API
  • GitHub 仓库

    GitHub 标志 Varshithvhegde /新闻中心

    NewsHub——人工智能驱动的新闻聚合平台

    NewsHub——人工智能驱动的新闻聚合平台

    NewsHub——人工智能驱动的新闻聚合平台

    NewsHub是一个现代化的全栈新闻聚合和摘要平台,采用React、TypeScript、Node.js和Redis构建。它利用Google Gemini AI和Redis向量搜索,为用户提供AI驱动的新闻摘要、个性化信息流和高级搜索功能。

    🚀 功能

    核心功能

    • AI驱动的新闻摘要:使用谷歌Gemini AI进行智能内容分析
    • 向量搜索与相似性:基于 Redis 的语义搜索与嵌入
    • 个性化新闻推送:基于用户偏好的内容推荐
    • 实时新闻抓取:从多个来源自动收集新闻
    • 高级搜索:按主题、情感、来源和关键词筛选文章
    • 响应式设计:针对台式机、平板电脑和移动设备进行了优化

    用户体验

    • 无限滚动:无缝浏览,内容自动加载
    • 文章分析:查看互动指标和热门文章
    • 情感分析:文章情感(正面、负面、中性)的可视化指标
    • 主题筛选:按类别和兴趣浏览新闻
    • 实时更新……

YouTube演示


音频及辅助功能说明:
视频中如有任何背景噪音或我的口音,敬请谅解。为了获得最佳观看体验,我建议您开启字幕。字幕提供英文版本,确保您不会错过任何精彩内容!

屏幕截图

首页 - 智能新闻推送

新闻中心主页

主仪表盘包含人工智能精选新闻,并附有情感指标、互动指标和个性化推荐。

高级搜索界面

高级搜索

强大的搜索功能,可按主题和情感进行实时筛选

个性化文章视图

文章详情

提供文章详情视图,包括人工智能生成的摘要、情感分析和相似文章推荐。

个性化“为你推荐”信息流

个性化信息流

由人工智能精心策划的个性化新闻推送,可根据用户偏好和阅读行为自动调整。

相关文章发现

相关文章

基于向量的语义相似度引擎,使用 Redis 向量搜索显示上下文相关的文章。

主要功能展示

  • 采用向量相似性搜索的智能搜索,响应时间低于 100 毫秒
  • 根据用户偏好进行动态内容策划,实现实时个性化
  • 智能文章移除功能,可自动从个性化信息流中移除已阅读的文章
  • 基于情感的过滤,带有视觉情感指标
  • 利用人工智能进行趋势检测并结合互动指标

我如何使用 Redis 8

Redis 8 是 NewsHub 智能功能的主要实时数据层。我之前主要使用传统数据库,学习 Redis 让我大开眼界。我发现 Redis 能够在处理复杂的 AI 工作负载的同时,保持卓越的性能。

向量搜索与语义智能

这是我使用 Redis 过程中最具挑战性的部分。如何实现向量搜索和语义相似度对我来说完全是全新的领域,但结果却令人惊艳。

// redisService.js - Vector Search Implementation
class RedisService {
  async createVectorIndex() {
    try {
      // Create vector search index for semantic similarity
      await this.client.ft.create('news:vector_index', {
        '$.title': 'TEXT',
        '$.content': 'TEXT',
        '$.embedding': 'VECTOR',
        '$.sentiment': 'TAG',
        '$.topic': 'TAG',
        '$.source': 'TAG',
        '$.publishedAt': 'NUMERIC'
      }, {
        ON: 'JSON',
        PREFIX: 'news:articles:',
        FILTER: '@publishedAt:[0 +inf]',
        SCHEMA: {
          '$.title': { type: 'TEXT', WEIGHT: 2.0 },
          '$.content': { type: 'TEXT', WEIGHT: 1.0 },
          '$.embedding': { 
            type: 'VECTOR', 
            DIM: 768, 
            DISTANCE_METRIC: 'COSINE',
            TYPE: 'FLOAT32'
          },
          '$.sentiment': { type: 'TAG' },
          '$.topic': { type: 'TAG' },
          '$.source': { type: 'TAG' },
          '$.publishedAt': { type: 'NUMERIC' }
        }
      });
      console.log('✅ Vector search index created successfully');
    } catch (error) {
      console.log('Vector index already exists or error:', error.message);
    }
  }

  async findSimilarArticles(articleId, limit = 10) {
    try {
      // Get article embedding
      const article = await this.client.json.get(`news:articles:${articleId}`);
      if (!article || !article.embedding) {
        throw new Error('Article or embedding not found');
      }

      // Vector similarity search
      const query = `*=>[KNN $k @embedding $embedding AS score]`;
      const params = {
        k: limit,
        embedding: article.embedding
      };

      const results = await this.client.ft.search('news:vector_index', query, {
        PARAMS: params,
        RETURN: ['$.title', '$.content', '$.sentiment', '$.topic', 'score'],
        SORTBY: 'score',
        DIALECT: 2
      });

      return results.documents.map(doc => ({
        id: doc.id.replace('news:articles:', ''),
        title: doc.value['$.title'],
        content: doc.value['$.content'],
        sentiment: doc.value['$.sentiment'],
        topic: doc.value['$.topic'],
        similarity: doc.value.score
      }));
    } catch (error) {
      console.error('Error finding similar articles:', error);
      throw error;
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

支持全文搜索的 JSON 存储

学习使用 Redis 作为主数据库是一次范式转变。它能够存储复杂的 JSON 文档,同时还能保持全文搜索功能,这简直太棒了。

// redisService.js - JSON Storage Implementation
class RedisService {
  async storeArticle(article) {
    try {
      const articleId = `news:articles:${article.id}`;

      // Store article as JSON with full-text search capabilities
      await this.client.json.set(articleId, '$', {
        id: article.id,
        title: article.title,
        content: article.content,
        summary: article.summary,
        sentiment: article.sentiment,
        topic: article.topic,
        source: article.source,
        url: article.url,
        publishedAt: article.publishedAt,
        embedding: article.embedding,
        keywords: article.keywords,
        metadata: {
          wordCount: article.wordCount,
          readingTime: article.readingTime,
          language: article.language
        }
      });

      // Create search index for full-text search
      await this.createSearchIndex();

      console.log(`✅ Article stored: ${articleId}`);
      return article.id;
    } catch (error) {
      console.error('Error storing article:', error);
      throw error;
    }
  }

  async searchArticles(query, filters = {}) {
    try {
      let searchQuery = `(@title:${query} | @content:${query} | @summary:${query})`;

      // Add filters
      if (filters.sentiment) {
        searchQuery += ` @sentiment:{${filters.sentiment}}`;
      }
      if (filters.topic) {
        searchQuery += ` @topic:{${filters.topic}}`;
      }
      if (filters.source) {
        searchQuery += ` @source:{${filters.source}}`;
      }
      if (filters.dateRange) {
        searchQuery += ` @publishedAt:[${filters.dateRange.start} ${filters.dateRange.end}]`;
      }

      const results = await this.client.ft.search('news:search_index', searchQuery, {
        RETURN: ['$.title', '$.content', '$.sentiment', '$.topic', '$.source'],
        SORTBY: '@publishedAt',
        LIMIT: { from: 0, size: 50 }
      });

      return results.documents.map(doc => ({
        id: doc.id.replace('news:articles:', ''),
        title: doc.value['$.title'],
        content: doc.value['$.content'],
        sentiment: doc.value['$.sentiment'],
        topic: doc.value['$.topic'],
        source: doc.value['$.source']
      }));
    } catch (error) {
      console.error('Error searching articles:', error);
      throw error;
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

多层缓存策略

理解 Redis 缓存模式对提升性能至关重要。我实现了一种复杂的多层缓存机制,显著提高了响应速度。

// cacheClearService.js - Multi-layer Caching Implementation
class CacheClearService {
  constructor(redisClient) {
    this.client = redisClient;
    this.cacheLayers = {
      REQUEST: 'cache:requests:',
      QUERY: 'cache:queries:',
      RESULT: 'cache:results:',
      SIMILARITY: 'cache:similarity:',
      USER: 'cache:user:'
    };
  }

  async setCacheWithTTL(key, data, ttl = 3600) {
    try {
      const cacheKey = `cache:results:${key}`;
      await this.client.json.set(cacheKey, '$', {
        data: data,
        timestamp: Date.now(),
        ttl: ttl
      });
      await this.client.expire(cacheKey, ttl);
      console.log(`✅ Cache set: ${cacheKey}`);
    } catch (error) {
      console.error('Error setting cache:', error);
    }
  }

  async getCache(key) {
    try {
      const cacheKey = `cache:results:${key}`;
      const cached = await this.client.json.get(cacheKey);

      if (cached && cached.data) {
        console.log(`✅ Cache hit: ${cacheKey}`);
        return cached.data;
      }

      console.log(`❌ Cache miss: ${cacheKey}`);
      return null;
    } catch (error) {
      console.error('Error getting cache:', error);
      return null;
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

实时个性化引擎

正是在个性化系统中,我学习到了 Redis 的高级数据结构。实现从个性化订阅源中自动删除文章的功能,是一次非常宝贵的学习经历。

// redisService.js - User Preferences Implementation
class RedisService {
  async storeUserPreferences(userId, preferences) {
    try {
      const userKey = `user:preferences:${userId}`;

      await this.client.hset(userKey, {
        topics: JSON.stringify(preferences.topics),
        sources: JSON.stringify(preferences.sources),
        sentiment: preferences.sentiment,
        language: preferences.language,
        updatedAt: Date.now()
      });

      // Set expiration for user preferences (30 days)
      await this.client.expire(userKey, 30 * 24 * 60 * 60);

      console.log(`✅ User preferences stored: ${userKey}`);
      return true;
    } catch (error) {
      console.error('Error storing user preferences:', error);
      throw error;
    }
  }

  async getPersonalizedNews(userId, limit = 20) {
    try {
      const preferences = await this.getUserPreferences(userId);
      if (!preferences) {
        return await this.getTrendingArticles(limit);
      }

      // Build personalized search query
      let searchQuery = '*';
      const filters = [];

      if (preferences.topics.length > 0) {
        filters.push(`@topic:{${preferences.topics.join('|')}}`);
      }
      if (preferences.sources.length > 0) {
        filters.push(`@source:{${preferences.sources.join('|')}}`);
      }
      if (preferences.sentiment) {
        filters.push(`@sentiment:{${preferences.sentiment}}`);
      }

      if (filters.length > 0) {
        searchQuery = filters.join(' ');
      }

      const results = await this.client.ft.search('news:search_index', searchQuery, {
        RETURN: ['$.title', '$.content', '$.sentiment', '$.topic', '$.source'],
        SORTBY: '@publishedAt',
        LIMIT: { from: 0, size: limit }
      });

      return results.documents.map(doc => ({
        id: doc.id.replace('news:articles:', ''),
        title: doc.value['$.title'],
        content: doc.value['$.content'],
        sentiment: doc.value['$.sentiment'],
        topic: doc.value['$.topic'],
        source: doc.value['$.source']
      }));
    } catch (error) {
      console.error('Error getting personalized news:', error);
      throw error;
    }
  }

  // Auto-remove viewed articles from personalized feed
  async trackArticleView(userId, articleId) {
    try {
      // Add to viewed articles set
      await this.client.sadd(`user:viewed:${userId}`, articleId);

      // Remove from personalized feed
      await this.client.srem(`user:personalized:${userId}`, articleId);

      // Track engagement metrics
      await this.trackEngagement(articleId, 'view');

      console.log(`✅ Article view tracked and removed from personalized feed: ${articleId}`);
    } catch (error) {
      console.error('Error tracking article view:', error);
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

热门文章与分析

学习使用 Redis 有序集合来实现热门算法真是太棒了。能够直接在 Redis 中实现时间衰减算法,简直是颠覆性的突破。

// redisService.js - Trending Articles Implementation
class RedisService {
  async updateTrendingArticles() {
    try {
      // Get all articles with engagement metrics
      const articles = await this.client.ft.search('news:search_index', '*', {
        RETURN: ['$.title', '$.source', '$.publishedAt'],
        SORTBY: '@publishedAt',
        LIMIT: { from: 0, size: 1000 }
      });

      const trendingScores = {};

      for (const doc of articles.documents) {
        const articleId = doc.id.replace('news:articles:', '');
        const publishedAt = parseInt(doc.value['$.publishedAt']);
        const now = Date.now();

        // Calculate trending score based on recency and engagement
        const timeDecay = Math.exp(-(now - publishedAt) / (24 * 60 * 60 * 1000)); // 24 hours
        const engagementScore = await this.getEngagementScore(articleId);

        trendingScores[articleId] = timeDecay * engagementScore;
      }

      // Store trending articles in sorted set
      const trendingKey = 'trending:articles';
      await this.client.del(trendingKey); // Clear existing

      for (const [articleId, score] of Object.entries(trendingScores)) {
        await this.client.zadd(trendingKey, score, articleId);
      }

      console.log(`✅ Updated trending articles: ${Object.keys(trendingScores).length} articles`);
    } catch (error) {
      console.error('Error updating trending articles:', error);
      throw error;
    }
  }

  async trackEngagement(articleId, action = 'view') {
    try {
      const engagementKey = `metrics:engagement:${articleId}`;
      const actionKey = `${action}:count`;

      await this.client.hincrby(engagementKey, actionKey, 1);
      await this.client.hset(engagementKey, 'last_updated', Date.now());

      // Set expiration for engagement metrics (7 days)
      await this.client.expire(engagementKey, 7 * 24 * 60 * 60);

      console.log(`✅ Tracked engagement: ${action} for article ${articleId}`);
    } catch (error) {
      console.error('Error tracking engagement:', error);
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

绩效结果

在学习 Redis 的过程中,我取得了令人瞩目的性能指标:

缓存性能

  • 常用数据的缓存命中率达到 85-90%
  • 缓存响应的响应时间低于 50 毫秒
  • 通过 LRU 淘汰策略优化内存使用

向量搜索性能

  • 在 100 毫秒内对 1000 多篇文章进行相似性搜索
  • 使用余弦距离的768维向量存储
  • 使用 RedisJSON 进行高效压缩

可扩展性指标

  • 支持 1000+ 并发用户
  • 高效的 JSON 存储,具备全文搜索功能
  • 个性化推送响应时间低于一秒

学习经验

这个项目让我第一次接触到 Redis,它彻底改变了我对数据存储和缓存的看法。我了解到 Redis 不仅仅是一个缓存——它是一个完整的数据平台,能够:

  • 作为包含 JSON 文档的主数据库
  • 为人工智能应用提供矢量搜索功能
  • 利用有序集合和哈希处理实时分析
  • 管理跨多层的复杂缓存策略
  • 支持实时流媒体和发布/订阅消息传递

学习曲线非常陡峭,尤其是理解向量搜索和 Redis 的查询语法,但我所取得的性能和能力让我觉得所有的挑战都是值得的。构建 NewsHub 让我明白了 Redis 如何加速 AI 应用,并处理通常需要多个专用系统才能完成的复杂实时工作负载。


NewsHub 展示了 Redis 8 如何为下一代 AI 应用提供强大支持,使其成为一个完整的实时智能平台。向量搜索、JSON 存储、多层缓存和实时分析的结合,打造出无缝、智能的用户体验,能够实时适应用户行为和偏好。

由Varshith V Hegde倾情打造

技术栈:React、TypeScript、Node.js、Express、Redis 8、Google Gemini AI、Tailwind CSS

文章来源:https://dev.to/varshithvhegde/newshub-ai-powered-news-aggregation-platform-5c11