大模型应用:快速搭建轻量级智能体:从模型下载到图文输出简单实践.75

一、引言

最近大模型的算法理论着实让大家CPU都要冒烟了,缓缓换一些简单的动手实操,体验一下大模型的趣味,我们前期把 Transformer 架构、分词器工作原理、模型推理逻辑这些知识点都聊透彻了,但有时实操刚开始就容易卡壳:高端大模型显存要求高,普通电脑根本跑不起来;复杂的部署配置绕来绕去,刚学的理论也不知道怎么和实际代码结合。其实入门阶段的实操,根本不用追求高参数模型,选对轻量级的练手模型才是关键。Qwen1.5-1.8B-Chat 就是特别适合的选择,18 亿参数的体量,单卡 4G 显存就能流畅运行,没有高端显卡用 CPU 也能正常推理,而且中文理解和生成能力都很在线,完全能满足基础智能体的搭建需求。

今天我们就围绕这款模型,做一次纯落地的实操展示,从模型的高速下载与缓存,到基础文本交互智能体的搭建,再到拓展实用的图文输出功能,步骤简单清晰、把 transformers、modelscope 这些工具的核心用法落到实处,简单的从搭建一个本地智能体。

二、模型下载与缓存

示例中已经实现了模型的核心下载逻辑,这里我们单独对其进行优化,增加异常处理、路径兼容性提示和运行状态反馈,让下载过程更稳定、更清晰,在初次可以分步操作加深理解;

python 复制代码
from transformers import AutoTokenizer, AutoModelForCausalLM
from modelscope import snapshot_download
import os

# 配置模型信息与存储路径
model_name = "qwen/Qwen1.5-1.8B-Chat"  # 轻量级对话模型,适合入门
cache_dir = "D:\\modelscope\\hub"

def download_qwen_model(model_name, cache_dir):
    """
    下载/校验Qwen1.5模型,返回本地模型路径
    """
    try:
        # 检查缓存目录是否存在,不存在则创建
        if not os.path.exists(cache_dir):
            os.makedirs(cache_dir)
            print(f"已创建缓存目录:{cache_dir}")
        
        print("正在下载/校验模型缓存...(首次下载需等待,取决于网络速度)")
        # 核心下载函数:自动下载、校验、缓存模型
        local_model_path = snapshot_download(
            model_name,
            cache_dir=cache_dir
        )
        
        print(f"模型下载/校验完成,本地存储路径:{local_model_path}")
        return local_model_path
    
    except Exception as e:
        print(f"模型下载失败,错误信息:{e}")
        return None

# 执行模型下载
if __name__ == "__main__":
    local_model_path = download_qwen_model(model_name, cache_dir)

代码说明:

  • snapshot_download:modelscope 提供的高速模型下载函数,相比 transformers 原生下载,国内访问速度更快,还能自动校验文件完整性、避免重复下载。
  • cache_dir:指定模型缓存目录,下载完成后,模型文件会保存在该目录下的qwen/Qwen1.5-1.8B-Chat子文件夹中。
  • 异常处理与目录创建:避免因目录不存在、网络中断等问题导致程序直接崩溃,同时给用户清晰的状态反馈。

运行效果:

运行代码后,终端会打印下载进度,首次下载完成后,后续运行会直接校验缓存并跳过下载,最终输出模型的本地绝对路径:

已创建缓存目录:D:\modelscope\hub

正在下载/校验模型缓存...(首次下载需等待,取决于网络速度)

模型下载/校验完成,本地存储路径:D:\modelscope\hub\qwen\Qwen1.5-1.8B-Chat

三、搭建基础文本交互智能体

模型下载完成后,我们基于transformers库加载模型和分词器,实现最基础的文本对话功能,让智能体能够理解并回复用户的文本输入。

1. 导入依赖与配置模型路径

模块化准备阶段,明确依赖、设定模型来源与存储位置,为后续下载和加载奠定基础

python 复制代码
from transformers import AutoTokenizer, AutoModelForCausalLM
from modelscope import snapshot_download
import os

# 配置信息(与下载步骤保持一致)
model_name = "qwen/Qwen1.5-1.8B-Chat"
cache_dir = "D:\\modelscope\\hub"

