diff --git a/ecommerce_tools.py b/ecommerce_tools.py new file mode 100644 index 0000000000000000000000000000000000000000..6accfd2223cd4b2514aec43fa2a68ab04687b8e3 --- /dev/null +++ b/ecommerce_tools.py @@ -0,0 +1,84 @@ +import requests +import re +from bs4 import BeautifulSoup +import json + +class ECommerceScraper: + """ + 一个专门用于从电商产品页面抓取关键信息的工具。 + 它可以提取商品标题、价格和顾客评分。 + """ + + def __init__(self): + # 这是一组基于常见电商网站(如亚马逊)HTML结构的启发式选择器 + self.selectors = { + 'title': ['#productTitle', 'h1.product-title', 'h1'], + 'price': [ + '.a-price-whole', '.price-large', '.price', + '[class*="price-value"]', '[class*="product-price"]' + ], + 'rating': [ + '#acrPopover', '[data-hook="rating-out-of-text"]', + '[class*="rating-stars"]', '[class*="average-rating"]' + ] + } + + def _scrape_element(self, soup, selectors): + """尝试用多个选择器定位元素并提取文本""" + for selector in selectors: + element = soup.select_one(selector) + if element: + return element.get_text(strip=True) + return None + + def __call__(self, url: str) -> str: + """ + 抓取给定的产品URL,提取标题、价格和评分。 + + Args: + url: 产品页面的URL。 + + Returns: + 一个包含抓取数据的JSON字符串,或一条错误信息。 + """ + try: + headers = { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36', + 'Accept-Language': 'en-US,en;q=0.9' # 伪装成英文浏览器以获取更标准化的页面 + } + response = requests.get(url, headers=headers, timeout=15) + response.raise_for_status() + soup = BeautifulSoup(response.text, 'html.parser') + + title = self._scrape_element(soup, self.selectors['title']) + price_text = self._scrape_element(soup, self.selectors['price']) + rating_text = self._scrape_element(soup, self.selectors['rating']) + + # 对提取的文本进行一些清理 + price = "Not Found" + if price_text: + price_match = re.search(r'[\d,.]+', price_text) + if price_match: + price = price_match.group() + + rating = "Not Found" + if rating_text: + rating_match = re.search(r'[\d.]+\s*out of\s*[\d.]+', rating_text) + if rating_match: + rating = rating_match.group() + else: + rating = rating_text # 如果格式不匹配,返回原始文本 + + product_data = { + 'product_title': title or "Not Found", + 'price': price, + 'customer_rating': rating + } + + # 以JSON格式返回结构化数据,便于LLM理解 + return json.dumps(product_data, indent=2, ensure_ascii=False) + + except requests.RequestException as e: + return f"Error: Network issue while fetching the URL: {e}" + except Exception as e: + return f"Error: An unexpected error occurred during scraping: {e}" \ No newline at end of file diff --git a/product_selection_agent.py b/product_selection_agent.py new file mode 100644 index 0000000000000000000000000000000000000000..62f8da122ca44c476f5134227ad2603c4974fbd3 --- /dev/null +++ b/product_selection_agent.py @@ -0,0 +1,36 @@ +import lazyllm +from ecommerce_tools import ECommerceScraper + +# --- 主程序 --- +if __name__ == '__main__': + # 1. 实例化我们为电商选品定制的工具 + ecommerce_scraper_tool = ECommerceScraper() + print("--- 定制工具 [ECommerceScraper] 加载成功 ---") + + # 2. 定义 Agent 的角色和目标 (System Prompt) + system_prompt = ( + "你是一名资深的跨境电商选品专家。你的任务是帮助用户分析产品的市场潜力。" + "请使用你所掌握的工具从产品页面抓取数据(如标题、价格、评分)。" + "基于抓取到的数据,给用户提供一个简明扼要的分析。例如,你可以评论其价格是否有竞争力,或根据评分判断顾客满意度。" + "当你调用工具后,会得到一个JSON格式的数据,请将这些信息以易于阅读的方式呈现给用户,然后再附上你的专家分析。" + ) + print("--- Agent 角色设定:跨境电商选品专家 ---") + + # 3. 创建聊天 Agent 核心 + # 使用通义千问模型,并装备新工具和系统角色 + product_agent = lazyllm.OnlineChatModule( + source="qwen", + model="qwen-turbo", + api_key="sk-0939b9db273c46089ecc48a18dbcd5f8", # 使用您提供的 API Key + tools=[ecommerce_scraper_tool], + system_prompt=system_prompt + ) + print("--- 选品 Agent [OnlineChatModule] 创建成功 ---") + + # 4. 创建并启动 Web 界面 (使用新的端口范围以避免冲突) + print("--- 正在准备启动 Gradio Web 界面... ---") + web_ui = lazyllm.WebModule(product_agent, port=range(23471, 23475)) + + print("--- 服务启动中,请在浏览器中打开给出的地址 ---") + web_ui.start().wait() + print("--- Web 界面已关闭 ---") \ No newline at end of file diff --git "a/\350\267\250\345\242\203\347\224\265\345\225\206\351\200\211\345\223\201 Agent \346\212\200\346\234\257\346\226\207\346\241\243.pdf" "b/\350\267\250\345\242\203\347\224\265\345\225\206\351\200\211\345\223\201 Agent \346\212\200\346\234\257\346\226\207\346\241\243.pdf" new file mode 100644 index 0000000000000000000000000000000000000000..35881344ffbbe963f626ef233a00ed42ee3d3fae Binary files /dev/null and "b/\350\267\250\345\242\203\347\224\265\345\225\206\351\200\211\345\223\201 Agent \346\212\200\346\234\257\346\226\207\346\241\243.pdf" differ