Tag: 教程

  • ChatGPT 4o:为什么它能颠覆人机交互的未来?

    ChatGPT 4o:为什么它能颠覆人机交互的未来?

    本文探讨了ChatGPT 4o如何通过多模态交互、无延迟回复、多任务处理、情感分析等特性,颠覆传统人机交互方式。我们将深入了解ChatGPT 4o的独特之处,并展望未来人机交互设计的新方向。

    多模态交互:未来人机交互的趋势

    人机交互(HCI)是现代科技发展的核心领域之一。随着技术的不断进步,人机交互的形式也在不断演变。从早期的命令行界面,到图形用户界面(GUI),再到今天的语音交互和聊天机器人(chatbot),人机交互的方式变得越来越自然、直观。作为一名早期的AI产品经理,我在人机交互,特别是自然语言处理(NLP)相关产品和语音交互,以及智能助手的产品设计和交互体验设计方面有着浓厚的兴趣。今天,我想围绕刚刚发布的ChatGPT 4o,和大家探讨一下人机交互的未来。

    1. 传统语音助手的局限性

    传统的语音助手主要依赖于单一的语音输入和输出。然而,这种方式有其局限性,例如用户在控制智能家居设备时,常常需要同时借助智能手机或平板上的应用界面进行更详细的设置。这种单一的交互模式往往不能提供最佳的用户体验。

    ChatGPT 4o:突破性的人机交互

    今天,OpenAI刚刚发布了ChatGPT 4o,这是一次真正意义上的多模态人机交互的突破。作为一个久未发表文章的从业者,我对这个技术进步深感振奋,迫不及待地想和大家分享我的想法。

    2. ChatGPT 4o的显著特点

    ChatGPT 4o的演示效果令人惊叹。它不仅能够实现无延迟的回复,还可以自然地被用户打断,同时处理多个任务。具体来说,ChatGPT 4o具备以下几个显著特点:

    • 无延迟回复:用户在与ChatGPT 4o互动时,几乎感觉不到任何延迟。它能够实时处理用户的输入,迅速给予反馈。
    • 多任务处理:ChatGPT 4o能够同时处理多个任务,用户可以在一个对话中切换不同的话题,系统仍能保持连贯性。
    • 视觉记忆与语言兼容:ChatGPT 4o可以结合视觉和语言输入,记忆用户之前的互动内容,并在适当的时候引用这些信息。
    • 情感分析与TTS输出:ChatGPT 4o能够分析用户的情感状态,并通过文本到语音(TTS)技术输出合适的,带有情感的语音回应。
    • 无延迟调用设备功能:ChatGPT 4o能够无延迟地调用手机摄像头和电脑桌面信息,增强了互动的实时性和灵活性。

    新的人机交互设计方法

    基于ChatGPT 4o的多模态效果,我认为未来的人机交互设计将彻底打破过去的设计理念。以下是我认为的三种全新的设计方法:

    1. 无缝会话流

    在传统的人机交互设计中,用户与系统的互动通常被划分为多个独立的会话(Session)。每次新的互动开始时,系统需要重新加载上下文信息,这不仅增加了系统的负担,也降低了用户体验的连续性和流畅性。未来的设计将注重无缝会话流,确保用户能够在不同的话题之间自由切换,而无需重新开始新的Session。

    应用示例:

    • 智能助手:用户可以在与智能助手的对话中无缝切换话题,例如从询问天气转到预定餐厅,系统能够记住用户之前的偏好和选择。
    • 语音客服:用户在与客服机器人互动时,可以中途更改问题或需求,系统仍然能够保持连贯的上下文理解和响应。
    • 教育和培训:在虚拟学习环境中,学生可以随时提出新问题或更改学习主题,而不影响学习进度和系统响应的连续性。

    2. 多模态记忆系统

    未来的多模态人机交互设计将更加注重系统的记忆和理解能力。系统能够记忆并理解用户的多模态输入(例如语音、视觉、触控),并在后续互动中智能地使用这些记忆信息,提升互动的个性化和精确性。

    应用示例:

    • 个人助理:系统能够记住用户的日常习惯和偏好,例如常用的通勤路线、喜爱的音乐类型等,并在适当的时候提供个性化建议。
    • 医疗保健:系统能够记忆患者的健康数据和医疗历史,提供更加精准的诊断和个性化的治疗建议。
    • 智能家居:系统能够记住家中每个成员的偏好和日常作息,自动调整灯光、温度、音乐等,营造舒适的居住环境。

    3. 情感与上下文感知

    随着AI技术的发展,未来的系统将更加注重情感和上下文的理解。通过综合分析用户的语言和非语言信号(如语调、面部表情、身体姿态等),系统可以提供更加贴心和人性化的服务。

    应用示例:

    • 心理健康支持:系统能够识别用户的情感状态,提供及时的心理支持和安慰,甚至建议专业的心理咨询。
    • 早教/老年陪伴:系统能够感知孩子的情绪和学习状态,动态调整互动内容和方式,提升学习和陪伴效果。
    • 电商助手:系统能够分析用户的情绪,提供更加个性化和 empathetic 的服务,提升客户满意度。

    结语

    虽然ChatGPT 4o的技术进步主要是整合现有的技术,但其交互体验和流畅度的实现并不容易。当年的iPhone也是整合了多种技术,却通过出色的设计和优化,带来了革命性的用户体验。

    在此之前,我们很少见到如此出色的多模态交互效果展示,OpenAI在这方面依然领先了一大步。我相信,这次发布会引发的技术革命将导致新一波AI初创公司涌现,同时也会淘汰一部分无法跟上步伐的企业。

    作为一名多年深耕人机交互的的AI从业者,我将持续关注这一领域的新动态,并与大家分享我的见解和思考。

  • 使用纯C/CUDA进行LLM训练:探索llm.c项目

    使用纯C/CUDA进行LLM训练:探索llm.c项目

    llm.c是一个使用简单、纯C/CUDA进行大型语言模型(LLM)训练的项目,不需要庞大的PyTorch或cPython库。本文将深入介绍如何通过llm.c快速入门并训练GPT-2模型,探索其高效的代码实现和训练过程,帮助开发者在简洁高效的环境中实现LLM训练。

    介绍llm.c

    llm.c项目的目标是通过纯C和CUDA代码实现大型语言模型的训练。与传统的使用PyTorch进行训练的方法相比,llm.c提供了一种更轻量级、高效的解决方案。项目中的代码整洁且易于理解,可以帮助开发者深入理解LLM的训练机制。

    项目背景

    llm.c选择了GPT-2作为第一个工作示例,因为它是现代LLM的先驱,首次将完整的LLM堆栈整合在一起。当前的主要目标是重现GPT-2模型。

    快速入门

    GPU版本(稳定版)

    如果你有GPU设备并希望快速开始训练,可以按照以下步骤进行操作:

    pip install -r requirements.txt
    python prepro_tinyshakespeare.py
    python train_gpt2.py
    make train_gpt2fp32cu
    ./train_gpt2fp32cu

    这些步骤将下载TinyShakespeare数据集,使用GPT-2分词器进行标记,并下载GPT-2权重,然后在C/CUDA中初始化并训练一个epoch。

    GPU版本(最新优化版)

    如果你希望以最快速度进行训练,可以使用以下步骤:

    pip install -r requirements.txt
    python prepro_tinyshakespeare.py
    python train_gpt2.py
    make train_gpt2cu
    ./train_gpt2cu

    启用flash attention可以进一步加快训练速度:

    make train_gpt2cu USE_CUDNN=1
    ./train_gpt2cu

    可以根据GPU内存调整批处理大小,例如:

    ./train_gpt2cu -b 32

    CPU版本

    如果你没有GPU设备,也可以在CPU上进行训练:

    pip install -r requirements.txt
    python prepro_tinyshakespeare.py
    python train_gpt2.py
    make train_gpt2
    OMP_NUM_THREADS=8 ./train_gpt2

    在CPU上训练虽然较慢,但对于理解模型训练过程仍然非常有帮助。

    多GPU训练

    llm.c还支持多GPU训练,使用混合精度代码:

    sudo apt install openmpi-bin openmpi-doc libopenmpi-dev
    pip install -r requirements.txt
    python prepro_tinyshakespeare.py
    python train_gpt2.py
    make train_gpt2cu
    mpirun -np <number of GPUs on your machine> ./train_gpt2cu

    详细的训练步骤

    下载并标记数据集是训练模型的第一步。可以使用以下命令下载并处理TinyShakespeare数据集:

    python prepro_tinyshakespeare.py

    然后初始化并训练模型:

    python train_gpt2.py
    make train_gpt2
    OMP_NUM_THREADS=8 ./train_gpt2

    代码解析

    训练脚本

    训练脚本train_gpt2.c是实现LLM训练的核心文件。以下是一个简单的训练示例:

    // 伪代码示例,展示如何初始化和训练GPT-2模型
    #include <stdio.h>
    #include "gpt2.h"
    
    int main() {
        // 初始化模型
        GPT2Model model = gpt2_init("gpt2_124M.bin");
    
        // 加载训练数据
        int *train_data = load_data("data/tiny_shakespeare_train.bin");
    
        // 训练模型
        for (int step = 0; step < 40; step++) {
            float loss = gpt2_train_step(&model, train_data);
            printf("Step %d: Loss %.4f\n", step, loss);
        }
    
        // 保存模型
        gpt2_save(model, "gpt2_trained.bin");
    
        return 0;
    }

    CUDA优化

    CUDA代码train_gpt2.cu进一步优化了训练过程,使用了混合精度和高效的CUDA内核。以下是一个简单的CUDA内核示例:

    // 伪代码示例,展示一个简单的CUDA内核
    __global__ void add(int n, float *x, float *y) {
        int index = blockIdx.x * blockDim.x + threadIdx.x;
        if (index < n) {
            y[index] = x[index] + y[index];
        }
    }
    
    int main() {
        int N = 1<<20;
        float *x, *y;
        cudaMallocManaged(&x, N*sizeof(float));
        cudaMallocManaged(&y, N*sizeof(float));
    
        // 初始化数据
        for (int i = 0; i < N; i++) {
            x[i] = 1.0f;
            y[i] = 2.0f;
        }
    
        // 执行CUDA内核
        add<<<(N+255)/256, 256>>>(N, x, y);
        cudaDeviceSynchronize();
    
        // 打印结果
        printf("y[0] = %f\n", y[0]);
        printf("y[N-1] = %f\n", y[N-1]);
    
        // 释放内存
        cudaFree(x);
        cudaFree(y);
        return 0;
    }

    多GPU训练

    使用MPI和NCCL实现多GPU训练,可以显著提升训练速度。以下是一个简单的多GPU训练示例:

    sudo apt install openmpi-bin openmpi-doc libopenmpi-dev
    make train_gpt2cu
    mpirun -np <number of GPUs> ./train_gpt2cu

    实验与超参数调优

    通过调整学习率和批处理大小等超参数,可以进一步优化模型训练。以下是一个简单的学习率扫描脚本示例:

    #!/bin/bash
    
    learning_rates=(3e-5 1e-4 3e-4 1e-3)
    
    for i in {0..3}; do
        export CUDA_VISIBLE_DEVICES=$i
        screen -dmS "tr$i" bash -c "./train_gpt2cu -i data/TinyStories -v 250 -s 250 -g 144 -l ${learning_rates[$i]} -o stories$i.log"
    done

    结论

    llm.c项目通过纯C/CUDA代码提供了一种高效、简洁的LLM训练方法,为开发者提供了深度理解LLM训练机制的机会。无论你是初学者还是有经验的开发者,llm.c都能帮助你在高效的环境中实现LLM训练。

  • 探索Meta Llama 3:释放大语言模型的潜力

    探索Meta Llama 3:释放大语言模型的潜力

    Meta Llama 3是Meta最新推出的大语言模型,提供从8B到70B参数的预训练和指令调优版本。本文将深入探讨如何下载、安装和运行Llama 3模型,帮助开发者快速入门并利用这项强大的技术进行创新。

    什么是Meta Llama 3?

    Meta Llama 3是Meta最新的大语言模型(LLM),旨在为个人、创作者、研究人员和企业提供强大的语言理解和生成能力。这个版本包含预训练和指令调优的模型,参数规模从8B到70B不等。Llama 3的发布标志着LLMs的又一次重大进步,为用户提供了更多的实验和创新机会。

    下载和安装

    要下载模型权重和分词器,可以访问Meta Llama网站并接受许可协议。请求通过后,你将收到一封包含签名URL的电子邮件。然后运行下载脚本并传入提供的URL开始下载。

    前提条件

    确保已安装wget和md5sum,然后运行以下脚本:

    ./download.sh

    需要注意的是,下载链接在24小时后会过期,且有一定的下载次数限制。如果看到403: Forbidden错误,可以重新请求链接。

    通过Hugging Face访问

    你也可以在Hugging Face上下载模型,支持transformers和原生llama3格式。以下是从Hugging Face下载权重的步骤:

    1. 访问其中一个仓库,例如meta-llama/Meta-Llama-3-8B-Instruct。
    2. 阅读并接受许可。请求通过后,你将获得所有Llama 3模型的访问权限。
    3. 从“Files and versions”标签下载original文件夹的内容,也可以通过命令行下载:
    huggingface-cli download meta-llama/Meta-Llama-3-8B-Instruct --include "original/*" --local-dir meta-llama/Meta-Llama-3-8B-Instruct
    1. 要与transformers一起使用,可以使用以下代码片段下载并缓存权重:
    import transformers
    import torch
    
    model_id = "meta-llama/Meta-Llama-3-8B-Instruct"
    
    pipeline = transformers.pipeline(
        "text-generation",
        model="meta-llama/Meta-Llama-3-8B-Instruct",
        model_kwargs={"torch_dtype": torch.bfloat16},
        device="cuda",
    )

    快速开始

    你可以按照以下步骤快速开始使用Llama 3模型,这些步骤将让你在本地运行快速推理。更多示例请参阅Llama recipes repository。

    1. 在一个包含PyTorch / CUDA的conda环境中克隆并下载此仓库。

    2. 在顶级目录下运行:

      pip install -e .
    3. 访问Meta Llama网站并注册以下载模型。

    4. 注册后,你会收到一封包含下载URL的电子邮件。你将在运行下载脚本时需要此URL。

    5. 收到电子邮件后,导航到已下载的Llama仓库并运行下载脚本:

      • 确保授予下载脚本执行权限。
      • 在此过程中,你将被提示输入电子邮件中的URL。
      • 不要使用“复制链接”选项;手动从电子邮件复制链接。
    6. 下载所需模型后,可以使用以下命令在本地运行模型:

    torchrun --nproc_per_node 1 example_chat_completion.py \
        --ckpt_dir Meta-Llama-3-8B-Instruct/ \
        --tokenizer_path Meta-Llama-3-8B-Instruct/tokenizer.model \
        --max_seq_len 512 --max_batch_size 6

    注意:

    • 将Meta-Llama-3-8B-Instruct/替换为你的检查点目录路径,并将Meta-Llama-3-8B-Instruct/tokenizer.model替换为你的分词器模型路径。
    • –nproc_per_node应设置为你使用的模型的MP值。
    • 根据需要调整max_seq_len和max_batch_size参数。

    推理

    不同模型需要不同的模型并行(MP)值:

    Model MP
    8B 1
    70B 8

    所有模型支持最长8192个tokens的序列长度,但我们根据max_seq_len和max_batch_size值预分配缓存。因此,请根据你的硬件设置这些参数。

    预训练模型

    这些模型未针对聊天或问答进行微调。它们应该被提示,以便预期答案是提示的自然延续。

    torchrun --nproc_per_node 1 example_text_completion.py \
        --ckpt_dir Meta-Llama-3-8B/ \
        --tokenizer_path Meta-Llama-3-8B/tokenizer.model \
        --max_seq_len 128 --max_batch_size 4

    指令调优模型

    微调模型针对对话应用进行了训练。要获得预期的功能和性能,需要遵循ChatFormat定义的特定格式:提示以特殊token开头,之后是一条或多条消息。每条消息以标签开头,角色可以是system、user或assistant,并以标签结束。消息内容在双换行\n\n之后跟随。每条消息的结束标记为 token。

    你还可以部署附加分类器,以过滤被认为不安全的输入和输出。有关如何向推理代码中添加安全检查器的示例,请参阅llama-recipes repo。

    torchrun --nproc_per_node 1 example_chat_completion.py \
        --ckpt_dir Meta-Llama-3-8B-Instruct/ \
        --tokenizer_path Meta-Llama-3-8B-Instruct/tokenizer.model \
        --max_seq_len 512 --max_batch_size 6

    问题反馈

    请通过以下方式报告软件“错误”或模型的其他问题:

    模型卡

    请参阅MODEL_CARD.md。

    许可

    我们的模型和权重对研究人员和商业实体开放,并遵循开放原则。我们的使命是通过这一机会赋予个人和行业力量,同时促进发现和伦理AI的进步。

    请参阅LICENSE文件以及我们的可接受使用政策。

    常见问题

    有关常见问题的解答,请参阅FAQ,我们将随着新问题的出现不断更新。

    结论

    Meta Llama 3通过提供从8B到70B参数的预训练和指令调优模型,为开发者和研究人员提供了强大的工具。无论是用于实验还是创新,Llama 3都能帮助你在语言模型的应用中实现更高的效率和效果。

  • 什么是LangChain?打造上下文感知的推理应用:深入了解LangChain

    什么是LangChain?打造上下文感知的推理应用:深入了解LangChain

    在这篇文章中,我们将深入探讨LangChain,一个用于开发大语言模型(LLM)应用程序的框架。LangChain不仅提供了丰富的开源库,还简化了应用程序的整个生命周期,包括生产化和部署。本文将详细介绍LangChain的组件、用例及其在生产环境中的优势。

    什么是LangChain?

    LangChain是一个框架,专为开发由大语言模型(LLMs)驱动的应用程序而设计。它简化了应用程序的整个生命周期,从最初的开发到生产环境的部署。LangChain提供了丰富的开源库、生产化工具以及简便的部署选项。

    LangChain的主要价值在于其组件和现成的链条。组件是模块化且易于使用的构建块,即使你不使用LangChain的其他部分,也可以独立使用这些组件。现成的链条则简化了高级任务的实现,使用户可以快速入门。

    安装与快速开始

    LangChain支持使用pip和conda两种方式进行安装:

    pip install langchain
    conda install langchain -c conda-forge

    安装完成后,你可以通过以下简单示例快速开始使用LangChain:

    from langchain.llms import OpenAI
    
    llm = OpenAI(model_name="text-davinci-003")
    response = llm("Translate the following English text to French: 'Hello, how are you?'")
    print(response)

    LangChain的主要组件

    LangChain的组件主要分为以下几个模块:

    📃 模型I/O

    模型I/O模块包括提示管理、提示优化、通用接口和模型输出工具。这些工具可以帮助开发者更好地管理和优化与LLMs的交互。

    • 提示管理:包括创建、存储和管理提示。
    • 提示优化:通过示例选择器来优化提示。
    • 通用接口:提供与聊天模型和LLMs的通用接口。
    • 模型输出工具:包括解析和处理模型输出的常用工具。

    📚 检索

    检索模块涉及从各种来源加载数据、准备数据并在生成步骤中进行检索。主要包括文档加载器和检索器。

    • 文档加载器:从不同的数据源加载文档。
    • 检索器:检索和处理用于生成的相关数据。

    🤖 代理

    代理允许LLM自主决定如何完成任务。代理会决定采取哪些行动,然后执行该行动,观察结果,并重复这一过程直到任务完成。

    • 标准接口:为代理提供标准接口。
    • 代理选择:提供多种代理类型供选择。
    • 端到端代理示例:完整的代理示例。

    使用LangChain构建应用

    ❓ 问答系统

    LangChain可以用于构建强大的问答系统,使用检索增强生成(RAG)技术。

    🧱 结构化输出提取

    通过LangChain,你可以从非结构化数据中提取结构化输出。

    🤖 聊天机器人

    LangChain还支持构建功能强大的聊天机器人。

    LangChain Expression Language (LCEL)

    LCEL是LangChain的基础,支持从简单的“提示+LLM”链条到最复杂的链条的无代码更改生产部署。它是一种声明性语言,用于组合链条。

    生产化与部署

    LangSmith

    LangSmith是一个开发者平台,让你可以调试、测试、评估和监控基于任何LLM框架的链条,并无缝集成到LangChain中。

    LangServe

    LangServe是一个用于将LangChain链条部署为REST API的库。

    生态系统

    • LangSmith:用于追踪和评估语言模型应用程序的开发者平台,帮助你从原型到生产环境的转换。
    • LangGraph:使用LLMs创建有状态的多角色应用程序,基于LangChain原语构建。
    • LangServe:将LangChain可运行程序和链条部署为REST API。

    结论

    LangChain是一个功能强大的框架,简化了大语言模型应用程序的开发、生产化和部署过程。无论你是初学者还是有经验的开发者,LangChain都能为你提供丰富的工具和资源,助你快速构建和优化你的LLM应用程序。

  • 为什么更换Ubuntu源?如何使用中文源替换Ubuntu源?

    为什么更换Ubuntu源?如何使用中文源替换Ubuntu源?

    本文将详细讲解为什么要更换Ubuntu源,以及如何更换为中文源。你将学习到什么是Ubuntu源,更换源的具体步骤,以及使用中文源的好处。


    Ubuntu是一款流行的Linux操作系统,许多开发者和普通用户都选择使用它。Ubuntu源是指软件包的下载地址,默认的源有时候会因为网络问题导致下载速度慢或者无法连接。因此,更换源尤其是使用速度更快的中文源成为了许多中国用户的选择。

    什么是Ubuntu源?

    Ubuntu源是指Ubuntu系统中的软件包下载地址。软件源(也称为仓库)包含了成千上万的已编译好的软件包,用户可以通过APT包管理工具方便地下载、安装和更新这些软件。Ubuntu默认使用的是官方源,但有时候这些源可能速度较慢,特别是在国内的用户会遇到网络问题。

    “更换源可以大幅提高软件包下载和系统更新的速度,尤其是在网络状况不佳时。”

    常见的Ubuntu源类型

    1. 官方源:由Ubuntu官方维护,安全性和稳定性较高。
    2. 第三方源:由其他组织或个人维护,可能包含一些官方源没有的软件包。
    3. 镜像源:官方源的镜像,分布在世界各地的数据中心,可以显著提升下载速度。

    为什么要更换Ubuntu源?

    在中国,访问Ubuntu官方源经常会遇到下载速度慢或者无法连接的问题。更换为中文源可以有效解决这些问题,提高下载和更新速度。以下是更换源的几个主要原因:

    1. 提高下载速度:国内的镜像源通常位于中国大陆,可以大幅提升下载速度。
    2. 稳定性:本地源通常更稳定,不容易受到国际网络波动的影响。
    3. 可用性:有些软件包在官方源上可能不完整或缺失,而本地源通常会及时同步更新。

    如何更换Ubuntu源?

    更换Ubuntu源其实非常简单,主要分为备份原有源文件、编辑源列表和更新源信息三个步骤。下面我们一步步进行操作。

    1. 备份原有源文件

    首先,我们需要备份当前的源文件,以防在更换源的过程中出现问题。可以通过以下命令完成备份:

    sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak

    2. 编辑源列表文件

    使用你喜欢的文本编辑器(例如nano或vim)编辑源列表文件。以下是使用nano编辑器的示例:

    sudo nano /etc/apt/sources.list

    将文件中的内容替换为你选择的中文源。以下是一些常用的中文源:

    • 阿里云源
    deb http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse
    deb http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe multiverse
    deb http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe multiverse
    deb http://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted universe multiverse
    deb http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse
    • 清华大学源
    deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal main restricted universe multiverse
    deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-updates main restricted universe multiverse
    deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-backports main restricted universe multiverse
    deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-security main restricted universe multiverse
    deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-proposed main restricted universe multiverse
    • 中科大源
    deb https://mirrors.ustc.edu.cn/ubuntu/ focal main restricted universe multiverse
    deb https://mirrors.ustc.edu.cn/ubuntu/ focal-updates main restricted universe multiverse
    deb https://mirrors.ustc.edu.cn/ubuntu/ focal-backports main restricted universe multiverse
    deb https://mirrors.ustc.edu.cn/ubuntu/ focal-security main restricted universe multiverse
    deb https://mirrors.ustc.edu.cn/ubuntu/ focal-proposed main restricted universe multiverse

    3. 更新源信息

    完成源文件编辑后,保存并退出编辑器,然后运行以下命令来更新源信息:

    sudo apt update

    使用中文源的好处

    下载速度更快

    使用位于中国大陆的镜像源,下载速度通常会显著提升,尤其是对于大文件和系统更新包。

    提高系统稳定性

    本地镜像源由于地理位置优势,通常受到网络波动的影响较小,连接稳定性更高。

    更多的软件包选择

    有些第三方中文源会包含一些官方源没有的软件包,提供更多的选择。

    常见问题及解决方法

    源文件损坏

    如果在编辑源文件的过程中出现错误,可以通过备份文件进行恢复:

    sudo cp /etc/apt/sources.list.bak /etc/apt/sources.list

    更新失败

    如果在更新过程中出现错误,可以尝试更换其他的镜像源,或者检查网络连接是否正常。

    软件包无法安装

    有时候某些软件包可能在特定的镜像源中缺失,尝试更换镜像源或直接使用官方源。

    结语

    更换Ubuntu源对于提升下载和更新速度、提高系统稳定性有着重要的作用,尤其是对于国内用户来说。希望本文能够帮助你轻松完成源的更换,享受更快、更稳定的Ubuntu使用体验。

  • 数据库监控工具2.0:全方位监控你的数据库健康状况

    数据库监控工具2.0:全方位监控你的数据库健康状况

    在现代数据驱动的世界中,数据库的稳定性和性能至关重要。为确保数据库始终运行在最佳状态,我们需要一款强大的监控工具。本文将介绍如何使用Tkinter和cx_Oracle库创建一个实时数据库监控工具。这个工具不仅可以实时显示数据库的健康状况,还可以定时更新监控数据,确保用户获取到最新的信息。

    开始构建数据库监控工具

    首先,我们需要导入必要的库:

    import tkinter as tk
    from tkinter import ttk, messagebox, simpledialog
    import cx_Oracle
    import threading
    from tkinter.ttk import Treeview

    这些库帮助我们构建用户界面、连接数据库以及实现多线程功能。

    创建主窗口

    我们使用Tkinter创建主窗口,并设置窗口的标题和大小:

    class demo(tk.Tk):
        def __init__(self):
            super().__init__()
            self.title("数据库监控工具")
            self.geometry("1200x400")
            self.resizable(True, True)

    添加笔记本卡片

    为了更好地组织和显示信息,我们使用Notebook组件添加多个选项卡,每个选项卡对应不同的监控项:

            # 创建笔记本卡片
            self.notebook = ttk.Notebook(self)
            self.notebook.pack(expand=True, fill="both")
    
            # 创建查询卡片
            self.sttscx = tk.Frame(self.notebook)
            self.notebook.add(self.sttscx, text="监控事项")
            self.sttscx_list = Treeview(self.sttscx, columns=('c1', 'c2', 'c3', 'c4', 'c5', 'c6', 'c7'), show="headings")
            self.sttscx_list.pack(expand=True, fill="both")
            self._setup_treeview(self.sttscx_list, 7)

    这里,我们通过Treeview组件显示数据库监控项,并使用_setup_treeview方法来设置列宽和标题:

    def _setup_treeview(self, tree, col_count):
        for i in range(1, col_count+1):
            tree.column(f'c{i}', width=100, anchor='center')
            tree.heading(f'c{i}', text=f'事项{i}')

    连接数据库

    为了获取数据库信息,我们需要连接到Oracle数据库:

    def connect_to_oracle(self):
        conn = cx_Oracle.connect(user='your_username', password='your_password', dsn='your_dsn')
        return conn

    请确保替换示例中的your_username、your_password和your_dsn为实际的数据库连接信息。

    获取和更新数据

    我们通过fetch_data_and_update_tree方法从数据库中获取数据并更新到Treeview中:

    def fetch_data_and_update_tree(self):
        conn = self.connect_to_oracle()
        cursor = conn.cursor()
        queries = ["SQL_QUERY_1", "SQL_QUERY_2", "SQL_QUERY_3", "SQL_QUERY_4"]
        treeviews = [self.sttscx_list, self.qrnrksxcx_list, self.jsydtj_list, self.wrksx_list]
    
        for query, tree in zip(queries, treeviews):
            cursor.execute(query)
            rows = cursor.fetchall()
            self._update_treeview(tree, rows)
    
        cursor.close()
        conn.close()
    
    def _update_treeview(self, tree, rows):
        for item in tree.get_children():
            tree.delete(item)
        for row in rows:
            tree.insert("", "end", values=row)

    定时刷新数据

    为了确保数据的实时性,我们使用after方法实现定时刷新:

    def refresh_tree(self):
        self.fetch_data_and_update_tree()
        self.after(5000, self.refresh_tree)

    运行应用

    最后,我们需要启动应用:

    if __name__ == "__main__":
        app = demo()
        app.mainloop()

    总结

    本文介绍了一款实用的数据库监控工具,它不仅可以实时监控数据库的健康状况,还能定时刷新数据,确保用户获取到最新的信息。通过本文的代码示例,你可以轻松搭建自己的数据库监控工具,从而提升数据库的稳定性和性能。

  • 为什么你需要了解如何抓取和下载M3U8视频?一步一步教你!

    为什么你需要了解如何抓取和下载M3U8视频?一步一步教你!

    在这篇文章中,我们将一步一步地讲解如何抓取和下载M3U8视频,介绍使用Python进行网络爬虫的基础知识,并提供一个完整的代码示例来帮助你轻松掌握这个技能。无论你是编程新手还是有经验的开发者,都能从中学到实用技巧。


    你是否曾经遇到过这样的问题:在网上看到一个很棒的视频,却无法下载保存?特别是那些以M3U8格式提供的视频,下载起来更是复杂。今天,我们将通过一个实战案例,教你如何使用Python爬虫技术来抓取和下载M3U8视频。

    什么是M3U8?

    在开始之前,我们需要了解什么是M3U8。M3U8是一种播放列表文件格式,常用于在线视频流媒体。它包含了媒体文件的路径,可以是本地路径,也可以是网络路径。通过M3U8文件,播放器能够按照顺序播放各个视频片段,从而实现流畅的播放体验。

    工具准备

    在开始编写代码之前,我们需要安装一些必备的Python库:

    pip install aiohttp aiofiles requests

    这些库分别用于异步HTTP请求、异步文件操作和常规HTTP请求。

    代码解析

    接下来,我们将一步步解析完整的代码示例,帮助你更好地理解每一部分的功能。

    1. 获取电影URL

    首先,我们需要获取电影页面的真实URL。因为有些网站的电影链接会包含特殊的标记或结构,通过以下函数我们可以确保获取到正确的URL:

    def get_movie_url(movie_url):
        if not movie_url.endswith('/1-1.html'):
            movie_url = movie_url.replace('.html', '/1-1.html')
        return movie_url

    2. 提取第一个M3U8链接和电影名称

    接下来,我们需要从电影页面中提取第一个M3U8链接和电影名称:

    def get_first_m3u8_url(movie_url):
        resp = requests.get(movie_url, headers=headers)
        pattern = re.compile(r'url":"(.*?)"')
        pattern_name = re.compile(r'class="hl-infos-title" href="(.*?)" title="(.*?)">')
        result = pattern.search(resp.text)
        result_name = pattern_name.search(resp.text)
        movie_name = result_name.group(2)
        encoded_url = result.group(1)
        decoded_url = urllib.parse.unquote(encoded_url)
        first_m3u8_url = decoded_url.split('url=')[-1]
        return first_m3u8_url, movie_name

    3. 处理第一个M3U8链接

    我们需要下载第一个M3U8文件,并从中提取出第二个M3U8链接:

    def deal_first_m3u8(first_m3u8_url, movie_name):
        if not os.path.exists(f'{movie_name}/2.m3u8'):
            if not os.path.exists(movie_name):
                os.makedirs(movie_name)
            if not os.path.exists(f'{movie_name}/1.m3u8'):
                file_name = '1.m3u8'
                file_path = f'{movie_name}/{file_name}'
                resp = requests.get(first_m3u8_url, headers=headers)
                with open(file_path, 'w', encoding='utf-8') as f:
                    f.write(resp.text)
                second_m3u8_url = ''
                with open(file_path, 'r', encoding='utf-8') as f:
                    for line in f:
                        if line.startswith('#') or line == '\n':
                            continue
                        second_m3u8 = line.strip()
            second_m3u8_url = urljoin(first_m3u8_url, second_m3u8)
            file_name = '2.m3u8'
            file_path = f'{movie_name}/{file_name}'
            resp = requests.get(second_m3u8_url, headers=headers)
            with open(file_path, 'w', encoding='utf-8') as f:
                f.write(resp.text)

    4. 解析第二个M3U8文件

    然后,我们解析第二个M3U8文件,获取电影片段的URL列表:

    def deal_second_m3u8(movie_name):
        file_path = f'{movie_name}/2.m3u8'
        lst_movies = []
        with open(file_path, 'r', encoding='utf-8') as f:
            for line in f:
                if line.startswith('#') or line == '\n':
                    continue
                lst_movies.append(line.strip())
        return lst_movies

    5. 异步下载电影片段

    使用异步方式下载电影片段,可以提高下载速度:

    async def download(down_url, file_path, sem):
        file_name = file_path + '/' + down_url[-13:]
        if not os.path.exists(file_name):
            for i in range(5):
                async with sem:
                    try:
                        print(f'{file_name}开始下载。')
                        async with aiohttp.ClientSession() as session:
                            async with session.get(down_url) as resp:
                                content = await resp.content.read()
                                async with aiofiles.open(file_name, 'wb') as f:
                                    await f.write(content)
                        print(f'{file_name}下载完成。')
                        break
                    except Exception as e:
                        print(f'{file_name}下载失败,已重新下载,错误信息为:{e}')
                        continue

    6. 合并电影片段

    最后,我们将所有下载好的电影片段合并成一个完整的电影文件:

    def merge_movie(lst_movies, movie_name):
        temp = []
        n = 1
        now_path = os.getcwd()
        path = f'{movie_name}/before_synthesis'
        os.chdir(path)
        for i in range(len(lst_movies)):
            file_name = lst_movies[i][-13:]
            temp.append(file_name)
            if len(temp) == 20:
                cmd = f'copy /b {"+".join(temp)} {n}.ts'
                r = os.popen(cmd)
                print(r.read())
                n += 1
                temp = []
        cmd = f'copy /b {"+".join(temp)} {n}.ts'
        r = os.popen(cmd)
        print(r.read())
        last_temp = []
        for i in range(1, n + 1):
            last_temp.append(f'{i}.ts')
        cmd = f'copy /b {"+".join(last_temp)} {movie_name}.mp4'
        r = os.popen(cmd)
        print(r.read())
        os.chdir(now_path)

    主函数

    if __name__ == '__main__':
        movie_url = 'https://www.7qhb.com/vod/qthl2024.html'
        movie_url = get_movie_url(movie_url)
        first_m3u8_url, movie_name = get_first_m3u8_url(movie_url)
        second_m3u8_url = deal_first_m3u8(first_m3u8_url, movie_name)
        lst_movies = deal_second_m3u8(movie_name)
        asyncio.run(main(lst_movies, movie_name))
        merge_movie(lst_movies[:], movie_name)
        print(len(lst_movies))
        print('电影下载完成!')

    总结

    通过这篇文章,我们从零开始,详细讲解了如何使用Python抓取和下载M3U8视频。这个过程涉及到网络请求、正则表达式、文件操作以及异步编程等多个知识点。希望这篇文章能帮助你掌握这些技能,为你在编程道路上提供一些有用的启示。

  • 为什么选择wgcf来配置Cloudflare Warp?简单高效的解决方案!

    为什么选择wgcf来配置Cloudflare Warp?简单高效的解决方案!

    在这篇文章中,我们将探讨使用wgcf这个非官方的跨平台CLI工具来配置Cloudflare Warp的优点。通过详细的配置步骤和功能介绍,你将了解到如何轻松设置Warp账户、生成WireGuard配置文件以及如何调试Warp状态。

    [原文图片缺失]


    为什么选择wgcf来配置Cloudflare Warp?

    对于需要高效、安全网络连接的用户来说,Cloudflare Warp是一个很好的选择。然而,官方应用在某些情况下可能不够灵活。这时候,wgcf这个非官方的跨平台CLI工具便显得尤为重要。它不仅能简化Warp账户的注册和管理,还能生成WireGuard配置文件,并提供详细的调试信息。


    wgcf的主要功能

    wgcf提供了丰富的功能,让用户可以更方便地管理Cloudflare Warp:

    • 注册新账户
    • 更改许可证密钥以使用现有的Warp+订阅
    • 生成WireGuard配置文件
    • 检查账户状态
    • 打印追踪信息以调试Warp/Warp+状态

    下载和安装

    你可以在releases页面找到预编译的二进制文件,下载并安装适合你操作系统的版本。

    如何使用wgcf?

    显示帮助屏幕

    运行以下命令来显示帮助屏幕,所有的命令和参数都被详细记录在这里:

    wgcf

    注册新账户

    要注册一个新的Warp账户,只需运行以下命令:

    wgcf register

    新账户的信息将保存在wgcf-account.toml文件中。

    生成WireGuard配置文件

    注册完账户后,你可以生成一个WireGuard配置文件:

    wgcf generate

    配置文件将保存在wgcf-profile.conf中。你可以参考官方的WireGuard快速入门指南来使用这个配置文件。

    最大传输单元(MTU)

    为了确保最大兼容性,生成的配置文件的MTU设置为1280。如果你遇到性能问题,可以尝试增加这个值。详细信息请参考Issue #40。

    更改许可证密钥

    如果你有一个现有的Warp+订阅,可以将其绑定到通过wgcf生成的账户上。首先,获取你的Warp+账户许可证密钥。在Android上查看密钥的步骤如下:

    1. 打开1.1.1.1应用
    2. 点击右上角的菜单按钮
    3. 导航到:账户 > 密钥

    编辑wgcf-account.toml文件,直接输入新的许可证密钥,然后运行:

    wgcf update

    或者,使用环境变量:

    WGCF_LICENSE_KEY="123412341234" wgcf update

    更新后,许可证将被应用,并为你的账户生成一个新的私钥。此时需要重新生成WireGuard配置文件以使用新的私钥。

    检查设备状态

    要检查Warp/Warp+的状态,可以运行以下命令:

    wgcf status

    验证Warp/Warp+工作状态

    连接到通过wgcf生成的WireGuard配置文件后,运行以下命令:

    wgcf trace

    最后一行应显示warp=on或warp=plus,分别表示你正在使用Warp或Warp+。


    开发者相关信息

    wgcf还提供了一些开发者工具,使用Optic来自动生成API文档,并使用openapi-generator生成Go客户端API代码。

    更新API文档

    首先,安装Optic:

    api start

    在Web UI中解析并保存所有差异。

    重新生成Go客户端API代码

    安装openapi-generator,然后运行:

    bash generate-api.sh

    此脚本支持Linux和WSL。


    非官方声明

    我们与Cloudflare无任何关系,也未获得其授权。Cloudflare和Cloudflare Warp等名称、标志和图片均为其各自所有者的注册商标。

  • 为什么要用Python批量压缩图片大小?如何实现?

    为什么要用Python批量压缩图片大小?如何实现?

    在本文中,我们将探讨为什么需要批量压缩图片大小,以及如何使用Python实现这一过程。通过简单的代码示例和详细的步骤说明,即使你是编程新手,也能轻松上手。


    在数字时代,图片已经成为我们生活中不可或缺的一部分。无论是个人照片,工作报告,还是社交媒体上的分享,图片无处不在。但是,图片的文件大小往往会影响存储空间和传输速度。特别是当你有大量图片需要处理时,手动压缩每张图片不仅耗时,而且效率低下。这时候,批量压缩图片大小的需求就显得尤为重要。

    那么,为什么要用Python来完成这个任务呢?Python作为一门简单且功能强大的编程语言,拥有丰富的库和工具,可以轻松实现图片的批量处理。接下来,我们将详细介绍如何使用Python批量压缩图片大小。

    为什么需要压缩图片大小?

    压缩图片大小不仅仅是为了节省存储空间,还有以下几个主要原因:

    • 提高网站加载速度:对于网站管理员来说,页面加载速度至关重要。过大的图片会拖慢页面加载速度,影响用户体验。
    • 节省带宽:特别是在移动设备上,带宽往往有限,压缩图片可以节省用户的数据流量。
    • 便于传输和分享:小文件更容易通过电子邮件或社交媒体进行分享。
    • 减少存储成本:对于企业来说,存储大量高分辨率图片的成本非常高,压缩图片可以节省存储空间和成本。

    如何用Python实现批量压缩图片大小?

    准备工作

    在开始之前,你需要确保已经安装了Python和Pillow库。Pillow是Python Imaging Library的一个分支,用于处理图像文件。你可以通过以下命令安装Pillow:

    pip install pillow

    步骤一:导入必要的库

    首先,我们需要导入Pillow库中的Image模块以及os模块来处理文件和目录。

    from PIL import Image
    import os

    步骤二:定义压缩函数

    接下来,我们定义一个函数,用于压缩单张图片。这个函数会接收图片路径、输出路径以及压缩质量作为参数。

    def compress_image(input_path, output_path, quality):
        # 打开图片
        image = Image.open(input_path)
        # 保存图片,并设置压缩质量
        image.save(output_path, quality=quality)

    步骤三:批量处理图片

    我们可以遍历指定目录下的所有图片,并调用上述压缩函数进行批量处理。

    def batch_compress_images(input_dir, output_dir, quality):
        # 确保输出目录存在
        if not os.path.exists(output_dir):
            os.makedirs(output_dir)
    
        # 遍历输入目录下的所有文件
        for filename in os.listdir(input_dir):
            if filename.endswith(('.png', '.jpg', '.jpeg')):
                input_path = os.path.join(input_dir, filename)
                output_path = os.path.join(output_dir, filename)
                compress_image(input_path, output_path, quality)
                print(f'压缩图片: {input_path} -> {output_path}')

    步骤四:执行压缩

    最后,我们可以通过调用batch_compress_images函数来批量压缩指定目录下的图片。以下是一个完整的示例:

    if __name__ == '__main__':
        input_directory = 'path/to/input/directory'
        output_directory = 'path/to/output/directory'
        compression_quality = 85  # 压缩质量(0-100)
    
        batch_compress_images(input_directory, output_directory, compression_quality)
        print('批量压缩完成!')

    代码解释

    1. 导入必要库:首先导入Pillow的Image模块和os模块。
    2. 定义压缩函数:compress_image函数用于压缩单张图片,接收输入路径、输出路径和压缩质量作为参数。
    3. 批量处理函数:batch_compress_images函数用于批量处理图片,遍历输入目录下的所有图片,并调用compress_image函数进行压缩。
    4. 执行脚本:通过指定输入目录、输出目录和压缩质量来执行批量压缩操作。

    扩展功能

    你还可以根据需要对代码进行扩展,例如:

    • 支持更多图片格式:可以通过修改filename.endswith部分来支持更多图片格式。
    • 动态调整压缩质量:根据图片的初始大小或分辨率来动态调整压缩质量。
    • 多线程处理:对于大量图片,可以使用多线程来提高处理效率。

    常见问题

    • 压缩质量的选择:压缩质量的选择需要根据实际需求进行调整,一般情况下,85%的压缩质量已经能够在保持较好图像质量的同时显著减小文件大小。
    • 图片格式的兼容性:不同图片格式的压缩效果不同,建议根据实际情况选择合适的格式进行压缩。

    总结

    通过本文的介绍,我们详细讲解了为什么需要压缩图片大小,以及如何使用Python和Pillow库来批量压缩图片。希望这篇文章能对你有所帮助,让你能够轻松处理大量图片,提高工作效率。

  • 为什么选择Nyanmisaka版本的Jellyfin?硬件解码轻松搞定!

    为什么选择Nyanmisaka版本的Jellyfin?硬件解码轻松搞定!

    在本篇文章中,我们将探讨为什么Nyanmisaka版本的Jellyfin成为了许多家庭媒体服务器用户的首选。通过具体的配置步骤和性能对比,你将了解如何利用该版本的优势,实现硬件解码和流畅播放高分辨率视频的目标。


    为什么选择Nyanmisaka版本的Jellyfin?

    对于家庭媒体服务器的爱好者来说,Jellyfin无疑是一个强大的工具。然而,当涉及到播放高分辨率视频时,官方版本的Jellyfin可能在硬件解码和性能优化方面存在一些不足。这时候,Nyanmisaka版本的Jellyfin便成为了解决这些问题的绝佳选择。

    Nyanmisaka是谁?他是Jellyfin的官方开发人员之一,专注于硬件解码和性能优化。据悉,他的Docker镜像主要强化了核显驱动、字库驱动、FFmpeg优化参数,以及10.8.0alpha3最新改进和尚未发布的各种功能。

    全新安装Nyanmisaka版本的Jellyfin

    不必担心复杂的安装过程。实际上,Nyanmisaka的版本与官方版本的配置目录完全兼容,可以实现无缝升级。

    步骤一:获取Nyanmisaka版本的Docker镜像

    首先,我们需要下载Nyanmisaka版本的Docker镜像。在群晖中操作非常简单:

    docker pull nyanmisaka/jellyfin:latest

    步骤二:启动新容器

    下载完成后,我们需要启动一个新的容器。在高级设置中,勾选高权限以便于使用硬件解码,并进行适当的资源限制。

    步骤三:配置网络和存储空间

    建议选择“使用与Docker Host相同的网络”模式,直接使用当前设备IP和端口。添加cache、config和media目录,并确保这些目录的路径正确。

    步骤四:高级设置

    在高级设置中,勾选自动启动,并在控制台中开启硬件解码。

    性能对比:Nyanmisaka版本的优势

    为了验证Nyanmisaka版本的优越性,我们进行了详细的性能测试。

    测试视频参数

    测试视频是一部63Mbps码率的HDR电影,需要HDR转SDR,并且带有烧录PGS字幕。目标分辨率为1080p,码率限制为15Mbps。

    编解码速度对比

    以下是不同解码方式下的转换帧率:

    编解码方式 映射方式 转换帧率 (fps)
    QSV OpenCL 108
    QSV VPP 77
    VAAPI OpenCL 48
    VAAPI VPP 61
    VAAPI 10.7.7 VPP 46

    可以看出,Nyanmisaka版本的QSV转码在OpenCL映射方式下表现最佳,帧率高达108fps,显著优于其他方式。

    新的色调映射算法

    Nyanmisaka版本还引入了BT.2390色调映射算法,改善了HDR转SDR的效果。

    色调映射算法对比

    以下是几种色调映射算法的对比效果:

    算法 映射效果描述
    VPP 无法调参数,效果偏暗
    BT.2390 默认推荐算法,效果最佳,色彩丰富,亮度适中
    Hable 较暗,但保留了高亮度细节
    None 直接去饱和处理,高亮部分颜色丢失
    Clip 硬剪辑超出部分,支持参数调整
    Linear 线性倍数拉伸,亮度高但细节丢失
    Gamma 对数曲线转换,参数可调,适合自定义需求
    Reinhard 非线性对比度转换,保留整体亮度,色彩稍差,参数可调
    Mobius 保留对比度和颜色,适合强调色彩准确性的需求

    结论

    通过以上配置和性能对比,我们可以看出Nyanmisaka版本的Jellyfin在硬件解码和转码效率方面有显著提升。对于需要播放高分辨率视频的用户来说,这个版本无疑是更好的选择。

    最后,再次提醒

    Nyanmisaka版本的Jellyfin不仅在硬件解码方面做了很多优化,还解决了许多官方版本中存在的问题。如果你正在寻找一个更稳定、更高效的Jellyfin版本,不妨试试Nyanmisaka的版本。