玩具网站模板,旅游网站有哪些功能,大型网站开发用的技术,旅游网站怎么自己做原文#xff1a;towardsdatascience.com/how-to-create-a-powerful-ai-email-search-for-gmail-with-rag-88d2bdb1aedc 在本文中#xff0c;我将向您展示如何使用 RAG#xff08;关系抽取和问答#xff09;技术来开发MailDiscoverer应用程序以搜索 Gmail 电子邮件。首先towardsdatascience.com/how-to-create-a-powerful-ai-email-search-for-gmail-with-rag-88d2bdb1aedc在本文中我将向您展示如何使用 RAG关系抽取和问答技术来开发MailDiscoverer应用程序以搜索 Gmail 电子邮件。首先我会向您展示如何设置认证管道以访问用户的电子邮件如果得到同意。然后使用 OpenAI 文本嵌入器将电子邮件嵌入并存储在 Pinecone 向量数据库中。这使用户能够就电子邮件提出问题RAG 系统将检索最相关的电子邮件并回答问题。…/Images/3dec31a820e32a1cb2b43651a727adff.png学习如何开发一个 RAG 系统来搜索您的电子邮件。图片由 ChatGPT 提供。OpenAI. (2024).ChatGPT(4o) [大型语言模型].chatgpt.com/c/66dd8280-5bc4-8012-9e7e-68fd66ccbfeb本文开发的程序可以在Streamlit上找到。此代码的 GitHub 仓库也可用。下面的视频展示了应用程序的工作方式。登录并上传您的电子邮件后您可以就它们提出问题应用程序将提供答案并展示用于提供答案的最相关电子邮件。cdn.embedly.com/widgets/media.html?srchttps%3A%2F%2Fwww.loom.com%2Fembed%2Fa16c5aec830e40b2b1375609e62680d5display_nameLoomurlhttps%3A%2F%2Fwww.loom.com%2Fshare%2Fa16c5aec830e40b2b1375609e62680d5%3Fsid%3Dc5177ecd-af15-4cb4-9f8b-4d60a0adcf17imagehttps%3A%2F%2Fcdn.loom.com%2Fsessions%2Fthumbnails%2Fa16c5aec830e40b2b1375609e62680d5-d2d1e7f7b020fbdc.gifkeya19fcc184b9711e1b4764040d3dc5c07typetext%2Fhtmlschemaloom动机我写这篇文章的动机是我经常搜索旧邮件花费大量时间试图找到它们。解决这个问题的方法是为您开发一个 RAG 系统您可以将您的邮件上传将邮件中的文本内容嵌入并提示系统找到邮件。例如我可以问“我最近有没有收到来自微软的邮件”系统将找到最相关的邮件并使用这些邮件中的文本进行回复。此外每个邮件的查看链接也很重要。我之前已经写过一篇关于开发类似工具的文章如何制作一个 RAG 系统以获取对您数据的强大访问权限展示了如何创建一个 RAG 系统来访问您的数据。这篇文章的不同之处在于我直接通过Google Gmail API这比下载然后上传您的邮件要用户友好得多访问电子邮件。我还使用Pinecone作为我的向量数据库这允许您免费上限为自然最大使用限制在服务器上托管向量数据库。目录· 动机 · 目录 · 计划 · 添加 Gmail 集成以访问邮件 ∘ 获取访问 Gmail API 的权限 ∘ 用户登录和获取同意 ∘ 检索邮件 · 将邮件存储在向量数据库中 · 结论计划下面的列表是我开发此Streamlit应用程序的计划添加 Gmail 集成以便我可以访问用户的邮件将所有邮件嵌入并存储在用户的数据库中为用户添加提示字段使用答案响应用户提示并使用最相关的电子邮件提供答案要遵循此教程您可以使用 pip 下载以下包openai pinecone-client google-api-python-client google-auth google-auth-httplib2 google-auth-oauthlib streamlit python-dotenv tqdm langchain langchain-openaitx添加 Gmail 集成以访问邮件获取访问 Gmail API 的权限开发 MailDiscoverer 应用程序的第一步是获取对用户的邮件的访问权限。为此您可以使用Google Gmail API它允许用户登录他们的 Google 账户并同意应用程序访问他们的邮件。通过 Google 登录增加了真实性您不必担心自己开发身份验证管道。此外Google Gmail API 在相对较大的使用限制内是免费的这使得它成为访问用户邮件的好选择。要获取 Gmail API 的访问权限您必须前往Google Cloud Console激活 Gmail API前往“凭证”页面并添加 OAuth 2.0 客户端 ID。将其设置为 Web 应用程序并将授权重定向 URI 设置为localhost:8080请注意这里的端口很重要。此外在托管您的应用程序时您需要将此 URI 更改为与您的应用程序 URI 匹配。注意确保在此处运行 Streamlit 与您在此处写入的端口相同例如要在端口 8080 上运行 Streamlitstreamlit run main.py – server.port 8080下载您的 credentials.json 文件您稍后将在编程文件夹中需要它。前往 OAuth 同意屏幕页面创建您的应用。填写所有必要的信息并添加两个作用域[www.googleapis.com/auth/userinfo.email]访问用户的电子邮件地址和www.googleapis.com/auth/gmail.readonly读取用户的电子邮件您现在应该可以访问 Gmail API我将向您展示如何使用 Python 利用它。登录用户并获取同意要验证用户我使用以下代码。首先定义您的导入importstreamlitasstfromgoogle.oauth2.credentialsimportCredentialsfromgoogle_auth_oauthlib.flowimportInstalledAppFlowfromgoogleapiclient.discoveryimportbuildfromgoogle.auth.transport.requestsimportRequestimportos然后定义您的常量。请记住更改最后四个常量使其与您之前下载的credentials.json文件中的那些相匹配。MAIN_REDIRECT_URIhttp://localhost:8080/SCOPES[https://www.googleapis.com/auth/gmail.readonly,https://www.googleapis.com/auth/userinfo.email]PROJECT_IDxxxAUTH_URIxxxTOKEN_URIxxxAUTH_PROVIDER_X509_CERT_URLxxx我还导入了我的客户端 ID 和客户端密钥请注意这些是敏感变量因此我将它们存储在.streamlit/secrets.toml文件中并在托管我的 streamlit 应用程序时确保在密钥变量部分定义这些变量CLIENT_IDst.secrets[GMAIL_API_CREDENTIALS][CLIENT_ID]CLIENT_SECRETst.secrets[GMAIL_API_CREDENTIALS][CLIENT_SECRET]然后您可以定义用于验证用户的客户端配置此配置本质上验证了您是您在 Google Gmail API 上注册的应用程序的作者CLIENT_CONFIG{web:{client_id:CLIENT_ID,project_id:PROJECT_ID,auth_uri:AUTH_URI,token_uri:TOKEN_URI,auth_provider_x509_cert_url:AUTH_PROVIDER_X509_CERT_URL,client_secret:CLIENT_SECRET,redirect_uris:ALL_REDIRECT_URIS,javascript_origins:ALL_JAVASCRIPT_ORIGINS}}使用 Streamlit您现在可以使用以下代码验证用户代码的解释如下defget_user_info(creds):# Build the OAuth2 service to get user infooauth2_servicebuild(oauth2,v2,credentialscreds)# Get user infouser_infooauth2_service.userinfo().get().execute()returnuser_info.get(email)defauthorize_gmail_api():Shows basic usage of the Gmail API. Lists the users Gmail labels. credsNoneifos.path.exists(token.json):credsCredentials.from_authorized_user_file(token.json,SCOPES)st.info(Already logged in)# If there are no (valid) credentials available, let the user log in.ifnotcredsornotcreds.valid:ifcredsandcreds.expiredandcreds.refresh_token:creds.refresh(Request())else:flowInstalledAppFlow.from_client_config(CLIENT_CONFIG,SCOPES)flow.redirect_uriMAIN_REDIRECT_URI authorization_url,stateflow.authorization_url(access_typeoffline,include_granted_scopestrue,promptconsent)# this is just a nice button with streamlitst.markdown(f style .custom-button {{ display: inline-block; background-color: #4CAF50; /* Green background */ color: white !important; /* White text */ padding: 10px 24px; text-align: center; text-decoration: none; font-size: 16px; border-radius: 5px; margin-top: 5px; /* Reduce space above the button */ margin-bottom: 5px; /* Reduce space below the button */ }} .custom-button:hover {{ background-color: #45a049; }} /style a href{authorization_url} target_blank classcustom-buttonAuthorize with Google/a ,unsafe_allow_htmlTrue)defauthenticate_user():after loggin in with google, you have a code in the url. This function retrieves the code and fetches the credentials and authenticates userauth_codest.query_params.get(code,None)ifauth_codeisnotNone:# make a new flow to fetch tokensflowInstalledAppFlow.from_client_config(CLIENT_CONFIG,SCOPES,)flow.redirect_uriMAIN_REDIRECT_URI flow.fetch_token(codeauth_code)st.query_params.clear()credsflow.credentialsifcreds:st.session_state.credscreds# Save the credentials for future usewithopen(token.json,w)astoken_file:token_file.write(creds.to_json())st.success(Authorization successful! Credentials have been saved.)# Save the credentials for the next runwithopen(token.json,w)astoken:token.write(creds.to_json())# get user emailuser_emailget_user_info(creds)st.session_state.user_emailuser_email st.rerun()else:st.error(Could not log in user)ifst.button(LOGIN):authorize_gmail_api()ifst.query_params.get(code,None):authenticate_user()这段代码有很多让我来解释一下。首先我有一个 _get_userinfo函数它返回登录凭证后用户的电子邮件地址。其次_authorize_gmailapi函数首先检查用户是否已经有了凭证一个tokens.json文件。如果有我们就不需要让用户登录。然后我使用我的配置文件初始化一个流程其中流程用于使用 Gmail 的身份验证系统对用户进行身份验证。使用流程您可以检索授权 URL该 URL 将用户带到 Google 页面在那里他们可以登录并同意提供的范围读取他们的电子邮件地址和读取他们的电子邮件。此函数中带有 st.markdown 的最后一行代码在 Streamlit 中是一个漂亮的绿色按钮。在用户输入授权 URL 并登录后他们将被返回到您的应用由重定向 URI 定义并且他们的 URL 中将包含一个代码这个代码将用于验证用户是他们所说的那个人。_authenticate_user函数从 URL 中检索代码用户登录后重定向回应用程序后出现并将其发送给 Google 进行身份验证。如果 Google 验证了代码您将收到凭证作为回报您可以将其存储您的用户将被验证。这允许您的应用程序访问用户同意您应用程序访问的数据。代码中的最后两个 if 语句用于触发我上面解释的函数。https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/ed7234fb21bdc0614359635880cfdf80.png如果您实现了上面的代码登录和注销按钮将看起来像这样。按下登录按钮后将出现一个绿色按钮允许用户使用 Google 进行身份验证。身份验证后他们将带着 URI 中的代码返回到应用程序您可以使用该代码获取用户的凭证正式验证用户并允许您的应用程序访问用户同意您应用程序访问的数据。图片由作者提供。您可以使用以下方式注销用户deflogout(is_from_login_funcFalse):Logs the user out by deleting the token and clearing session data.st.query_params.clear()st.session_state.user_emailNonest.session_state.credsNoneifos.path.exists(token.json):os.remove(token.json)ifnotis_from_login_func:st.success(Logged out successfully!)实现此认证流程相当困难尤其是在生产环境中在本地运行更容易但上面的代码在本地测试和生产环境中都适用。但是使用上面的代码您应该能够使用用户的 Gmail 来验证您的用户。如果您对此部分有任何疑问请告诉我获取电子邮件用户验证后由于您有读取权限您可以访问他们的电子邮件。以下功能允许您访问用户的电子邮件def_get_email_body(msg):ifpartsinmsg[payload]:# The email has multiple parts (possibly plain text and HTML)forpartinmsg[payload][parts]:ifpart[mimeType]text/plain:# Look for plain textbodypart[body][data]returnbase64.urlsafe_b64decode(body).decode(utf-8)else:# The email might have a single part, like plain text or HTMLbodymsg[payload][body].get(data)ifbody:returnbase64.urlsafe_b64decode(body).decode(utf-8)returnNone# In case no plain text is found# Function to list emails with a max limit and additional detailsdef_list_emails_with_details(service,max_emails100):all_emails[]resultsservice.users().messages().list(userIdme,maxResultsmax_emails).execute()# Fetch the first page of messagesmessagesresults.get(messages,[])all_emails.extend(messages)# Keep fetching emails until we reach the max limit or there are no more pageswhilenextPageTokeninresultsandlen(all_emails)max_emails:page_tokenresults[nextPageToken]resultsservice.users().messages().list(userIdme,pageTokenpage_token).execute()messagesresults.get(messages,[])all_emails.extend(messages)# Break if we exceed the max limitiflen(all_emails)max_emails:all_emailsall_emails[:max_emails]# Trim to max limitbreakprogress_bar2st.progress(0)status_text2st.text(Retrieving your emails...)email_details[]foridx,emailintqdm(enumerate(all_emails),descFetching email details):# Fetch full email detailsmsgservice.users().messages().get(userIdme,idemail[id]).execute()headersmsg[payload][headers]email_textself._get_email_body(msg)ifemail_textisNoneoremail_text:continueiflen(email_text)MAX_CHARACTER_LENGTH_EMAIL:email_textemail_text[:MAX_CHARACTER_LENGTH_EMAIL]# Truncate long emails# Extract date, sender, and subject from headersemail_data{text:email_text,id:msg[id],date:next((header[value]forheaderinheadersifheader[name]Date),None),from:next((header[value]forheaderinheadersifheader[name]From),None),subject:next((header[value]forheaderinheadersifheader[name]Subject),None),email_link:fhttps://mail.google.com/mail/u/0/#inbox/{email[id]}}email_details.append(email_data)progress_bar2.progress((idx1)/len(all_emails))# Progress bar updatestatus_text2.text(fRetrieving email{idx1}of{len(all_emails)})returnemail_details第一个函数__get_email_body是一个辅助函数用于检索电子邮件的完整文本内容由于您需要解码邮件等可能会看起来有些混乱但它按预期工作。第二个函数首先使用函数的第二行检索用户的邮件。由于可以检索到许多结果因此使用nextPageToken这允许我们提取所有结果。在检索电子邮件并将它们存储在_all_emails变量中之后您可以从电子邮件中提取所需的内容如文本内容、ID、日期、发件人、主题以及打开邮件的链接。此外我在 Streamlit 中使用进度条以便用户可以看到检索电子邮件还需要多少时间。解决隐私问题在开发此类应用程序时考虑到用户的隐私至关重要。当你想要部署一个利用用户电子邮件的应用程序时谷歌必须验证你的应用程序包括展示你的应用程序如何利用用户数据添加隐私政策我的在这里[这里](https://maildiscoverer.streamlit.app/privacy_page))添加服务条款我的在这里并保证你不会滥用用户数据。在开发本文讨论的应用程序时认真对待隐私问题并小心处理用户数据非常重要。我已经确保遵循谷歌对处理敏感信息的要求并自然保证我不会滥用此应用程序存储的任何数据。在下一节中我将讨论如何在矢量数据库中存储电子邮件。在执行此操作时你应该考虑几个要素。首先向你的用户披露你正在收集和存储信息例如在隐私政策中。其次确保通过使用信誉良好的数据库我使用 Pinecone一个我相信会妥善处理数据的服务的数据库或者如果你在自己的托管数据库中存储数据确保数据库是安全的。在矢量数据库中存储电子邮件由于我已经在关于使用 RAG 系统快速访问存储在矢量数据库中的数据的get_email_body中讨论了存储数据的问题因此我不会在本文章中深入探讨该主题。然而我将总结我是如何处理这个问题的。首先我决定使用Pinecone因为它是我已经熟悉的工具。还有很多其他的矢量数据库可供选择所以请随意选择你喜欢的。如果你想要轻松部署你的应用程序Pinecone 非常不错因为你可以将数据快速存储在云端索引存储在云端。此外Pinecone 提供了良好的免费套餐这意味着在需要付费之前你可以大量使用 Pinecone。https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/1e7034a1106b90e246e80469607e3e50.png此流程图突出了回答用户关于其电子邮件的问题的步骤。首先用户登录并允许应用程序读取他们的电子邮件。然后这些电子邮件被嵌入并存储在向量数据库中。用户可以就他们的电子邮件提出问题。检索与该问题最相关的电子邮件然后 GPT-4o mini 使用这些最相关的电子邮件来回答用户的问题。图像由作者提供在本文的最后一章之后检索到电子邮件后我使用 OpenAI 的text-embedding-3-small文本嵌入模型进行了嵌入。再次强调您可以使用任何您想要的模型但我使用的模型效果良好且价格低廉。然后您收集所有想要存储在向量数据库中的信息在这种情况下是电子邮件信息日期、发件人、主题、文本和嵌入。要从给定的查询中找到相关的电子邮件您接下来需要使用与您用于嵌入电子邮件相同的嵌入方法来嵌入查询。然后使用向量数据库进行比较返回最相似的 k 封电子邮件其中 k 是一个您自己决定的数字。在检索到最相关的电子邮件后您然后从这些电子邮件中获取文本并将该文本以及用户的提问输入到 LLM例如 GPT-4o mini它将根据您提供的最相关电子邮件作为上下文来回答用户的问题。确保在数据库中存储向量时您可以根据用户分离信息也很重要。在这种情况下用户电子邮件将是一个唯一的属性这就是为什么我们之前检索电子邮件的原因所以请确保将每封电子邮件以随附所有者的电子邮件地址存储在数据库中。在搜索与给定查询最相关的电子邮件时您然后只需搜索具有相同用户的电子邮件。https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/39b2256e682f92f761dad65f728d7640.png此图像显示了应用程序如何检索用户的电子邮件在这种情况下是我的电子邮件出于隐私原因已隐藏然后嵌入电子邮件。图像由作者提供应用程序性能我还希望包括一个关于应用程序性能如何的章节。为此我将向您展示几个具体的例子说明电子邮件如何回答用户的提示。不幸的是我无法分享我所有的电子邮件来验证结果但我将展示应用程序如何正确回答用户的问题。您当然可以自己尝试使用该应用程序来验证它是否有效。测试 1在我的第一次测试中我提示 MailDiscoverer 查看我最近是否收到了任何针对我的 Google 账户的安全警报例如如果有一个新设备登录到我的账户。我输入以下提示Have I gotanysecurity alerts lately?应用响应如下Yes,you have received several security alerts recently:X(Twitter)Login Alerts:On September1,2024,you received two alerts about logins to your accountfromnew devices:OnefromChromeDesktop on WindowsinOslo,Norway.Anotherfromip addresson iPhoneinOslo,Norway.Google Account Access:On September7,2024,you received a security alertfromGoogle indicating that an application named maildiscoverer was granted access to your Google Account.If you didnotgrant this access,itisadvised to check the activityandsecure your account.These alerts indicate potential security concerns that you should reviewandaddressifnecessary.这是正确的我在那些确切日期上收到了这些警报。然而我要指出我还收到了一些 GitHub 可靠的警报关于我仓库中过时的包这些警报语言模型在其响应中没有包括。但是这些电子邮件作为最相关的电子邮件的一部分被包括在内。测试 2我也想测试一下这个应用回答特定问题的工作效果如何。AWS 最近邀请我通过他们的网站申请 300 美元的信用额度。因此我提示应用查询一下我通过申请 AWS 能得到多少美元。我用以下内容提示模型How many dollars of credits on AWS have I been offered toapplyfor?模型响应如下You have been offered toapplyfor$300inAWS credits.这是正确答案。关于测试的思考我进行了一个简单的测试来验证系统的性能系统表现良好。总的来说从这两个测试以及开发过程中对应用的测试来看应用表现良好解决了我想解决的问题更快地访问电子邮件中的信息。由于我不想分享我所有的电子邮件所以很难进行完全透明的测试但如果你想验证应用的表现非常欢迎你自己尝试在MailDiscoverer 网站上试用。结论在这篇文章中我讨论了我的应用MailDiscoverer它使电子邮件对用户更加易于访问。使用这个应用你可以就你的电子邮件提出问题应用会回答你的问题并链接到用于回答问题的最相关电子邮件。首先我讨论了创建这个应用的动机我时不时地会花很多时间搜索旧电子邮件。此外我还讨论了如何设置 Google Gmail API 以在用户同意的情况下访问他们的电子邮件。然后我展示了如何检索这些电子邮件。我还讨论了使用像 Pinecone 这样的向量数据库来存储电子邮件并快速搜索与给定查询最相关的邮件。这可以在 RAG 系统中用来为用户提供关于他们电子邮件的答案。最后我对系统进行了两个简单的测试来验证其性能。在输入的提示中应用成功提取了正确的答案。