开源模型落地指南:DeepSeek微调实战,在垂直场景打造差异化竞争力

朋友,可以转载,但请注明出处,谢谢!
http://blog.csdn.net/jiangjunshow

现在AI圈里最火的词是什么?不是"大模型"也不是"生成式AI",而是"落地"。很多开发者和企业都卡在了最后一公里------手里有需求,也知道开源模型好用,但就是不知道怎么把通用模型改成自己行业的"专属专家"。今天这篇文章,就带大家手把手实战DeepSeek微调,从环境搭建到数据集准备,再到训练部署全流程,用最口语化的方式讲明白,让你在医疗、金融、电商等垂直场景快速打造差异化竞争力。

先跟大家交个底,我之前做过不少行业AI解决方案,从电商智能客服到医疗症状咨询,踩过很多坑。发现很多人对微调有误解,觉得"必须有顶级GPU""得懂复杂算法",其实现在的工具已经把门槛降得很低了。DeepSeek作为开源模型里的"六边形战士",不仅推理能力强,支持中文优化,微调起来还特别灵活,不管是消费级显卡还是云端服务器都能跑。更重要的是,微调后的模型能精准适配你的业务场景,比如让客服AI只说你行业的专业术语,让数据分析AI读懂你公司的专属数据格式,这可不是直接调用API能比的。

一、为什么要做DeepSeek微调?通用模型的"水土不服"问题

先给大家举个真实案例。我之前帮一家连锁药店做智能咨询AI,一开始直接用DeepSeek的预训练模型,结果问题百出:用户问"高血压患者能吃布洛芬吗",模型回答得模棱两可,还夹杂着一堆专业医疗术语;用户说"孩子感冒发烧38.5度该吃什么药",模型居然推荐了成人用药。后来才发现,通用模型的知识库虽然广,但缺乏行业针对性,对医疗这种高精准度场景来说完全不够用。

这就是通用模型的"水土不服"------它们是用海量通用数据训练出来的,就像"百科全书",啥都知道但啥都不精。而我们做业务落地,需要的是"行业手册",能精准解决特定场景的问题。这时候微调就派上用场了,它相当于给通用模型做"专业培训",用你行业的专属数据让模型快速上手业务。

具体来说,微调有三个核心价值,这也是我推荐大家一定要做的原因:

  1. 提升行业适配性:让模型学会行业术语和业务逻辑,比如金融场景的"北向资金""期权行权",教育场景的"课标考点""学情分析",再也不会出现答非所问的情况。

  2. 降低部署成本:微调后的模型可以本地部署,不用反复调用API,不仅响应速度快,还能避免数据泄露,对于对隐私要求高的医疗、金融行业来说太重要了。

  3. 打造差异化优势:别人都在用通用模型做同质化产品,你用微调后的专属模型,不管是响应精准度还是用户体验都能更胜一筹,这就是核心竞争力。

这里跟大家插一句心里话:虽然不懂AI基础知识也能开发AI应用,但是懂的人往往可以开发出更复杂更优秀的AI高级应用。如果你对AI基础知识感兴趣,可以看看我的人工智能入门教程https://blog.csdn.net/jiangjunshow。很多朋友跟着这个教程打基础后,再做微调时能更快理解参数含义,遇到问题也能自己排查,效率提升特别明显。

二、微调前的准备:硬件、工具、数据集,一个都不能少

在开始实战前,我们得把"弹药"备足。很多人卡在第一步就是准备工作没做好,要么硬件不够用,要么工具装错了,所以这部分一定要仔细看。

1. 硬件要求:不用顶级GPU,消费级也能跑

很多人觉得微调需要A100这种天价GPU,其实完全没必要。我实测下来,不同需求对应不同配置,大家可以对号入座:

  • 入门尝试(比如500条以内数据集,4B参数模型):RTX 3090/4090(24GB显存)就够了,我用4090跑4.7B参数的DeepSeek-R1,全程没爆显存。
  • 中小规模业务(1-5万条数据集,7B参数模型):可以用两张3090或者云端的T4 GPU(16GB显存),Google Colab Pro+也能满足需求。
  • 大规模生产(10万条以上数据集,13B参数模型):建议用A100(80GB)或者多卡并行,不过大多数中小企业和开发者用不到这个级别。

