使用Llama Index与Streamlit实现一个从文本中提取专业术语和定义网页小程序

Llama Index有许多用例(语义搜索、摘要等),并且都有很好的记录。然而,这并不意味着我们不能将Llama Index应用到非常具体的用例中!

在本教程中,我们将介绍使用Llama Index从文本中提取专业术语和定义的设计过程,同时允许用户稍后查询这些术语。使用Streamlit,我们可以提供一种简单的方法来构建用于运行和测试所有这些的前端,并快速迭代我们的设计。

本教程假设您已经安装了Python3.9+和以下软件包:

  • llama-index-core
  • llama-index-llms-dashscope
  • llama-index-embeddings-dashscope
  • streamlit

在最基础的功能设计层面上,我们的目标是从文档中获取文本,提取术语和定义,然后为用户提供查询专业术语和定义知识库的方法。本教程将介绍Llama IndexStreamlit的功能,并希望为出现的常见问题提供一些有用的解决方案。

上传文本

第一步是为用户提供一种手动输入文本的方法。让我们使用Streamlit编写一些代码来提供此网页界面!使用以下代码并使用streamlit run app.py命令启动应用程序。

import streamlit as stst.title("🦙 骆驼索引术语提取器 🦙")document_text = st.text_area("输入原始文本")
if st.button("提取术语和定义") and document_text:with st.spinner("提取中..."):extracted_terms = document_text  # 这是一个临时的,下面是提取术语实现st.write(extracted_terms)

在这里插入图片描述

超级简单,对吧!但你会注意到这个应用程序还没有做任何有用的事情。要使用llama_index,我们还需要设置DashScope LLMLLM有很多可能的设置,所以我们可以让用户自己决定哪种设置最好。我们也应该允许用户设置用于提取术语的提示词(这也有助于我们调试出最有效的设置)。

LLM 设置

下一步给我们的应用引入了一些标签页,以将其分为提供不同功能的不同面板。让我们创建一个标签页用于 LLM 设置,另一个用于上传文本:

import streamlit as stDEFAULT_TERM_STR = ("列出在上下文中定义的术语和定义的列表, ""每一行上有一对。 ""如果一个术语缺少它的定义,用你最好的判断。""按如下方式书写每一行:\n术语: <term> 定义: <definition>"
)st.title("🦙 骆驼索引术语提取器 🦙")setup_tab, upload_tab = st.tabs(["设置", "上传/提取术语"])with setup_tab:st.subheader("LLM 设置")api_key = st.text_input("在这里输入OpenAI API密钥", type="password")llm_name = st.selectbox("选择LLM模型?", ["qwen-turbo", "qwen-plus"])model_temperature = st.slider("LLM Temperature", min_value=0.0, max_value=1.0, step=0.1)term_extract_str = st.text_area("提取术语和定义的查询。",value=DEFAULT_TERM_STR,)with upload_tab:st.subheader("提取和查询定义")document_text = st.text_area("输入原始文本")if st.button("提取术语和定义") and document_text:with st.spinner("提取中..."):extracted_terms = document_text  #默认提示符 临时定义,后面实现st.write(extracted_terms)

现在我们的应用有了两个标签页,这真的有助于组织应用的功能。你还会注意到我添加了一个默认的提示词用于提取术语——你可以稍后在尝试提取一些术语后更改它,这只是我在经过一些实验后得出的一个提示词。

说到提取术语,是时候添加一些函数来实现这一功能了!
在这里插入图片描述

提取和存储术语

现在我们已经能够定义LLM设置和输入文本,我们可以尝试使用Llama Index从文本中提取专业术语!

我们可以添加以下函数来初始化LLM,并使用它从输入文本中提取术语。

