为了账号安全,请及时绑定邮箱和手机立即绑定

实战指南:如何在大型代码库中使用Gemini上下文缓存功能

Google 再次通过为 Vertex AI 和 Google AI Studio 用户推出 Gemini 上下文缓存功能,推动了人工智能创新的边界。这一开创性功能充分发挥了 Gemini 巨大上下文窗口的全部潜力,允许用户轻松缓存庞大的复杂数据,包括法律文件、医疗记录、长视频、图像和音频文件等。通过消除每次提问时重复发送这些内容的必要,上下文缓存显著降低了成本,提升了用户体验,为高效和强大的人工智能应用铺平了道路。

我们不妨花点时间再看看那些重要的突破,正是这些突破让 Gemini 成为人工智能创新领域的领头羊。

  • 2017年6月:Transformer
  • ……….
  • 2023年12月:多模态Gemini
  • 2024年2月:1百万上下文(现为2百万)和1千万实验室版本——无限制,正如研究论文中所述……换句话说:谷歌解决了这一难题,而许多人认为这是无法解决的Transformer架构限制
  • 2024年5月:缓存上下文

想象一下,上下文缓存就像给 Gemini 背的一个背包。之前,当你在视频、代码仓库、大量文档等地方提问复杂问题时,你不得不背着一个装满这些信息的大包。这既繁琐又费时,就像每次想要查找一个事实时,都得拖着一本巨大的百科全书那样繁琐。

不过现在,有了上下文缓存功能,Gemini 只需要你把那个包放在一个方便的地方,这样就好。

跟着我看看实际操作。我将使用Gemini的上下文缓存特性来询问来自整个代码库的问题。通过提供整个Git仓库的访问给Gemini,我们为Gemini提供了您项目代码的完整上下文。这种深入的上下文理解使Gemini能够分析代码并在多个文件之间连接依赖关系。

我们将在Vertex AI Colab上进行编码,要跟着做,请打开一个新的空笔记本。

首先我们需要的是一个库来帮助我们用Python克隆代码库。我将使用这个GitPython:

安装GitPython包
python  
!pip install GitPython

这里有一个函数可以克隆一个 Git 仓库,并创建一个文件路径及其内容的字典。这种方法对于较小的仓库来说效果不错,但如果面对的是一个庞大的代码库,也不必担心!Gemini 可以帮助你重新设计方案以提高内存效率——只需提出需求即可!

    import git  
    import os  

    def list_and_read_repo_files(repo_url, branch="main"):  
        """  
        克隆一个Git仓库,列出所有文件(不包括.git文件夹及其内容),并读取其内容。  
        返回一个字典,键为文件路径,值为文件内容。  

        参数:  
            repo_url (str): Git仓库的URL。  
            branch (str, optional): 要切换的分支。默认为"main"。  

        返回:  
            dict: 键为文件路径,值为文件内容的字典。  
        """  
        try:  
            # 用于克隆的临时目录  
            repo_dir = "temp_repo"  

            # 克隆仓库  
            print(f"从{repo_url}克隆仓库...")  
            git.Repo.clone_from(repo_url, repo_dir, branch=branch)  
            print("克隆完成!")  

            file_contents = {}  
            for root, _, files in os.walk(repo_dir):  
                for file in files:  
                    # 排除包含.git的文件夹及其内容  
                    if ".git" not in root:  
                        file_path = os.path.join(root, file)  
                        try:   
                          with open(file_path, "r", encoding="utf-8") as f:  
                            file_contents[file_path] = f.read()  
                        except Exception as e:  # 捕获任何未预料的错误  
                             print(f"出现意外错误: {e}")  

            return file_contents  

        except git.exc.GitCommandError as e:  
            print(f"克隆仓库错误: {e}")  
        except UnicodeDecodeError as e:  
            print(f"字符解码错误: {e}")  
        except Exception as e:  # 捕获任何未预料的错误  
            print(f"出现意外错误: {e}")  
        finally:  
            # 清理临时仓库目录  
            if os.path.exists(repo_dir):  
                git.rmtree(repo_dir)

那我们就来运行一下吧。我会下载最近谷歌DeepMind开源的一个项目的代码仓库。这个项目叫做OneTwo。

    repo_url = "https://github.com/google-deepmind/onetwo.git"  # 请根据实际情况替换此URL  
    branch = "main"  # 如果分支名不同,请更改  

    file_data = list_and_read_repo_files(repo_url, branch)