配置参数:

  • model_name 指定要使用的 Qwen1.5 对话模型,1.8B 参数量,适合本地轻量部署;
  • cache_dir 指定模型缓存目录,避免重复下载,提升加载效率。

2. 定义模型下载函数

资源获取层,将"模型下载"封装为可复用、容错的独立函数,解耦下载与推理逻辑。

python 复制代码
def download_qwen_model(model_name, cache_dir):
    try:
        if not os.path.exists(cache_dir):
            os.makedirs(cache_dir)
            print(f"已创建缓存目录:{cache_dir}")
        
        print("正在下载/校验模型缓存...")
        local_model_path = snapshot_download(
            model_name,
            cache_dir=cache_dir
        )
        
        print(f"模型准备完成,本地路径:{local_model_path}")
        return local_model_path
    except Exception as e:
        print(f"模型下载失败:{e}")
        return None
  • 使用 modelscope.snapshot_download 安全地从平台下载模型到指定目录;
  • 若不存在则自动处理目录创建;
  • 若模型已存在,则直接返回本地路径,避免重复下载;
  • 异常捕获确保程序健壮性。

3. 定义模型加载函数

模型初始化层,抽象出加载过程,支持灵活部署(CPU/GPU 自适应),并确保推理稳定性。

python 复制代码
def load_model_and_tokenizer(local_model_path):
    try:
        print("正在加载模型与分词器...")
        tokenizer = AutoTokenizer.from_pretrained(
            local_model_path,
            trust_remote_code=True
        )
        
        model = AutoModelForCausalLM.from_pretrained(
            local_model_path,
            trust_remote_code=True,
            device_map="auto",
            torch_dtype="auto"
        )
        
        model.eval()
        print("模型与分词器加载完成!")
        return tokenizer, model
    except Exception as e:
        print(f"模型加载失败:{e}")
        return None, None
  • 使用 AutoTokenizer 和 AutoModelForCausalLM 从本地路径加载;
  • trust_remote_code=True 是 Qwen 系列必需项,因其使用自定义建模代码;
  • device_map="auto" 自动分配 CPU/GPU,torch_dtype="auto" 自动选择 float16/float32 以节省显存;
  • model.eval() 切换到推理模式,关闭 dropout 等训练相关行为。

4. 实现对话生成函数

核心推理层,完整封装"输入→预处理→推理→后处理→输出"流程,符合智能体交互过程的最佳实践

python 复制代码
def text_chat(tokenizer, model, user_input):
    try:
        messages = [
            {"role": "system", "content": "你是一个乐于助人的轻量级智能体,回答简洁、准确、有温度。"},
            {"role": "user", "content": user_input}
        ]

        inputs = tokenizer.apply_chat_template(
            messages,
            add_generation_prompt=True,
            return_tensors="pt"
        )
        
        inputs = {k: v.to(model.device) for k, v in inputs.items()}

        print(f"[调试] 输入形状: {inputs['input_ids'].shape}")
        print(f"[调试] 设备: {model.device}")

        outputs = model.generate(
            **inputs,
            max_new_tokens=512,
            temperature=0.7,
            do_sample=True,
            eos_token_id=tokenizer.eos_token_id,
            pad_token_id=tokenizer.pad_token_id if tokenizer.pad_token_id is not None else tokenizer.eos_token_id
        )

        response = tokenizer.decode(
            outputs[0][inputs['input_ids'].shape[1]:],
            skip_special_tokens=True
        )

        return response
    except Exception as e:
        import traceback
        error_detail = traceback.format_exc()
        return f"对话生成失败,错误信息:{e}\n详细信息:{error_detail}"
  • 构建标准对话格式:Qwen1.5 要求输入为 [{"role": "...", "content": "..."}] 格式;
  • 使用 apply_chat_template:自动应用官方推荐的 prompt 模板,含特殊 token 如 <|im_start|>;
  • 设备对齐:确保输入张量与模型在同一设备(如 GPU);
  • 生成控制:
    • max_new_tokens=512 限制回复长度;
    • temperature=0.7 平衡创造性与确定性;
  • 正确设置 eos_token_id 和 pad_token_id 避免生成异常;
  • 输出截取:仅保留新生成部分(跳过输入 prompt);
  • 异常回溯:提供详细错误信息便于调试。

5. 启动交互循环