如果显存实在不够,后面会教大家用LoRA技术,能减少70%的显存占用,消费级显卡也能轻松hold住。

2. 工具栈:认准这几个库,高效又省心

微调需要的工具其实不多,核心就几个,我把它们的作用和安装命令整理得明明白白,直接复制粘贴就能用:

  • PyTorch:深度学习的核心框架,负责模型训练的底层计算。
  • Transformers:Hugging Face的大模型库,加载和管理DeepSeek模型的神器。
  • PEFT:参数高效微调工具,核心是LoRA技术,省显存的关键。
  • Datasets:处理训练数据的工具,支持各种格式的数据加载和预处理。
  • Accelerate:优化训练速度,支持GPU、CPU多种设备。
  • Unsloth:可选工具,能进一步提升微调速度,减少内存占用。

安装命令(建议用Python 3.9+版本):

bash 复制代码
# 基础依赖安装
pip install -U torch transformers datasets accelerate peft bitsandbytes
# 可选:安装unsloth提升速度
pip install unsloth

安装完成后,我们可以测试一下环境是否正常,运行下面的代码如果不报错,就说明环境没问题了:

python 复制代码
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer

# 测试是否能正常加载模型
tokenizer = AutoTokenizer.from_pretrained("deepseek-ai/deepseek-llm-7b-chat")
model = AutoModelForCausalLM.from_pretrained(
    "deepseek-ai/deepseek-llm-7b-chat",
    torch_dtype=torch.float16,
    device_map="auto"
)
print("环境测试成功!")
3. 数据集准备:数据质量决定微调效果,这3个原则要记牢

数据集是微调的核心,很多人微调失败就是因为数据质量差。记住一句话:"宁要100条高质量数据,不要1万条垃圾数据"。这里给大家讲清楚数据集的要求、格式和预处理方法,新手也能快速上手。

(1)数据集的3个核心原则

  • 相关性:数据必须和你的业务场景强相关。比如做医疗咨询,就用医疗问答数据;做电商客服,就用商品咨询、售后问题数据。
  • 高质量:数据要准确无误,尤其是专业领域。比如金融数据不能有错别字,医疗数据的症状和用药建议要符合常识。
  • 结构化:数据格式要统一,最好是"问题-答案""指令-响应"的形式,方便模型学习。

(2)推荐数据集格式:Alpaca格式最通用

我推荐大家用Alpaca格式,大部分微调框架都支持,格式如下:

json 复制代码
[
  {
    "instruction": "用户的指令或问题",
    "input": "补充信息(可选)",
    "output": "正确的回答或响应"
  },
  {
    "instruction": "高血压患者能吃布洛芬吗?",
    "input": "患者年龄65岁,有高血压病史5年,目前血压控制在130/85mmHg",
    "output": "高血压患者在血压控制稳定的情况下,可短期服用布洛芬,但需遵医嘱。布洛芬可能会影响血压控制,长期或大量服用可能导致血压升高,因此不建议自行长期使用。用药期间需监测血压,若出现头晕、头痛等不适,应立即停药并就医。"
  }
]

如果是多轮对话场景,比如客服聊天,可以用ShareGPT格式:

json 复制代码
[
  {
    "conversations": [
      {"from": "human", "value": "请问这款冰箱的保鲜期是多久?"},
      {"from": "gpt", "value": "这款冰箱的果蔬保鲜区采用控温保湿技术,绿叶蔬菜可保鲜7-10天,水果可保鲜15-20天。建议将食材洗净擦干后存放,效果更佳。"},
      {"from": "human", "value": "那肉类呢?冷冻室能放多久?"},
      {"from": "gpt", "value": "冷冻室温度可达-18℃,鲜肉可冷冻保存3-6个月,海鲜类建议1-3个月内食用,以保证口感和营养。存放时建议分袋密封,避免串味。"}
    ]
  }
]

(3)数据集预处理:3行代码搞定清洗和格式化

拿到原始数据后,需要做简单的预处理,比如去除重复数据、过滤无效内容、格式化数据结构。这里给大家一个通用的预处理代码,不管是CSV还是JSON格式的数据,稍微修改一下就能用:

python 复制代码
import json
import pandas as pd
from tqdm import tqdm

