AI编程新体验:InternLM2-Chat-1.8B结对编程实战演示

1. 引言

你有没有过这样的经历?深夜对着屏幕,想写一个功能,思路卡壳,身边又没人可以讨论。或者,写了一段代码,总觉得哪里不对劲,但又说不出来。这时候,如果有一个随时在线、思路清晰的编程伙伴,那该多好。

今天,我们就来体验一下这种全新的编程方式。我找来了InternLM2-Chat-1.8B模型,让它扮演我的“结对编程”搭档。我们一起来完成一个具体的编程任务:用Python写一个递归遍历目录并统计文件类型的脚本

这不是一次简单的代码生成演示,而是一场真实的、交互式的编程对话。我会像和真人搭档一样,向它提出需求,讨论实现思路,让它写代码,然后对代码提出疑问,再让它修改优化。整个过程,你会看到AI如何理解问题、如何思考、如何回应反馈,以及最终如何交付一个可用的解决方案。

准备好了吗?让我们开始这场特别的编程协作。

2. 任务设定与开场

我决定从一个非常具体且常见的需求入手:统计一个文件夹及其所有子文件夹中,各种类型文件的数量。比如,一个项目目录里有多少个.py文件、多少个.txt文件、多少个图片文件等等。这个需求看似简单,但涉及文件系统操作、递归逻辑和数据结构统计,很适合检验AI的编程协作能力。

我打开了与InternLM2-Chat-1.8B的对话窗口,输入了我们的第一个“用户故事”:

我(开发者):你好,我需要写一个Python脚本。它的功能是:递归遍历一个指定的目录,统计该目录下(包括所有子目录)各种文件类型的数量,并输出一个清晰的统计报告。你能帮我一步步实现吗?

AI(结对伙伴):当然可以。这是一个很实用的功能。我们可以分步来实现它。首先,我们需要明确几个关键点:

  1. 输入:脚本需要接收一个目录路径作为参数。
  2. 核心逻辑:递归遍历目录树,收集所有文件的扩展名。
  3. 统计:对扩展名进行计数。
  4. 输出:将统计结果以易读的方式打印出来。

我们先从最核心的递归遍历和文件收集开始写,你觉得怎么样?

看,它没有直接扔给我一大段代码,而是先梳理了需求,并提出了一个实现框架。这种“先讨论,再动手”的方式,正是结对编程的精髓。我同意了它的建议。

3. 第一轮迭代:核心遍历与统计

基于我们达成的共识,AI输出了第一版代码。

import os
from collections import defaultdict

def count_file_types(directory_path):
    """
    递归统计目录中各类文件的数量。

    Args:
        directory_path (str): 要统计的根目录路径。

    Returns:
        dict: 一个字典,键为文件扩展名(如 '.txt'),值为该类型文件的数量。
    """
    type_count = defaultdict(int)

    for root, dirs, files in os.walk(directory_path):
        for file in files:
            # 获取文件扩展名,并将其转换为小写以确保统计一致性(如.TXT和.txt视为同一种)
            _, ext = os.path.splitext(file)
            ext = ext.lower()
            # 对于没有扩展名的文件,将其归类为‘无扩展名’
            if not ext:
                ext = ‘no_extension’
            type_count[ext] += 1

    return type_count

if __name__ == "__main__":
    target_dir = input("请输入要统计的目录路径: ").strip()
    if os.path.isdir(target_dir):
        result = count_file_types(target_dir)
        print("\n文件类型统计结果:")
        for ext, count in sorted(result.items()):
            print(f"  {ext}: {count} 个")
    else:
        print("错误:输入的路径不是一个有效的目录。")

代码看起来干净利落。它使用了os.walk来优雅地处理递归遍历,用defaultdict(int)来简化计数逻辑,还考虑到了文件扩展名大小写统一和无扩展名文件的情况。注释也写得清晰明了。

我运行了一下,针对我的一个测试目录,它输出了类似这样的结果:

文件类型统计结果:
  .py: 15 个
  .txt: 8 个
  .md: 3 个
  .jpg: 5 个
  no_extension: 2 个