import osimport streamlit as st
from llama_index.core import Document, SummaryIndex
from llama_index.llms.dashscope import DashScopeDEFAULT_TERM_STR = ("列出在上下文中定义的术语和定义的列表, ""每一行上有一对。 ""如果一个术语缺少它的定义,用你最好的判断。""按如下方式书写每一行:\nTerm: <term> Definition: <definition>"
)def get_llm(llm_name, model_temperature, api_key, max_tokens=256):os.environ["DASHSCOPE_API_KEY"] = api_keyreturn DashScope(emperature=model_temperature,model_name=llm_name, api_key=api_key, max_tokens=max_tokens)def extract_terms(documents, term_extract_str, llm_name, model_temperature, api_key
):llm = get_llm(llm_name, model_temperature, api_key, max_tokens=1024)temp_index = SummaryIndex.from_documents(documents,)query_engine = temp_index.as_query_engine(response_mode="tree_summarize", llm=llm)terms_definitions = str(query_engine.query(term_extract_str))print(terms_definitions)terms_definitions = [xfor x in terms_definitions.split("\n")if x and "Term:" in x and "Definition:" in x]# 将文本解析为字典terms_to_definition = {x.split("Definition:")[0].split("Term:")[-1].strip(): x.split("Definition:")[-1].strip()for x in terms_definitions}return terms_to_definitionst.title("🦙 骆驼索引术语提取器 🦙")setup_tab, upload_tab = st.tabs(["设置", "上传/提取术语"])with setup_tab:st.subheader("LLM 设置")api_key = st.text_input("在这里输入OpenAI API密钥", type="password")llm_name = st.selectbox("选择LLM模型?", ["qwen-turbo", "qwen-plus"])model_temperature = st.slider("LLM Temperature", min_value=0.0, max_value=1.0, step=0.1)term_extract_str = st.text_area("提取术语和定义的查询。",value=DEFAULT_TERM_STR,)with upload_tab:st.subheader("提取和查询定义")document_text = st.text_area("输入原始文本")if st.button("提取术语和定义") and document_text:with st.spinner("提取中..."):extracted_terms = extract_terms([Document(text=document_text)],term_extract_str,llm_name,model_temperature,api_key,)st.write(extracted_terms)

在这里插入图片描述

代码发生了很多变动,让我们花点时间来回顾一下代码发生的改变。

get_llm()基于setup选项卡中的用户配置实例化LLM。基于模型名称,我们需要使用适当的类(DashScope)。

extract_terms()函数是所有核心操作发生的地方。首先,我们使用max_tokens=1024调用get_llm(),因为我们不想在提取术语和定义时过多地限制模型(如果没有设置,默认值是256)。然后,我们定义Settings对象,将num_outputmax_tokens值对齐,并将块大小设置为不大于输出。当文档被Llama Index索引时,如果文档很大,它们会被分解成块(也称为节点),chunk_size设置这些块的大小。

接下来,我们创建一个临时摘要索引并传入我们的llm。摘要索引将读取索引中的每一条文本,这对于提取术语来说是完美的。最后,使用response_mode="tree_summarize "使用预定义的查询文本提取术语。此响应模式将自底向上生成一个摘要树,其中每个父节点总结其子节点。最后,返回树的顶部,它将包含我们提取的所有术语和定义。

最后,我们做一些次要的后期处理。我们假设模型遵循了说明,并在每行上放置了一个术语/定义对。如果一行缺少Term:或Definition:标签,我们跳过它。然后,我们将其转换为便于存储的字典!

保存提取的术语

现在我们可以提取术语了,我们需要将它们放在某个地方,以便以后查询它们。VectorStoreIndex现在应该是一个完美的选择!但除此之外,我们的应用程序还应该跟踪哪些项被插入到索引中,以便我们稍后可以检查它们。使用st.session_state,我们可以将当前的术语列表存储在会话字典中,每个用户都是唯一的!

首先,让我们添加一个特性来初始化全局向量索引,并添加另一个函数来插入提取的术语。

