主页 > 互联网  > 

RAG基于用户问题的内容,对其进行分类和路由,然后选择适当的处理方式(2)

RAG基于用户问题的内容,对其进行分类和路由,然后选择适当的处理方式(2)

示例代码:

import datetime from typing import Literal, Optional, Tuple from pydantic import BaseModel, Field class TutorialSearch(BaseModel): """在关于某个软件库的教程视频数据库中进行搜索。""" content_search: str = Field( ..., description="应用于视频字幕的相似性搜索查询。", ) title_search: str = Field( ..., description=( "内容搜索查询的另一种版本,应用于视频标题。" "应简洁明了,仅包含可能出现在视频标题中的关键字。" ), ) min_view_count: Optional[int] = Field( None, description="最小观看次数过滤器(包含该值)。仅在明确指定时使用。", ) max_view_count: Optional[int] = Field( None, description="最大观看次数过滤器(不包含该值)。仅在明确指定时使用。", ) earliest_publish_date: Optional[datetime.date] = Field( None, description="最早发布时间过滤器(包含该值)。仅在明确指定时使用。", ) latest_publish_date: Optional[datetime.date] = Field( None, description="最晚发布时间过滤器(不包含该值)。仅在明确指定时使用。", ) min_length_sec: Optional[int] = Field( None, description="最小视频时长(秒),包含该值。仅在明确指定时使用。", ) max_length_sec: Optional[int] = Field( None, description="最大视频时长(秒),不包含该值。仅在明确指定时使用。", ) def pretty_print(self) -> None: for field in self.__fields__: if getattr(self, field) is not None and getattr(self, field) != getattr( self.__fields__[field], "default", None ): print(f"{field}: {getattr(self, field)}") from langchain_groq import ChatGroq from langchain_core.prompts import ChatPromptTemplate system = """你是一名擅长将用户问题转换为结构化数据库查询的专家。 你的任务是根据用户输入生成结构化的搜索查询。 始终返回一个包含以下键的 JSON 对象: - **content_search**:从查询中提取与内容相关的关键字,**不能为空**,即使用户输入过于宽泛,也要尽量提取最有用的关键词。 - **title_search**:content_search 的简化版本,优化用于匹配标题,**不能为空**,应当为简短但精准的关键词。 - **min_view_count、max_view_count、earliest_publish_date、latest_publish_date、min_length_sec、max_length_sec**:如果用户未明确提供,则使用 `None`。 如果无法确定 `content_search` 和 `title_search`,请合理推测关键词,而不是返回 `null`。 """ prompt = ChatPromptTemplate.from_messages( [ ("system", system), ("human", "{question}"), ] ) llm = ChatGroq() structured_llm = llm.with_structured_output(TutorialSearch) query_analyzer = prompt | structured_llm query_analyzer.invoke({"question": "从零开始实现购物网站的建设"}).pretty_print()

这段代码的主要作用是让 LLM(大语言模型)自动把用户的搜索问题转换为结构化的查询条件,从而方便在数据库或向量检索系统中使用。

比如,用户可能随口问:

“后端数据库最新教程”

我们希望 LLM 能自动转换成可用于数据库查询的结构化数据,比如:

{ "content_search": "最新数据库教程", "title_search": "新数据库", "earliest_publish_date": null, "latest_publish_date": null, "min_view_count": null, "max_view_count": null, "min_length_sec": null, "max_length_sec": null }

这样,后续代码就可以用这个结构化数据去筛选视频,比如:

内容搜索(content_search):在视频字幕里查找「最新数据库教程」标题搜索(title_search):查找标题中包含「新数据库」的内容发布时间(earliest_publish_date 和 latest_publish_date):如果用户要求最近的教程,可以加上时间筛选观看次数过滤(min_view_count 和 max_view_count):可以筛选出最热门的教程时长过滤(min_length_sec 和 max_length_sec):可以选择短视频还是完整课程
代码作用拆解 第一步:定义结构化搜索格式 from typing import Optional from pydantic import BaseModel, Field import datetime class TutorialSearch(BaseModel): """在教程数据库中搜索相关视频""" content_search: str = Field(..., description="应用于视频字幕的相似性搜索查询。") title_search: str = Field(..., description="内容搜索查询的简化版本,适用于视频标题。") min_view_count: Optional[int] = Field(None, description="最小观看次数过滤器") max_view_count: Optional[int] = Field(None, description="最大观看次数过滤器") earliest_publish_date: Optional[datetime.date] = Field(None, description="最早发布时间") latest_publish_date: Optional[datetime.date] = Field(None, description="最晚发布时间") min_length_sec: Optional[int] = Field(None, description="最短视频时长(秒)") max_length_sec: Optional[int] = Field(None, description="最长视频时长(秒)") 这部分的作用 这里用了 Pydantic 的 BaseModel,它是 Python 里专门用于定义结构化数据格式的工具。content_search 和 title_search 是必填字段(... 表示不能是 None)。其他字段都是可选的,比如 min_view_count 之类,默认是 None,只有用户提供了相关信息时才会启用。作用:确保 LLM 生成的搜索查询是标准化的,而不是乱七八糟的字符串。
第二步:让 LLM 自动转换搜索条件 from langchain_core.prompts import ChatPromptTemplate system = """你是一名擅长将用户问题转换为结构化数据库查询的专家。 你的任务是根据用户输入生成结构化的搜索查询。 始终返回一个包含以下键的 JSON 对象: - **content_search**:从查询中提取与内容相关的关键字,**不能为空**,即使用户输入过于宽泛,也要尽量提取最有用的关键词。 - **title_search**:content_search 的简化版本,优化用于匹配标题,**不能为空**,应当为简短但精准的关键词。 - **min_view_count、max_view_count、earliest_publish_date、latest_publish_date、min_length_sec、max_length_sec**:如果用户未明确提供,则使用 `None`。 如果无法确定 `content_search` 和 `title_search`,请合理推测关键词,而不是返回 `null`。 """ prompt = ChatPromptTemplate.from_messages( [ ("system", system), # 设定 LLM 的角色和任务 ("human", "{question}"), # 让 LLM 处理用户输入 ] ) 这部分的作用 system 变量定义了LLM 的角色,告诉它:“你是一名数据库搜索优化专家。”规定 LLM 必须返回 结构化的 JSON 对象,这样可以确保数据格式统一。让 LLM 提取最重要的关键词,而不是简单重复用户的输入。
第三步:调用 LLM 进行函数调用 llm = ChatGroq() structured_llm = llm.with_structured_output(TutorialSearch) query_analyzer = prompt | structured_llm 这部分的作用

ChatGroq()

这里用的是 ChatGroq(),Groq 是一个运行 LLM(比如 GPT-4)的 API。它就像 OpenAI.ChatCompletion.create(),但速度更快,适合 RAG(检索增强生成)。

llm.with_structured_output(TutorialSearch)

这一步的作用是:让 LLM 输出的内容严格符合 TutorialSearch 这个结构。LLM 不会随便输出自由文本,而是必须返回 JSON 形式的结构化数据。

query_analyzer = prompt | structured_llm

这个 | 符号表示管道(Pipeline),相当于:def query_analyzer(question): prompt_text = generate_prompt(question) response = llm.call(prompt_text) return parse_response_to_TutorialSearch(response) 也就是说,把用户输入的 question 传给 prompt,然后让 LLM 生成结构化数据。
第四步:执行搜索 query_analyzer.invoke({"question": "后端数据库最新教程"}).pretty_print()

假设 LLM 处理完后返回:

{ "content_search": "最新数据库教程", "title_search": "新数据库", "earliest_publish_date": null, "latest_publish_date": null, "min_view_count": null, "max_view_count": null, "min_length_sec": null, "max_length_sec": null }

这时候 pretty_print() 的作用是打印:

content_search: 最新数据库教程 title_search: 新数据库

这样,我们的后端就可以拿 content_search 和 title_search 去检索匹配的视频,并根据其他过滤条件(比如发布时间、观看次数)进一步筛选。


示例 1:用户查询 “Python 高级教程,最好是 2023 年之后的”

LLM 可能返回:

{ "content_search": "Python 高级教程", "title_search": "Python 进阶", "earliest_publish_date": "2023-01-01", "latest_publish_date": null, "min_view_count": null, "max_view_count": null, "min_length_sec": null, "max_length_sec": null }

这表示:

只搜索 Python 相关的高级教程发布时间必须是 2023 年及之后不限制观看次数和时长
示例 2:用户查询 “Vue.js 快速入门(不要太长)”

LLM 可能返回:

{ "content_search": "Vue.js 快速入门", "title_search": "Vue.js 教程", "earliest_publish_date": null, "latest_publish_date": null, "min_view_count": null, "max_view_count": null, "min_length_sec": null, "max_length_sec": 600 }

这里 max_length_sec: 600 表示只要 10 分钟以内的短视频。


总结

这段代码的作用是: ✅ 智能分析用户输入,生成结构化查询 ✅ 确保数据格式统一,方便后续检索 ✅ 结合 LLM 的理解能力,优化查询关键词

这样,我们的后端可以直接用 content_search 和 title_search 进行向量数据库检索,再用其他字段做过滤查询,最终返回最相关的视频! 🚀

标签:

RAG基于用户问题的内容,对其进行分类和路由,然后选择适当的处理方式(2)由讯客互联互联网栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“RAG基于用户问题的内容,对其进行分类和路由,然后选择适当的处理方式(2)