应用驱动层,将底层能力整合为一个可运行的终端聊天机器人,体现端到端 AI 应用架构。

python 复制代码
if __name__ == "__main__":
    local_model_path = download_qwen_model(model_name, cache_dir)
    if not local_model_path:
        exit(1)
    
    tokenizer, model = load_model_and_tokenizer(local_model_path)
    if not tokenizer or not model:
        exit(1)
    
    print("\n===== Qwen1.5 轻量级智能体已启动(输入'quit'退出)=====")
    while True:
        user_input = input("\n你:")
        if user_input.lower() == "quit":
            print("智能体:再见啦,下次再见!")
            break
        
        response = text_chat(tokenizer, model, user_input)
        print(f"智能体:{response}")
  • 顺序执行三步:下载 → 加载 → 对话;
  • 失败快速退出:任一环节失败则终止程序;
  • 简易 REPL 循环:持续接收用户输入,直到输入 "quit";
  • 友好交互提示:清晰的启动/退出提示,提升用户体验。

6. 运行效果示例

===== Qwen1.5 轻量级智能体已启动(输入'quit'退出)=====

你:你可以做什么

调试\] 输入形状: torch.Size(\[1, 35\]) \[调试\] 设备: cpu 智能体:我可以帮助您完成许多任务,包括但不限于: 1. 提供信息查询:如果您需要查找某个特定的知识点、新闻事件或产品信息,我可以提供相关的内容和链接。 2. 撰写文字和电子邮件:我能够生成各种类型的文本,如新闻报道、说明书、邮件草稿等,甚至可以自动撰写并修改文章或邮件内容。 3. 语言翻译:我能将一种语言的文本翻译成另一种语言,满足您的跨文化沟通需求。 ........ 以上只是我的基本功能,具体使用方式取决于您需要解决的具体问题或任务。如果您有任何具体的需求,欢迎随时告诉我,我会尽力提供最合适的帮助。 你:可以画画吗 \[调试\] 输入形状: torch.Size(\[1, 36\]) \[调试\] 设备: cpu 智能体:当然可以!作为一个AI语言模型,我具备绘画技能,可以生成各种形状和风格的图像。我可以使用文本描述或提供现成的绘画素材,帮助您创作出一幅符合您的想象的作品。例如,如果您想画一个简单的卡通人物,我可以提供一些角色设计元素,如眼睛、鼻子、嘴巴、身体比例、服装样式等,然后您可以根据这些信息进行填充和调整,以创建出独特的形象。如果您对某种特定主题或风格感兴趣,比如抽象艺术、风景画、动物画等等,我也很乐意为您提供相关的建议和指导。 如果您需要在画布上直接作画,我会提供相应的绘画工具和软件,包括绘图笔、颜料盒、画板、橡皮擦等,并协助您完成每一笔线条的绘制。无论您是初学者还是专业人士,只要您能提供足够的信息和要求,我都能帮您轻松实现自己的创意。

四、扩展图文输出功能

Qwen1.5-1.8B-Chat 本身是文本模型,不支持直接处理图片输入,但我们可以扩展其功能,让智能体生成图片描述或绘图参数,再通过Pillow库将这些内容转换为实际图片并保存和显示,实现"文本指令→智能体解析→图片输出"的完整流程。

1. 参数和模型初始化

确保所有必要的库被加载,并提供一个可靠的方法来获取所需的模型资源。

python 复制代码
from transformers import AutoTokenizer, AutoModelForCausalLM
from modelscope import snapshot_download
from PIL import Image, ImageDraw, ImageFont
import os
import numpy as np
import random
import math

# 配置信息
model_name = "qwen/Qwen1.5-1.8B-Chat"
cache_dir = "D:\\modelscope\\hub"
output_image_dir = "D:\\qwen_agent_output\\images"  # 图片输出目录

# 第一步:下载模型(复用函数)
def download_qwen_model(model_name, cache_dir):
    try:
        if not os.path.exists(cache_dir):
            os.makedirs(cache_dir)
            print(f"已创建缓存目录:{cache_dir}")
        
        print("正在下载/校验模型缓存...")
        local_model_path = snapshot_download(
            model_name,
            cache_dir=cache_dir
        )
        
        print(f"模型准备完成,本地路径:{local_model_path}")
        return local_model_path
    except Exception as e:
        print(f"模型下载失败:{e}")
        return None
  • 导入库:包括用于处理语言模型的 transformers 和 modelscope,以及用于图像处理的 PIL。
  • 配置信息:定义了模型名称、缓存目录及图片输出目录。
  • 下载模型:实现了一个函数来从模型平台下载指定的 Qwen 模型到本地缓存目录。如果目录不存在,则先创建它。