import osimport streamlit as st
from llama_index.core import Document, SummaryIndex, Settings, VectorStoreIndex
from llama_index.embeddings.dashscope import DashScopeEmbedding, DashScopeTextEmbeddingModels, \DashScopeTextEmbeddingType
from llama_index.llms.dashscope import DashScopeDEFAULT_TERM_STR = ("列出在上下文中定义的术语和定义的列表, ""每一行上有一对。 ""如果一个术语缺少它的定义,用你最好的判断。""按如下方式书写每一行:\nTerm: <term> Definition: <definition>"
)if "all_terms" not in st.session_state:st.session_state["all_terms"] = {}def insert_terms(terms_to_definition):for term, definition in terms_to_definition.items():doc = Document(text=f"Term: {term}\nDefinition: {definition}")st.session_state["llama_index"].insert(doc)@st.cache_resource
def initialize_index(api_key):Settings.embed_model = DashScopeEmbedding(api_key=api_key,model_name=DashScopeTextEmbeddingModels.TEXT_EMBEDDING_V2,text_type=DashScopeTextEmbeddingType.TEXT_TYPE_DOCUMENT,)return VectorStoreIndex([])def get_llm(llm_name, model_temperature, api_key, max_tokens=256):return DashScope(emperature=model_temperature, model_name=llm_name, api_key=api_key, max_tokens=max_tokens)def extract_terms(documents, term_extract_str, llm_name, model_temperature, api_key
):llm = get_llm(llm_name, model_temperature, api_key, max_tokens=1024)temp_index = SummaryIndex.from_documents(documents,)query_engine = temp_index.as_query_engine(response_mode="tree_summarize", llm=llm)terms_definitions = str(query_engine.query(term_extract_str))print(terms_definitions)terms_definitions = [xfor x in terms_definitions.split("\n")if x and "Term:" in x and "Definition:" in x]# 将文本解析为字典terms_to_definition = {x.split("Definition:")[0].split("Term:")[-1].strip(): x.split("Definition:")[-1].strip()for x in terms_definitions}return terms_to_definitionst.title("🦙 骆驼索引术语提取器 🦙")setup_tab, upload_tab = st.tabs(["设置", "上传/提取术语"])with setup_tab:st.subheader("LLM 设置")api_key = st.text_input("在这里输入OpenAI API密钥", type="password")llm_name = st.selectbox("选择LLM模型?", ["qwen-turbo", "qwen-plus"])model_temperature = st.slider("LLM Temperature", min_value=0.0, max_value=1.0, step=0.1)term_extract_str = st.text_area("提取术语和定义的查询。",value=DEFAULT_TERM_STR,)with upload_tab:st.subheader("提取和查询定义")if st.button("初始化索引和重置术语"):st.session_state["llama_index"] = initialize_index(api_key)st.session_state["all_terms"] = {}if "llama_index" in st.session_state:st.markdown("请在下面输入要提取术语的文本。")document_text = st.text_area("输入原始文本")if st.button("提取术语和定义") and document_text:st.session_state["terms"] = {}terms_docs = {}with st.spinner("提取中..."):terms_docs.update(extract_terms([Document(text=document_text)],term_extract_str,llm_name,model_temperature,api_key,))st.session_state["terms"].update(terms_docs)if "terms" in st.session_state and st.session_state["terms"]:st.markdown("提取术语")st.json(st.session_state["terms"])if st.button("是否插入术语?"):with st.spinner("正在插入术语"):insert_terms(st.session_state["terms"])st.session_state["all_terms"].update(st.session_state["terms"])st.session_state["terms"] = {}st.rerun()

现在你真的开始使用Streamlit的强大功能了!让我们从upload上传标签下的代码开始。我们添加了一个按钮来初始化向量索引,并将其存储在全局的Streamlit状态字典中,同时重置当前提取的术语。然后,在从输入文本中提取术语之后,我们将提取的术语再次存储到全局状态中,并给用户一个机会来审查这些术语。如果按下插入按钮,那么我们将调用我们的插入术语函数,更新我们对已插入术语的全局跟踪,并从会话状态中移除最近提取的术语。
在这里插入图片描述

查询提取的术语/定义

提取并保存了术语和定义后,我们如何使用它们?用户如何记住之前保存的内容?我们可以简单地在应用程序中添加一些选项卡来处理这些功能。

