Type something to search...
从帖子到报告:利用 LLM 进行社交媒体数据挖掘

从帖子到报告:利用 LLM 进行社交媒体数据挖掘

如何指导LLMs过滤餐厅帖子并提取对业务增长至关重要的见解。

应用概述

我们正处于自动化的黄金时代,这得益于大型语言模型(LLMs)的崛起。从改变行业到解锁无尽的应用,LLMs彻底改变了我们与数据的互动方式,主要通过自然语言。

在本文中,我将向您展示如何指示LLM穿透社交媒体的噪音,提取最重要的信息。具体来说,我们将深入探讨如何挖掘Instagram上的餐厅帖子,以收集有价值的数据——例如特价优惠、折扣和活动——并将其汇编成一份简洁的每周报告。

为什么这很有用?

正如古老的谚语所说,“知识就是力量。”

使用本文中介绍的算法,您可以在特定领域获取所有重要数据,只需按下一个按钮,让LLM完成所有工作,从而将您寻找这些数据的时间减少到0。

稍后在本文中,我还将向您展示如何将这些数据以易于阅读的结构写入CSVEXCEL中,以便于存储或数据查询/过滤。

这种方法比旧的网页爬虫/抓取方法先进得多,因为在LLM的帮助下,我们可以根据自己的需求过滤提取的内容,只关注我们感兴趣的部分。

目录:

1. 数据爬取2. 数据存储3. 提示工程4. LLM 使用5. 响应格式化6. 整合所有内容

1. 数据爬取

免责声明:根据您的地区,此实现可能对您无效,因为不同的法规适用于网络爬取。(这是在罗马尼亚IP下测试的)

数据爬虫(或网络爬虫)是一个自动化程序或脚本,系统地浏览互联网以收集和索引来自网站的数据。

在本例中,我们将使用 Instaloader [2], 一个处理爬取方面的Python库,它将为我们提供关于公开Instagram个人资料的所有信息。

class InstagramCrawler:
    def __init__(self, page_name: str, proxy=None):
        self.page_name = page_name
        self.loader = instaloader.Instaloader()
        self._until = datetime.now()
        self._since = self._until - timedelta(days=7)

    def scrap(self) -> List[Dict[str, str | Any]]:
        profile = instaloader.Profile.from_username(self.loader.context, self.page_name)
        posts = takewhile(lambda p: p.date > self._since, dropwhile(lambda p: p.date > self._until, profile.get_posts()))

        return [
            {'content': post.caption, 'date': post.date, 'link': f"https://www.instagram.com/{self.page_name}"}
            for post in posts
        ]

在这里,我们使用 datetime.now() 获取运行时的确切日期,并减去7天,以便只获取上周的帖子。

我们还需要一个 config.py 模块来创建一个 Settings 类,在其中我们将保留所有常量,并将环境秘密传递到其他方法中,以便稍后访问,而不是做类似于: os.getenv(‘SOME_ENV_VALUE’) 的事情。

这通过 Pydantic 的 BaseSettings 类来实现。

如果您不知道 Pydantic 是什么,我建议阅读其文档。Pydantic 模型在 Python 编程中至关重要,我将在本文稍后讨论它们。

from pydantic_settings import BaseSettings, SettingsConfigDict


class Settings(BaseSettings):
    model_config = SettingsConfigDict(env_file='.env', env_file_encoding='utf-8', extra='ignore')

    # OPENAI
    OPENAI_API_KEY: str
    OPENAI_MODEl: str = "gtp-4o-mini"

    # DB
    MONGO_HOST: str = 'localhost'
    MONGO_PORT: int = 27017
    MONGO_USER: str = None
    MONGO_PASSWORD: str = None
    MONGO_DATABASE: str = 'restaurants'
    MONGO_URI: str = f"mongodb://{MONGO_USER}:{MONGO_PASSWORD}@{MONGO_HOST}:{MONGO_PORT}"

    # 要爬取的个人资料
    PROFILES_TO_SCRAP: dict = {
        "KFC": {"page_name": "kfc", "city": "Salt Lake"},
        "MC": {"page_name": "mcdonalds", "city": "San Bernardino"},
        "In-N-Out Burger": {"page_name": "innout", "city": "Baldwin Park"},
        "Taco Bell": {"page_name": "tacobell", "city": "Downey"},
        "Wendy's": {"page_name": "wendys", "city": "Columbus"},
    }