2. 构建智能体生成绘图指令

实现了模型的初始化,并提供了根据用户需求自动生成绘图参数的能力,这是连接文本理解和图像生成的关键环节。

python 复制代码
# 第二步:加载模型与分词器(复用函数)
def load_model_and_tokenizer(local_model_path):
    try:
        print("正在加载模型与分词器...")
        tokenizer = AutoTokenizer.from_pretrained(
            local_model_path,
            trust_remote_code=True
        )
        
        model = AutoModelForCausalLM.from_pretrained(
            local_model_path,
            trust_remote_code=True,
            device_map="auto",
            torch_dtype="auto"
        )
        
        model.eval()
        print("模型与分词器加载完成!")
        return tokenizer, model
    except Exception as e:
        print(f"模型加载失败:{e}")
        return None, None

# 第三步:智能体生成创意绘图指令
def get_draw_params_from_agent(tokenizer, model, user_draw需求):
    """
    接收用户绘图需求,让智能体生成标准化绘图参数
    支持多种创意图形:几何图形、渐变背景、装饰元素等
    """
    try:
        # 构建更精准的系统提示,引导智能体返回标准化参数
        messages = [
            {
                "role": "system",
                "content": "你是一个创意绘图专家,根据用户需求生成精美图片。仅返回以下标准化格式:\
1. 图片类型:text/geometry/gradient/abstract(文字/几何/渐变/抽象)\
2. 图片尺寸:宽,高(例如:800,600)\
3. 背景颜色:RGB值(例如:240,248,255 或 255,200,200)\
4. 文字内容:简短文案(文字模式必需)\
5. 文字颜色:RGB值(例如:50,50,50)\
6. 文字大小:数字(例如:36)\
7. 图形类型:circle/rect/triangle/star(几何模式可选)\
8. 图形颜色:RGB值(几何模式可选)\
9. 图形数量:数字(抽象模式可选,3-8)\
10. 渐变方向:horizontal/vertical/diagonal(渐变模式可选)\
11. 渐变结束色:RGB值(渐变模式可选)"
            },
            {"role": "user", "content": user_draw需求}
        ]
        
        # 模型推理生成绘图参数
        inputs = tokenizer.apply_chat_template(
            messages,
            add_generation_prompt=True,
            return_tensors="pt"
        )
        inputs = {k: v.to(model.device) for k, v in inputs.items()}

        outputs = model.generate(
            **inputs,
            max_new_tokens=300,  # 增加token支持更复杂参数
            temperature=0.7,  # 提高创造性
            do_sample=True,
            eos_token_id=tokenizer.eos_token_id
        )

        # 解码并返回参数
        draw_params = tokenizer.decode(
            outputs[0][inputs['input_ids'].shape[1]:],
            skip_special_tokens=True
        )
        return draw_params
    except Exception as e:
        return f"绘图参数生成失败:{e}"
  • 加载模型与分词器:通过预训练接口加载Qwen模型及其相应的分词器,为后续文本处理做准备。
  • 生成绘图指令:基于用户输入的需求,利用已经加载的语言模型生成符合特定格式的绘图参数。这一步骤是整个流程的核心之一,它将用户的自然语言请求转化为机器可理解的绘图指令。

3. 绘图参数解析与基础图像创建

将由AI生成的文字描述转换成具体的视觉元素,为最终图像的形成打下基础。