import streamlit as st
from llama_index.core import Document, SummaryIndex, Settings, VectorStoreIndex
from llama_index.embeddings.dashscope import DashScopeEmbedding, DashScopeTextEmbeddingModels, \DashScopeTextEmbeddingType
from llama_index.llms.dashscope import DashScope, DashScopeGenerationModelsDEFAULT_TERM_STR = ("列出在上下文中定义的术语和定义的列表, ""每一行上有一对。 ""如果一个术语缺少它的定义,用你最好的判断。""按如下方式书写每一行:\nTerm: <term> Definition: <definition>"
)if "all_terms" not in st.session_state:st.session_state["all_terms"] = {}def insert_terms(terms_to_definition):for term, definition in terms_to_definition.items():doc = Document(text=f"Term: {term}\nDefinition: {definition}")st.session_state["llama_index"].insert(doc)def initialize_index(api_key: str):print('api_key', api_key)Settings.llm = DashScope(model_name=DashScopeGenerationModels.QWEN_TURBO, api_key=api_key, max_tokens=512)Settings.embed_model = DashScopeEmbedding(api_key=api_key,model_name=DashScopeTextEmbeddingModels.TEXT_EMBEDDING_V2,text_type=DashScopeTextEmbeddingType.TEXT_TYPE_DOCUMENT,)return VectorStoreIndex([])def get_llm(llm_name, model_temperature, api_key, max_tokens=256):return DashScope(emperature=model_temperature, model_name=llm_name, api_key=api_key, max_tokens=max_tokens)def extract_terms(documents, term_extract_str, llm_name, model_temperature, api_key
):llm = get_llm(llm_name, model_temperature, api_key, max_tokens=1024)temp_index = SummaryIndex.from_documents(documents,)query_engine = temp_index.as_query_engine(response_mode="tree_summarize", llm=llm)terms_definitions = str(query_engine.query(term_extract_str))print(terms_definitions)terms_definitions = [xfor x in terms_definitions.split("\n")if x and "Term:" in x and "Definition:" in x]# 将文本解析为字典terms_to_definition = {x.split("Definition:")[0].split("Term:")[-1].strip(): x.split("Definition:")[-1].strip()for x in terms_definitions}return terms_to_definitionst.title("🦙 骆驼索引术语提取器 🦙")setup_tab, terms_tab, upload_tab, query_tab = st.tabs(["设置", "所有术语", "上传/提取术语", "查询术语"]
)with setup_tab:st.subheader("LLM 设置")api_key = st.text_input("在这里输入OpenAI API密钥", type="password")llm_name = st.selectbox("选择LLM模型?", ["qwen-turbo", "qwen-plus"])model_temperature = st.slider("LLM Temperature", min_value=0.0, max_value=1.0, step=0.1)term_extract_str = st.text_area("提取术语和定义的查询。",value=DEFAULT_TERM_STR,)with upload_tab:st.subheader("提取和查询定义")if st.button("初始化索引和重置术语"):st.session_state["llama_index"] = initialize_index(api_key)st.session_state["all_terms"] = {}if "llama_index" in st.session_state:st.markdown("请在下面输入要提取术语的文本。")document_text = st.text_area("输入原始文本")if st.button("提取术语和定义") and document_text:st.session_state["terms"] = {}terms_docs = {}with st.spinner("提取中..."):terms_docs.update(extract_terms([Document(text=document_text)],term_extract_str,llm_name,model_temperature,api_key,))st.session_state["terms"].update(terms_docs)if "terms" in st.session_state and st.session_state["terms"]:st.markdown("提取术语")st.json(st.session_state["terms"])if st.button("是否插入术语?"):with st.spinner("正在插入术语"):insert_terms(st.session_state["terms"])st.session_state["all_terms"].update(st.session_state["terms"])st.session_state["terms"] = {}st.rerun()with terms_tab:with terms_tab:st.subheader("当前提取的术语和定义")st.json(st.session_state["all_terms"])with query_tab:st.subheader("查询术语/定义!")st.markdown(("LLM将尝试回答您的查询,并使用您插入的术语/定义来扩展它的答案。 ""如果一个项不在索引中,它将使用它的内部知识来回答。"))if st.button("初始化索引和重置术语", key="init_index_2"):st.session_state["llama_index"] = initialize_index(api_key)st.session_state["all_terms"] = {}if "llama_index" in st.session_state:query_text = st.text_input("询问一个术语或定义:")if query_text:query_text = (query_text+ "\n如果你找不到答案,那就尽你所能去回答这个问题。")with st.spinner("生成回答..."):response = (st.session_state["llama_index"].as_query_engine(similarity_top_k=5,response_mode="compact",).query(query_text))st.markdown(str(response))

虽然这大部分是基础性的,但有些重要的点需要注意:

  • 我们的初始化按钮与其它按钮有相同的文本。Streamlit会对此提出警告,因此我们提供了一个唯一的键来解决这个问题。
  • 查询中添加了一些额外的文本!这是为了尝试弥补索引没有答案的情况。
  • 在我们的索引查询中,我们指定了两个选项:
    • similarity_top_k=5 表示索引将获取与查询最接近的前5个匹配的术语/定义。
    • response_mode="compact" 表示尽可能多的文本将从5个匹配的术语/定义中用于每次LLM调用。如果没有这个设置,索引会对LLM进行至少5次调用,这可能会减慢用户的使用速度。

在这里插入图片描述
在这里插入图片描述

测试运行