settings = Settings()

2. 数据存储

我还添加了一个数据库,在这种情况下是 MongoDB, 因为我们处理的是非结构化数据。这样,如果我们想稍后对提取的帖子做些什么,就可以存储它们(小心总比后悔好**)。**

from pymongo.errors import ConnectionFailure
from pymongo import MongoClient
from config import settings


class DatabaseConnection:
    _client: MongoClient = None

    @classmethod
    def connect(cls):
        if cls._client is None:
            try:
                cls._client = MongoClient(settings.MONGO_URI)
            except ConnectionFailure as exc:
                print(f'Exception while connecting to database: {exc}')
                raise

    @classmethod
    def get_database(cls, name: str):
        if cls._client is None:
            cls.connect()
        return cls._client[name]

    @classmethod
    def close(cls):
        if cls._client is not None:
            cls._client.close()


database = DatabaseConnection.get_database(settings.MONGO_DATABASE)

数据库在本地运行于一个 Docker 容器内。

version: '3.8'

services:
  mongodb:
    image: mongo:latest
    container_name: mongo_db
    ports:
      - "27017:27017"
    volumes:
      - mongo-data:/data/db
    environment:
      MONGO_INITDB_ROOT_USERNAME: ${MONGO_USER}
      MONGO_INITDB_ROOT_PASSWORD: ${MONGO_PASSWORD}

volumes:
  mongo-data:

3. 提示工程

提示工程可以总结为设计和优化提示,以有效引导语言模型或AI系统的行为。它涉及到精心制作输入,以优化模型的输出,确保生成准确、相关和连贯的响应,满足用户的需求。简单来说,可以将其视为调整输入以最大化输出质量的过程。

这就是该应用程序中魔法发生的地方。

在此步骤中,我们定义我们的大型语言模型(LLM)的行为,并指示它寻找和提取哪些信息。

我们还通过设置第二个提示来避免幻觉,以精炼响应。该组件位于 templates.py 模块中。

PROFILES_REPORT_TEMPLATE = (
    "You're a Restaurnat specialist. Analyze social media posts from various restaurant pages and create a concise report extracting the following information:\n"
    "1. Giveaways\n"
    "2. Events (including dates)\n"
    "3. Deals and discounts (e.g., price reductions, 1+1 offers)\n"
    "4. New menu items\n"
    "For each item, include:\n"
    "- Restaurant page name"
    "- Post link"
    "- Restaurant location (city)\n"
    "Only include information from the provided posts that fits these categories. Avoid descriptive posts about dishes unless they mention specific offers or discounts.\n"
    "Posts to analyze: {input_var}"

)

PROFILES_TEMPLATE_REFINE = (
    "You're a restaurant specialist who has generated a report on various restaurant social media posts.\n"
    "Previous report: {raport}\n"
    "This report needs to be more concise and follow a predefined structure:\n"
    "1. Analyze your previous report.\n"
    "2. Adapt the report to the following structure: {format_instructions}\n"
    "If there's no relevant information for a key, leave it as an empty list\n."
    "Your response should only contain the specified structure, without ```json ``` tags."
)

第一个提示旨在从社交媒体帖子(如Instagram或Facebook)中提取特定类型的信息,专注于相关的商业信息。

餐厅经常发布关于活动、促销或新项目的内容,这些内容通常与菜品描述或美学照片等无关内容混合在一起。该提示的目标是过滤噪音,提取关键的商业相关数据。

第二个提示是一个精炼阶段,以确保初始输出符合预定义结构,并更加简洁。

在初步提取后,我们仍可能遇到格式不完美或过于冗长的数据。该提示确保模型重新分析并正确格式化数据,同时删除不必要的信息。

4. LLM 使用

在这一步,工作量不大。我们需要一种方法来创建对话链。

在这里,我们设置与 LLM 相关的所有内容,如模型名称。我们传递提示并将所有可能使用的变量注入其中,例如在上述第一个提示的情况下从数据库提取的帖子。

为了实现这一点,我们将使用 Langchain [3],这是一个旨在围绕大型语言模型 (LLMs) 构建应用程序的框架。它提供了管理提示、将 LLM 连接到外部数据源、处理 操作链,以及将模型集成到聊天机器人或问答系统等应用程序中的工具,使开发 AI 驱动的应用程序变得更加容易。

from langchain.chains.llm import LLMChain
from langchain_core.prompts import PromptTemplate