# 读取原始数据(以CSV为例,若为JSON可改用json.load)
df = pd.read_csv("原始数据.csv")

# 预处理函数:去除空值、重复值,格式化数据
def process_data(df):
    # 去除空值
    df = df.dropna(subset=["instruction", "output"])
    # 去除重复值
    df = df.drop_duplicates(subset=["instruction"])
    # 格式化数据为Alpaca格式
    formatted_data = []
    for _, row in tqdm(df.iterrows(), total=len(df)):
        item = {
            "instruction": str(row["instruction"]),
            "input": str(row.get("input", "")),  # 可选字段
            "output": str(row["output"])
        }
        formatted_data.append(item)
    return formatted_data

# 执行预处理
processed_data = process_data(df)

# 保存为JSON文件
with open("processed_dataset.json", "w", encoding="utf-8") as f:
    json.dump(processed_data, f, ensure_ascii=False, indent=2)

print(f"预处理完成!共生成{len(processed_data)}条有效数据")

这里给大家一个小建议:如果没有足够的自有数据,可以去Hugging Face Hub或ModelScope下载公开的行业数据集,比如医疗领域的medical-o1-reasoning-SFT,电商领域的alpaca-cleaned,下载后用上面的代码稍作修改就能用。

三、DeepSeek微调实战:LoRA微调全流程,代码可直接复用

接下来就是核心部分------实战微调。这里我们用最常用的LoRA(低秩适配)方法,这种方法的优点是训练参数少、显存占用低、训练速度快,非常适合新手入门。整个流程分为5步:加载模型和Tokenizer、配置LoRA参数、加载并格式化数据集、训练模型、保存模型。

1. 加载模型和Tokenizer

首先我们要加载DeepSeek的预训练模型和分词器。这里用4-bit量化加载,能大幅减少显存占用,同时保证模型性能。代码如下,关键参数都有注释:

python 复制代码
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
from peft import LoraConfig, get_peft_model
import torch

# 4-bit量化配置,减少显存占用
bnb_config = BitsAndBytesConfig(
    load_in_4bit=True,  # 启用4-bit量化
    bnb_4bit_use_double_quant=True,
    bnb_4bit_quant_type="nf4",
    bnb_4bit_compute_dtype=torch.float16
)

# 加载模型和Tokenizer
model_name = "deepseek-ai/deepseek-llm-7b-chat"  # 7B参数模型,平衡性能和显存
tokenizer = AutoTokenizer.from_pretrained(model_name)
tokenizer.pad_token = tokenizer.eos_token  # 设置pad token,避免警告

model = AutoModelForCausalLM.from_pretrained(
    model_name,
    quantization_config=bnb_config,
    device_map="auto",  # 自动分配设备(GPU优先)
    trust_remote_code=True
)

# 冻结原始模型参数,只训练LoRA适配器
model.train()
for param in model.parameters():
    param.requires_grad = False  # 冻结原始参数
2. 配置LoRA参数

LoRA的核心是在模型的关键层添加低秩矩阵,只训练这些矩阵的参数,从而减少计算量。参数配置不用太复杂,参考下面的设置就行,新手直接复用:

python 复制代码
lora_config = LoraConfig(
    r=64,  # LoRA秩,越大效果越好但显存占用越高,建议8-128
    lora_alpha=32,  # 缩放因子,通常是r的一半
    target_modules=["q_proj", "k_proj", "v_proj", "o_proj", "gate_proj", "up_proj", "down_proj"],  # DeepSeek的关键层
    lora_dropout=0.05,  # dropout率,防止过拟合
    bias="none",  # 不训练偏置参数
    task_type="CAUSAL_LM"  # 任务类型,文本生成用这个
)

# 给模型添加LoRA适配器
model = get_peft_model(model, lora_config)

# 查看训练参数数量,确认配置正确
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
total_params = sum(p.numel() for p in model.parameters())
print(f"训练参数占比:{trainable_params/total_params*100:.2f}%")  # 通常在0.1%-1%之间
3. 加载并格式化数据集

这里我们用之前预处理好的数据集,将其格式化为模型能接受的输入格式。关键是要把"指令+输入+输出"拼接成模型的训练样本,并进行分词和padding:

python 复制代码
from datasets import load_dataset
import transformers