接下来要讲的是,我们将深入克隆的OneTwo仓库,并创建一个包含所有文件内容的单一文本文件。为了方便Gemini处理这些文件,每个文件的内容都将被包装在一个XML“信封”中。这将给我们提供一个结构化的纯文本文件,包含了许多XML条目,准备好供Gemini分析。

    <文件>  
    ...内容...  
    </file> 
    如果 file_data 存在:  
       output_file = 'fullcode.text'  
       with open(output_file, "w", encoding="utf-8") as outfile:  

           for file_path, content in file_data.items():  
               outfile.write(f"<路径:{file_path}>")  
               outfile.write(f"{content}")  
               outfile.write(

如果一切顺利,你应该在当前工作目录中找到一个名为 fullcode.text 的文件。此文件包含来自 OneTwo 仓库中的所有代码,并且这些代码已经用 XML 标签整齐地组织好了。如果在过程中遇到任何问题,请不要犹豫向 Gemini 寻求帮助进行故障排查,我们可以解决所有问题后继续前进。

让我们看一下我们刚创建的 fullcode.text 文件。

    文件的字节大小 = os.path.getsize(output_file)  

    print(f"文件大小:{文件的字节大小/1024/1024} MB")

对于上下文缓存来说,关键是看它是否超过10MB。如果超过10MB,我们就需要从Google云存储加载到缓存中。

现在我们已经准备好直奔主题去了:缓存上下文。

这里是一些关于上下文缓存的常见问题及其答案,这些问题你可能经常会遇到。

  • 你必须先创建上下文缓存,才能使用它。

缓存存储于创建缓存的同一区域,你创建的上下文缓存数据包含大量数据,这些数据可以在向 Gemini 模型发出的多个请求中重复使用。

  • 缓存的内容可以是Gemini支持的任何MIME类型的多模态内容。
  • 您可以通过指定一个blob、文本或存储在Cloud Storage存储桶中的文件来指定要缓存的内容。
  • 缓存的内容具有有限的生命周期。默认情况下,缓存会在创建后60分钟后过期。
  • 您可以在创建缓存的上下文时使用ttl或expire_time属性来指定不同的过期时间。您也可以更新过期时间。
  • 缓存的上下文过期后将不可用,过期后需要重新创建。
  • 最小缓存大小:32K令牌
  • 缓存创建后最小过期时间1分钟
  • 没有最大过期时间限制
  • 它支持流式和非流式响应。

现在是确保你使用最新版本的Vertex AI SDK的最佳时机。

安装 Python 包命令
!pip install --upgrade google-cloud-aiplatform

接下来,我们来导入一些必需的库。

    import vertexai  
    from vertexai.preview import caching
引入vertexai库以及其中的缓存功能预览模块

现在,我们将制定系统指令来引导 Gemini 进入 OneTwo 框架。把 Gemini 当作您的主要软件工程师,准备分析代码库并提供专业意见:

    project_id = "<在这里填入您的项目ID>""." 

    vertexai.init(project=project_id, location="us-central1")

    system_instruction = """  
    你是一位首席软件工程师。你总是根据提供的资料中的事实行事,从不编造任何新的事实。  
    现在查看这个项目的代码库,并回答这些问题。  
    """

现在让我们将代码库的内容加载到内容缓存中。为了提高效率,我们将根据内容类型采取不同的处理方式。在处理音频、视频和图片等大文件时,通常最好先将它们上传到谷歌云存储,然后使用如下类似的命令:

    contents = [  
        Part.from_uri(  
            "gs://cloud-samples-data/generative-ai/pdf/2312.11805v3.pdf",  
            mime_type="application/pdf",  
        ),  # 下面的代码将PDF文件的内容加载到contents列表中。
    ]

在我们的情况下,我们处理的是纯文本内容,并且我们的fullcode.txt文件远低于10MB的限制值。因此,我们将采取直接的方法来创建一个包含整个文件内容的Python列表,该列表中只有一个长字符串。

with open("fullcode.text", "r", encoding="utf-8") as f:  # 打开文件并以UTF-8编码读取
    fullcode_as_string = f.read()  # 读取文件内容并存储为字符串
contents = [  # 将读取的内容放入列表中
    fullcode_as_string
]

当我们的内容数组准备好了之后,现在是时候释放上下文缓存了!我已经配置它保留一小时的信息,并将其与我们选择的模型 gemini-1.5-pro-001 关联。让我们看看这会如何让我们的OneTwo代码库互动更加流畅吧!

    导入 datetime 模块   

    cached_content = 缓存内容的创建(  
        模型名称="gemini-1.5-pro-001",  
        系统指令=system_instruction,  
        内容=contents,  
        有效期=datetime.timedelta(minutes=60),  # 有效期为60分钟  
    )

当你运行代码时,你应该看到类似上面的输出。关键的是缓存名称。有了这个信息,我们只需一步就能直接访问模型,直接从缓存中创建它的实例。

当你运行代码时,你应该看到类似于上面显示的输出。最关键的信息是缓存名称。有了这个,我们只需一步就能直接使用模型:直接从缓存中创建模型实例。

    从 vertexai.preview.generative_models 导入 GenerativeModel  

    cache_id = cached_content.name  # 缓存ID为cached_content的name属性  
    cached_content = caching.CachedContent(cached_content_name=cache_id)  

    model = GenerativeModel.from_cached_content(cached_content=cached_content)

好的,让我们开始,问第一个问题:既然我们已经加载了OneTwo代码库,简单地问一句,这段代码实际在做什么?

    resp = model.generate_content("这段代码在干嘛?")  
    resp

哇,这真是好多要消化的信息啊!我们先别被细节困住。先解决眼前的问题,我们来看看这个查询用了多少个token。

resp.使用元数据

好的,完整的OneTwo代码库占据了令人惊讶的449,556个token,但多亏了缓存,我们所有的内容都触手可及,轻而易举!我们的第一个查询及其响应仅仅使用了1,114个token——这就是上下文缓存的作用!

准备好迎接下一个问题了吗?开炮吧!

    resp = model.generate_content("解释这个框架,就像我五岁一样简单。")

再来看看 token 数量

太酷了!仅用217个字符就能完成那个对话——上下文缓存真是个革命性的特性!

太棒了!现在我们知道了关于“one two”的事,让我们用一个真实的任务来测试一下“one two”。

    resp = model.generate_content("生成一段执行两个任务的Python代码段")

回复:

太好了!听起来我们可以先试试这段生成的代码。由于OneTwo不是Colab的标准库,我们首先需要安装它,这样我们才能运行代码。这应该是个快速的步骤。

    !pip install git+https://github.com/google-deepmind/onetwo

嗯……看来我们有点问题:

错误信息是:‘ValueError: 尝试调用一个尚未配置的内置函数 (onetwo.builtins.llm.generate_text)。’

好的,让我们询问热缓存版本的 Gemini 这个错误可能意味着什么,假设它会重新生成代码以便我们运行并了解……为了修复这个错误,我需要注册一个后端。

到目前为止,我们在这种简单的问答模式中的问答并没有被保存到上下文缓存中。这是这种模式下的预期行为。因此,Gemini在回答我最新问题时没有参考之前的交流,而是更专注于提供关于代码的澄清和解释,而不是直接修复代码的问题。

让我们切换到聊天模式,看看上下文缓存是否按预期工作。在这种模式下,我们所有的对话会自动添加到新查询中,但不会保存到上下文缓存里。这意味着我可以引用之前的问答,比如请求Gemini修复上一步生成的代码。

chat = 模型开始对话() # 开始一个新的对话

使用辅助函数来简化聊天响应的打印是一个明智之举,这将节省我们的时间,并让我们更专注于Gemini提供的信息。

    从vertexai.generative_models导入ChatSession # (导入ChatSession模块,用于聊天会话)
    def get_chat_response(chat: ChatSession, prompt: str) -> str:  
        text_response = []  
        responses = chat.send_message(prompt, stream=True) # (将prompt发送出去,并设置stream=True以接收分块回复)
        for chunk in responses:  
            text_response.append(chunk.text)  
        # (将所有分块回复合并成一个字符串并返回)
        return "".join(text_response)

我们准备再做一次这个测试。

    prompt = "生成用于执行两个任务的Python代码"  # 获取聊天响应的函数
    print(get_chat_response(chat, prompt))

当我把这个东西粘贴到新单元格时:

嗯,有一点错误

那么让我们在这个聊天模式里问一下Gemini怎么修好它。

    prompt = "我在运行你的代码时遇到了一个错误:嗯,是这样的错误:ValueError: 好像尝试调用未配置的内置函数 (onetwo.builtins.llm.generate_text 这个函数)"
    print(get_chat_response(chat, prompt))

双子座保证:这段代码现在应该能正常运行,不会出现错误。请注意,它使用了一个总是返回“Test Reply”的测试后端。要使用真实的后端,您需要使用相应的API密钥和模型名称进行配置,如在OneTwo Colab中的说明所示。

那也行,但让我来确认一下这个说法;)

哇塞!Gemini果然说到做到!

本文作者是Lukasz Olejniczak — Google Cloud 的客户工程师。文中观点仅代表作者个人意见,不一定反映 Google 的立场。

如果你喜欢这篇文章,请为它鼓掌。如果你想了解更多关于Google云、数据科学、数据工程和AI/ML的信息,请关注我LinkedIn上的内容。

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号

举报

0/150
提交
取消