功能基本实现了。但作为一个挑剔的“搭档”,我觉得还有优化空间。于是,我提出了第一轮反馈。

4. 交互与优化:让输出更友好

我(开发者):代码运行得很好,核心功能没问题。不过,输出结果可以更友好一些吗?比如,把‘.py’显示为‘Python文件’,把‘no_extension’显示为‘无扩展名文件’。另外,能不能按文件数量从多到少排序?这样我一眼就能看出哪种文件最多。

AI(结对伙伴):很好的建议!让输出更人性化确实能提升使用体验。我们可以创建一个扩展名到类型描述的映射字典。对于未知的扩展名,可以保留原样。排序也很简单。我来修改一下输出部分的代码。

很快,它给出了修改后的版本,主要更新了if __name__ == “__main__”:部分:

# ... (count_file_types函数保持不变) ...

if __name__ == "__main__":
    # 定义一个扩展名到友好名称的映射(可根据需要扩充)
    friendly_names = {
        ‘.py’: ‘Python文件’,
        ‘.txt’: ‘文本文件’,
        ‘.md’: ‘Markdown文件’,
        ‘.jpg’: ‘JPEG图像’,
        ‘.png’: ‘PNG图像’,
        ‘.pdf’: ‘PDF文档’,
        ‘.zip’: ‘ZIP压缩包’,
        ‘no_extension’: ‘无扩展名文件’
    }

    target_dir = input("请输入要统计的目录路径: ").strip()
    if os.path.isdir(target_dir):
        result = count_file_types(target_dir)

        # 按文件数量降序排序
        sorted_items = sorted(result.items(), key=lambda x: x[1], reverse=True)

        print(f"\n目录 ‘{target_dir}‘ 下的文件类型统计(按数量降序):")
        print("-" * 50)
        total_files = sum(result.values())
        for ext, count in sorted_items:
            # 获取友好名称,如果没有映射则使用扩展名本身
            name = friendly_names.get(ext, ext)
            print(f"  {name:20} {count:4d} 个")
        print("-" * 50)
        print(f"  文件总数:{total_files} 个")
    else:
        print("错误:输入的路径不是一个有效的目录。")

再次运行,输出变成了:

目录 ‘./my_project‘ 下的文件类型统计(按数量降序):
--------------------------------------------------
  Python文件            15 个
  文本文件               8 个
  JPEG图像               5 个
  Markdown文件           3 个
  .log                  2 个
  无扩展名文件           2 个
--------------------------------------------------
  文件总数:35 个

这下看起来专业多了!不仅排序了,还有了友好的类型名称、分隔线和总计。对于映射表中没有的扩展名(如.log),它也做了回退处理,直接显示扩展名。

5. 深度探讨:处理隐藏文件与性能考量

代码已经很好用了,但我想把这次结对编程推向更深层次的讨论,看看AI能否处理一些边界情况和工程问题。

我(开发者):很棒!现在输出清晰多了。我还有两个问题想探讨:

  1. 有些系统文件或隐藏文件(比如以点开头的.gitignore)可能我不需要统计。能否增加一个过滤选项?
  2. 如果遍历一个非常大的目录(比如整个硬盘),这个脚本可能会占用较多内存,因为os.walk是一次性遍历的。有没有更节省内存的迭代方式?

AI(结对伙伴):这两个都是非常实际的工程问题。

  1. 过滤隐藏文件:我们可以修改遍历逻辑,在统计前检查文件名。在Unix/Linux系统中,隐藏文件通常以点开头。我们可以添加一个参数来控制是否跳过它们。
  2. 内存优化os.walk默认是自顶向下的生成器,它本身不会一次性将所有结果加载到内存。但在极端深的目录树下,dirsfiles列表可能会比较大。更节省内存的方式是使用os.scandir()自己写递归,它可以提供更高效的文件属性访问,并且我们可以更精细地控制遍历过程。

为了平衡代码复杂性和实用性,我们先实现隐藏文件过滤功能。如果需要处理超大规模目录,我们可以再重构为基于os.scandir的递归。你觉得这样可以吗?

