分析输入信息的类别,目前是一个闭集、但是要按照开集的方式来进行分析;名称越乱越好,让系统自己来进行划分。必须首先考虑传统的方法;优先考虑数据结构的构建;强化监控机制的构建、首先进行认知和技术积累。
一、数据情况
找到了清华大学整理的关于体育的新闻,每篇一个新闻,第一行是标题,而后是内容。基于现有工具,直接撰写代码。首先按照9条为基准,完成代码撰写。
这9篇文章,目视是包括了 足球、高尔夫球、兵乓球 这些子类的。
import os
def read_first_line_of_txt_files(folder_path):
# 获取指定文件夹内的所有文件
files = os.listdir(folder_path)
# 筛选出扩展名为.txt的文件
txt_files = [f for f in files if f.endswith('.txt')]
# 读取每个.txt文件的第一行
first_lines = []
for txt_file in txt_files:
with open(os.path.join(folder_path, txt_file), 'r', encoding='utf-8') as f:
first_line = f.readline()
first_lines.append((txt_file, first_line.strip())) # 添加文件名和第一行内容
return first_lines
folder_path = './sports' # 替换为你要读取的文件夹路径
first_lines = read_first_line_of_txt_files(folder_path)
# 输出文件名和第一行内容
for file_name, first_line in first_lines:
print(f'文件名:{file_name}, 第一行内容:{first_line}')
从结果上来看:
一个是发现了一个帆船的问题,所以这里的分类问题是开集任务;
二个是有一些问题,从名字上来看,很难区分出是啥类别。
这里的函数可以继续变化:
def read_name_and_content_of_txt_files(folder_path):
# 获取指定文件夹内的所有文件
files = os.listdir(folder_path)
# 筛选出扩展名为.txt的文件
txt_files = [f for f in files if f.endswith('.txt')]
# 读取每个.txt文件的第一行
first_lines = []
for txt_file in txt_files:
with open(os.path.join(folder_path, txt_file), 'r', encoding='utf-8') as f:
first_line = f.readline()
file_content = f.read()
first_lines.append((txt_file, first_line.strip(),file_content.strip())) # 添加文件名和第一行内容
return first_lines
注意体会这里的小细节。
二、现有流程
目前基于glm3+bge+langchain构建主流的RAG流程。未来我也会结合数据实际,对比一下bce以及千问、百川等的能力。目前已经开始具备相关的能力。
这里我想做的:
1、首先是由llm根据标题,直接在我指定的类别上进行分类;
2、如果llm无法成功分类,则阅读内容,进行区分;
3、如果出现“开集”情况,也需要进行报告(我将迭代重新执行任务)
这里实际上没有使用RAG,然后不使用自动agent等的功能。也不使用lcel的相关能力。一个可以参考的代码:
from langchain_community.llms.chatglm3 import ChatGLM3
from langchain.memory import ConversationBufferMemory
from langchain.sql_database import SQLDatabase
from langchain.prompts import PromptTemplate
from langchain.chains import LLMChain
from langchain.chains import SimpleSequentialChain
import os
os.environ["LANGCHAIN_TRACING_V2"] ="true"
os.environ["LANGCHAIN_API_KEY"]="ls__96d567894428421db2d42dec4edde0b4"
file=open('santi.txt',encoding="GBK")
try:
article=file.read()
finally:
file.close()
endpoint_url = "https://u4378-b286-79485e25.westc.gpuhub.com:8443/v1/chat/completions"
llm = ChatGLM3(
endpoint_url=endpoint_url,
max_tokens=8000,
top_p=0.9,
timeout=999
)
fact_extraction_prompt = PromptTemplate(
input_variables=["text_input"],
template="从下列才来中提取事实.不要包含观点.给每个事实一个序号并且保证简短 :{text_input}"
)
investor_update_prompt = PromptTemplate(
input_variables=["facts"],
template="你是一名作家,基于以下事实写一个短篇小说。不要丢失关键信息,不要包含序号: {facts}"
)
fact_extraction_chain = LLMChain(llm=llm, prompt=fact_extraction_prompt)
investor_update_chain = LLMChain(llm=llm, prompt=investor_update_prompt)
full_chain = SimpleSequentialChain(
chains=[fact_extraction_chain,investor_update_chain],
verbose = True
)
response = full_chain.run(article)
print("response:",response)
三、具体实验
3.1 思路一,直接根据名称进行划分
from langchain_community.llms.chatglm3 import ChatGLM3
from langchain.memory import ConversationBufferMemory
from langchain.sql_database import SQLDatabase
from langchain.prompts import PromptTemplate
from langchain.chains import LLMChain
from langchain.chains import SimpleSequentialChain
import os
os.environ["LANGCHAIN_TRACING_V2"] ="true"
os.environ["LANGCHAIN_API_KEY"]="ls__96d567894428421db2d42dec4edde0b4"
def read_first_line_of_txt_files(folder_path):
# 获取指定文件夹内的所有文件
files = os.listdir(folder_path)
# 筛选出扩展名为.txt的文件
txt_files = [f for f in files if f.endswith('.txt')]
# 读取每个.txt文件的第一行
first_lines = []
for txt_file in txt_files:
with open(os.path.join(folder_path, txt_file), 'r', encoding='utf-8') as f:
first_line = f.readline()
first_lines.append((txt_file, first_line.strip())) # 添加文件名和第一行内容
return first_lines
###prework###
folder_path = './sports' # 替换为你要读取的文件夹路径
content = ""
first_lines = read_first_line_of_txt_files(folder_path)
for file_name, first_line in first_lines:
#print(f'文件名:{file_name}, 第一行内容:{first_line}')
content = content + "\n" + first_line # 将列表中的内容连接成一个字符串,用 \n 分隔
###prompt####
sort_prompt = PromptTemplate(
input_variables=["text_input"],
template="将下列材料进行分类。按照“足球”“高尔夫球”“兵乓球”进行区分。不要丢失信息。如果无法分类则划为“其他”:{text_input}"
)
###llm###
endpoint_url = "https://u4378-b286-79485e25.westc.gpuhub.com:8443/v1/chat/completions"
llm = ChatGLM3(endpoint_url=endpoint_url,temperature = 0, timeout=999)
###chain###
sort_chain = LLMChain(llm=llm, prompt=sort_prompt)
full_chain = SimpleSequentialChain(
chains=[sort_chain],
verbose = True
)
###run###
response = full_chain.run(content)
print("response:",response)
不考虑正确性,这是唯一可以召全的方法
这里需要修改的是标点符号。提示词的撰写非常的“微妙”。而且这里的划分很可能是错误的。再做两次平行实验。
实验2
实验3
这个方向可以被证明是错误的,也就是说将不同的内容混在一起,让llm去进行分类,它会丢东西、也不稳定。
3.2 思路二,每一条带标题和内容一起进行分类。
from langchain_community.llms.chatglm3 import ChatGLM3
from langchain.memory import ConversationBufferMemory
from langchain.sql_database import SQLDatabase
from langchain.prompts import PromptTemplate
from langchain.chains import LLMChain
from langchain.chains import SimpleSequentialChain
import os
os.environ["LANGCHAIN_TRACING_V2"] ="true"
os.environ["LANGCHAIN_API_KEY"]="ls__96d567894428421db2d42dec4edde0b4"
def read_name_and_content_of_txt_files(folder_path):
# 获取指定文件夹内的所有文件
files = os.listdir(folder_path)
# 筛选出扩展名为.txt的文件
txt_files = [f for f in files if f.endswith('.txt')]
# 读取每个.txt文件的第一行
first_lines = []
for txt_file in txt_files:
with open(os.path.join(folder_path, txt_file), 'r', encoding='utf-8') as f:
first_line = f.readline()
file_content = f.read()
first_lines.append((txt_file, first_line.strip(),file_content.strip())) # 添加文件名和第一行内容
return first_lines
###prompt####
sort_prompt = PromptTemplate(
input_variables=["text_input"],
template="将这段材料按照“足球”“高尔夫球”“兵乓球”进行区分。如果无法分类则划为“其他”:{text_input}。返回的结果只能是“足球”“高尔夫球”“兵乓球”和“其他”中的一个。"
)
###llm###
endpoint_url = "https://u4378-b286-79485e25.westc.gpuhub.com:8443/v1/chat/completions"
llm = ChatGLM3(endpoint_url=endpoint_url,temperature = 0, timeout=999)
###chain###
sort_chain = LLMChain(llm=llm, prompt=sort_prompt)
full_chain = SimpleSequentialChain(
chains=[sort_chain],
verbose = True
)
###main work###
folder_path = './sports' # 替换为你要读取的文件夹路径
read_files = read_name_and_content_of_txt_files(folder_path)
for file_name, first_line,file_content in read_files:
#print(f'文件名:{file_name}, 名称:{first_line},内容:{file_content}')
content = f'名称:{first_line},内容:{file_content}'
###run###
response = full_chain.run(content)
print("response:",response)
应该说仍然是相当糟糕的,语句的划分、结果的判断,提示词怎么写都没有用。
3.3 思路三,使用向量模型
embeded一直都是用来进行RAG的,实际上它不是用于分类最合适的吗?
import numpy as np
import faiss
from numpy import dot
from numpy.linalg import norm
from sentence_transformers import SentenceTransformer
model = SentenceTransformer('/home/jsxyhelu/CODES/bge-large-zh-v1.5')
###functions && classes####
def get_datas_embedding(datas):
return model.encode(datas)
# 构建索引,FlatL2为例
def create_index(datas_embedding):
index = faiss.IndexFlatL2(datas_embedding.shape[1]) # 这里必须传入一个向量的维度,创建一个空的索引
index.add(datas_embedding) # 把向量数据加入索引
return index
# 查询索引
def data_recall(faiss_index, query, top_k):
query_embedding = model.encode([query])
Distance, Index = faiss_index.search(query_embedding, top_k)
return Index
###############################
#query = "体育"
# 且能支持跨语言
query = "高尔夫球"
documents = [
"马晓旭意外受伤让国奥警惕 无奈大雨格外青睐殷家军",
"商瑞华首战复仇心切 中国玫瑰要用美国方式攻克瑞典",
"性感比基尼亮丽奥帆中心 “帆女郎”亲吻阳光(图)",
"女单抽签:张怡宁独守上半区 王楠郭跃遭遇劲敌",
"冠军球队迎新欢乐派对 黄旭获大奖张军赢下PK赛",
"休斯顿公开赛尼蒂斯暂领先 米克尔森77杆面临淘汰",
"达利迫不及待要回“家” 下周将角逐爱尔兰公开赛",
"黄沧江:没有球僮服务是传统?",
"米克尔森确认参加大满贯赛 伍兹回应这是积极信号"
]
datas_embedding = get_datas_embedding(documents)
faiss_index = create_index(datas_embedding)
sim_data_Index = data_recall(faiss_index,query, 5)
print("相似的top5数据是:")
for index in sim_data_Index[0]:
print(documents[int(index)] + "\n")
在这里最初的反向测试中,就出现了令人惊讶的结果,分类成功了绝大多数的信息。
再进行正向测试:
其实这句话,如果没有背景知识的话,很难判断出来是和高尔夫球相关的。做系列实验。
import numpy as np
import faiss
from numpy import dot
from numpy.linalg import norm
from sentence_transformers import SentenceTransformer
import os
model = SentenceTransformer('/home/jsxyhelu/CODES/bge-large-zh-v1.5')
def read_first_line_of_txt_files(folder_path):
# 获取指定文件夹内的所有文件
files = os.listdir(folder_path)
# 筛选出扩展名为.txt的文件
txt_files = [f for f in files if f.endswith('.txt')]
# 读取每个.txt文件的第一行
first_lines = []
for txt_file in txt_files:
with open(os.path.join(folder_path, txt_file), 'r', encoding='utf-8') as f:
first_line = f.readline()
first_lines.append((txt_file, first_line.strip())) # 添加文件名和第一行内容
return first_lines
folder_path = './sports' # 替换为你要读取的文件夹路径
first_lines = read_first_line_of_txt_files(folder_path)
###functions && classes####
def get_datas_embedding(datas):
return model.encode(datas)
# 构建索引,FlatL2为例
def create_index(datas_embedding):
index = faiss.IndexFlatL2(datas_embedding.shape[1]) # 这里必须传入一个向量的维度,创建一个空的索引
index.add(datas_embedding) # 把向量数据加入索引
return index
# 查询索引
def data_recall(faiss_index, query, top_k):
query_embedding = model.encode([query])
Distance, Index = faiss_index.search(query_embedding, top_k)
return Distance,Index
###############################
#query = "体育"
# 且能支持跨语言
#query = "达利迫不及待要回“家” 下周将角逐爱尔兰公开赛"
documents = [
"足球",
"乒乓球",
"高尔夫球",
"篮球",
"游泳",
"跑步",
"网球",
"举重",
"羽毛球"
]
datas_embedding = get_datas_embedding(documents)
faiss_index = create_index(datas_embedding)
# 输出文件名和第一行内容
for file_name, first_line in first_lines:
print(f'文件名:{file_name}, 第一行内容:{first_line}')
Distance,sim_data_Index = data_recall(faiss_index,first_line, 1)
for index in sim_data_Index[0]:
print(documents[int(index)] + " "+ str(Distance[0][0]))
应该说可以正确识别绝大多数的内容,很有启发的价值。
对于这里的分类错误的情况,可以看到距离也是比较大的。
【这里需要注意的一点就是我采用的数据集,是否已经被模型学习了,所以还有很多细致的工作需要做】
四、初步小结
那么目前可以想出来的思路是:
1、预先定下来一个开放的分类,作为分类的一句;
2、embeded分析名称,获得初步的结果;这里要同时获得分类的分值;
3、对于分值过低的情况,llm进一步分析其内容,必要情况下由人处理。【初步定这个值为1.33】
from langchain_community.llms.chatglm3 import ChatGLM3
from langchain.memory import ConversationBufferMemory
from langchain.sql_database import SQLDatabase
from langchain.prompts import PromptTemplate
from langchain.chains import LLMChain
from langchain.chains import SimpleSequentialChain
from langchain_community.embeddings import HuggingFaceBgeEmbeddings
from langchain_community.vectorstores import FAISS
from sentence_transformers import SentenceTransformer
import os
import faiss
os.environ["LANGCHAIN_TRACING_V2"] ="true"
os.environ["LANGCHAIN_API_KEY"]="ls__96d567894428421db2d42dec4edde0b4"
model = SentenceTransformer('/home/jsxyhelu/CODES/bge-large-zh-v1.5')
###functions && classes####
def read_name_and_content_of_txt_files(folder_path):
# 获取指定文件夹内的所有文件
files = os.listdir(folder_path)
# 筛选出扩展名为.txt的文件
txt_files = [f for f in files if f.endswith('.txt')]
# 读取每个.txt文件的第一行
first_lines = []
for txt_file in txt_files:
with open(os.path.join(folder_path, txt_file), 'r', encoding='utf-8') as f:
first_line = f.readline()
file_content = f.read()
first_lines.append((txt_file, first_line.strip(),file_content.strip())) # 添加文件名和第一行内容
return first_lines
def get_datas_embedding(datas):
return model.encode(datas)
# 构建索引,FlatL2为例
def create_index(datas_embedding):
index = faiss.IndexFlatL2(datas_embedding.shape[1]) # 这里必须传入一个向量的维度,创建一个空的索引
index.add(datas_embedding) # 把向量数据加入索引
return index
# 查询索引
def data_recall(faiss_index, query, top_k):
query_embedding = model.encode([query])
Distance, Index = faiss_index.search(query_embedding, top_k)
return Distance,Index
###prompt####
documents = [
"足球",
"乒乓球",
"高尔夫球",
"篮球",
"游泳",
"跑步",
"网球",
"举重",
"羽毛球",
"帆船"
]
sort_prompt = PromptTemplate(
input_variables=["text_input"],
template="将这段材料按照足球、乒乓球、高尔夫球、篮球、游泳、跑步、网球、举重、羽毛球、帆船进行区分。如果无法分类则划为“其他”:{text_input}。"
)
###llm###
endpoint_url = "https://u4378-b286-79485e25.westc.gpuhub.com:8443/v1/chat/completions"
llm = ChatGLM3(endpoint_url=endpoint_url,temperature = 0, timeout=999)
###chain###
sort_chain = LLMChain(llm=llm, prompt=sort_prompt)
full_chain = SimpleSequentialChain(
chains=[sort_chain],
#verbose = True
)
###main work###
folder_path = './sports' # 替换为你要读取的文件夹路径
datas_embedding = get_datas_embedding(documents)
faiss_index = create_index(datas_embedding)
read_files = read_name_and_content_of_txt_files(folder_path)
for file_name, first_line,file_content in read_files:
print(f'文件名:{file_name}, 标题:{first_line}')
Distance,sim_data_Index = data_recall(faiss_index,first_line, 1)
dis = Distance[0][0]
if dis > 1.33:
print("向量分类不明。")
response = full_chain.run(first_line+file_content)
print("llm分类:",response)
else:
for index in sim_data_Index[0]:
print(documents[int(index)] + " "+ str(Distance[0][0]))
小结:
1、今天的研究最重要的就是确定了 通过向量检索 来进行分类的主体;
2、向量检索还有很多写的东西,我需要再研究学习;
3、无法处理的情况,需要llm来进行分类,但是这块因为提示词的问题,导致比较拉跨。
现在想一想,关于具体问题的研究琢磨做得还是比较少,这块需要抓住问题,继续研究。
标签:files,探索,分类,file,path,import,预研,txt,first From: https://www.cnblogs.com/jsxyhelu/p/18134336