python 复制代码
# 第四步:解析参数并生成创意图片
def generate_image_from_params(draw_params, image_save_path):
    """
    解析智能体生成的参数,绘制创意图片
    支持文字、几何图形、渐变背景、抽象艺术等多种风格
    """
    try:
        # 初始化默认参数
        img_type = "text"
        width, height = 800, 600
        bg_rgb = (240, 248, 255)
        text_content = "创意图片"
        text_rgb = (50, 50, 50)
        font_size = 36
        shape_type = "circle"
        shape_color = (255, 100, 100)
        shape_count = 5
        gradient_dir = "diagonal"
        gradient_end = (100, 149, 237)

        # 解析智能体返回的参数(支持多种格式)
        param_lines = draw_params.split("\n")

        # 收集所有包含文字内容的行
        text_content_lines = []

        for line in param_lines:
            line = line.strip()
            if "图片类型" in line or "类型" in line:
                img_type = extract_simple_value(line, ["text", "geometry", "gradient", "abstract"], "text")
            elif "尺寸" in line or "宽" in line or "高" in line:
                width, height = parse_dimensions(line)
            elif "背景颜色" in line or "背景色" in line or "背景" in line:
                bg_rgb = parse_rgb_color(line)
            elif "文字内容" in line or "内容" in line:
                content = extract_text_content(line)
                if content and content != "创意图片":
                    text_content_lines.append(content)
            elif "文字颜色" in line or "文字色" in line:
                text_rgb = parse_rgb_color(line)
            elif "文字大小" in line or "字号" in line or "大小" in line:
                font_size = parse_number(line, 36)
            elif "图形类型" in line or "形状" in line:
                shape_type = extract_simple_value(line, ["circle", "rect", "triangle", "star"], "circle")
            elif "图形颜色" in line or "形状颜色" in line:
                shape_color = parse_rgb_color(line)
            elif "图形数量" in line or "数量" in line:
                shape_count = parse_number(line, 5)
            elif "渐变方向" in line:
                gradient_dir = extract_simple_value(line, ["horizontal", "vertical", "diagonal"], "diagonal")
            elif "渐变结束色" in line or "渐变色" in line:
                gradient_end = parse_rgb_color(line)

        # 合并文字内容(取第一个有效的内容)
        if text_content_lines:
            text_content = text_content_lines[0]
            # 移除引号
            text_content = text_content.replace('"', '').replace("'", '')

        # 1. 创建基础图片
        image = create_base_image(width, height, bg_rgb, gradient_dir, gradient_end, img_type)
        draw = ImageDraw.Draw(image)

        # 调试输出
        print(f"[解析结果] 类型: {img_type}, 尺寸: {width}x{height}")
        print(f"[解析结果] 文字: '{text_content}' (长度: {len(text_content)})")
        print(f"[解析结果] 颜色: {text_rgb}, 字号: {font_size}")

        # 2. 根据类型绘制不同内容
        if img_type == "text":
            draw_text_image(draw, width, height, text_content, text_rgb, font_size)
        elif img_type == "geometry":
            draw_geometry_image(draw, width, height, shape_type, shape_color, shape_count)
        elif img_type == "gradient":
            draw_gradient_text(draw, width, height, text_content, text_rgb, font_size)
        elif img_type == "abstract":
            draw_abstract_art(draw, width, height, shape_count, bg_rgb)

        # 3. 保存并显示图片
        image.save(image_save_path)
        print(f"✨ 创意图片已生成:{image_save_path} (类型: {img_type})")
        image.show()
        return True

    except Exception as e:
        print(f"图片生成失败:{e}")
        import traceback
        traceback.print_exc()
        return False

def parse_rgb_color(color_str):
    """解析RGB颜色字符串,支持多种格式"""
    import re
    # 提取所有数字
    numbers = re.findall(r'\d+', color_str)
    if len(numbers) >= 3:
        return tuple(map(int, numbers[:3]))
    return (240, 248, 255)

def extract_simple_value(line, valid_values, default):
    """从行中提取简单值"""
    for val in valid_values:
        if val in line.lower():
            return val
    return default

def extract_text_content(line):
    """提取文字内容"""
    # 移除标签部分(中文冒号)
    parts = line.split(":")
    if len(parts) > 1:
        content = parts[1].strip()
        # 移除描述性文字,只保留核心内容
        if "-" in content:
            content = content.split("-")[0].strip()
        return content

    # 移除标签部分(英文冒号)
    parts = line.split(":")
    if len(parts) > 1:
        content = parts[1].strip()
        if "-" in content:
            content = content.split("-")[0].strip()
        return content

    # 检查是否是引号包裹的内容
    if '"' in line:
        start = line.find('"')
        end = line.rfind('"')
        if start != -1 and end != -1 and end > start:
            return line[start + 1:end]

    return None