def get_chain(llm, template: str, input_variables=None, verbose=True, output_key=""):
    return LLMChain(
        llm=llm,
        prompt=PromptTemplate(
            input_variables=input_variables, template=template, verbose=verbose
        ),
        output_key=output_key,
        verbose=verbose,
    )

对于这个应用中的 LLM,我选择使用 OpenAI 模型,因为它使用简单,因此要使用此方法,您需要一个 OPENAI_API_KEY

如果您不想使用 OpenAI,您可以尝试使用 Grok API,它具有相同的 API 接口。

5. 响应格式化

使用生成性人工智能通常会产生多样的响应,这些响应有时可能包含不准确的信息或缺乏相同的结构。

如果我们想在 Excel 或 CSV 中编写报告,这将是个坏消息,因为如果没有预定义的结构,在写入文件时可能会出现各种错误。

然而,好消息是,我们可以通过使用 Pydantic [4](再次)来解决这个问题。它允许开发者使用 Python 类定义数据模型,确保数据遵循指定的 类型约束,同时提供自动类型转换和详细的错误信息。

在这里,我们实现了 3 个 pydantic 类,这些类将被传递到上面呈现的第二个提示中,以格式化 LLM 响应为可以稍后写入 EXCEL 的预定义结构。

from pydantic import BaseModel, Field


class InformationProfiles(BaseModel):
    name: str = Field(description='信息提取页面的名称')
    information: str = Field(description='为指定键提取的信息。')
    link: str = Field(description='信息提取的帖子的链接。')
    city: str = Field(description='餐厅所在的城市。')


class FieldProfiles(BaseModel):
    name: str = Field(description='键的名称。可用选项包括:赠品、优惠和折扣、活动。')
    keys: list[InformationProfiles] = Field(description='餐厅及其相关信息的列表。')


class ReportProfiles(BaseModel):
    name: str = Field(description='报告名称:报告餐厅新闻')
    fields: list[FieldProfiles] = Field(description='此报告的所有相关键的列表。')

6. 整合所有内容

我们只需在我们的 report_generator.py 模块中整合所有内容。

为此,我们将创建一个类来封装所有逻辑:

import datetime
import io
import json

import pandas as pd

from typing import List, Dict, Any
from langchain_core.output_parsers import PydanticOutputParser
from langchain_openai import ChatOpenAI

from src.config import settings
from src.crawler import InstagramCrawler
from src.db import database
from src.llm import get_chain
from schemas import ReportProfiles
from templates import PROFILES_REPORT_TEMPLATE, PROFILES_TEMPLATE_REFINE


