零售供应链分析工具
一种用于分析零售供应链数据的人工智能工具,为库存优化、供应商管理和销售预测提供可行的见解。
特征
- 上传并分析多个 Excel/CSV 文件
- 支持采购订单、销售数据和库存文件
- 自动文件类型检测
- 多数据源联合交叉分析
- 详细的可视化和指标
- 供应链优化的可行建议
入门
- 克隆存储库
- 安装依赖项:
npm install
- 启动开发服务器:
npm run dev
- 在浏览器中打开http://localhost:3000
用法
- 上传一个或多个包含零售数据的 Excel/CSV 文件
- 如果未自动检测到,请为每个文件选择适当的数据类型
- 点击“分析文件”来处理数据
- 查看不同类别的见解(概览、库存、供应商、销售)
- 在组合分析和单个文件类型分析之间切换
技术
- 用于前端和 API 路由的 Next.js
- Claude AI 用于智能数据分析
- Chart.js 用于数据可视化
- XLSX 用于 Excel 文件处理
环境变量
使用以下变量创建.env.local
文件:
ANTHROPIC_API_KEY=your_api_key_here
执照
麻省理工学院
我想创建一个 MCP,可以上传包含零售店数据(包括库存报告、销售报告等)的 Excel 电子表格,然后让人工智能分析这些数据,从而得出趋势、预测和其他洞察,就像这个人工智能是零售商的高级供应链专家一样。您能帮我吗?
如果有帮助的话,我有数据示例。
零售供应链分析 MCP 是的,我绝对可以帮助您创建一个多模态对话角色 (MCP),像高级供应链专家一样分析零售店数据。这是 AI 分析的绝佳用例。高级方法 我们可以这样构建这个项目:数据上传和处理:创建一个界面来上传包含库存、销售和其他零售数据的 Excel 文件 数据分析:处理数据以提取有意义的见解 专家角色:设计 AI,使其像高级供应链专家一样传达见解 可视化:提供趋势和预测的可视化表示
实施步骤
- 数据上传组件首先,我们需要一种上传和处理 Excel 文件的方法:
从 'react' 导入 React,{ useState };从 'xlsx' 导入 * 作为 XLSX;
函数 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' });
// Process the first sheet by default
const worksheet = workbook.Sheets[workbook.SheetNames[0]];
const jsonData = XLSX.utils.sheet_to_json(worksheet);
// Detect data type based on column headers
const detectedType = detectDataType(jsonData);
// Process and normalize the data based on type
const processedData = {
type: detectedType || dataType,
location: location,
data: normalizeData(jsonData, detectedType || dataType)
};
onDataProcessed(processedData);
} catch (error) {
console.error("Error processing Excel file:", error);
} finally {
setIsProcessing(false);
}
};
reader.readAsArrayBuffer(file);
};
// 根据列标题检测数据类型 const detectDataType = (data) => { 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'], amountOrdered: item['# Ordered'], amountReceived: item['# Received'], amountOutstanding: 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':
// Normalize sales data based on your fourth screenshot
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;
}
};
返回(数据类型:<select value={dataType} onChange={(e) => setDataType(e.target.value)} > 采购订单销售数据库存
<div className="form-group">
<label>Store Location:</label>
<input
type="text"
value={location}
onChange={(e) => setLocation(e.target.value)}
placeholder="Aberdeen, Huron, Luverne, etc."
/>
</div>
</div>
<div className="file-upload">
<input
type="file"
accept=".xlsx,.xls,.csv"
onChange={handleFileUpload}
disabled={isProcessing}
/>
{isProcessing && <p>Processing data...</p>}
</div>
</div>
); }
导出默认的 RetailDataProcessor;
2.供应链分析组件
接下来,我们将创建一个组件来处理 AI 分析:
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 {
// This would call your AI service
const result = await analyzeRetailData(data);
setAnalysis(result);
} catch (error) {
console.error("Error analyzing data:", error);
} finally {
setIsAnalyzing(false);
}
};
return (
<div className="analysis-container">
<h2>Supply Chain Analysis</h2>
{isAnalyzing && <p>Analyzing your retail data...</p>}
{analysis && (
<div className="analysis-results">
<h3>Key Insights</h3>
<div dangerouslySetInnerHTML={{ __html: analysis.insights }} />
<h3>Inventory Recommendations</h3>
<div dangerouslySetInnerHTML={{ __html: analysis.inventoryRecommendations }} />
<h3>Sales Trends</h3>
<div dangerouslySetInnerHTML={{ __html: analysis.salesTrends }} />
<h3>Forecasts</h3>
<div dangerouslySetInnerHTML={{ __html: analysis.forecasts }} />
</div>
)}
</div>
);
}
export default SupplyChainAnalysis;
3.人工智能服务
现在,让我们创建一个与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;
}
}
4. 后端 API 端点
对于后端,我们需要一个端点来处理数据并与 AI 交互:
// 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;
// Create a specialized prompt based on data type
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);
}
// Call the AI
const completion = await openai.chat.completions.create({
model: "gpt-4-turbo",
messages: [
{
role: "system",
content: "You are a senior supply chain expert with 20+ years of experience in mobile device retail. You analyze data and provide actionable insights with a focus on inventory optimization, vendor management, and sales forecasting for smartphone and mobile accessory retailers."
},
{ role: "user", content: prompt }
],
temperature: 0.2,
});
// Process the AI response
const analysisText = completion.choices[0].message.content;
// Parse the response into structured data
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' });
}
}
// Create specialized prompts based on data type
function createPurchaseOrderPrompt(data) {
return `
As a senior supply chain expert for a mobile device retailer, analyze the following purchase order data for ${data.location || 'our stores'}:
${JSON.stringify(data.data, null, 2)}
Focus your analysis on:
1. Vendor performance (delivery times, order fulfillment)
2. Product category insights (smartphones, accessories, etc.)
3. Inventory management recommendations
4. Cost optimization opportunities
5. Order cycle time improvements
Provide specific actionable recommendations for improving the supply chain.
`;
}
function createSalesDataPrompt(data) {
return `
As a senior supply chain expert for a mobile device retailer, analyze the following sales data for ${data.location || 'our stores'}:
${JSON.stringify(data.data, null, 2)}
Focus your analysis on:
1. Sales trends by product category and specific models
2. Profitability analysis by product type
3. Seasonal patterns and forecasting
4. Product mix optimization
5. Inventory replenishment recommendations based on sales velocity
Provide specific actionable recommendations for improving sales and inventory alignment.
`;
}
function createInventoryPrompt(data) {
// Similar structure for inventory data
}
function createGeneralPrompt(data) {
// Fallback for other data types
}
// Parse the AI response into structured data
function parseAnalysisResponse(text, dataType) {
// Basic parsing logic - this could be enhanced with more sophisticated parsing
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")
};
// Add placeholder metrics and chart data
// In a real implementation, you might extract these from the AI response
// or calculate them directly from the data
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. 主应用程序组件
最后,让我们把所有内容放在一起:
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 (
<div className="retail-analysis-app">
<header>
<h1>Retail Supply Chain Analysis</h1>
<p>Upload your retail data for expert supply chain analysis</p>
</header>
<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 从 'react' 导入 React、{ useState、useEffect };从 '../services/aiService' 导入 { analyzeRetailData };从 './charts' 导入 { InventoryTurnoverChart、ProductCategoryChart、VendorPerformanceChart、SalesVsPurchasesChart };
函数 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); } finally { setIsAnalyzing(false); } };
// 根据选择渲染不同的视图 const renderAnalysisView = () => { if (!analysis) return null;
switch(selectedView) {
case 'overview':
return (
<div className="analysis-overview">
<h3>Key Insights</h3>
<div dangerouslySetInnerHTML={{ __html: analysis.keyInsights }} />
<div className="metrics-summary">
<div className="metric-card">
<h4>Inventory Turnover</h4>
<p className="metric-value">{analysis.metrics.inventoryTurnover}</p>
</div>
<div className="metric-card">
<h4>Order Fulfillment Rate</h4>
<p className="metric-value">{analysis.metrics.fulfillmentRate}%</p>
</div>
<div className="metric-card">
<h4>Average Days on Order</h4>
<p className="metric-value">{analysis.metrics.avgDaysOnOrder}</p>
</div>
</div>
</div>
);
case 'inventory':
return (
<div className="inventory-analysis">
<h3>Inventory Analysis</h3>
<div dangerouslySetInnerHTML={{ __html: analysis.inventoryAnalysis }} />
<h4>Top Products by Turnover</h4>
<InventoryTurnoverChart data={analysis.charts.inventoryTurnover} />
<h4>Category Performance</h4>
<ProductCategoryChart data={analysis.charts.categoryPerformance} />
<h3>Inventory Recommendations</h3>
<div dangerouslySetInnerHTML={{ __html: analysis.inventoryRecommendations }} />
</div>
);
case 'vendor':
return (
<div className="vendor-analysis">
<h3>Vendor Performance</h3>
<div dangerouslySetInnerHTML={{ __html: analysis.vendorAnalysis }} />
<h4>Vendor Delivery Performance</h4>
<VendorPerformanceChart data={analysis.charts.vendorPerformance} />
<h3>Vendor Recommendations</h3>
<div dangerouslySetInnerHTML={{ __html: analysis.vendorRecommendations }} />
</div>
);
case 'sales':
return (
<div className="sales-analysis">
<h3>Sales Trends</h3>
<div dangerouslySetInnerHTML={{ __html: analysis.salesTrends }} />
<h4>Sales vs Purchases</h4>
<SalesVsPurchasesChart data={analysis.charts.salesVsPurchases} />
<h3>Sales Forecasts</h3>
<div dangerouslySetInnerHTML={{ __html: analysis.salesForecasts }} />
</div>
);
default:
return null;
}
};
返回(移动零售供应链分析 <button className={selectedView === 'overview' ? 'active' : ''} onClick={() => setSelectedView('overview')} > 概览 <button className={selectedView === 'inventory' ? 'active' : ''} onClick={() => setSelectedView('inventory')} > 库存 <button className={selectedView === 'vendor' ? 'active' : ''} onClick={() => setSelectedView('vendor')} > 供应商 <button className={selectedView === 'sales' ? 'active' : ''} onClick={() => setSelectedView('sales')} > 销售
{isAnalyzing ? (
<div className="loading">
<p>Analyzing your mobile retail data...</p>
</div>
) : renderAnalysisView()}
</div>
); }
导出默认的MobileRetailAnalysis;
现在,让我们更新 AI 服务,使其更具体地针对您的移动零售数据:
// services/aiService.js 导出异步函数 analyzeRetailData(data) { 尝试 { const respond = 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('AI分析服务出错:', error); throw error; } }