def parse_dimensions(line):
    """解析图片尺寸"""
    import re
    # 提取所有数字
    numbers = re.findall(r'\d+', line)
    if len(numbers) >= 2:
        return int(numbers[0]), int(numbers[1])
    return 800, 600

def parse_number(line, default):
    """解析数字"""
    import re
    numbers = re.findall(r'\d+', line)
    if numbers:
        return int(numbers[0])
    return default
  • 解析绘图参数:根据上一步生成的绘图参数,提取出各种绘画所需的具体数值,如尺寸、颜色等。
  • 创建基础图像:基于解析出来的参数,创建一个基础图像对象,可能是纯色背景、渐变背景等,作为后续绘画的基础。

4. 图形绘制函数集合

通过一系列分解的功能模块,将初步形成的图像进一步丰富和完善,直至达到预期的艺术效果。

python 复制代码
def create_base_image(width, height, bg_rgb, gradient_dir, gradient_end, img_type):
    """创建基础图片(纯色或渐变背景)"""
    if img_type == "gradient":
        # 创建渐变背景
        image = Image.new("RGB", (width, height))
        pixels = np.array(image)

        for y in range(height):
            for x in range(width):
                if gradient_dir == "horizontal":
                    ratio = x / width
                elif gradient_dir == "vertical":
                    ratio = y / height
                else:  # diagonal
                    ratio = (x + y) / (width + height)

                r = int(bg_rgb[0] * (1 - ratio) + gradient_end[0] * ratio)
                g = int(bg_rgb[1] * (1 - ratio) + gradient_end[1] * ratio)
                b = int(bg_rgb[2] * (1 - ratio) + gradient_end[2] * ratio)
                pixels[y, x] = [r, g, b]

        return Image.fromarray(pixels)
    else:
        return Image.new("RGB", (width, height), bg_rgb)

