322 查看 · 2026-07-07 更新
零售供应链分析工具
一款基于AI的工具,用于分析零售供应链数据,提供库存优化、供应商管理和销售预测方面的可操作见解。
功能
- 上传并分析多个Excel/CSV文件
- 支持采购订单、销售数据和库存文件
- 自动文件类型检测
- 多个数据源的综合交叉分析
- 详细的可视化和指标
- 供应链优化的可操作建议
开始使用
- 克隆仓库
- 安装依赖项:
npm install - 启动开发服务器:
npm run dev - 在浏览器中打开http://localhost:3000
使用方法
- 上传一个或多个包含零售数据的Excel/CSV文件
- 如果未自动检测到,请为每个文件选择适当的数据类型
- 点击“分析文件”以处理数据
- 查看不同类别的见解(概览、库存、供应商、销售)
- 在综合分析和个人文件类型分析之间切换
技术栈
- Next.js 用于前端和API路由
- Claude AI 用于智能数据分析
- Chart.js 用于数据可视化
- XLSX 用于Excel文件处理
环境变量
创建一个.env.local文件,并添加以下变量:
ANTHROPIC_API_KEY=your_api_key_here
许可证
我想创建一个MCP,在其中我可以上传包含零售商店数据(包括库存报告、销售报告等)的Excel电子表格,然后让AI像资深供应链专家一样分析这些数据,找出趋势、预测和其他见解。你能帮我实现这个功能吗?
我有一些数据示例,如果需要的话可以提供。
零售供应链分析MCP 是的,我绝对可以帮助你创建一个多模态对话角色(MCP),它能够像资深供应链专家一样分析零售商店数据。这是一个非常适合AI分析的应用场景。 高层次方法 我们可以这样构建这个项目:
- 数据上传与处理:创建一个界面来上传包含库存、销售及其他零售数据的Excel文件
- 数据分析:处理数据以提取有意义的见解
- 专家角色设计:设计AI以像资深供应链专家那样传达见解
- 可视化:提供趋势和预测的视觉表示
实施步骤
- 数据上传组件 首先,我们需要一种方式来上传和处理Excel文件:
javascript import React, { useState } from 'react'; import * as XLSX from 'xlsx';
function RetailDataProcessor({ onDataProcessed }) { const [isProcessing, setIsProcessing] = useState(false); const [dataType, setDataType] = useState('purchase_orders'); const [location, setLocation] = useState('');
const handleFileUpload = async (e) => { const file = e.target.files[0]; setIsProcessing(true);
const reader = new FileReader(); reader.onload = (event) => { try { const data = new Uint8Array(event.target.result); const workbook = XLSX.read(data, { type: 'array' }); // 默认处理第一个工作表 const worksheet = workbook.Sheets[workbook.SheetNames[0]]; const jsonData = XLSX.utils.sheet_to_json(worksheet); // 根据列标题检测数据类型 const detectedType = detectDataType(jsonData); // 根据类型处理和规范化数据 const processedData = { type: detectedType || dataType, location: location, data: normalizeData(jsonData, detectedType || dataType) }; onDataProcessed(processedData); } catch (error) { console.error("处理Excel文件时出错:", error); } finally { setIsProcessing(false); } }; reader.readAsArrayBuffer(file);
};
// 根据列标题检测数据类型 const detectDataType = (data) => { // 实现具体的检测逻辑 }; }
请注意,上述代码片段中的detectDataType函数需要根据实际需求进一步实现具体的检测逻辑。javascript
if (!data || data.length === 0) return null;
const headers = Object.keys(data[0]);
if (headers.includes('PO #') && headers.includes('# Ordered')) { return 'purchase_orders'; } else if (headers.includes('Invoice #') || headers.includes('Sale By')) { return 'sales_data'; } else if (headers.includes('On Hand') || headers.includes('In Stock')) { return 'inventory'; }
return null; };
// 根据类型规范化数据 const normalizeData = (data, type) => { switch(type) { case 'purchase_orders': return data.map(item => ({ poNumber: item['PO #'], status: item['Status'], vendor: item['Vendor'], productSku: item['Product SKU'], productName: item['Product Name'], category: item['Category'], quantityOrdered: item['# Ordered'], quantityReceived: item['# Received'], quantityOutstanding: item['# Outstanding'], costPerItem: item['Cost Per Item'], costReceived: item['Cost Received'], costOutstanding: item['Cost Outstanding'], orderedAt: item['Ordered At'], daysOnOrder: item['Days on Order'], eta: item['ETA'] }));
case 'sales_data': // 根据您的第四张截图规范化销售数据 return data.map(item => ({ invoiceNumber: item['Invoice #'], saleDate: item['Date'], saleBy: item['Sale By'], product: item['Product Name'], category: item['Category'], quantity: item['Qty'], price: item['Price'], cost: item['Cost'], profit: item['Profit'], location: item['Location'] || location })); default: return data;
} };
return (
<div className="form-group"> <label>商店位置:</label> <input type="text" value={location} onChange={(e) => setLocation(e.target.value)} placeholder="Aberdeen, Huron, Luverne, 等" /> </div> </div> <div className="file-upload"> <input type="file" accept=".xlsx,.xls,.csv" onChange={handleFileUpload} disabled={isProcessing} /> {isProcessing && <p>正在处理数据...</p>} </div>
export default RetailDataProcessor;
2. 供应链分析组件
接下来,我们将创建一个组件来处理AI分析:
javascript import React, { useState, useEffect } from 'react'; import { analyzeRetailData } from '../services/aiService';
function SupplyChainAnalysis({ data }) { const [analysis, setAnalysis] = useState(null); const [isAnalyzing, setIsAnalyzing] = useState(false);
useEffect(() => { if (data) { performAnalysis(); } }, [data]);
const performAnalysis = async () => { setIsAnalyzing(true); try { // 这里会调用您的AI服务 const result = await analyzeRetailData(data); setAnalysis(result); } catch (error) { console.error("分析数据时出错:", error); } finally { setIsAnalyzing(false); } };
return (
供应链分析
{isAnalyzing && <p>正在分析您的零售数据...</p>} {analysis && ( <div className="analysis-results"> <h3>关键洞察</h3> <div dangerouslySetInnerHTML={{ __html: analysis.insights }} /> <h3>库存建议</h3> <div dangerouslySetInnerHTML={{ __html: analysis.inventoryRecommendations }} /> <h3>销售趋势</h3> <div dangerouslySetInnerHTML={{ __html: analysis.salesTrends }} /> <h3>预测</h3> <div dangerouslySetInnerHTML={{ __html: analysis.forecasts }} /> </div> )} </div>
); }
export default SupplyChainAnalysis;### 3. AI 服务
现在,让我们创建一个与AI交互的服务:
javascript:README.md // services/aiService.js
export async function analyzeRetailData(data) { try { const response = await fetch('/api/analyze-mobile-retail', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ data }), });
if (!response.ok) { throw new Error('Failed to analyze data'); } return await response.json();
} catch (error) { console.error('Error in AI analysis service:', error); throw error; } }
4. 后端 API 端点
对于后端,我们需要一个端点来处理数据并与AI交互:
javascript // api/analyze-mobile-retail.js import { OpenAI } from 'openai';
const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY, });
export default async function handler(req, res) { if (req.method !== 'POST') { return res.status(405).json({ error: 'Method not allowed' }); }
try { const { data } = req.body;
// 根据数据类型创建专门的提示 let prompt = ''; if (data.type === 'purchase_orders') { prompt = createPurchaseOrderPrompt(data); } else if (data.type === 'sales_data') { prompt = createSalesDataPrompt(data); } else if (data.type === 'inventory') { prompt = createInventoryPrompt(data); } else { prompt = createGeneralPrompt(data); } // 调用AI const completion = await openai.chat.completions.create({ model: "gpt-4-turbo", messages: [ { role: "system", content: "你是一位拥有20多年移动设备零售经验的高级供应链专家。你分析数据并提供可操作的见解,重点是库存优化、供应商管理和智能手机及移动配件零售商的销售预测。" }, { role: "user", content: prompt } ], temperature: 0.2, }); // 处理AI响应 const analysisText = completion.choices[0].message.content; // 将响应解析为结构化数据 const analysisData = parseAnalysisResponse(analysisText, data.type); return res.status(200).json(analysisData);
} catch (error) { console.error('Error analyzing mobile retail data:', error); return res.status(500).json({ error: 'Failed to analyze data' }); } }
// 根据数据类型创建专门的提示 function createPurchaseOrderPrompt(data) { return ` 作为一位移动设备零售商的高级供应链专家,请分析以下${data.location || '我们的商店'}的采购订单数据:
${JSON.stringify(data.data, null, 2)} 分析重点: 1. 供应商表现(交货时间、订单履行) 2. 产品类别洞察(智能手机、配件等) 3. 库存管理建议 4. 成本优化机会 5. 订单周期时间改进 提供具体的可操作建议以改善供应链。
`; }
function createSalesDataPrompt(data) { return ` 作为一位移动设备零售商的高级供应链专家,请分析以下${data.location || '我们的商店'}的销售数据:
${JSON.stringify(data.data, null, 2)} 分析重点: 1. 按产品类别和具体型号的销售趋势 2. 按产品类型的盈利能力分析 3. 季节性模式和预测 4. 产品组合优化 5. 基于销售速度的库存补货建议 提供具体的可操作建议以改善销售和库存对齐。
`; }
function createInventoryPrompt(data) { // 类似结构用于库存数据 }
function createGeneralPrompt(data) { // 其他数据类型的备用 }
// 将AI响应解析为结构化数据 function parseAnalysisResponse(text, dataType) { // 基本解析逻辑 - 可以通过更复杂的解析进行增强 const sections = { keyInsights: extractSection(text, "Key Insights"), inventoryAnalysis: extractSection(text, "Inventory Analysis"), inventoryRecommendations: extractSection(text, "Inventory Recommendations"), vendorAnalysis: extractSection(text, "Vendor Analysis"), vendorRecommendations: extractSection(text, "Vendor Recommendations"), salesTrends: extractSection(text, "Sales Trends"), salesForecasts: extractSection(text, "Sales Forecasts") };
// 添加占位符指标和图表数据 // 在实际实现中,您可能需要从AI响应中提取这些数据 // 或直接从数据中计算 const metrics = { inventoryTurnover: "4.2", fulfillmentRate: "92.5", avgDaysOnOrder: "6.3" };
const charts = { inventoryTurnover: [], categoryPerformance: [], vendorPerformance: [], salesVsPurchases: [] };
return { ...sections, metrics, charts }; }
function extractSection(text, sectionName) {
const regex = new RegExp(${sectionName}[:\\s]+(.*?)(?=\\d+\\.\\s+[A-Z]|#|$), 's');
const match = text.match(regex);
return match ? match[1].trim() : '';
}### 5. 主应用程序组件
最后,让我们将所有内容整合在一起:
javascript import React, { useState } from 'react'; import DataUploader from './components/DataUploader'; import SupplyChainAnalysis from './components/SupplyChainAnalysis';
function RetailAnalysisMCP() { const [retailData, setRetailData] = useState(null);
const handleDataProcessed = (data) => { setRetailData(data); };
return (
零售供应链分析
上传您的零售数据以进行专业的供应链分析
<main> <DataUploader onDataProcessed={handleDataProcessed} /> {retailData && <SupplyChainAnalysis data={retailData} />} </main> </div>
); }
export default RetailAnalysisMCP;
下一步
为了让这个MCP更加强大:
-
数据示例:是的,看到您实际数据的示例将非常有助于微调分析,并确保AI能够正确解释您的特定零售数据格式。
-
数据可视化:使用如Chart.js或D3.js等库添加图表和图形,以可视化趋势和预测。
-
对话界面:添加一个聊天界面,用户可以在其中询问有关分析的后续问题。
-
领域特定提示:根据您的行业细化AI提示,使用特定的供应链术语和框架。
-
数据预处理:在分析之前添加更复杂的数据清洗和规范化步骤。
您是否愿意分享一些数据示例,以便我能够更具体地调整此解决方案以满足您的需求?
是的,我很乐意分享示例。我可以上传文件给您查看吗?
是的,您可以上传Excel文件供我审阅。这将帮助我根据您的数据结构和零售背景量身定制解决方案。 当您上传文件时,我将能够:
- 分析您的数据结构和格式
- 识别关键字段和关系
- 建议所需的特定预处理步骤
- 细化AI提示以更好地解释您的特定零售数据
- 推荐适当的可视化方法来展示洞察结果 请继续上传您的库存报告、销售数据或其他希望我检查的零售电子表格。一旦我看到实际数据,我就可以提供更具体的指导,以最大限度地提高MCP的有效性。
我将分享4张屏幕截图。
第一张 - 阿伯丁采购订单: 第二张 - 赫伦采购订单: 第三张 - 卢弗恩采购订单: 第四张 - 2023年7月至2024年2月的销售数据:
感谢您分享这些屏幕截图!我现在可以看到您的零售数据结构,这将帮助我设计一个更加量身定制的MCP解决方案。让我来分析一下我所看到的内容:
数据分析
-
采购订单报告 前三张截图显示了不同地点(阿伯丁、赫伦和卢弗恩)的采购订单详细信息,具有相似的结构:
- 关键字段:采购订单号、状态、收货地点、供应商信息、产品SKU/ID、产品名称、类别
- 数量数据:订购数量、已收数量、未收数量
- 财务数据:每件成本、已收成本、未收成本
- 时间信息:承诺日期、订购日期、订单天数、预计到达时间
- 其他信息:订购备注、收货备注、订单录入号 这些报告跟踪移动设备及其配件(智能手机、电缆、充电器等)的详细采购信息。
-
销售数据 第四张截图显示了销售数据,包括:
- 交易详情:发票号、收到日期、销售人员信息
- 产品信息:各种移动设备及其配件
- 价格数据:多个与价格相关的列
- 地点/商店信息
基于您的数据的MCP设计
现在我已经了解了您的数据结构,这里是一个更适合您的零售供应链MCP的方法:
// components/MobileRetailAnalysis.js javascript import React, { useState, useEffect } from 'react'; import { analyzeRetailData } from '../services/aiService';javascript import { InventoryTurnoverChart, ProductCategoryChart, VendorPerformanceChart, SalesVsPurchasesChart } from './charts';
function MobileRetailAnalysis({ data }) { const [analysis, setAnalysis] = useState(null); const [isAnalyzing, setIsAnalyzing] = useState(false); const [selectedView, setSelectedView] = useState('overview');
useEffect(() => { if (data) { performAnalysis(); } }, [data]);
const performAnalysis = async () => { setIsAnalyzing(true); try { const result = await analyzeRetailData(data); setAnalysis(result); } catch (error) { console.error("Error analyzing data:", error); } finally { setIsAnalyzing(false); } };
// 根据选择渲染不同的视图 const renderAnalysisView = () => { if (!analysis) return null;
switch(selectedView) { case 'overview': return ( <div className="analysis-overview"> <h3>关键洞察</h3> <div dangerouslySetInnerHTML={{ __html: analysis.keyInsights }} /> <div className="metrics-summary"> <div className="metric-card"> <h4>库存周转率</h4> <p className="metric-value">{analysis.metrics.inventoryTurnover}</p> </div> <div className="metric-card"> <h4>订单履行率</h4> <p className="metric-value">{analysis.metrics.fulfillmentRate}%</p> </div> <div className="metric-card"> <h4>平均订单天数</h4> <p className="metric-value">{analysis.metrics.avgDaysOnOrder}</p> </div> </div> </div> ); case 'inventory': return ( <div className="inventory-analysis"> <h3>库存分析</h3> <div dangerouslySetInnerHTML={{ __html: analysis.inventoryAnalysis }} /> <h4>按周转率排名的产品</h4> <InventoryTurnoverChart data={analysis.charts.inventoryTurnover} /> <h4>类别表现</h4> <ProductCategoryChart data={analysis.charts.categoryPerformance} /> <h3>库存建议</h3> <div dangerouslySetInnerHTML={{ __html: analysis.inventoryRecommendations }} /> </div> ); case 'vendor': return ( <div className="vendor-analysis"> <h3>供应商表现</h3> <div dangerouslySetInnerHTML={{ __html: analysis.vendorAnalysis }} /> <h4>供应商交付表现</h4> <VendorPerformanceChart data={analysis.charts.vendorPerformance} /> <h3>供应商建议</h3> <div dangerouslySetInnerHTML={{ __html: analysis.vendorRecommendations }} /> </div> ); case 'sales': return ( <div className="sales-analysis"> <h3>销售趋势</h3> <div dangerouslySetInnerHTML={{ __html: analysis.salesTrends }} /> <h4>销售与采购对比</h4> <SalesVsPurchasesChart data={analysis.charts.salesVsPurchases} /> <h3>销售预测</h3> <div dangerouslySetInnerHTML={{ __html: analysis.salesForecasts }} /> </div> ); default: return null; }
};
return (
移动零售供应链分析
库存 <button className={selectedView === vendor ? 'active' : ''} onClick={() => setSelectedView(vendor)}
供应商 <button className={selectedView === sales ? 'active' : ''} onClick={() => setSelectedView(sales)}
销售
{isAnalyzing ? (
正在分析您的移动零售数据...
export default MobileRetailAnalysis;
现在,让我们更新AI服务以更具体地针对您的移动零售数据:
// services/aiService.js export async function analyzeRetailData(data) { try { const response = await fetch('/api/analyze-mobile-retail', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ data }), });
if (!response.ok) { throw new Error('Failed to analyze data'); } return await response.json();
} catch (error) { console.error('Error in AI analysis service:', error); throw error; } }
请注意,翻译时保留了代码块和链接,并保持了格式结构。专业术语也得到了准确翻译。
来源
- 来源:github
- 链接:https://github.com/jaydrage/MCP_VMI