class ReportGenerator:
    def __init__(self):
        self.crawler = InstagramCrawler()
        self.database = database
        self.llm = ChatOpenAI(model_name=settings.OPENAI_MODEl, api_key=settings.OPENAI_API_KEY)

    def crawl_and_store_posts(self):
        posts = self.crawler.get_posts(settings.PROFILES_TO_SCRAP)
        posts_collection = self.database['instagram_posts']
        for post in posts:
            posts_collection.update_one(
                {'link': post['link']},
                {'$set': post},
                upsert=True
            )
        return len(posts)

    def get_posts_from_db(self) -> List[Dict[str, Any]]:
        posts_collection = self.database['instagram_posts']
        end_date = datetime.datetime.now()
        start_date = end_date - datetime.timedelta(days=7)
        return list(posts_collection.find({
            'date': {'$gte': start_date, '$lte': end_date}
        }))

    @staticmethod
    def get_posts_text(posts: List[Dict[str, Any]]) -> List[str]:
        unique_posts = set()
        for post in posts:
            post_text = post.get("content", "")
            page_text = post.get("restaurant_name", "")
            link_text = post.get("link", "")
            city_text = post.get("city", "")

            if post_text:
                unique_posts.add(f"{post_text} | {page_text} | {link_text} | {city_text}\n")

        return list(unique_posts)

    def create_report(self, posts: List[str]) -> str:
        chain_1 = get_chain(
            self.llm,
            PROFILES_REPORT_TEMPLATE,
            input_variables=["input_var"],
            output_key="report",
        )

        result_1 = chain_1.invoke({"input_var": posts})
        report = result_1["report"]

        output_parser = PydanticOutputParser(pydantic_object=ReportProfiles)
        format_output = {"format_instructions": output_parser.get_format_instructions()}

        chain_2 = get_chain(
            self.llm,
            PROFILES_TEMPLATE_REFINE,
            input_variables=["raport", "format_instructions"],
            output_key="formatted_report",
        )

        result_2 = chain_2.invoke({"raport": report, "format_instructions": format_output})

        return result_2["formatted_report"]

    @staticmethod
    def create_excel_file(data: Dict[str, Any]):
        rows = []
        excel_filename = f"Profiles_report_{datetime.datetime.now().strftime('%Y-%m-%d')}.xlsx"

        report_name = data.get("name", "未知报告")
        for field in data.get("fields", []):
            field_name = field.get("name", "未知字段")
            for key in field.get("keys", []):
                rows.append({
                    "报告类型": report_name,
                    "信息类型": field_name,
                    "来源": key.get("name", "无名称"),
                    "信息": key.get("information", "无信息"),
                    "链接": key.get("link", "无链接"),
                    "城市": key.get("city", "无城市"),
                })

        df = pd.DataFrame(rows)
        buffer = io.BytesIO()
        df.to_excel(buffer, index=False)
        buffer.seek(0)

        return buffer, excel_filename

    def generate_report(self):
        # 第一步:抓取并存储Instagram帖子
        posts_count = self.crawl_and_store_posts()
        print(f"抓取并存储了 {posts_count} 条帖子。")

        # 第二步:从数据库中检索帖子
        db_posts = self.get_posts_from_db()
        print(f"从数据库中检索了 {len(db_posts)} 条帖子。")

        # 第三步:处理帖子并创建报告
        posts_text = self.get_posts_text(db_posts)
        report_data_str = self.create_report(posts_text)
        print(f"从帖子生成的报告:{report_data_str}")

        # 解析JSON字符串
        try:
            report_data = json.loads(report_data_str)
        except json.JSONDecodeError:
            print("错误:无法将报告数据解析为JSON。")
            return None

        # 第四步:创建Excel文件
        excel_buffer, excel_filename = self.create_excel_file(report_data)

        # 第五步:保存Excel文件
        with open(excel_filename, 'wb') as f:
            f.write(excel_buffer.getvalue())

        print(f"Excel文件 '{excel_filename}' 创建成功。")
        return excel_filename

generate_report() 方法是这个应用程序的“入口点”,其中包含生成每周报告所需的所有步骤。

由于这个类比较大,我将详细说明 generate_report() 方法中呈现的每个步骤:

1. self.crawl_and_store_posts()

此方法从选定的Instagram个人资料中检索上周的帖子并将其存储在我们的数据库中。

2. self.get_posts_from_db() :

在这里,我们提取所有存储在数据库中的帖子,同时根据日期应用过滤逻辑,因为我们可能有来自前几周的帖子存储在数据库中,不想检索它们。

3. self.get_posts_text()self.create_report() :

第一个方法用于提取我们将作为输入变量传递给提示的所有信息,这些信息来自返回的数据库模型。

然后我们有第二个方法,LLM接收提示并创建报告。

4. self.create_excel_file() :

在这一步之前,我们首先需要调用 json.loads(report_data_str),以便使用JSON格式来写入EXCEL。如果我们在这里打印,报告可能看起来像这样:

{
  "name": "REPORT RESTAURANTS NEWS",
  "fields": [
    {
      "name": "Giveaways",
      "keys": []
    },
    {
      "name": "Deals and Discounts",
      "keys": []
    },
    {
      "name": "Events",
      "keys": [
        {
          "name": "Taco Bell",
          "information": "Early access event for the disha hot discovery box on 9/24 & 9/25.",
          "link": "https://www.instagram.com/tacobell",
          "city": "Downey"
        }
      ]
    }
  ]
}

该应用程序可以通过在终端中使用以下命令高效运行: make setupmake run,或者您可以使用 make help 查看所有可用命令的列表。

结论

我希望通过阅读本文(或像某些人那样跳过代码行 🤫),您已经学会了如何使用 LLM 从社交媒体平台提取信息。

我也认为,学习的最佳方式是将知识付诸实践,我鼓励您将我在这里实现的内容进行定制,以满足您自己的需求。

此应用程序可以根据任何用例进行更改,并可以与其他爬虫集成,以便从不同的社交媒体网站获取数据。

您可以在 GitHub 上找到完整代码 这里 [1]