def draw_text_image(draw, width, height, text_content, text_rgb, font_size):
    """绘制文字图片(带装饰边框)"""
    try:
        font = ImageFont.truetype("simhei.ttf", font_size)
    except:
        font = ImageFont.load_default(size=font_size)

    # 绘制装饰边框(确保边框宽度不超过图片尺寸的一半)
    border_color = tuple(min(255, c + 30) for c in text_rgb)
    border_width = min(max(10, font_size // 3), min(width, height) // 4)
    if width > 2 * border_width and height > 2 * border_width:
        draw.rectangle([border_width, border_width, width - border_width, height - border_width],
                       outline=border_color, width=border_width)

    # 绘制文字(居中)
    text_bbox = draw.textbbox((0, 0), text_content, font=font)
    text_width = text_bbox[2] - text_bbox[0]
    text_height = text_bbox[3] - text_bbox[1]
    text_x = (width - text_width) // 2
    text_y = (height - text_height) // 2
    draw.text((text_x, text_y), text_content, fill=text_rgb, font=font)

def draw_geometry_image(draw, width, height, shape_type, shape_color, count):
    """绘制几何图形图片"""
    random.seed(42)  # 确保可重现性

    for _ in range(count):
        x = random.randint(50, width - 50)
        y = random.randint(50, height - 50)
        size = random.randint(30, 100)

        # 随机调整颜色
        color = tuple(max(0, min(255, c + random.randint(-30, 30))) for c in shape_color)

        if shape_type == "circle":
            draw.ellipse([x, y, x + size, y + size], fill=color, outline=(0, 0, 0))
        elif shape_type == "rect":
            draw.rectangle([x, y, x + size, y + size], fill=color, outline=(0, 0, 0))
        elif shape_type == "triangle":
            points = [(x + size // 2, y), (x, y + size), (x + size, y + size)]
            draw.polygon(points, fill=color, outline=(0, 0, 0))
        elif shape_type == "star":
            draw_star(draw, x + size // 2, y + size // 2, size // 2, color)

def draw_star(draw, cx, cy, radius, color):
    """绘制五角星"""
    points = []
    for i in range(10):
        angle = i * 36 - 90
        r = radius if i % 2 == 0 else radius / 2
        x = cx + r * math.cos(math.radians(angle))
        y = cy + r * math.sin(math.radians(angle))
        points.append((x, y))
    draw.polygon(points, fill=color, outline=(0, 0, 0))

def draw_gradient_text(draw, width, height, text_content, text_rgb, font_size):
    """在渐变背景上绘制文字"""
    try:
        font = ImageFont.truetype("simhei.ttf", font_size)
    except:
        font = ImageFont.load_default(size=font_size)

    # 文字阴影效果
    shadow_offset = max(3, font_size // 10)
    shadow_color = (200, 200, 200)
    text_bbox = draw.textbbox((0, 0), text_content, font=font)
    text_width = text_bbox[2] - text_bbox[0]
    text_height = text_bbox[3] - text_bbox[1]
    text_x = (width - text_width) // 2
    text_y = (height - text_height) // 2

    # 绘制阴影
    draw.text((text_x + shadow_offset, text_y + shadow_offset), text_content,
              fill=shadow_color, font=font)
    # 绘制主文字
    draw.text((text_x, text_y), text_content, fill=text_rgb, font=font)

def draw_abstract_art(draw, width, height, count, bg_rgb):
    """绘制抽象艺术图片"""
    random.seed(42)

    for _ in range(count):
        x1 = random.randint(0, width)
        y1 = random.randint(0, height)
        x2 = random.randint(0, width)
        y2 = random.randint(0, height)

        # 互补色
        color = tuple(random.randint(0, 255) for _ in range(3))
        line_width = random.randint(2, 8)

        draw.line([x1, y1, x2, y2], fill=color, width=line_width)

    # 添加随机圆点
    for _ in range(count * 2):
        x = random.randint(0, width)
        y = random.randint(0, height)
        radius = random.randint(5, 30)
        color = tuple(random.randint(0, 255) for _ in range(3))
        draw.ellipse([x - radius, y - radius, x + radius, y + radius], fill=color)
  • 具体图形绘制:这一部分包含了一系列专门用于绘制不同类型图像元素的函数,如添加文本、绘制几何形状、应用渐变效果等。
  • 这些函数共同作用于前面创建的基础图像之上,逐步构建出最终的创意作品。

5. 智能体循环交互

集成了前面所有步骤,形成了完整的用户体验流程,从接收用户输入开始,到生成个性化图像结束,体现系统的易用性和灵活性。

python 复制代码
# 主程序:图文输出智能体
if __name__ == "__main__":
    # 1. 创建图片输出目录
    if not os.path.exists(output_image_dir):
        os.makedirs(output_image_dir)
        print(f"已创建图片输出目录:{output_image_dir}")
    
    # 2. 下载/加载模型
    local_model_path = download_qwen_model(model_name, cache_dir)
    if not local_model_path:
        exit(1)
    
    tokenizer, model = load_model_and_tokenizer(local_model_path)
    if not tokenizer or not model:
        exit(1)
    
    # 3. 启动图文交互循环
    print("\n" + "="*50)
    print("🎨 Qwen1.5 创意图文智能体已启动")
    print("="*50)
    print("支持类型:文字海报 | 几何图形 | 渐变艺术 | 抽象艺术")
    print("输入示例:")
    print("  - '画一个生日快乐的海报'")
    print("  - '生成蓝色的圆形几何图案'")
    print("  - '做一个从粉色到紫色的渐变背景'")
    print("  - '创作一幅抽象艺术画'")
    print("="*50)

    image_index = 1
    while True:
        user_input = input("\n🎯 请输入你的创意绘图需求(输入'quit'退出):")
        if user_input.lower() == "quit":
            print("👋 智能体:再见啦,期待下次创作!")
            break

        # 4. 智能体生成绘图参数
        print("🤖 智能体正在解析你的创意...")
        draw_params = get_draw_params_from_agent(tokenizer, model, user_input)
        print(f"\n📋 生成的绘图参数:\n{draw_params}\n")

        # 5. 生成并保存图片
        image_file_name = f"creative_{image_index}.png"
        image_save_path = os.path.join(output_image_dir, image_file_name)
        generate_image_from_params(draw_params, image_save_path)

        # 6. 更新图片序号
        image_index += 1
  • 主程序入口:检查并创建图片输出目录;下载并加载模型。
  • 用户交互循环:提供一个简单的命令行界面,让用户能够输入自己的创意需求,系统则根据这些需求生成对应的图像,并保存到指定目录中。
  • 持续互动:直到用户输入"quit"为止,程序将持续运行,允许用户不断尝试新的创意。

6. 运行效果示例

==================================================

🎨 Qwen1.5 创意图文智能体已启动

==================================================

支持类型:文字海报 | 几何图形 | 渐变艺术 | 抽象艺术

输入示例:

  • '画一个生日快乐的海报'

  • '生成蓝色的圆形几何图案'

  • '做一个从粉色到紫色的渐变背景'

  • '创作一幅抽象艺术画'

==================================================

🎯 请输入你的创意绘图需求(输入'quit'退出):画一个生日快乐的海报

🤖 智能体正在解析你的创意...

📋 生成的绘图参数:

以下是根据您的要求生成的生日快乐海报设计:

  1. 图片类型:text/geometry/gradient/abstract
  • 图片尺寸:宽: 800 厘米,高: 600 厘米

  • 背景颜色:RGB值(240, 248, 255)

  • 文字内容:

  • "Happy Birthday to You!"

  • 字体颜色:RGB值(50, 50, 50)

  • 字体大小:36 厘米

  • 文字内容:

  • "Wishing you a very happy birthday! May your day be filled with joy and love."

  • 字体颜色:RGB值(255, 200, 200)

  • 字体大小:36 厘米

  • 图形类型:circle/rect/triangle/star

  • 图形颜色:RGB值(255, 255, 255),表示圆形或星形的背景,象征着生日派对的欢乐气氛。

  • 图形数量:4

  • 渐变方向:horizontal

  • 渐变结束色:RGB值(255, 0, 0),表示从红色渐变为无色的过渡效果,象征着生日蛋糕的颜色和氛围。

五、总结

经历了一阶段又烧脑又费劲儿的算力、算法知识点!整天琢磨参数调优、算力适配那套,脑子都快被公式和配置绕晕了。今天通过一个简单的Qwen1.5 智能体示例,来个降速解压,不用纠结高端显卡够不够用,也不用死磕复杂的部署逻辑,就一个轻量级小模型,几步简单操作,既能实现对话交互,还能顺手生成小图片。全程没什么晦涩的硬骨头,代码复制过去稍作调整就能跑通,刚好把之前学的理论知识点,用最不费脑子的方式落地练手。

相当于学完一堆硬核内容后,来个轻松的小实践缓冲下,既尝着了动手做智能体的成就感,又不用被算力、算法的压力裹挟。这种不折腾、简单的示例,也算是一阶段学习后的适配小甜点,为后续深入探索先攒下点轻松的底气,后续还有硬骨头等着未完待续。

相关推荐
爱敲代码的TOM1 天前
大模型应用开发-LangChain框架基础
python·langchain·大模型应用
minhuan4 天前
大模型应用:批量文档摘要与分类实践:本地合同、报告数据处理与导出.70
文本分类·大模型应用·批量文档摘要提取·textsplitter·schema提示词
minhuan4 天前
大模型架构算力对比:Decoder-only、Encoder-Decoder、MoE深度解析.71
大模型应用·模型架构的算力·算力分析·moe算力节省
minhuan7 天前
大模型应用:矩阵乘加(GEMM)全解析:大模型算力消耗的逻辑与优化.68
gemm·大模型应用·矩阵乘加运算·大模型算力优化
minhuan8 天前
大模型应用:GPU的黑盒拆解:可视化看透大模型并行计算的底层逻辑.67
gpu算力·大模型应用·cuda原理·张量核心·显存解析
minhuan11 天前
大模型应用:电商智能推荐:基于本地大模型的冷启动智能推荐系统实例.61
大模型应用·智能推荐·冷启动推荐
minhuan11 天前
大模型应用:拆解大模型算力需求:算力是什么?怎么衡量?如何匹配?.64
人工智能·gpu算力·大模型应用·算力评估·算力优化
minhuan13 天前
大模型应用:联邦学习融合本地大模型:隐私合规推荐的核心流程与实践.62
大数据·人工智能·大模型应用·联邦学习推荐系统·推荐系统案例
minhuan15 天前
大模型应用:本地部署 vs 云端调用:成本、隐私、效率、方式的综合考量.60
大模型api调用·大模型应用·模型的本地部署·模型的成本指标