# 加载数据集(支持本地JSON文件或Hugging Face数据集)
dataset = load_dataset("json", data_files="processed_dataset.json")
dataset = dataset["train"].train_test_split(test_size=0.1)  # 划分训练集(90%)和测试集(10%)

# 格式化函数:将样本拼接成模型需要的格式
def format_example(example):
    instruction = example["instruction"]
    input_text = example["input"] if example["input"] else ""
    output_text = example["output"]
    # 拼接格式:指令+输入+输出,模型会学习从指令+输入生成输出
    return f"### 指令:{instruction}\n### 输入:{input_text}\n### 输出:{output_text}"

# 分词函数
def tokenize_function(examples):
    texts = [format_example(example) for example in examples]
    # 分词,设置padding和truncation
    tokenized = tokenizer(
        texts,
        truncation=True,
        max_length=2048,  # 最大序列长度,根据模型支持的长度设置
        padding="max_length",
        return_tensors="pt"
    )
    # 设置标签,这里直接用输入的token作为标签(文本生成任务)
    tokenized["labels"] = tokenized["input_ids"].clone()
    return tokenized

# 应用分词函数到数据集
tokenized_dataset = dataset.map(
    tokenize_function,
    batched=True,  # 批量处理,提升速度
    remove_columns=dataset["train"].column_names  # 移除不需要的列
)

# 创建数据加载器
trainer_args = transformers.TrainingArguments(
    output_dir="./deepseek-finetune",  # 模型保存路径
    per_device_train_batch_size=4,  # 每个设备的批次大小,根据显存调整
    per_device_eval_batch_size=4,
    learning_rate=2e-4,  # 学习率,推荐1e-4~3e-4
    num_train_epochs=3,  # 训练轮数,3轮左右足够,多了容易过拟合
    logging_steps=10,  # 每10步打印一次日志
    evaluation_strategy="epoch",  # 每轮结束后评估
    save_strategy="epoch",  # 每轮结束后保存模型
    fp16=True,  # 启用混合精度训练,提升速度
    gradient_accumulation_steps=2,  # 梯度累积,显存不够时用
)
4. 启动训练

一切准备就绪,现在可以启动训练了。用Transformers的Trainer类,一行代码就能搞定:

python 复制代码
from transformers import Trainer, DataCollatorForLanguageModeling

# 数据收集器,处理批量数据
data_collator = DataCollatorForLanguageModeling(
    tokenizer=tokenizer,
    mlm=False,  # 文本生成任务,关闭掩码语言模型
)

# 创建Trainer实例
trainer = Trainer(
    model=model,
    args=trainer_args,
    train_dataset=tokenized_dataset["train"],
    eval_dataset=tokenized_dataset["test"],
    data_collator=data_collator,
)

# 启动训练
print("开始训练...")
trainer.train()

# 保存最终模型
trainer.save_model("./deepseek-finetune-final")
print("训练完成!模型保存至 ./deepseek-finetune-final")

这里给大家一个训练时长参考:用4090 GPU,5000条数据,7B参数模型,大概2-3小时就能训练完成;如果用T4 GPU,大概需要4-6小时。训练过程中可以关注日志里的loss(损失值),如果loss持续下降,说明训练正常;如果loss不再下降或者上升,可能是学习率太高或数据有问题,可以适当调整。

5. 模型测试和部署

训练完成后,我们需要测试一下模型效果,然后部署到实际应用中。

(1)模型测试

加载训练好的模型,输入问题看看效果:

python 复制代码
from transformers import pipeline

# 加载微调后的模型
generator = pipeline(
    "text-generation",
    model="./deepseek-finetune-final",
    tokenizer=tokenizer,
    torch_dtype=torch.float16,
    device_map="auto"
)

# 测试函数
def test_model(instruction, input_text=""):
    prompt = f"### 指令:{instruction}\n### 输入:{input_text}\n### 输出:"
    outputs = generator(
        prompt,
        max_new_tokens=512,  # 最大生成长度
        temperature=0.7,  # 随机性,越小越精准
        top_p=0.9,
        do_sample=True,
        eos_token_id=tokenizer.eos_token_id
    )
    print(f"输入:{instruction} {input_text}")
    print(f"输出:{outputs[0]['generated_text'].split('### 输出:')[-1]}")