最后,我要特别感谢 Decoding ML 的团队,让我第一次作为客座作者。对此机会以及我从他们身上学到的东西,我非常感激。

我鼓励您关注 Substack 上的 每周 𝗗𝗲𝗰𝗼𝗱𝗶𝗻𝗴 𝗠𝗟 𝗡𝗲𝘄𝘀𝗹𝗲𝘁𝘁𝗲𝗿,获取更多 顶尖 文章,涵盖生产 AI 和 MLOps。

参考文献

[1] 使用LLM从社交媒体帖子中提取数据 — Github仓库 (2024),Decoding ML GitHub组织

[2] Instaloader文档 (2024),Instaloader

[3] Langchain文档 (2024),Langchain

[4] Pydantic文档 (2024),Pydantic

Related Posts

使用 ChatGPT 搜索网络功能的 10 种创意方法

使用 ChatGPT 搜索网络功能的 10 种创意方法

例如,提示和输出 你知道可以使用 ChatGPT 的“搜索网络”功能来完成许多任务,而不仅仅是基本的网络搜索吗? 对于那些不知道的人,ChatGPT 新的“搜索网络”功能提供实时信息。 截至撰写此帖时,该功能仅对使用 ChatGPT 4o 和 4o-mini 的付费会员开放。 ![](https://images.weserv.nl/?url=https://cdn-im

阅读更多
在人工智能和技术领域保持领先地位的 10 项必学技能 📚

在人工智能和技术领域保持领先地位的 10 项必学技能 📚

在人工智能和科技这样一个动态的行业中,保持领先意味着不断提升你的技能。无论你是希望深入了解人工智能模型性能、掌握数据分析,还是希望通过人工智能转变传统领域如法律,这些课程都是你成功的捷径。以下是一个精心策划的高价值课程列表,可以助力你的职业发展,并让你始终处于创新的前沿。 1. 生成性人工智能简介课程: [生成性人工智能简介](https://genai.works

阅读更多
10 个强大的 Perplexity AI 提示,让您的营销任务自动化

10 个强大的 Perplexity AI 提示,让您的营销任务自动化

在当今快速变化的数字世界中,营销人员总是在寻找更智能的方法来简化他们的工作。想象一下,有一个个人助理可以为您创建受众档案,建议营销策略,甚至为您撰写广告文案。这听起来像是一个梦想? 多亏了像 Perplexity 这样的 AI 工具,这个梦想现在成为现实。通过正确的提示,您可以将 AI 转变为您的 个人营销助理。在本文中,我将分享 10 个强大的提示,帮助您自动

阅读更多
10+ 面向 UI/UX 设计师的顶级 ChatGPT 提示

10+ 面向 UI/UX 设计师的顶级 ChatGPT 提示

人工智能技术,如机器学习、自然语言处理和数据分析,正在重新定义传统设计方法。从自动化重复任务到实现个性化用户体验,人工智能使设计师能够更加专注于战略思维和创造力。随着这一趋势的不断增长,UI/UX 设计师越来越多地采用 AI 驱动的工具来促进他们的工作。利用人工智能不仅能提供基于数据的洞察,还为满足多样化用户需求的创新设计解决方案开辟了机会。 1. 用户角色开发 目的

阅读更多
在几分钟内完成数月工作的 100 种人工智能工具

在几分钟内完成数月工作的 100 种人工智能工具

人工智能(AI)的快速发展改变了企业的运作方式,使人们能够在短短几分钟内完成曾经需要几周或几个月的任务。从内容创作到网站设计,AI工具帮助专业人士节省时间,提高生产力,专注于创造力。以下是按功能分类的100个AI工具的全面列表,以及它们在现实世界中的使用实例。 1. 研究工具 研究可能耗时,但人工智能工具使查找、分析和组织数据变得更加容易。**ChatGPT, Cop

阅读更多
你从未知道的 17 个令人惊叹的 GitHub 仓库

你从未知道的 17 个令人惊叹的 GitHub 仓库

Github 隐藏的宝石!! 立即收藏的代码库 学习编程相对简单,但掌握编写更好代码的艺术要困难得多。GitHub 是开发者的宝藏,那里“金子”是其他人分享的精心编写的代码。通过探索 GitHub,您可以发现如何编写更清晰的代码,理解高质量代码的样子,并学习成为更熟练开发者的基本步骤。 1. notwaldorf/emoji-translate *谁需

阅读更多