好吧,实际上我希望我们在进行的过程中一直在测试。但现在,让我们尝试一次完整的测试。

  1. 刷新应用程序
  2. 输入您的LLM设置
  3. 转到查询选项卡
  4. 询问以下问题:什么是兔抱(bunnyhug)?
  5. 应用程序应该给出一些无意义的回答。如果你不知道的话,兔抱(bunnyhug)是加拿大草原地区人们用来指代连帽衫的另一种说法!
    6.让我们把这个定义添加到应用程序中。打开上传标签并输入以下文本:兔抱(bunnyhug)是用来描述连帽衫的一个常见术语。这个术语由加拿大草原地区的人们使用。
  6. 单击提取按钮。几分钟后,应用程序应该显示正确提取的术语/定义。单击插入术语按钮保存它!
  7. 如果我们打开术语选项卡,应该会显示我们刚刚提取的术语和定义。
  8. 回到查询选项卡,尝试询问兔抱是什么。现在,答案应该是正确的!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/457701.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Ovis: 多模态大语言模型的结构化嵌入对齐

论文题目&#xff1a;Ovis: Structural Embedding Alignment for Multimodal Large Language Model 论文地址&#xff1a;https://arxiv.org/pdf/2405.20797 github地址&#xff1a;https://github.com/AIDC-AI/Ovis/?tabreadme-ov-file 今天&#xff0c;我将分享一项重要的研…

量子机器学习:颠覆性的前沿技术

量子机器学习&#xff1a;颠覆性的前沿技术 引言 在科技日新月异的今天&#xff0c;量子计算和机器学习作为两大前沿领域&#xff0c;各自在推动科技进步中发挥着重要作用。而当这两者结合时&#xff0c;便诞生了一个全新的领域——量子机器学习&#xff08;Quantum Machine …

GCC 简介

Linux 中的编译器 GCC 的编译原理和使用详解 GCC 简介 GCC&#xff08;GNU Compiler Collection&#xff09;是一套由 GNU 开发的编程语言编译器&#xff0c;它支持多种编程语言&#xff0c;包括 C、C、Objective-C、Fortran、Ada 和 Go 等。GCC 是一个开源的工具集&#xff…

Spring Boot框架在学生宿舍管理中的应用研究

摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了学生宿舍信息管理系统的开发全过程。通过分析学生宿舍信息管理系统管理的不足&#xff0c;创建了一个计算机管理学生宿舍信息管理系统的方案。文章介绍了学生宿舍…

AI读教链《为什么今年ETH对BTC表现这么拉垮?》

以太坊&#xff08;ETH&#xff09;近期表现不佳&#xff0c;主要是由于市场对其价值存储功能的信心下降&#xff0c;尤其是在比特币&#xff08;BTC&#xff09;表现强劲的背景下。ETH的市值逐渐被以Solana等新兴公链抢占&#xff0c;流失了大量用户和炒币的流量。此外&#x…

JAVA排序

排序的概念 排序&#xff1a;所谓排序&#xff0c;就是使一串记录&#xff0c;按照其中的某个或某些关键字的大小&#xff0c;递增或递减的排列起来的操作。 稳定性&#xff1a;假定在待排序的记录序列中&#xff0c;存在多个具有相同的关键字的记录&#xff0c;若经过排序&…

跟着鸟儿学飞行?扑翼机器人的感知秘籍

大家好&#xff01;今天来了解一篇扑翼机器人的研究——《Avian-inspired embodied perception in biohybrid flapping-wing robotics》发表于《Nature Communications》。在广阔天空中&#xff0c;鸟类凭借精妙翅膀结构与敏锐感知自由翱翔&#xff0c;这一直吸引着科学家探索其…

cherry pick commit

cherry pick commit git cherry-pick 是一个 Git 命令&#xff0c;用于将特定的提交&#xff08;commit&#xff09;应用到当前分支上。这在需要从其他分支中挑选某些提交到当前分支时非常有用&#xff0c;例如当你需要修复一个 bug&#xff0c;但想只应用特定的变更&#xff…

国内大语言模型哪家更好用?

大家好&#xff0c;我是袁庭新。 过去一年&#xff0c;AI大语言模型在爆发式增长&#xff0c;呈现百家争鸣之态。国内外相关厂商积极布局&#xff0c;并相继推出自家研发的智能化产品。 我在工作中已习惯借助AI来辅助完成些编码、创作、文生图等任务&#xff0c;甚至对它们产…