# 测试案例(根据你的行业场景修改)
test_model("高血压患者能吃布洛芬吗?", "患者年龄65岁,有高血压病史5年,目前血压控制在130/85mmHg")
test_model("请问这款冰箱的冷冻室能放多久肉类?")

如果测试结果能准确回答问题,并且符合行业规范,说明微调成功了。如果效果不好,可以从这几个方面优化:增加高质量数据、调整LoRA参数、修改学习率或训练轮数。

(2)模型部署

微调后的模型可以本地部署,也可以部署到云端。这里给大家一个简单的Flask部署代码,能快速搭建一个API服务:

python 复制代码
from flask import Flask, request, jsonify
from transformers import pipeline
import torch

app = Flask(__name__)

# 加载模型(启动时加载一次即可)
tokenizer = AutoTokenizer.from_pretrained("./deepseek-finetune-final")
model = AutoModelForCausalLM.from_pretrained(
    "./deepseek-finetune-final",
    torch_dtype=torch.float16,
    device_map="auto"
)
generator = pipeline(
    "text-generation",
    model=model,
    tokenizer=tokenizer,
    torch_dtype=torch.float16,
    device_map="auto"
)

@app.route("/generate", methods=["POST"])
def generate():
    data = request.json
    instruction = data.get("instruction", "")
    input_text = data.get("input", "")
    prompt = f"### 指令:{instruction}\n### 输入:{input_text}\n### 输出:"
    outputs = generator(
        prompt,
        max_new_tokens=512,
        temperature=0.7,
        top_p=0.9,
        do_sample=True,
        eos_token_id=tokenizer.eos_token_id
    )
    result = outputs[0]['generated_text'].split('### 输出:')[-1]
    return jsonify({"result": result})

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000)

启动服务后,用Postman或curl发送请求就能调用模型了:

bash 复制代码
curl -X POST http://localhost:5000/generate \
-H "Content-Type: application/json" \
-d '{"instruction":"高血压患者能吃布洛芬吗?","input":"患者年龄65岁,有高血压病史5年,目前血压控制在130/85mmHg"}'

四、垂直场景实战案例:医疗咨询AI的微调与优化

为了让大家更有代入感,这里分享一个我之前做的医疗咨询AI微调案例,看看在实际场景中如何应用上面的流程。

1. 场景需求

客户是一家互联网医疗平台,需要一个智能咨询AI,能解答用户的常见健康问题,比如症状咨询、用药指导、健康管理建议,要求回答准确、专业,符合医疗规范。

2. 数据集准备

我们用了ModelScope上的medical-o1-reasoning-SFT数据集,包含25371条医疗问答和推理过程数据,质量很高。然后根据客户的业务需求,补充了1000条常见疾病咨询数据,用之前的预处理代码格式化为ShareGPT格式:

python 复制代码
import json
from tqdm import tqdm

# 加载原始医疗数据集
with open('medical_o1_sft_Chinese.json', 'r', encoding='utf-8') as f:
    data = json.load(f)

# 格式化为ShareGPT格式
output_data = []
for item in tqdm(data):
    conversation = {
        "conversations": [
            {"from": "human", "value": item["Question"]},
            {"from": "gpt", "value": f"[{item['Complex_CoT']}] {item['Response']}"}
        ],
        "system": "您是一位专业的医疗咨询顾问,需基于医学常识和临床规范,为用户提供准确、安全的健康建议。回答需通俗易懂,避免使用过于专业的术语,同时提醒用户严重疾病需及时就医。"
    }
    output_data.append(conversation)

# 保存数据集
with open('medical_dataset.json', 'w', encoding='utf-8') as f:
    json.dump(output_data, f, ensure_ascii=False, indent=2)
3. 微调优化

考虑到医疗场景的专业性,我们做了三个优化:

  • 调整LoRA参数:将r值调到96,提升模型学习能力;
  • 增加训练轮数:训练4轮,确保模型充分学习医疗知识;
  • 加入系统提示词:在数据集中加入系统提示,规范模型的回答风格。
4. 效果对比

