一、简介
我们之前实现了基于python来抓取页面的信息,然后让大模型llm为我们生成一个简介。
我们这次再进一步,我们抓取到网址上的标题,正文,有用链接等信息,来为这个网址的公司生成一个宣传文案。
二、编码实现
1、环境变量文件
我们需要一个配置文件.env文件来把我们的openai的key配置好。
OPENAI_API_KEY="sk-proj-XXX"
2、解析网址
我们把解析网址的功能封装到一个类里面。称之为Website
Website.py
import requests
from bs4 import BeautifulSoup
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36"
}
# 构建一个class,实现功能:解析url网页,取出
class Website5:
# 构造函数接收一个参数 url,表示要抓取的网页地址。
def __init__(self, url):
# 初始化
self.url = url
# 发起 HTTP 请求
response = requests.get(url, headers=headers)
# 取出网页的正文部分
self.body = response.content
# 使用 BeautifulSoup 库解析 HTML 内容。'html.parser' 是解析器的名称。
soup = BeautifulSoup(self.body, 'html.parser')
# 尝试获取网页的标题。如果 <title> 标签存在,则将其内容保存到 self.title;否则,设置为默认值 "网页标题不存在"。
self.title = soup.title.string if soup.title else "网页标题不存在"
"""
如果网页有 <body> 标签:遍历 <body> 标签中的 <script>、<style>、<img> 和 <input> 标签,并使用 decompose() 方法移除这些标签及其内容。
使用 get_text() 方法提取正文内容,设置 separator="\n" 以换行分隔文本,strip=True 去除多余的空白字符。如果网页没有 <body> 标签,则将 self.text 设置为空字符串
"""
if soup.body:
for irrelevant in soup.body(["script", "style", "img", "input"]):
irrelevant.decompose()
self.text = soup.body.get_text(separator="\n", strip=True)
else:
self.text = ""
# 使用 find_all('a') 查找所有 <a> 标签。提取每个 <a> 标签的 href 属性值,存入 links 列表。过滤掉空的链接,将有效的链接存入 self.links。
links = [link.get('href') for link in soup.find_all('a')]
self.links = [link for link in links if link]
# 返回网页的标题和正文内容的字符串表示。
def get_contents(self):
return f"页面标题:\n{self.title}\n页面正文:\n{self.text}\n\n"
3、工具类
Utils.py
import os
from dotenv import load_dotenv
from openai import OpenAI
class OpenAiUtil:
def __init__(self, data):
self.data = data
@staticmethod
def buildOpenAiClient() -> OpenAI:
load_dotenv("../.env")
api_key = os.getenv('OPENAI_API_KEY')
if not api_key:
print("api-key 未发现设置!")
elif not api_key.startswith("sk-proj-"):
print("api-key 有问题")
else:
print("ok,api-key没问题了")
return OpenAI()
3、核心逻辑
我们的核心逻辑很简单,就是通过Website的能力解析出来对应的地址上的信息,并且构建prompt给大模型,让他把我们解析出来的链接和正文标题输出得到页面的结果。
然后基于页面的结果再次构建prompt,把这个prompt给大模型,然后让他总结出一篇宣传语。得到我们的结果。
import json
from IPython.display import Markdown, display, update_display
from Utils import OpenAiUtil
from Website import Website5
MODEL = 'gpt-4o-mini'
# 加载openAi客户端
openai = OpenAiUtil.buildOpenAiClient()
# 构建获取网页链接的prompt,包括system和user
def get_links_system_prompt()->str:
link_system_prompt = "你得到了一个网页上找到的链接列表。你可以决定哪些链接最相关,应该包含在公司的宣传册中,比如关于公司页面的链接,或者公司介绍页面的链接,或者招聘/职位页面的链接。\n"
link_system_prompt += "你应该像这个示例一样以JSON格式进行回复:"
link_system_prompt += """
{
"links": [
{"type": "相关页面", "url": "https://full.url/goes/here/about"},
{"type": "职业相关页面": "url": "https://another.full.url/careers"}
]
}
"""
return link_system_prompt
def get_links_user_prompt(website):
user_prompt = f"这里有一个在网页{website.url}上的链接集合"
user_prompt += "请决定这些链接中哪些与公司的宣传册相关,并以 JSON 格式回复完整的 https URL。不要包括服务条款、隐私政策、电子邮件链接。\n"
user_prompt += "链接(其中一些可能是相对地址的链接)\n"
user_prompt += "\n".join(website.links)
return user_prompt
# 获取url页面上的link链接地址。根据我们构建的prompt
def get_links(url):
website = Website5(url)
response = openai.chat.completions.create(
model=MODEL,
messages=[
{"role": "system", "content": get_links_system_prompt()},
{"role": "user", "content": get_links_user_prompt(website)}
],
# 这里是必须的要传入json,不然它不会给你按照json返回,openai的官网地址https://platform.openai.com/docs/api-reference/chat/create
# JSON object response format. An older method of generating JSON responses. Using json_schema is recommended for models that support it.
# Note that the model will not generate JSON without a system or user message instructing it to do so.
response_format={"type": "json_object"}
)
# 只获取第一个返回的格式,有时候大模型会返回多个,千奇百怪的,什么都有
result = response.choices[0].message.content
# 以json格式约束
return json.loads(result)
# 获取网页的所有的链接信息
def get_all_details(url):
result = "登陆页面:\n"
result += Website5(url).get_contents()
links = get_links(url)
print("找到的链接:", links)
for link in links["links"]:
result += f"\n\n{link['type']}\n"
result += Website5(link["url"]).get_contents()
return result
# 构建生成宣传报告的user prompt
def get_brochure_system_prompt()->str:
return "你是一个分析公司网站上几个相关页面的内容并为潜在客户、投资者和招聘对象创建公司简介的助手。请以 Markdown 格式回复。如果有的话,请包含公司文化、客户和招聘/职位的详细信息。"
# 构建生成宣传报告的system prompt
def get_brochure_user_prompt(company_name, url):
user_prompt = f"你正在查看一家名为: {company_name}\n"
user_prompt += f"以下是其首页和其他相关页面的内容;请使用这些信息以 Markdown 格式制作一份关于该公司的简短宣传册。\n"
user_prompt += get_all_details(url)
user_prompt = user_prompt[:5000] # 只要5000字的
return user_prompt
# 构建宣传报告
def create_brochure(company_name, url):
# llm call
response = openai.chat.completions.create(
model=MODEL,
messages=[
{"role": "system", "content": get_brochure_system_prompt()},
{"role": "user", "content": get_brochure_user_prompt(company_name, url)}
],
)
# 只要第一个结果
result = response.choices[0].message.content
display(result)
# 执行调用
create_brochure("OpenAi", "https://openai.com/")
# 构建流式的输出,可选
def stream_brochure(company_name, url):
stream = openai.chat.completions.create(
model=MODEL,
messages=[
{"role": "system", "content": get_brochure_system_prompt()},
{"role": "user", "content": get_brochure_user_prompt(company_name, url)}
],
stream=True
)
response = ""
display_handle = display(Markdown(""), display_id=True)
for chunk in stream:
response += chunk.choices[0].delta.content or ''
response = response.replace("```", "").replace("markdown", "")
print(response)
#update_display(response, display_id=display_handle.display_id)
# stream_brochure("OpenAi", "https://openai.com/")
我们以openai的网址为案例,让大模型为openai总结一个宣传文案。结果如下:
# OpenAI 公司简介
## 公司简介
OpenAI 是一家致力于人工智能研究与开发的前沿科技公司。我们的使命是确保人工智能的益处能够惠及全人类。虽然我们无法直接访问公司网站的具体信息,但我们致力于推动AI技术的进步,以创建安全、可持续的AI系统。
## 公司文化
OpenAI 的核心价值观强调透明性、合作和创新。我们鼓励团队的多样性和包容性,重视员工的专业成长与持续学习。我们的工作环境支持技术挑战和思维碰撞,以推动人工智能领域的发展。
## 客户
虽然具体客户信息未能获取,但OpenAI 的技术被广泛应用于多个行业,包括教育、医疗、金融和娱乐等。我们与各类机构和组织合作,致力于将先进的AI解决方案带入实际应用中。
## 招聘信息
OpenAI 正在寻找对人工智能充满热情的人才。如果你对计算机科学、机器学习和AI技术有深入的理解,并希望参与到改变世界的项目中,我们欢迎你加入我们的团队!具体职位和招聘信息可通过官方网站查阅。
## 研究方向
OpenAI 在多个领域开展了广泛的研究,包括但不限于自然语言处理、计算机视觉和智能代理等。我们的研究成果旨在推动科学进步,同时确保AI的安全性和可控性。
---
感谢您对 OpenAI 的关注!我们期待与您共同探索人工智能的未来。
看起来效果还不错。