基于物联网的智慧考场系统设计(论文+源码)

1. 功能设计 &#xff08;1&#xff09;温度监测与控制功能&#xff1a; 系统需要能够实时采集考场内的温度信息&#xff0c;通过DS18B20传感器获取准确的数据&#xff0c;并在OLED屏幕和APP上显示。当温度异常过高时&#xff0c;系统应自动启动继电器&#xff0c;模拟空调开启…

【Python】深入理解Python的列表推导式与生成器表达式:简洁与性能的权衡

引言 Python因其简洁易懂的语法和强大的标准库&#xff0c;深受开发者的喜爱。为了提升代码的简洁性与可读性&#xff0c;Python引入了许多方便的语法特性&#xff0c;其中列表推导式和生成器表达式是非常重要的工具。这两者为我们提供了优雅的方式来生成序列数据&#xff0c;…

API接口开放与安全管控 - 原理与实践

API安全是接口开放的前提条件 在API对外开放时&#xff0c;确保其安全性至关重要&#xff0c;因为API直接暴露给外部环境&#xff0c;容易成为攻击目标。一旦被恶意利用&#xff0c;可能导致数据泄露、服务滥用等严重后果。因此&#xff0c;通过API网关实施严格的接口安全管理…

用“堆”模拟实现“优先级队列”

PriorityQueue优先级队列 1. 优先级队列的概念2. 优先队列的模拟实现3 堆的概念4. 堆的存储方式5. 堆向下调整6. 堆的创建7. 堆的插入8. 堆的删除9. 用堆模拟实现优先级队列 1. 优先级队列的概念 前面我们学习了队列&#xff0c;队列是一种“先进先出”的数据结构&#xff0c;…

智慧农业大数据平台:智汇田园,数驭未来

智慧农业大数据平台 计讯物联智慧农业大数据平台是一个集管理数字化、作业自动化、生产智能化、产品绿色化、环境信息化、服务现代化于一体的多功能监管系统。它通过与硬件产品的搭配使用&#xff0c;实现对农业生产全过程的实时监测、精准控制和科学管理。该平台集成了多个数…

blender 小车建模 建模 学习笔记

一、学习blender视频教程链接 案例4&#xff1a;狂奔的小车_建模_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1Bt4y1E7qn?p14&spm_id_from333.788.videopod.episodes&vd_sourced0ea58f1127eed138a4ba5421c577eb1 二、开始建模 &#xff08;1&#xff09;创…

逻辑回归与神经网络

从逻辑回归开始学习神经网络 神经网络直观上解释&#xff0c;就是由许多相互连接的圆圈组成的网络模型&#xff1a; 而逻辑回归可以看作是这个网络中的一个圆圈&#xff1a; 圆圈被称为神经元&#xff0c;整个网络被称为神经网络。 本节的任务是我们究竟如何理解具体的一个神…

华为OD机试 - 芯片资源占用(Java 2024 E卷 200分)

华为OD机试 2024E卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xff08;E卷D卷A卷B卷C卷&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;私信哪吒&#xff0c;备注华为OD&#xff0c;加…

QT仿QQ聊天项目,第一节,创建项目并布置编辑登录界面

目录 一&#xff0c;创建项目 二&#xff0c;编辑登录界面 1&#xff0c;登录界面整体构造 2&#xff0c;登录界面的宽高 3&#xff0c;登录界面使用到的控件 4&#xff0c;登录界面中的控件所在的位置和大小 &#xff08;1&#xff09;qq图标label位置和大小 &#xff0…

MySQL-事务隔离级别

1. MySQL事务的四种隔离级别 1.1 读未提交&#xff08;READ UNCOMMITTED&#xff09; READ UNCOMMITED提供了事务之间最小限度的隔离&#xff0c;除了幻读和不可重复读取的操作外&#xff0c;处于这个隔离级别的事务可以读到其它事务还未提交的数据。 1.2 读已提交&#xf…

哪个牌子的电容笔值得入手?!实测西圣、品胜、倍思三大热门品牌!

电容笔逐渐走入了大众视野&#xff0c;不仅数码博主人手一支&#xff0c;很多上班族和学生党也开始使用电容笔来进行无纸化办公和学习。然而&#xff0c;市场上的电容笔品牌众多&#xff0c;产品质量参差不齐&#xff0c;为了帮助大家挑选出真正优质的产品&#xff0c;我花费了…