产品 Demo 效果展示

当我看到 Honeywell Aerospace 确定在6月29日独立上市的消息时,第一反应不是买股票,而是:能不能用 AI 搭一个面板,实时跟踪这类重大事件对行业的影响?

5小时后,我做出了这个产品:

AI aviation dashboard screenshot

功能包括:

  • 新闻流:自动抓取 HNW 相关新闻(来自 Tavily 搜索)
  • 智能摘要:用 OpenAI 提取每条新闻的核心实体(公司、人物、金额)
  • 趋势图表:按天统计新闻数量,显示情感倾向(正面/负面)
  • 搜索过滤:按关键词或日期范围筛选

整个项目代码放在 GitHub,前后端分离,本地5分钟就能跑起来。

技术选型

模块 选择 原因
新闻数据源 Tavily Search API 专为 AI 优化,返回结构化摘要,免费额度够用
实体提取 OpenAI GPT-4o-mini 速度快,成本低,直接输出 JSON
后端框架 Express.js 轻量,适合快速搭建 API 路由
前端框架 React 18 + Vite 开发体验好,HMR 快
图表库 Recharts 基于 D3,API 友好,支持响应式
部署 Railway / Vercel 一键部署,支持 Node + 静态

选择 Tavily 的关键理由是它对技术新闻的搜索结果更干净,不会像普通搜索那样出现大量垃圾站点。每天 1000 次免费请求,足够个人开发者做 demo。

核心代码实现(关键片段)

1. 后端:搜索新闻 + AI 实体提取

javascript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
// server/routes/news.js
const express = require('express');
const router = express.Router();
const { tavily } = require('@tavily/core');
const OpenAI = require('openai');

const tavilyClient = tavily({ apiKey: process.env.TAVILY_API_KEY });
const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });

router.get('/search', async (req, res) => {
  const query = req.query.q || 'Honeywell Aerospace';
  const daysBack = req.query.days || 7;

  // 1. 搜新闻
  const response = await tavilyClient.search(query, {
    topic: 'news',
    days: daysBack,
    maxResults: 20,
  });

  // 2. 用 AI 提取实体和情感
  const results = await Promise.all(response.results.map(async (item) => {
    const aiResponse = await openai.chat.completions.create({
      model: 'gpt-4o-mini',
      messages: [{
        role: 'system',
        content: `Extract entities from the news and classify sentiment (positive/negative/neutral).
Return JSON: {entities: [{name, type}], sentiment: string, summary: string}`
      }, {
        role: 'user',
        content: `Title: ${item.title}\nContent: ${item.content}`
      }],
      temperature: 0,
      response_format: { type: 'json_object' }
    });

    const parsed = JSON.parse(aiResponse.choices[0].message.content);
    return {
      ...item,
      entities: parsed.entities,
      sentiment: parsed.sentiment,
      summary: parsed.summary
    };
  }));

  res.json({ results });
});

module.exports = router;

关键点response_format: { type: 'json_object' } 保证 AI 输出严格 JSON,后端无需解析字符串,直接使用。同时设置 temperature: 0 避免随机性,保证同一新闻多次调用结果一致。

2. 前端:趋势图表组件

jsx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
// src/components/TrendChart.jsx
import { LineChart, Line, XAxis, YAxis, Tooltip, ResponsiveContainer } from 'recharts';

export default function TrendChart({ data }) {
  // data 格式: [{ date: '2026-06-16', count: 12, positive: 5, negative: 2 }]
  return (
    <ResponsiveContainer width="100%" height={300}>
      <LineChart data={data}>
        <XAxis dataKey="date" />
        <YAxis />
        <Tooltip />
        <Line type="monotone" dataKey="count" stroke="#8884d8" name="新闻数" />
        <Line type="monotone" dataKey="positive" stroke="#82ca9d" name="正面" />
        <Line type="monotone" dataKey="negative" stroke="#ff7300" name="负面" />
      </LineChart>
    </ResponsiveContainer>
  );
}

数据聚合逻辑:后端返回 raw results 后,前端按日期 groupBy,计算每天新闻总数和情感数量。这一步可以直接用 Lodash 的 groupBy,代码不超过10行。

项目结构和配置

text
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
aviation-monitor/
├── server/
│   ├── routes/
│   │   └── news.js          # 搜索+AI处理
│   ├── .env.example         # 存放 API Key 模板
│   ├── package.json
│   └── index.js             # Express 入口
├── client/
│   ├── src/
│   │   ├── App.jsx
│   │   ├── components/
│   │   │   ├── NewsCard.jsx       # 新闻卡片,显示摘要和实体标签
│   │   │   ├── TrendChart.jsx     # 趋势图
│   │   │   └── SearchBar.jsx      # 搜索框
│   │   └── api.js                 # 封装 fetch 请求
│   ├── package.json
│   └── vite.config.js             # 添加 proxy 到 localhost:5000
├── docker-compose.yml            # 可选,一键启动前后端
└── README.md

关键配置

  • .env 需要 TAVILY_API_KEYOPENAI_API_KEY
  • Vite 的 proxy 配置:'/api': 'http://localhost:5000'
  • 后端启用 CORS 中间件 cors() 允许开发环境跨域

上线要注意的坑

1. API 限流

Tavily 免费版每秒 1 次请求,OpenAI 免费版每分钟 3 次(取决于账号)。如果前端每次搜索都调 20 条新闻的 AI,很容易触发限流。

解决方案

  • 加缓存:对同一新闻 url 的 AI 结果缓存 1 小时(用内存 Map 或 Redis)
  • 后台批量处理:用队列(Bull)异步处理 AI 调用,前端先返回原始新闻,再轮询更新实体

2. 成本控制

每次搜索 20 条新闻,每条调用一次 OpenAI 迷你模型,成本约 ¥0.5 元。如果大量用户使用,很快就烧钱。

解决方案

  • 改为本地模型(如 llama 3.1 8B)做实体提取,部署在服务器上,无调用成本
  • 使用 Together AI 等便宜推理服务,价格是 OpenAI 的 1/3

3. 部署时跨域

如果前后端分开部署(前端 Vercel,后端 Railway),需要配置 CORS 允许生产域名。

javascript
1 2 3 4 5 6
// server/index.js
const cors = require('cors');
app.use(cors({
  origin: process.env.CLIENT_ORIGIN || 'http://localhost:5173',
  methods: ['GET']
}));

4. 内容版权

Tavily 返回的新闻内容片段受版权保护。在 UI 上只显示标题和摘要,不要直接展示全文。并且提供原文链接。

一点个人看法

Honeywell Aerospace 分拆是一个典型的重大业务事件,如果你只当新闻看看,就浪费了。作为开发者,这类事件是极好的 AI 应用 demo 素材——它天然具有时效性、热点性、可分析性。用 Tavily + LLM 做一个监控面板,比传统的 Google Alert 强在:

  • 自动提取结构化数据(公司名、金额、日期)
  • 情感分析和趋势可视化
  • 可定制搜索词,扩展到任何垂直行业

我强烈建议每个想切入 AI 应用开发的人,先拿一个具体的行业事件做 demo。不用做复杂系统,5小时出一个能跑的原型,就能展示完整闭环。这比花一个月做完美产品重要得多。

代码完整版已发布:GitHub - yeyu/aviation-monitor(示例链接,非真实)。欢迎 star 和提 issue。

AI aviation news dashboard React code