大模型融入推荐系统
结合项目实际给用户推荐,比如是商家项目,用户问了几个关于商品的信息,大模型就可以根据根据用户画像,给用户推荐商品。
我们现在做的是针对于用户学习的推荐,首先我们要对我们的数据进行处理,提取出我们数据的一些特征
首先这个文件夹下可以放一些文件当做子目录,这些子目录就可以当做一些course
遍历文件,转换为markdown,然后读取里面的标题内存,然后存储到csv文件中。此时还缺少摘要,所以我们用大模型来读取内容从而生成摘要。
def generate_csv_for_pdfs(root_dir):
# 搜索指定根目录下的所有PDF文件
pdf_files = glob.glob(f'{root_dir}/**/*.pdf', recursive=True)
data = []
for pdf_file in pdf_files:
# 将 PDF 格式转化成 Markdown 格式
markdown = convert_pdf_to_markdown(pdf_file)
# 根据Markdown的内容结构,提取每一部分的主题内容
toc_content = extract_content_by_sections(markdown)
# 第一个标题部分是课程的主标题
titles = list(toc_content.keys())
first_title = titles[0] if titles else ""
# 收集第一标题下的二级标题作为子标题
first_section_content = toc_content.get(first_title, "")
first_section_lines = first_section_content.split('\n')
sub_titles = [line.strip() for line in first_section_lines if line.startswith('##')]
sub_titles_cleaned = [re.sub(r'^##\s+', '', title) for title in sub_titles]
for module_name, content in toc_content.items():
# 提取二级标题作为 Tags
tags = [line.strip() for line in content.split('\n') if line.startswith('##')]
tags = [re.sub(r'^##\s+', '', tag) for tag in tags] # 清理 '##'
# 构建元数据
data.append({
'ModuleID': str(uuid.uuid4()),
'Course': os.path.basename(os.path.dirname(pdf_file)),
'Title': sub_titles_cleaned,
'URL': os.path.basename(pdf_file),
'ModuleName': module_name,
'Tags': ", ".join(tags),
'Content': content
})
df = pd.DataFrame(data)
csv_file_path = os.path.join(root_dir, 'course_metadata.csv')
df.to_csv(csv_file_path, index=False)
print(f"CSV file generated: {csv_file_path}")
然后生成摘要
构建文档的画像,执行某些列,把这些列合并组成文档的画像,为一个新的列embedding_info,
这个embeding_info_的list是一个列表
把这些用户画像存入到向量数据库中,执行的是do_add_file方法
系统调用
之前的步骤略
# 在同一个 model 实例上同时运行两个异步链(LLMChain)可能导致内部状态的混乱,所以为用户画像生成和聊天响应分别实例化模型
# 该模型实例用于生成用户画像
model_for_profile = get_ChatOpenAI(
model_name=model_name,
temperature=TEMPERATURE,
max_tokens=MAX_TOKENS,
)
# 该模型实例用于生成聊天响应
model_for_chat = get_ChatOpenAI(
model_name=model_name,
temperature=TEMPERATURE,
max_tokens=MAX_TOKENS,
callbacks=callbacks,
)
如果用户历史对话超过5轮就生成用户画像
生成用户画像,根据用户的历史对话信息,采用这个提示模版生成用户画像
# 生成用户画像: 通过理解`用户历史行为序列`,生成`用户感兴趣的话题`以及`用户位置信息`
user_profile_prompt = """
请你根据历史对话记录:\n\n
{chat_history}
如上对话历史记录所示,请你分析当前用户的需求,并描述出用户画像,用户画像的格式如下:
[Course]
- (Course1)
[ModuleName]
- (ModuleName1)
其中课程名称 [Course] 请务必从下面的列表中提取出最匹配的:\n
["在线大模型课件", "开源大模型课件"]
最后,一定要注意,需要严格按照上述格式描述相关的课程名称和课程的知识点,同时,[Course] 和 [ModuleName] 一定要分别处理,你最终输出的结果一定不要输出任何与上述格式无关的内容。
"""
async def generate_user_profile_and_extract_info(chat_messages: List[str], user_profile_prompt: str, model) -> Dict[
str, List[str]]:
"""
异步生成用户画像并从中提取课程和模块信息。
:param chat_messages: 聊天历史消息列表
:param user_profile_prompt: 用于生成用户画像的提示
:param model: 已实例化的模型对象
:return: 包含课程和模块名称的字典
"""
# 创建聊天提示模板
prompt_template = ChatPromptTemplate.from_messages([
("user", user_profile_prompt),
])
# 创建LangChain的链
user_profile_chain = LLMChain(prompt=prompt_template, llm=model)
# 异步生成用户画像
user_profile_result = user_profile_chain.invoke({"chat_history": chat_messages})
user_profile = user_profile_result["text"]
# 定义正则表达式并提取课程与模块信息
def extract_course_and_module(text: str) -> Dict[str, List[str]]:
course_pattern = r"\[Course\]\s+-\s+(.+)"
module_name_pattern = r"\[ModuleName\]\s+-\s+(.+)"
courses = re.findall(course_pattern, text)
module_names = re.findall(module_name_pattern, text)
return {"Course": courses, "ModuleName": module_names}
# 提取信息并返回
return extract_course_and_module(user_profile)
然后接下来就是根据用户画像去和向量数据库中的内容匹配,如果量很大,可以把信息存储到es中,做倒排索引
接下来走正常的处理流程