【AI产品经理学习】从0到1保姆级实战:用 Dify Agent + Python 打造自动化竞品分析AI助手(附完整代码)
通过这个实验,我们不仅构建了一个非常实用的AI助手,更重要的是,我们完整地经历了一次从需求分析、架构设计、技术攻坚到最终实现的AI应用工程落地过程。这比单纯调用一个API要酷得多!当然,从这个Demo到真正成熟的生产级应用还有很长的路要走,但这无疑是一个完美的起点。我是阿亚,我们下次再聊!觉得这篇文章对你有帮助吗?请帮忙点个「赞」或「在看」,让需要的人也能看到!下一个你想看我研究什么主题?欢迎在「
公众号:dify实验室
基于LLMOps平台-Dify的一站式学习平台。包含不限于:Dify工作流案例、DSL文件分享、模型接入、Dify交流讨论等各类资源分享。
大家好,我是dify实验室的超人阿亚。
今天,我们要挑战一个几乎让每个产品经理、市场分析师甚至创业者都“闻风丧胆”的任务——竞品分析。传统的方式不仅耗时耗力,而且信息零散,效率极低。我就在想,能不能让AI来帮我们干这件苦差事?
于是,这个实验诞生了:我们要打造一个AI助手,你只需要丢给它一个竞品名称,它就能自动上网搜集信息,并生成一份结构化的分析报告初稿。听起来很酷?让我们开始吧!
【核心1:踩坑与弯路】—— 我天真了
一开始,我以为这会很简单。Dify 提供了强大的工作流(Workflow)和内置的 Google Search 工具,我的初步构想是:
“一步到位法” (已失败)
用户输入 -> Google Search 找官网 -> Dify的HTTP节点直接访问官网 -> LLM分析 -> 输出报告。
结果呢?现实给了我一记响亮的耳光。几乎所有稍微正规一点的网站都部署了反爬虫机制(比如Cloudflare),我用HTTP节点发出的请求,就像一个没带通行证的游客,被无情地挡在了门外,返回的都是些无意义的错误代码或加载页面。
这个坑告诉我们: Dify 的代码执行节点有安全沙箱,无法执行网络请求等I/O操作;而直接用HTTP节点去“裸奔”访问,成功率极低。这是从“玩具”到“工具”必须迈过的第一道坎。
【核心2:顿悟与新方案】—— 专业的事交给专业的“特工”
在碰壁之后,我意识到,必须将“信息获取”这个专业任务外包出去。Dify 应该扮演“总指挥”的角色,负责编排整个流程;而网页抓取,需要一个能模拟真实浏览器、应对反爬虫的“前线特工”。
这个“特工”,就是我们即将用 Python 和 Docker 构建的一个独立的网页抓取微服务。它接收 Dify 指挥部发来的 URL,然后将“情报”(网页纯文本)传回。
于是,我们清晰的技术架构诞生了:
graph TD subgraph "用户端 (User)" A[用户输入竞品名称] end subgraph "Dify 平台 (总指挥)" B(开始节点) C(工具: Google Search) D(代码执行: 提取URL) E(HTTP请求: 调用特工) F(LLM分析: 整合情报) G(直接回复) end subgraph "外部服务 (前线特工)" H[网页抓取服务 (Python API)] end A --> B B -- 竞品名称 --> C C -- 搜索结果 --> D D -- 官网URL --> E E -- 请求抓取URL --> H H -- 返回网页纯文本 --> E C -- 搜索结果摘要 --> F E -- 网页纯文本 --> F F -- 结构化分析报告 --> G G --> A
这个架构完美地实现了“解耦”,让每个组件各司其职,既保证了 Dify 工作流的稳定,又解决了最关键的技术难题。
【核心3:实战步骤】—— 保姆级“抄作业”指南
光说不练假把式,我们来动手实现!
Step 1: 搭建“前线特工”(网页抓取API)
这个服务的目标很纯粹:给它一个URL,它还你一个干净的网页文本。
1. 编写代码 (main.py
)
from flask import Flask, request, jsonify
import requests
from bs4 import BeautifulSoup
import logging
logging.basicConfig(level=logging.INFO)
app = Flask(__name__)
@app.route('/scrape', methods=['POST'])
def scrape_website():
data = request.json
if not data or 'url' not in data:
return jsonify({"error": "Missing 'url' in request body"}), 400
url = data['url']
logging.info(f"Received request to scrape URL: {url}")
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'
}
try:
response = requests.get(url, headers=headers, timeout=15)
response.raise_for_status()
soup = BeautifulSoup(response.text, 'html.parser')
for script_or_style in soup(['script', 'style']):
script_or_style.decompose()
text = soup.get_text()
lines = (line.strip() for line in text.splitlines())
chunks = (phrase.strip() for line in lines for phrase in line.split(" "))
clean_text = '\n'.join(chunk for chunk in chunks if chunk)
logging.info(f"Successfully scraped content from {url}. Content length: {len(clean_text)}")
return jsonify({"content": clean_text})
except requests.exceptions.RequestException as e:
logging.error(f"Failed to scrape {url}. Error: {e}")
return jsonify({"error": f"Failed to fetch URL: {str(e)}"}), 500
except Exception as e:
logging.error(f"An unexpected error occurred. Error: {e}")
return jsonify({"error": f"An unexpected error occurred: {str(e)}"}), 500
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
2. 定义依赖 (requirements.txt
)
Flask==2.2.2
requests==2.28.1
beautifulsoup4==4.11.1
3. 容器化部署 (Dockerfile
)
FROM python:3.9-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY main.py .
EXPOSE 5000
CMD ["python", "main.py"]
4. 启动服务
在包含以上三个文件的目录下,打开终端执行:
# 1. 构建Docker镜像
docker build -t competitor-scraper .
# 2. 运行容器 (我们将外部端口映射为5001)
docker run -d -p 5001:5000 --name scraper-container competitor-scraper
现在,你的“前线特工”已经在 http://localhost:5001/scrape
待命了!
Step 2: 配置 Dify“总指挥部”
进入 Dify,创建一个新的对话型应用,开始编排工作流。
- 「开始」节点:
- 添加输入字段,变量名设为
competitor_name
。
- 添加输入字段,变量名设为
- 「Google Search」节点:
- Query输入: 引用变量
{{start.competitor_name}} official website
。
- Query输入: 引用变量
- 「代码执行」节点 (提取URL):
- 输入变量: 添加一个
search_results
,引用自上一步Google搜索节点的result
。 - 代码:
def main(search_results: list) -> dict: first_url = "" if isinstance(search_results, list) and len(search_results) > 0: first_item = search_results[0] if isinstance(first_item, dict) and 'link' in first_item: first_url = first_item['link'] return {'first_url': first_url}
- 输入变量: 添加一个
- 「HTTP请求」节点:
- 请求方法: POST
- URL:
http://<你的电脑局域网IP>:5001/scrape
(注意: 这里不能用localhost,必须是Dify能访问到的IP)。 - Headers:
Content-Type
:application/json
- Body (JSON):
{ "url": "{{code_1.first_url}}" }
- 「LLM」节点 (核心分析大脑):
- 模型: 选择一个能力强的,如 GPT-4, Claude 3 Sonnet。
- 上下文: 分别添加上游 Google Search 的结果和 HTTP请求 节点的
body.content
。 - 提示词 (Prompt):
你是一位顶级的市场分析专家。请根据我提供的【搜索引擎摘要】和【竞品官网内容】,为 "{{start.competitor_name}}" 生成一份简明扼要的竞品分析报告。 **严格遵守以下规则:** 1. 所有分析必须严格基于我提供的内容,严禁使用你的任何背景知识或进行凭空想象。 2. 如果提供的内容不足以分析某个项目,请明确指出“信息不足,无法分析”。 3. 使用清晰的Markdown格式输出报告。 **分析框架:** - **公司/产品简介:** 总结其核心业务和价值主张。 - **核心功能:** 列出3-5个主要的产品功能或服务。 - **目标用户:** 推断其主要服务的客户群体。 - **SWOT初步分析:** - **优势(Strengths):** 基于内容,总结其最突出的优点。 - **劣势(Weaknesses):** 基于内容,推断可能存在的不足。 - **机会(Opportunities):** 市场中可能存在的机会。 - **威胁(Threats):** 面临的潜在威胁。
- 「直接回复」节点:
- 引用上一步LLM节点的输出
{{llm_1.text}}
即可。
- 引用上一步LLM节点的输出
将所有节点连接起来,点击发布,大功告成!
【升华:生产级思考】—— 从Demo到实用工具
这个Demo本质上是一个小型的 RAG (检索增强生成) 应用。它让LLM在回答前,先去检索(Google)和增强(抓取网页)上下文,从而生成更准确、更具时效性的答案,极大地避免了模型幻觉。
如果想让它在真实世界更好用,我们还可以思考:
- 动态内容抓取: 当前的抓取服务对付不了JavaScript动态加载的网站,未来可以升级为使用 Selenium 或 Playwright 等更强大的工具。
- 信息源容错: 如果搜索到的第一个链接不是官网怎么办?可以设计一个循环或判断逻辑,尝试多个链接。
- 深度分析: 除了官网,我们还可以让它去抓取新闻稿、社交媒体评价等,为LLM提供更全面的分析材料。
【附赠:我的工具箱】
- 核心编排: Dify - 毫无疑问,可视化编排AI工作流的神器。
- 外部服务: Python (Flask + Requests + BeautifulSoup) - 构建API和网页抓取的经典组合,轻量且强大。
- 部署利器: Docker - 一次打包,到处运行,现代软件工程必备技能。
- 分析大脑: GPT-4 / Claude 3 Sonnet - 强大的LLM是保证分析质量的核心。
【结尾:总结与回归】
通过这个实验,我们不仅构建了一个非常实用的AI助手,更重要的是,我们完整地经历了一次从需求分析、架构设计、技术攻坚到最终实现的AI应用工程落地过程。这比单纯调用一个API要酷得多!
当然,从这个Demo到真正成熟的生产级应用还有很长的路要走,但这无疑是一个完美的起点。
我是阿亚,我们下次再聊!
觉得这篇文章对你有帮助吗?请帮忙点个「赞」或「在看」,让需要的人也能看到!
下一个你想看我研究什么主题?欢迎在「评论区」给我留言!
更多推荐
所有评论(0)