我同意了它的分析。先解决过滤问题。它随后给出了增强版的count_file_types函数:

def count_file_types(directory_path, ignore_hidden=True):
    """
    递归统计目录中各类文件的数量。

    Args:
        directory_path (str): 要统计的根目录路径。
        ignore_hidden (bool): 是否忽略以点‘.’开头的隐藏文件。默认为True。

    Returns:
        dict: 一个字典,键为文件扩展名(如 ‘.txt‘),值为该类型文件的数量。
    """
    type_count = defaultdict(int)

    for root, dirs, files in os.walk(directory_path):
        for file in files:
            # 如果启用忽略隐藏文件,且文件名以点开头,则跳过
            if ignore_hidden and file.startswith(‘.’):
                continue

            _, ext = os.path.splitext(file)
            ext = ext.lower()
            if not ext:
                ext = ‘no_extension’
            type_count[ext] += 1

    return type_count

它增加了一个ignore_hidden参数,并在循环中增加了相应的判断逻辑。主程序调用时,可以传入这个参数。这个改动简单而有效。

关于第二个性能问题,AI虽然没有直接重写代码,但它清晰地解释了os.walkos.scandir的差异,并给出了一个简化的伪代码思路,说明如何用后者实现更手动的、可能更省内存的递归。这表明它不仅能写代码,还能理解不同方案背后的权衡。

6. 最终成果与体验总结

经过几轮交互,我们得到了一个功能完善、输出友好、且考虑了一定边界情况的脚本。这场结对编程会话也接近尾声。

我(开发者):非常感谢!经过这几轮修改,这个脚本已经完全满足我的需求了,甚至比我想的还要周到。这次合作很愉快。

AI(结对伙伴):不客气!能帮到你很高兴。这个脚本现在具备了核心统计、友好输出、隐藏文件过滤等功能。如果你将来需要处理超大规模目录,或者想增加按文件大小统计、过滤特定目录等功能,我们可以继续在此基础上修改。随时可以再找我“结对”。

回顾整个会话,InternLM2-Chat-1.8B展现出了令人印象深刻的“结对编程”素养:

  • 理解与拆解:它能准确理解“递归遍历统计文件类型”这个自然语言描述的需求,并将其拆解为输入、处理、输出等可执行的步骤。
  • 代码实现能力:生成的Python代码结构清晰,使用了合适的标准库(os, collections),并包含了基本的错误处理和边界情况考虑(如无扩展名文件)。
  • 交互与迭代:它不仅能接受模糊的需求,更能根据具体的反馈进行精准修改。从“优化输出”到“增加过滤功能”,它都能快速理解意图并落实在代码上。
  • 技术讨论深度:当被问及性能和高级方案时,它能指出os.walkos.scandir的区别,并进行权衡分析,这超出了简单的代码补全,进入了方案设计的层面。

当然,它并非完美。在整个过程中,我需要提出明确的、结构化的反馈。它更像一个反应迅速、知识渊博但需要明确引导的初级搭档。然而,这对于解决日常编程中那些“知道要做什么,但懒得敲细节”或者“想找个思路参考”的场景,已经绰绰有余。

7. 结语

这次与InternLM2-Chat-1.8B的结对编程实战,不仅仅是一次代码生成演示。它更像是一次对未来编程工作流的预演。AI不再是那个藏在自动补全后面的神秘工具,而是走到了台前,成为一个可以对话、可以讨论、可以共同迭代的编程伙伴。

它可能不会完全替代人类开发者天马行空的架构设计能力,但对于实现具体功能、编写样板代码、快速原型验证、甚至学习新的API用法来说,这样一个随时在线的“搭档”无疑能极大提升效率,减少孤独感,甚至能在思路上给你带来意想不到的启发。

下次当你面对一个编程任务时,不妨也试着向AI描述你的问题,和它聊一聊,一起写写看。你可能会发现,编程这件事,从此多了一份不一样的乐趣和可能。


获取更多AI镜像

想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