diff --git a/pet_supplies_agent.py b/pet_supplies_agent.py new file mode 100644 index 0000000000000000000000000000000000000000..8a80c2218548ed800a2c6883ed533c597981f455 --- /dev/null +++ b/pet_supplies_agent.py @@ -0,0 +1,726 @@ +import os +import json +from datetime import datetime +from lazyllm import OnlineChatModule, WebModule, pipeline, TrainableModule +import re + +# 宠物用品选品智能助手Agent +class PetSuppliesAgent: + def __init__(self): + # 初始化LazyLLM聊天模块 + try: + # 首先尝试使用OnlineChatModule + self.chat_module = self._init_local_model() + print(f"成功加载模型") + except Exception as e: + print(f"无法初始化模型: {e}") + try: + # 如果模型加载失败,尝试在线模型 + self.chat_module = OnlineChatModule() + print("成功加载在线模型") + except Exception as e2: + print(f"无法初始化在线模型: {e2}") + print("请设置API密钥,例如:export OPENAI_API_KEY=your_key") + # 使用模拟的聊天模块作为后备 + self.chat_module = self._create_mock_chat_module() + print("使用模拟聊天模块作为后备方案") + + # 宠物用品类别数据 + self.product_categories = { + "宠物食品": { + "subcategories": ["干粮", "湿粮", "零食", "营养品", "处方粮", "冻干食品", "生骨肉"], + "features": ["营养均衡", "适口性", "安全性", "功能性"] + }, + "宠物用品": { + "subcategories": ["食盆水盆", "宠物窝", "玩具", "牵引绳", "猫砂盆", "宠物笼", "美容工具"], + "features": ["耐用性", "安全性", "舒适度", "易清洁"] + }, + "宠物护理": { + "subcategories": ["洗护用品", "驱虫药", "美容用品", "口腔护理", "耳部清洁", "眼部护理"], + "features": ["温和性", "有效性", "安全性", "便捷性"] + }, + "宠物健康": { + "subcategories": ["保健品", "医疗用品", "监测设备", "急救用品", "康复用品", "疫苗"], + "features": ["专业性", "安全性", "有效性", "易用性"] + }, + "宠物出行": { + "subcategories": ["宠物包", "车载用品", "旅行用品", "户外装备", "航空箱", "便携用品"], + "features": ["便携性", "安全性", "舒适度", "多功能性"] + } + } + + # 目标市场数据 + self.target_markets = { + "北美": { + "countries": ["美国", "加拿大"], + "preferences": ["高品质", "有机认证", "人性化设计", "环保材料"], + "price_sensitivity": "中低", + "logistics_cost_factor": 1.2 + }, + "欧洲": { + "countries": ["德国", "英国", "法国", "意大利", "西班牙"], + "preferences": ["动物福利认证", "环保包装", "设计感", "天然成分"], + "price_sensitivity": "中", + "logistics_cost_factor": 1.3 + }, + "东南亚": { + "countries": ["新加坡", "马来西亚", "泰国", "越南", "菲律宾"], + "preferences": ["性价比", "耐用性", "多功能", "本地化口味"], + "price_sensitivity": "高", + "logistics_cost_factor": 0.8 + } + } + + # 构建选品流程 + self.selection_pipeline = self._build_selection_pipeline() + + # 构建对话流程 + self.chat_pipeline = self._build_chat_pipeline() + + def _init_local_model(self): + """初始化本地模型""" + try: + # 尝试从环境变量获取API密钥 + api_key = os.environ.get("DOUBAO_API_KEY") or os.environ.get("LAZYLLM_DOUBAO_API_KEY") or os.environ.get("OPENAI_API_KEY") + if api_key: + print("检测到环境变量中的API密钥,使用在线模型") + try: + # 优先尝试豆包模型 + if os.environ.get("DOUBAO_API_KEY") or os.environ.get("LAZYLLM_DOUBAO_API_KEY"): + model = OnlineChatModule( + source="doubao", + api_key=api_key + ) + else: + # 如果没有豆包密钥但有OpenAI密钥,尝试OpenAI + model = OnlineChatModule( + source="openai", + api_key=api_key + ) + + # 测试API密钥是否有效 + try: + test_response = model("测试") + print("API密钥验证成功,使用在线模型") + return model + except Exception as test_error: + print(f"API密钥验证失败: {str(test_error)}") + print("将尝试其他模型选项") + # 继续尝试其他选项 + except Exception as api_error: + print(f"使用API密钥初始化在线模型失败: {str(api_error)}") + print("将尝试其他模型选项") + # 继续尝试其他选项 + + # 尝试加载本地模型 + local_model_path = os.environ.get("LOCAL_MODEL_PATH") + if local_model_path: + if os.path.exists(local_model_path): + print(f"尝试加载本地模型: {local_model_path}") + try: + model = TrainableModule(local_model_path) + # 尝试启动模型 + try: + model.start() + print("本地模型启动成功") + except Exception as start_error: + print(f"本地模型启动失败: {str(start_error)}") + print("将尝试使用在线模型作为后备") + raise start_error + return model + except Exception as e: + print(f"加载本地模型失败: {str(e)}") + else: + print(f"本地模型路径不存在: {local_model_path}") + + # 尝试使用常见的本地模型路径 + common_model_paths = [ + os.path.expanduser("~/.cache/huggingface/hub"), + "/models", + "./models" + ] + + for path in common_model_paths: + if os.path.exists(path): + print(f"尝试从常见路径加载模型: {path}") + try: + # 尝试列出目录中的模型 + model_dirs = [d for d in os.listdir(path) + if os.path.isdir(os.path.join(path, d))] + if model_dirs: + # 尝试第一个模型目录 + model_path = os.path.join(path, model_dirs[0]) + print(f"找到模型目录: {model_path}") + model = TrainableModule(model_path) + # 尝试启动模型 + try: + model.start() + print("本地模型启动成功") + return model + except Exception as start_error: + print(f"本地模型启动失败: {str(start_error)}") + print("将尝试下一个模型或在线模型") + continue + except Exception as e: + print(f"从常见路径加载模型失败: {str(e)}") + continue + + # 尝试使用在线模型 + print("尝试使用在线模型...") + try: + model = OnlineChatModule(source="doubao") + # 测试模型是否可用 + try: + test_response = model("测试") + print("在线模型验证成功") + return model + except Exception as test_error: + print(f"在线模型验证失败: {str(test_error)}") + # 使用模拟聊天模块作为后备 + print("使用模拟聊天模块作为后备") + model = self._create_mock_chat_module() + return model + except Exception as online_error: + print(f"在线模型初始化失败: {str(online_error)}") + # 使用模拟聊天模块作为后备 + print("使用模拟聊天模块作为后备") + model = self._create_mock_chat_module() + return model + except Exception as e: + print(f"初始化模型失败: {str(e)}") + # 使用模拟聊天模块作为后备 + print("使用模拟聊天模块作为后备") + model = self._create_mock_chat_module() + return model + + def _create_mock_chat_module(self): + """创建模拟聊天模块作为后备方案""" + class MockChatModule: + def __call__(self, prompt): + # 简单的模拟响应 + if "产品类别" in prompt or "选择最合适的一个" in prompt: + return "宠物食品" + elif "热门的" in prompt and "产品" in prompt: + return """```json + { + "products": [ + { + "name": "天然有机狗粮", + "features": ["无谷物配方", "高蛋白含量", "天然成分"], + "target_audience": "注重健康的宠物主人", + "price_range": {"min": 30, "max": 80} + }, + { + "name": "智能宠物喂食器", + "features": ["定时喂食", "远程控制", "大容量储粮"], + "target_audience": "上班族宠物主人", + "price_range": {"min": 50, "max": 150} + } + ] + } + ```""" + elif "供应商" in prompt or "成本" in prompt: + return """```json + { + "production_cost": {"min": 10, "max": 25}, + "logistics_cost": {"min": 8, "max": 18}, + "tariffs": {"percentage": 8}, + "risks": ["原材料供应不稳定", "动物疫情风险"], + "supplier_type": "宠物食品加工厂" + } + ```""" + elif "竞争对手" in prompt or "竞争分析" in prompt: + return """```json + { + "competitors": [ + { + "name": "皇家宠物食品", + "price_range": {"min": 35, "max": 90}, + "market_share": "20%", + "strengths": ["品牌知名度", "专业配方"], + "weaknesses": ["价格较高", "产品线单一"] + } + ] + } + ```""" + else: + return "这是一个模拟响应,请配置API密钥以获取真实的大模型响应。" + + return MockChatModule() + + def _build_selection_pipeline(self): + """构建宠物用品选品流程""" + + def market_analysis(user_input): + """市场分析:根据用户需求分析目标市场和产品类别""" + # 提取目标市场 + target_market = None + for market in self.target_markets: + if market in user_input: + target_market = market + break + + # 如果没有指定市场,默认为北美 + if not target_market: + target_market = "北美" + + # 提取产品类别 + product_category = None + for category in self.product_categories: + if category in user_input: + product_category = category + break + + # 如果没有指定类别,使用大模型分析 + if not product_category: + prompt = f""" + 根据用户需求"{user_input}",从以下宠物用品类别中选择最合适的一个: + {list(self.product_categories.keys())} + + 只回答类别名称,不需要解释。 + """ + product_category = self.chat_module(prompt).strip() + if product_category not in self.product_categories: + product_category = "宠物食品" # 默认类别 + + return { + "target_market": target_market, + "product_category": product_category, + "market_info": self.target_markets[target_market], + "category_info": self.product_categories[product_category] + } + + def product_research(analysis_result): + """产品研究:基于市场和类别研究热门产品""" + target_market = analysis_result["target_market"] + product_category = analysis_result["product_category"] + + # 构建产品研究提示 + prompt = f""" + 作为跨境电商选品专家,请为{target_market}市场研究5款热门的{product_category}产品。 + + 要求: + 1. 每款产品包含:产品名称、主要特点、目标客户群体、价格区间(美元) + 2. 考虑{target_market}市场的消费者偏好:{', '.join(analysis_result['market_info']['preferences'])} + 3. 考虑价格敏感度:{analysis_result['market_info']['price_sensitivity']} + 4. 产品应具有创新性和差异化优势 + 5. 以JSON格式返回,包含products数组,每个产品包含name, features, target_audience, price_range字段 + + 示例格式: + {{ + "products": [ + {{ + "name": "产品名称", + "features": ["特点1", "特点2"], + "target_audience": "目标客户群体", + "price_range": {{ + "min": 10, + "max": 50 + }} + }} + ] + }} + """ + + try: + response = self.chat_module(prompt) + # 尝试解析JSON + if "```json" in response: + json_str = response.split("```json")[1].split("```")[0].strip() + else: + # 尝试提取JSON部分 + json_match = re.search(r'\{.*\}', response, re.DOTALL) + json_str = json_match.group(0) if json_match else response + + product_data = json.loads(json_str) + return { + **analysis_result, + "researched_products": product_data.get("products", []) + } + except Exception as e: + print(f"解析产品研究数据失败: {e}") + # 返回默认产品数据 + default_products = [ + { + "name": f"优质{product_category}A", + "features": ["天然成分", "营养均衡", "易消化"], + "target_audience": "注重健康的宠物主人", + "price_range": {"min": 25, "max": 70} + }, + { + "name": f"智能{product_category}B", + "features": ["自动化", "远程控制", "大容量"], + "target_audience": "上班族宠物主人", + "price_range": {"min": 40, "max": 120} + } + ] + + return { + **analysis_result, + "researched_products": default_products + } + + def supplier_analysis(research_result): + """供应商分析:分析潜在供应商和成本结构""" + products = research_result["researched_products"] + target_market = research_result["target_market"] + logistics_factor = research_result["market_info"]["logistics_cost_factor"] + + analyzed_products = [] + + for product in products: + # 构建供应商分析提示 + prompt = f""" + 作为供应链专家,请分析"{product['name']}"的供应商情况: + + 1. 估算生产成本(基于产品特点和价格区间) + 2. 估算物流成本(考虑{target_market}市场,物流系数{logistics_factor}) + 3. 估算关税和税费 + 4. 识别潜在供应链风险 + 5. 推荐供应商类型(工厂、贸易公司等) + + 以JSON格式返回,包含production_cost, logistics_cost, tariffs, risks, supplier_type字段 + """ + + try: + response = self.chat_module(prompt) + # 尝试解析JSON + if "```json" in response: + json_str = response.split("```json")[1].split("```")[0].strip() + else: + # 尝试提取JSON部分 + json_match = re.search(r'\{.*\}', response, re.DOTALL) + json_str = json_match.group(0) if json_match else response + + analysis_data = json.loads(json_str) + except Exception as e: + print(f"解析供应商分析数据失败: {e}") + # 返回默认分析数据 + price_mid = (product["price_range"]["min"] + product["price_range"]["max"]) / 2 + analysis_data = { + "production_cost": price_mid * 0.3, + "logistics_cost": price_mid * 0.1 * logistics_factor, + "tariffs": price_mid * 0.05, + "risks": ["供应链不稳定", "质量波动"], + "supplier_type": "工厂直销" + } + + # 计算利润率 + # 确保cost_analysis中的值是数字类型 + try: + production_cost = float(analysis_data.get("production_cost", 0)) + # 如果production_cost是字典,尝试获取其中的值 + if isinstance(production_cost, dict): + production_cost = float(production_cost.get("min", production_cost.get("max", 0))) + except (ValueError, TypeError): + production_cost = 0 + + try: + logistics_cost = float(analysis_data.get("logistics_cost", 0)) + # 如果logistics_cost是字典,尝试获取其中的值 + if isinstance(logistics_cost, dict): + logistics_cost = float(logistics_cost.get("min", logistics_cost.get("max", 0))) + except (ValueError, TypeError): + logistics_cost = 0 + + try: + tariffs = float(analysis_data.get("tariffs", 0)) + # 如果tariffs是字典,尝试获取其中的值 + if isinstance(tariffs, dict): + tariffs = float(tariffs.get("percentage", tariffs.get("min", tariffs.get("max", 0)))) + except (ValueError, TypeError): + tariffs = 0 + + total_cost = production_cost + logistics_cost + tariffs + avg_price = (product["price_range"]["min"] + product["price_range"]["max"]) / 2 + profit_margin = (avg_price - total_cost) / avg_price * 100 + + analyzed_products.append({ + **product, + "cost_analysis": analysis_data, + "total_cost": total_cost, + "average_price": avg_price, + "profit_margin": profit_margin + }) + + return { + **research_result, + "analyzed_products": analyzed_products + } + + def competition_analysis(analysis_result): + """竞争分析:分析市场竞争格局和差异化机会""" + products = analysis_result["analyzed_products"] + target_market = analysis_result["target_market"] + product_category = analysis_result["product_category"] + + competition_results = [] + + for product in products: + # 构建竞争分析提示 + prompt = f""" + 作为市场分析师,请分析"{product['name']}"在{target_market}{product_category}市场的竞争情况: + + 1. 识别主要竞争对手(2-3个) + 2. 分析竞争对手定价策略 + 3. 识别市场空白和差异化机会 + 4. 评估市场进入难度 + 5. 提供差异化建议 + + 以JSON格式返回,包含competitors, pricing_strategy, market_gaps, entry_difficulty, differentiation字段 + """ + + try: + response = self.chat_module(prompt) + # 尝试解析JSON + if "```json" in response: + json_str = response.split("```json")[1].split("```")[0].strip() + else: + # 尝试提取JSON部分 + json_match = re.search(r'\{.*\}', response, re.DOTALL) + json_str = json_match.group(0) if json_match else response + + competition_data = json.loads(json_str) + except Exception as e: + print(f"解析竞争分析数据失败: {e}") + # 返回默认分析数据 + competition_data = { + "competitors": ["品牌A", "品牌B"], + "pricing_strategy": "中高端定价", + "market_gaps": ["环保材料", "个性化定制"], + "entry_difficulty": "中等", + "differentiation": ["创新设计", "优质材料"] + } + + competition_results.append({ + **product, + "competition_analysis": competition_data + }) + + return { + **analysis_result, + "competition_results": competition_results + } + + def generate_recommendation(competition_result): + """生成最终推荐:基于所有分析生成选品推荐""" + products = competition_result["competition_results"] + target_market = competition_result["target_market"] + product_category = competition_result["product_category"] + + # 按利润率排序 + sorted_products = sorted(products, key=lambda x: x["profit_margin"], reverse=True) + + # 构建推荐提示 + top_products = sorted_products[:3] # 取前3个产品 + products_summary = "\n".join([ + f"{i+1}. {p['name']}: 利润率{p['profit_margin']:.1f}%, 市场差异化: {', '.join(p['competition_analysis'].get('differentiation', ['无差异化信息']))}" + for i, p in enumerate(top_products) + ]) + + prompt = f""" + 基于以下分析结果,为{target_market}{product_category}市场提供选品建议: + + 产品分析结果: + {products_summary} + + 请提供: + 1. 最推荐的产品及理由 + 2. 市场进入策略 + 3. 风险控制建议 + 4. 长期发展规划 + + 以专业、简洁的顾问口吻回答,突出关键建议。 + """ + + recommendation = self.chat_module(prompt) + + return { + "market": target_market, + "category": product_category, + "top_recommendations": sorted_products[:3], + "detailed_recommendation": recommendation, + "generation_time": datetime.now().strftime("%Y-%m-%d %H:%M:%S") + } + + # 构建流程 + return pipeline([ + market_analysis, + product_research, + supplier_analysis, + competition_analysis, + generate_recommendation + ]) + + def _build_chat_pipeline(self): + """构建对话流程""" + + def intent_recognition(user_input): + """意图识别:识别用户意图是选品咨询还是其他问题""" + prompt = f""" + 请识别用户意图:"用户说:{user_input}" + + 意图类型: + 1. 选品咨询 - 用户想要获取产品选品建议 + 2. 市场咨询 - 用户想了解市场情况 + 3. 产品咨询 - 用户想了解特定产品信息 + 4. 其他 - 其他类型问题 + + 只回答意图类型编号(1-4),不需要解释。 + """ + + try: + intent = self.chat_module(prompt).strip() + intent_map = { + "1": "选品咨询", + "2": "市场咨询", + "3": "产品咨询", + "4": "其他" + } + return intent_map.get(intent, "其他") + except: + return "其他" + + def response_generation(user_input, intent): + """根据意图生成回复""" + if intent == "选品咨询": + # 调用选品流程 + try: + result = self.selection_pipeline(user_input) + return self._format_selection_result(result) + except Exception as e: + return f"选品分析过程中出现错误:{str(e)}。请尝试重新描述您的需求。" + + elif intent == "市场咨询": + prompt = f""" + 作为跨境电商市场专家,请回答以下市场咨询问题: + 用户问题:{user_input} + + 请提供专业、简洁的回答,重点关注北美、欧洲和东南亚市场。 + """ + return self.chat_module(prompt) + + elif intent == "产品咨询": + prompt = f""" + 作为宠物用品产品专家,请回答以下产品咨询问题: + 用户问题:{user_input} + + 请提供专业、准确的产品信息和建议。 + """ + return self.chat_module(prompt) + + else: + prompt = f""" + 作为跨境宠物用品选品智能助手,请回答以下问题: + 用户问题:{user_input} + + 请提供专业、有帮助的回答。如果问题超出范围,请礼貌说明。 + """ + return self.chat_module(prompt) + + # 构建对话流程 + def chat_process(user_input): + intent = intent_recognition(user_input) + response = response_generation(user_input, intent) + return { + "user_input": user_input, + "intent": intent, + "response": response, + "timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S") + } + + return chat_process + + def _format_selection_result(self, result): + """格式化选品结果为易读的文本""" + # 检查result是否为字典类型 + if not isinstance(result, dict): + return f"选品结果格式错误:期望字典类型,收到{type(result).__name__}类型\n\n原始内容:\n{str(result)}" + + # 检查必要的键是否存在 + required_keys = ['market', 'category', 'generation_time', 'top_recommendations', 'detailed_recommendation'] + for key in required_keys: + if key not in result: + return f"选品结果格式错误:缺少必要字段 {key}" + + response = f""" +## 🌍 {result['market']}市场{result['category']}选品分析报告 + +**生成时间:** {result['generation_time']} + +### 📊 推荐产品 + +""" + + # 检查top_recommendations是否为列表 + if not isinstance(result['top_recommendations'], list): + response += "推荐产品数据格式错误:期望列表类型\n\n" + else: + for i, product in enumerate(result['top_recommendations'], 1): + # 检查product是否为字典且包含必要字段 + if not isinstance(product, dict): + response += f"产品 {i} 数据格式错误:期望字典类型,收到{type(product).__name__}类型\n\n" + continue + + # 检查必要字段是否存在 + product_required_keys = ['name', 'target_audience', 'price_range', 'profit_margin', 'features', 'competition_analysis'] + missing_keys = [key for key in product_required_keys if key not in product] + if missing_keys: + response += f"产品 {i} 缺少必要字段: {', '.join(missing_keys)}\n\n" + continue + + # 检查price_range是否为字典且包含min和max + if not isinstance(product['price_range'], dict) or 'min' not in product['price_range'] or 'max' not in product['price_range']: + response += f"产品 {i} 价格范围格式错误\n\n" + continue + + # 检查competition_analysis是否为字典且包含differentiation和entry_difficulty + if not isinstance(product['competition_analysis'], dict) or 'differentiation' not in product['competition_analysis'] or 'entry_difficulty' not in product['competition_analysis']: + response += f"产品 {i} 竞争分析格式错误\n\n" + continue + + response += f""" +**{i}. {product['name']}** +- 目标客户:{product['target_audience']} +- 价格区间:${product['price_range']['min']}-${product['price_range']['max']} +- 预估利润率:{product['profit_margin']:.1f}% +- 产品特点:{', '.join(product['features'])} +- 差异化优势:{', '.join(product['competition_analysis']['differentiation'])} +- 市场进入难度:{product['competition_analysis']['entry_difficulty']} + +""" + + response += f""" +### 💡 专业建议 + +{result['detailed_recommendation']} + +--- +*本分析由跨境宠物用品选品智能助手基于LazyLLM框架生成* + """ + + return response + + def chat(self, user_input): + """处理用户输入并返回回复""" + result = self.chat_pipeline(user_input) + # 如果结果是字典,返回response字段;否则直接返回结果 + if isinstance(result, dict): + return result.get("response", str(result)) + return result + + def start_web_chat(self): + """启动Web聊天界面""" + # 创建Web模块 + web_module = WebModule(self.chat_pipeline) + # 启动Web服务 + web_module.start().wait() + +# 主函数 +if __name__ == "__main__": + # 创建宠物用品选品智能助手 + agent = CrossBorderPetSuppliesAgent() + + # 启动Web聊天界面 + print("正在启动跨境宠物用品选品智能助手Web界面...") + agent.start_web_chat() \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..d119c62c7522e0e936a557648ba201ed390b67cc --- /dev/null +++ b/requirements.txt @@ -0,0 +1,18 @@ +lazyllm>=0.1.0 +transformers>=4.30.0 +pydantic>=2.0.0 +requests>=2.31.0 +pandas>=2.0.0 +flask>=2.0.0 +numpy>=1.24.0 +matplotlib>=3.7.0 +openai>=1.0.0 # 用于真实API调用 +tiktoken>=0.5.0 # 用于token计算 +aiohttp>=3.8.0 # 用于异步HTTP请求 +asyncio # 用于异步处理 +torch>=2.0.0 # 本地模型所需 +accelerate>=0.20.0 # 本地模型加速 +sentencepiece>=0.1.99 # 本地模型分词 +protobuf>=3.20.0 # 本地模型依赖 +scipy>=1.10.0 # 本地模型依赖 +modelscope>=1.30.0 # 本地模型下载和管理 \ No newline at end of file diff --git a/web_app.py b/web_app.py new file mode 100644 index 0000000000000000000000000000000000000000..4065b6efd39c639e491bf300dc568ffdf170db50 --- /dev/null +++ b/web_app.py @@ -0,0 +1,568 @@ +from flask import Flask, render_template_string, request, jsonify +from pet_supplies_agent import PetSuppliesAgent + +app = Flask(__name__) + +# 创建宠物用品选品智能助手实例 +agent = PetSuppliesAgent() + +# HTML模板 +html_template = ''' + + +
+ + +基于LazyLLM框架的智能选品顾问,助您开拓宠物用品全球市场
+基于市场数据和AI分析,为您提供精准的宠物用品选品建议
+覆盖北美、欧洲、东南亚等主要市场,了解各地宠物主人偏好
+全面分析产品成本、物流费用和预期利润率,优化定价策略
+深入分析竞争对手和市场机会,找到差异化优势
+基于LazyLLM的智能顾问
+