微调前后的效果差异非常明显:

  • 微调前:用户问"感冒发烧38.5度该怎么办",模型回答笼统,没有区分成人和儿童,也没有提到用药剂量;
  • 微调后:模型会明确区分成人和儿童用药,提醒"儿童可服用对乙酰氨基酚混悬液,按年龄和体重给药,具体剂量参考药品说明书",还会补充"若发烧持续3天以上或伴随咳嗽、呕吐等症状,需及时就医"。

这个案例后来上线后,用户咨询满意度提升了40%,客服压力减少了60%,充分说明微调在垂直场景的价值。

五、常见问题排查:新手必看的避坑指南

很多人在微调过程中会遇到各种问题,这里整理了几个最常见的坑和解决方案,帮大家少走弯路:

  1. 显存不足(最常见)
  • 解决方案1:降低batch size,比如从4改成2;
  • 解决方案2:启用梯度累积,设置gradient_accumulation_steps=4;
  • 解决方案3:使用4-bit量化加载模型,就是我们前面代码里的bnb_config;
  • 解决方案4:换用更小参数的模型,比如从7B改成4B。
  1. 训练loss不下降
  • 原因:数据质量差、学习率不合适、训练轮数不够;
  • 解决方案1:检查数据集,去除重复、无效数据,增加高质量样本;
  • 解决方案2:调整学习率,比如从2e-4改成1e-4;
  • 解决方案3:增加训练轮数,或减少dropout率。
  1. 模型回答重复或逻辑混乱
  • 原因:数据集存在重复样本、训练轮数过多导致过拟合;
  • 解决方案1:去重数据集,确保样本多样性;
  • 解决方案2:减少训练轮数,或增加dropout率;
  • 解决方案3:调整temperature参数,测试时设置为0.5-0.7。
  1. 部署后响应速度慢
  • 解决方案1:使用GPU部署,或启用TensorRT加速;
  • 解决方案2:降低模型参数,比如用4B模型替代7B;
  • 解决方案3:优化batch size,批量处理请求。

六、总结:微调是垂直场景落地的核心竞争力

现在AI技术越来越普及,直接调用API已经很难形成差异化优势。而微调能让开源模型快速适配你的业务场景,打造专属AI助手,这才是AI落地的核心竞争力。

通过本文的实战教程,相信大家已经掌握了DeepSeek微调的全流程:从环境搭建到数据集准备,再到训练部署,每一步都有详细的代码和说明,即使是新手也能跟着做。记住,微调不是玄学,关键在于数据质量和参数调整,多尝试几次就能找到最优方案。

最后再跟大家强调一下:虽然不懂AI基础知识也能开发AI应用,但是懂的人往往可以开发出更复杂更优秀的AI高级应用。如果你对AI基础知识感兴趣,可以看看我的人工智能入门教程https://blog.csdn.net/jiangjunshow。打好基础后,不管是微调还是更复杂的AI开发,你都能游刃有余。

如果在实操过程中遇到问题,欢迎在评论区留言,我会一一解答。也欢迎大家分享自己的微调案例,一起交流进步!祝大家都能顺利实现AI落地,在垂直场景打造出属于自己的差异化竞争力!

相关推荐
Baihai_IDP17 小时前
Andrej Karpathy:2025 年 LLM 领域的六项范式转变
人工智能·面试·llm
踩着两条虫17 小时前
VTJ.PRO「AI + 低代码」应用开发平台的后端模块系统
前端·人工智能·低代码
一个会的不多的人17 小时前
人工智能基础篇:概念性名词浅谈(第二十二讲)
人工智能·制造·数字化转型
极新17 小时前
新看点/818AI创始人冷煜:AI落地,决胜“最后100米” | 2025极新AIGC峰会演讲实录
大数据·人工智能
环黄金线HHJX.17 小时前
《QuantumTuan ⇆ QT:Qt》
人工智能·qt·算法·编辑器·量子计算
用户51914958484517 小时前
Docker Buildx:构建容器镜像的瑞士军刀
人工智能·aigc
zl_vslam17 小时前
SLAM中的非线性优-3D图优化之地平面约束(十五)
人工智能·算法·计算机视觉·3d
移远通信17 小时前
移远通信×古月居:AI算力模组加持,OriginMan机器人焕新升级
人工智能·ai·机器人·移远通信
彼岸花开了吗17 小时前
构建AI智能体:七十八、参数的艺术:如何在有限算力下实现高质量的AI诗歌创作
人工智能·python·llm