《大模型应用实战:从0到1教你开发 “小说续写 + 风格迁移” 工具(Llama 3+StyleGAN)》
第一部分:启航 - 我们的创造之旅
1.1 开场白:当文字拥有“灵魂”,当想象可以“看见”
你好,欢迎来到这里!
你是否也曾有过这样的瞬间:深夜里,灵感如泉涌,你在文档上敲下了一个引人入胜的开头,一个剑客在雨夜的酒馆里擦拭着他的剑,或是一艘飞船跃迁至陌生的星系。但写着写着,思路却突然卡住,仿佛前方被一团浓雾笼罩。
又或者,当你描绘出一个瑰丽奇绝的世界时,你是否也曾幻想,如果能有一位画师,能精准地捕捉你的思绪,将那些只存在于脑海中的光影、建筑和人物,真实地呈现在眼前,那该是何等激动人心的体验?
在过去,这两者之间的鸿沟——从灵感枯竭到文思泉涌,从文字描述到视觉呈现——需要大量的努力,甚至是天赋,才能跨越。但今天,我们正处在一个激动人心的技术变革时代。人工智能,特别是大模型的崛起,给了我们普通人一把钥匙,一把开启无限创造力大门的钥匙。
本篇博客,以及后续的系列文章,就是为了带你亲手打造这把钥匙。我们将要创造的,不仅仅是一个简单的“玩具”或“Demo”,而是一个真正实用的“灵感放大器”。它能理解你故事的开头,用合乎逻辑且充满创意的方式为你续写后续章节;更神奇的是,它还能读懂新章节的场景,自动为你生成一幅风格独特的插画,让你的文字世界跃然纸上。
通过这个项目,你将学到的远不止是几行代码:
- 端到端的项目思维:你将体验一个AI应用从概念构思、技术选型、架构设计,到分步实现、最终整合的全过程。这比零散地学习某个API要有价值得多。
- 两大核心AI模型的协同作战:你将掌握当今最火热的两种模型——大语言模型(LLM,我们用Llama 3)和文生图模型(我们用Stable Diffusion)——如何“对话”和“协作”,完成复杂的创意任务。
- 真正有用的实战技能:从环境配置、代码组织,到最重要的“提示词工程”(Prompt Engineering),你将获得一套可以迁移到其他AI项目中的实战经验。
最重要的是,这个教程是为像你一样的“探索者”准备的——也许你对AI充满好奇,但对复杂的代码和算法感到畏惧;也许你有一些理论知识,但缺乏一个能将它们串联起来的实战项目。别担心,我会像一个向导,牵着你的手,从创建第一个文件夹开始,解释每一行代码背后的“为什么”,让你不仅知其然,更知其所以然。
准备好了吗?让我们一起启程,将想象力化为现实,创造一个真正属于你自己的、能让文字“活”起来的神奇工具。
1.2 项目蓝图:我们的工具如何工作?
在动手之前,我们首先要像一位建筑师那样,画出设计蓝图。理解了整体结构,后续的每一块“砖”才知道应该砌在哪里。
我们的工具,其核心逻辑非常清晰,可以用下面这张流程图来概括:
graph TD
A[用户输入: 小说开头 + 选择风格] --> B{前端交互界面 (Gradio)};
B --> C[后端处理逻辑];
C --> D[第一步: Llama 3 小说续写];
D -- 生成的完整章节 --> C;
C --> E[第二步: Llama 3 提取场景关键词];
E -- 提炼出的绘画关键词 --> C;
C --> F[第三步: Stable Diffusion 生成插画];
F -- 生成的图片 --> B;
D -- 生成的完整章节 --> B;
B --> G[输出: 图文并茂的小说章节];
subgraph "AI核心引擎"
D
E
F
end
subgraph "应用层"
A
B
C
G
end
让我们用大白话来解读一下这张图:
- 用户输入 (A):旅程的起点。用户在我们提供的网页界面上,输入一段故事的开头,比如“残阳如血,长河落日,独孤剑客站在悬崖边上,身后是万丈深渊。” 同时,从一个下拉菜单中选择想要的风格,比如“古风”。
- 前端界面 (B):这是我们工具的“脸面”,用户直接与之交互。我们选用Gradio来构建,因为它非常简单,能让我们专注于核心功能而非繁琐的前端开发。
- 后端处理逻辑 ©:这是我们应用的“大脑中枢”。它接收到前端传来的数据后,会像一个总指挥,按顺序调用各个AI模型去完成任务。
- Llama 3 小说续写 (D):总指挥发出的第一个指令。它将用户的开头和选择的风格,打包成一个精巧的“提示”(Prompt),发送给Llama 3。Llama 3会像一位博学的作家,续写出一段精彩的后续。
- Llama 3 提取关键词 (E):总指挥发出第二个指令。它将刚刚生成的一整段小说,再次发送给Llama 3,但这次给它的任务不同:“请把这段文字里最适合画成画的场景,用几个关键词描述出来”。Llama 3会切换成一个“艺术总监”的角色,输出类似“悬崖,落日,剑客,背影,孤寂感”这样的关键词。
- Stable Diffusion 生成插画 (F):总指挥发出最后的指令。它将“艺术总监”提炼的关键词,和用户最初选择的“古风”风格指令结合起来,交给“天才画师”Stable Diffusion。画师挥动神奇的画笔,将这些关键词变成一幅具体的图像。
- 最终输出 (G):所有任务完成。续写好的文字和生成好的插画被送回前端界面,一同呈现在用户面前。一次“文字到图文”的创作之旅就此完成。
一个重要的说明:细心的读者可能注意到了,我们的标题里写的是StyleGAN,但流程图里用的是Stable Diffusion。这是一个特意的选择。StyleGAN是生成对抗网络(GAN)的杰出代表,在特定领域(如人脸生成)图像的风格化和质量上非常惊艳。但对于我们这个需要根据任意文字描述来生成多样化场景的项目来说,基于扩散(Diffusion)模型的Stable Diffusion是目前更通用、更灵活、社区支持也更广泛的选择。它天生就擅长理解文本“咒语”来作画。我们沿用StyleGAN的概念,是为了强调“风格化生成”这一核心玩法,但在实践中,我们会选择最合适的工具来实现它。
1.3 技术选型:为什么是它们?
蓝图已经清晰,现在我们需要为这座建筑挑选最合适的建材。
-
主角一:Llama 3 (Meta AI)
- 它是什么:当今世界最顶尖的开源大语言模型之一。你可以把它想象成一个拥有海量知识、精通语言艺术的“超级大脑”。
- 为什么选它:
- 性能强大:在文本创作、逻辑推理和指令遵循方面都表现卓越,能胜任“小说家”和“艺术总监”的双重角色。
- 完全开源:意味着我们可以免费使用,甚至在合规的情况下进行微调和商业化,拥有极高的自由度。
- 社区活跃:有海量的开发者在研究和优化它,我们可以轻松找到各种量化压缩版本,大大降低对硬件(尤其是显存)的要求,让项目能在更多人的电脑上跑起来。
-
主角二:Stable Diffusion (Stability AI)
- 它是什么:一个革命性的文生图模型,能将文字描述转化为高质量的图像。它是AI绘画领域的事实标准之一。
- 为什么选它:
- 开源且强大:与Llama 3一样,它也是开源的,让我们的项目不必依赖任何付费API。
- 强大的可控性:通过精确的提示词(Prompt),我们可以很大程度上控制画面的内容、风格、构图。
- 生态极度丰富:拥有海量的社区微调模型(Checkpoints)、风格化模型(LoRA),可以轻松实现从水墨画到赛博朋克、从二次元到写实照片的万千变化,完美契合我们“风格迁移”的需求。
-
开发语言与核心框架:
- Python:无需多言,它是数据科学和AI领域的“官方语言”,几乎所有的主流框架都提供最优先的Python支持。
- Hugging Face (
transformers,diffusers): 如果说Llama 3和Stable Diffusion是两匹千里马,那Hugging Face提供的库就是最好的“马鞍”和“缰绳”。它将复杂的模型加载、推理过程封装得极其优雅简洁,让我们能用几行代码就驾驭这些强大的AI模型。 - Gradio:一个神奇的Python库。你不需要懂HTML、CSS、JavaScript,只需要定义好输入和输出,它就能自动为你生成一个功能完备、简洁美观的Web界面,用于测试和分享你的AI应用。对于我们这种希望快速验证核心功能的项目来说,是绝佳的选择。
第二部分:奠基 - 搭建我们的开发环境
理论的蓝图再完美,也需要坚实的地基来承载。在编程世界里,这个地基就是我们的开发环境。一个干净、稳定、配置正确的环境,能避免未来90%的奇怪问题。请跟随我的脚步,我们将一步步完成所有准备工作。
2.1 “开辟一方净土”:创建虚拟环境
在开始安装任何东西之前,我们要先学会一个专业开发者必备的技能:使用虚拟环境。
-
为什么需要?
想象一下你的电脑是你的家,你要做好几个项目:项目A是个木工活,需要锤子和钉子;项目B是个烹饪活,需要锅和铲子。如果你把所有工具都扔在客厅里,很快就会乱作一团,甚至可能拿错工具。虚拟环境,就相当于为每个项目单独创建一个“工具房”(比如木工房、厨房)。项目A的工具放在木工房,项目B的工具放在厨房,它们互不干扰,清晰明了。在Python中,这些“工具”就是我们需要的各种第三方库。虚拟环境能确保我们为“小说生成器”项目安装的库,不会与你电脑上其他Python项目(甚至系统自带的Python)的库产生冲突。 -
手把手操作
-
首先,在你的电脑上找一个你喜欢的位置,创建一个新的文件夹来存放我们整个项目。比如,我叫它
novel_ai_tool。 -
打开你的终端(Terminal)或者命令提示符(Command Prompt)。如果你是Windows用户,可以在开始菜单搜索“cmd”或“PowerShell”;如果你是macOS或Linux用户,它通常叫做“终端”或“Terminal”。
-
使用
cd命令进入你刚刚创建的项目文件夹:# 将 "your/path/to/novel_ai_tool" 替换成你自己的实际路径 cd your/path/to/novel_ai_tool -
现在,我们来创建虚拟环境。我们把它命名为
venv(这是社区的通用惯例)。运行以下命令:python -m venv venv这个命令的意思是:“嘿,Python,请使用你的
venv模块,帮我创建一个名为venv的虚拟环境。”执行完毕后,你会发现项目文件夹里多了一个名为venv的子文件夹。那里就存放着一个独立的Python解释器和未来我们将要安装的所有库。 -
最后,也是最关键的一步:激活这个虚拟环境。每次你要在这个项目上工作时,都需要先激活它。
- 在 Windows 上:
venv\Scripts\activate - 在 macOS 或 Linux 上:
source venv/bin/activate
当你看到终端命令行的前面出现了
(venv)的字样,恭喜你,你已经成功进入了我们为项目开辟的这片“净土”! - 在 Windows 上:
-
2.2 “招兵买马”:安装核心依赖库
环境已经激活,现在我们可以安全地安装项目所需的“精兵强将”了。我们把所有需要安装的库放在一个命令里,一次性搞定。
在你的终端(确保 (venv) 前缀存在)中,复制并粘贴以下命令,然后回车:
pip install torch transformers accelerate bitsandbytes diffusers gradio
这行命令会通过 pip(Python的包管理器)下载并安装所有必要的库。让我们逐一认识一下这些新招募的“成员”:
torch: 它是几乎所有主流深度学习框架的底层核心,提供了张量计算(可以理解为处理数据的多维数组)和GPU加速等基础功能。它是我们AI模型的“发动机”。transformers: 由Hugging Face公司开发的神器。它让我们能够以极简的方式下载、加载和使用像Llama 3这样的语言模型。它是驾驭“语言模型”这匹千里马的“缰绳”。accelerate: 同样来自Hugging Face,transformers的好搭档,能帮助我们更轻松地在不同硬件(CPU, GPU, 多GPU)上高效运行模型,实现加速。bitsandbytes: 一位“内存魔法师”。它实现了模型量化的关键算法,能将庞大的模型(动辄几十GB)压缩到普通消费级显卡(如8GB显存)也能容纳的大小,是实现大模型“平民化”的关键。diffusers: 还是来自Hugging Face!它是专门用于操作Stable Diffusion这类扩散模型的“遥控器”,让我们能方便地进行文生图操作。gradio: 我们的“前端UI设计师”。只需几行Python代码,它就能为我们的程序构建一个可交互的网页界面,极大降低了应用展示的门槛。
安装过程可能需要一些时间,具体取决于你的网络速度。请耐心等待它完成。
2.3 “请神入位”:下载预训练模型
我们的代码需要调用Llama 3和Stable Diffusion模型才能工作。这些模型体积巨大,由Meta和Stability AI等公司花费巨大成本训练而成。我们要做的是“站在巨人的肩膀上”,直接使用他们训练好的“预训练模型”。
你可能会问:“我们需要现在就去手动下载这些几十GB的文件吗?”
答案是:不需要!
这正是Hugging Face框架的优雅之处。当我们后续编写代码,第一次尝试加载某个模型时,transformers和diffusers库会自动从Hugging Face的官方模型仓库(Hugging Face Hub,可以理解为AI界的GitHub)检查本地缓存。如果发现模型不在,它会自动下载并缓存到本地。
这意味着我们只需要在代码中指定模型的ID(比如 meta-llama/Meta-Llama-3-8B-Instruct),剩下的事情框架会为我们打理好。这个过程是全自动的,我们只需在首次运行时,耐心等待模型下载完成即可。
至此,我们的地基已经完全打好。一个干净的虚拟环境、所有必需的库、以及自动化的模型下载机制都已就位。下一章,我们将正式开始添砖加瓦,编写核心代码。
第三部分:构筑 - 逐行代码实现核心功能
万事俱备,只欠代码。现在,我们将进入最激动人心的编码阶段。为了让项目结构清晰,我们将把不同功能的代码拆分到不同的文件中,最后再用一个主文件将它们“组装”起来。
请在你的项目文件夹 novel_ai_tool 中,创建以下四个空的 .py 文件:
novel_generator.py(负责小说续写)keyword_extractor.py(负责提取绘画关键词)image_generator.py(负责生成插画)app.py(负责整合所有功能并启动UI界面)
3.1 核心模块一:小说续写器 (novel_generator.py)
这是我们系统的“文学家”。它接收故事开头和风格指令,输出续写的内容。
打开 novel_generator.py 文件,输入以下代码:
# novel_generator.py
import torch
from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline
# 定义我们将使用的模型ID。这里我们选用Llama-3 8B的指令微调版本
MODEL_ID = "meta-llama/Meta-Llama-3-8B-Instruct"
# 加载分词器(Tokenizer),它负责将文本转换成模型能理解的数字ID
tokenizer = AutoTokenizer.from_pretrained(MODEL_ID)
# 加载模型本身
# torch_dtype="auto" 会自动使用最高效的数据类型(如bfloat16)
# device_map="auto" 会自动将模型分配到可用的硬件上(优先使用GPU)
model = AutoModelForCausalLM.from_pretrained(
MODEL_ID,
torch_dtype="auto",
device_map="auto"
)
# 使用Hugging Face的pipeline,可以更方便地处理文本生成任务
# 这比手动构建prompt和调用model.generate更简洁
pipe = pipeline(
"text-generation",
model=model,
tokenizer=tokenizer,
)
def continue_story(prompt: str, style_prompt: str) -> str:
"""
根据用户输入和风格提示,续写小说。
Args:
prompt (str): 用户输入的小说开头。
style_prompt (str): 定义小说风格和AI角色的系统提示。
Returns:
str: AI生成的续写内容。
"""
print("开始续写小说...")
# Llama 3的官方聊天模板格式
# 我们将系统提示、用户输入包装在这个模板中
messages = [
{"role": "system", "content": style_prompt},
{"role": "user", "content": prompt},
]
# pipeline的参数
# max_new_tokens: 控制生成文本的最大长度
# do_sample=True: 启用采样,让生成结果更多样
# temperature: 控制随机性,值越小越保守,越大越有创意
# top_p: 核采样,与temperature类似,用于控制生成的多样性
terminators = [
pipe.tokenizer.eos_token_id,
pipe.tokenizer.convert_tokens_to_ids("<|eot_id|>")
]
outputs = pipe(
messages,
max_new_tokens=512,
eos_token_id=terminators,
do_sample=True,
temperature=0.7,
top_p=0.9,
)
# 提取并返回生成的文本
generated_text = outputs[0]["generated_text"][-1]['content']
print("小说续写完成。")
return generated_text
# --- 这是一个简单的测试代码块 ---
if __name__ == '__main__':
test_prompt = "在一个名为‘艾德瑞安’的魔法王国,失落的‘星辰之冠’传说再次被提起。年轻的寻宝猎人凯尔,在酒馆的角落里,从一位神秘老人的口中听到了这个传说的片段:"
test_style = "你是一位知识渊博、文笔优美的奇幻小说家。请以第三人称视角,续写下面的故事。要求文笔流畅,富有想象力,并营造出一种史诗感的氛围。"
continued = continue_story(test_prompt, test_style)
print("\n--- 续写结果 ---")
print(continued)
代码精讲:
- 我们首先指定了
MODEL_ID。transformers库会根据这个ID去Hugging Face Hub下载模型。 AutoTokenizer和AutoModelForCausalLM是两个“智能加载器”,能自动识别并加载与模型ID匹配的分词器和模型架构。device_map="auto"是一个非常重要的参数,它让Hugging Face自动处理硬件分配。如果你有可用的NVIDIA显卡且CUDA环境配置正确,它会自动把模型加载到显存中,速度会快非常多。pipeline是一个高级封装,它简化了从输入到输出的整个流程。- 在
continue_story函数中,我们使用了messages列表来构建对话。这是与指令微调模型(如Llama 3 Instruct)交互的标准方式。role: "system"的部分用来设定AI的身份和行为准则,而role: "user"则用来传递用户的直接指令。 model.generate()的参数决定了生成文本的“性格”。max_new_tokens限制了长度,temperature和top_p则共同控制着生成内容的创造性和多样性。- 代码末尾的
if __name__ == '__main__':是一个Python的惯例,表示这部分代码只有在直接运行此文件时才会执行,方便我们单独测试这个模块的功能。
3.2 核心模块二:场景关键词提取器 (keyword_extractor.py)
现在,我们需要一个“艺术总监”,它能阅读小说章节,并提炼出最核心的画面元素。有趣的是,这个角色我们依然可以请Llama 3来扮演,只是需要给它下达不同的指令。
打开 keyword_extractor.py 文件,输入以下代码:
# keyword_extractor.py
import torch
from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline
# 复用与小说生成器相同的模型,无需重复加载
# 注意:在实际应用中,我们会将模型加载部分抽离成公共模块
# 但为了教学清晰,这里我们暂时保持文件独立
MODEL_ID = "meta-llama/Meta-Llama-3-8B-Instruct"
tokenizer = AutoTokenizer.from_pretrained(MODEL_ID)
model = AutoModelForCausalLM.from_pretrained(
MODEL_ID,
torch_dtype="auto",
device_map="auto"
)
pipe = pipeline(
"text-generation",
model=model,
tokenizer=tokenizer,
)
# 这是我们为“艺术总监”AI设计的系统提示,非常关键!
KEYWORD_SYSTEM_PROMPT = """
你是一个专业的插画概念艺术家。你的任务是阅读一段小说文本,然后提取出最适合用于AI绘画的核心视觉关键词。
请遵循以下规则:
1. 输出格式为英文,以逗号分隔。
2. 关键词应描述画面的核心主体、场景环境、氛围光照和构图。
3. 优先使用能产生强烈视觉效果的词语。
4. 忽略对话和心理活动,只关注物理上可被描绘的元素。
5. 关键词总数控制在20个以内。
例如,对于文本“骑士在暴风雨的悬崖上,高举着闪电环绕的圣剑,眼神坚毅”,你应该提取出:“1man, knight, holding a sword, lightning sword, standing on cliff, storm, heavy rain, dramatic lighting, determined expression, cinematic angle”。
"""
def extract_keywords(story_text: str) -> str:
"""
从小说文本中提取用于AI绘画的关键词。
Args:
story_text (str): 一段小说章节内容。
Returns:
str: 英文的、逗号分隔的关键词字符串。
"""
print("开始提取关键词...")
messages = [
{"role": "system", "content": KEYWORD_SYSTEM_PROMPT},
{"role": "user", "content": story_text},
]
terminators = [
pipe.tokenizer.eos_token_id,
pipe.tokenizer.convert_tokens_to_ids("<|eot_id|>")
]
outputs = pipe(
messages,
max_new_tokens=100, # 关键词不需要太长
eos_token_id=terminators,
do_sample=False, # 提取任务需要确定性,关闭采样
)
keywords = outputs[0]["generated_text"][-1]['content'].strip()
print(f"关键词提取完成: {keywords}")
return keywords
# --- 测试代码块 ---
if __name__ == '__main__':
test_story = "凯尔穿过喧闹的人群,来到吧台前。酒馆里灯光昏暗,空气中弥漫着麦酒和湿木头的味道。窗外,暴雨倾盆,一道闪电划破夜空,瞬间照亮了酒馆里龙蛇混杂的面孔。"
extracted_keywords = extract_keywords(test_story)
print("\n--- 提取结果 ---")
print(extracted_keywords)
代码精讲:
- 代码结构与
novel_generator.py几乎一样,因为我们复用了同一个模型。 - 核心区别在于
KEYWORD_SYSTEM_PROMPT。这个提示词(Prompt)是本模块的灵魂。我们通过它,将Llama 3的角色从“小说家”转变为“概念艺术家”。我们明确地给出了任务、输出格式、规则和示例(Few-shot learning),这极大地提高了Llama 3输出结果的稳定性和可用性。这就是“提示词工程”的威力。 - 在调用
pipe时,我们设置do_sample=False。因为提取关键词是一个相对确定的任务,我们不希望它有太多随机发挥,而是希望它每次都给出最符合逻辑的结果。
3.3 核心模块三:风格插画师 (image_generator.py)
现在,轮到我们的“天才画师”Stable Diffusion登场了。它将接收关键词和风格指令,创作出最终的插画。
打开 image_generator.py 文件,输入以下代码:
# image_generator.py
import torch
from diffusers import DiffusionPipeline
# 这里我们选用Stable Diffusion 1.5版本,它是一个经典且效果很好的模型
IMAGE_MODEL_ID = "runwayml/stable-diffusion-v1-5"
# 加载文生图的pipeline
# torch_dtype=torch.float16 是为了在GPU上使用半精度浮点数,可以节省显存并加速
# use_safetensors=True 是为了更安全地加载模型权重
pipe = DiffusionPipeline.from_pretrained(
IMAGE_MODEL_ID,
torch_dtype=torch.float16,
use_safetensors=True
)
# 将pipeline移动到GPU上
pipe = pipe.to("cuda")
# 通用的、提升画面质量的正面提示词
GENERAL_QUALITY_PROMPT = ", masterpiece, best quality, highres, cinematic lighting, intricate details"
# 通用的负面提示词,用于避免常见的生成缺陷
GENERAL_NEGATIVE_PROMPT = "worst quality, low quality, normal quality, lowres, simple background, blurry, text, watermark, signature, username, artist name, deformed, mutilated, poorly drawn hands, malformed limbs"
def generate_image(keywords: str, style_keywords: str) -> object:
"""
根据关键词和风格,生成一张插画。
Args:
keywords (str): 从小说中提取的核心画面关键词。
style_keywords (str): 代表特定艺术风格的关键词。
Returns:
object: PIL.Image 对象,可以直接显示或保存。
"""
print("开始生成插画...")
# 将核心关键词、风格关键词和通用质量词组合成最终的正面提示
full_prompt = f"{keywords}, {style_keywords}{GENERAL_QUALITY_PROMPT}"
# 使用pipeline生成图片
# num_inference_steps 控制去噪步数,步数太少细节不足,太多则边际效益递减
# guidance_scale 控制提示词与生成图像的符合程度,值越高越贴近提示,但可能越死板
image = pipe(
prompt=full_prompt,
negative_prompt=GENERAL_NEGATIVE_PROMPT,
num_inference_steps=30,
guidance_scale=7.5
).images[0]
print("插画生成完成。")
return image
# --- 测试代码块 ---
if __name__ == '__main__':
test_keywords = "1man, knight, tavern, dim light, cinematic, rain outside window, moody"
test_style = "fantasy art, oil painting, by Greg Rutkowski" # 一种常见的奇幻艺术风格
generated_img = generate_image(test_keywords, test_style)
# 保存图片到本地以便查看
generated_img.save("test_generated_image.png")
print("测试图片已保存为 test_generated_image.png")
代码精讲:
- 我们这次使用
diffusers库和DiffusionPipeline来加载Stable Diffusion模型。 .to("cuda")明确告诉程序将模型放在GPU上运行。文生图是计算密集型任务,几乎必须使用GPU。- Prompt的艺术:我们定义了通用的“正面质量词”和“负面词”。这是AI绘画的常用技巧,相当于告诉模型:“请画出最好的效果,并避免那些常见的错误”。
- 在
generate_image函数中,我们将所有提示词(内容、风格、质量)“拼接”成一个最终的full_prompt。这给了模型最全面的指令。 pipe()的参数,如num_inference_steps和guidance_scale,是影响生成速度和质量的关键。你可以尝试调整这些值,看看会对结果产生什么影响。- 调用
pipe()后返回的是一个包含多张图片的列表(默认是1张),所以我们用.images[0]来获取第一张图片。
3.4 最终整合:打造交互式应用 (app.py)
所有核心模块都已就绪,现在是时候将它们组装起来,并为它们穿上一件漂亮的外衣了。
打开 app.py 文件,输入以下代码:
# app.py
import gradio as gr
from novel_generator import continue_story
from keyword_extractor import extract_keywords
from image_generator import generate_image
# --- 1. 定义不同风格的Prompt模板 ---
# 这是我们将要提供给用户选择的风格
style_templates = {
"奇幻史诗": {
"style_prompt": "你是一位知识渊博、文笔优美的奇幻小说家。请以第三人称视角,续写下面的故事。要求文笔流畅,富有想象力,并营造出一种史诗感的氛围。",
"image_style_keywords": "epic fantasy art, cinematic, dramatic, digital painting, masterpiece, by Artgerm and Greg Rutkowski"
},
"赛博朋克": {
"style_prompt": "你是一位冷峻、锐利的赛博朋克故事作家。请以第三人称视角,续写下面的故事。语言要简洁、有力,充满科技感和宿命感,描绘一个霓虹闪烁、技术与腐朽并存的未来都市。",
"image_style_keywords": "cyberpunk, futuristic city, neon lights, holographic displays, blade runner style, cinematic, detailed, by Syd Mead"
},
"东方志怪": {
"style_prompt": "你是一位精通古代志怪小说的说书人。请以第三人称视角,续写下面的故事。文风需带有古典韵味,多用场景和氛围描写,营造出一种神秘、诡谲的东方恐怖氛围。",
"image_style_keywords": "chinese mythology, dark fantasy, ink wash painting style, horror, mysterious, by Zdzisław Beksiński and Guweiz"
}
}
# --- 2. 定义核心处理函数 ---
def generate_novel_and_image(text_prompt, style_name):
"""
接收用户输入,完整地执行“续写->提取->绘画”流程。
"""
if not text_prompt or not style_name:
return "请输入小说开头并选择一种风格。", None
print(f"接收到任务: 风格={style_name}")
# 从模板中获取对应的Prompt
selected_style = style_templates[style_name]
style_prompt = selected_style["style_prompt"]
image_style_keywords = selected_style["image_style_keywords"]
# 第一步:续写小说
# 我们将用户输入和续写内容拼接起来
continued_text = continue_story(text_prompt, style_prompt)
full_story = text_prompt + "\n\n" + continued_text
# 第二步:从续写的新内容中提取关键词
# 注意:我们只对新生成的部分提取关键词,这样更聚焦
keywords = extract_keywords(continued_text)
# 第三步:生成插画
generated_image = generate_image(keywords, image_style_keywords)
# 返回最终结果
return full_story, generated_image
# --- 3. 搭建Gradio界面 ---
with gr.Blocks(theme=gr.themes.Soft()) as app:
gr.Markdown("# AI小说续写 & 插画生成器")
gr.Markdown("输入一个故事的开头,选择你喜欢的风格,然后让AI为你续写故事并生成一幅插画。")
with gr.Row():
with gr.Column(scale=1):
text_prompt = gr.Textbox(label="小说开头", lines=5, placeholder="例如:在一个名为‘艾德瑞安’的魔法王国...")
style_dropdown = gr.Dropdown(label="选择风格", choices=list(style_templates.keys()))
submit_btn = gr.Button("开始创作", variant="primary")
with gr.Column(scale=2):
output_text = gr.Textbox(label="生成的故事章节", lines=20)
output_image = gr.Image(label="生成的插画")
# 绑定按钮的点击事件到我们的核心处理函数
submit_btn.click(
fn=generate_novel_and_image,
inputs=[text_prompt, style_dropdown],
outputs=[output_text, output_image]
)
# --- 4. 启动应用 ---
if __name__ == "__main__":
# share=True 会生成一个公网链接,方便你分享给朋友体验(有效期72小时)
app.launch(share=True)
代码精讲:
- Prompt模板库:我们首先定义了一个字典
style_templates。这是我们实现“风格切换”功能的核心。它将用户在界面上选择的“奇幻史诗”等名字,映射到背后真正驱动AI的、精心设计的style_prompt(给Llama 3)和image_style_keywords(给Stable Diffusion)。 - 核心处理函数:
generate_novel_and_image函数是整个应用的“总指挥”。它接收前端传来的输入,按顺序调用我们之前写好的三个模块的函数,最后将结果返回。 - Gradio界面:
gr.Blocks提供了一种更灵活的界面布局方式。我们用gr.Row和gr.Column搭建了一个左侧输入、右侧输出的经典布局。gr.Textbox,gr.Dropdown,gr.Button,gr.Image等都是Gradio提供的现成组件。 - 事件绑定:最关键的一行是
submit_btn.click(...)。它告诉Gradio:“当这个按钮被点击时,请执行generate_novel_and_image函数,把text_prompt和style_dropdown的当前值作为输入,然后将函数的返回值更新到output_text和output_image组件上。” 这就完成了前后端的交互逻辑。 - 启动应用:
app.launch()会启动一个本地Web服务器。你会在终端看到一个类似http://127.0.0.1:7860的地址,在浏览器中打开它,就能看到并使用我们的应用了!share=True还会额外生成一个公网链接,你可以发给朋友,让他们也能玩你的应用。
现在,在你的终端中,确保你仍处于激活的虚拟环境 (venv) 下,运行我们的主程序:
python app.py
等待所有模型加载完毕(首次运行会比较慢,因为需要下载模型),然后打开浏览器访问终端里显示的URL。恭喜你,你的第一个端到端AI应用,已经成功运行起来了!
第四部分:升华 - 从“能用”到“好用”的艺术
程序跑起来只是第一步。要让AI的输出真正惊艳,我们需要掌握与它沟通的艺术——提示词工程(Prompt Engineering)。下面,我将为你揭示app.py中那些提示词模板背后的设计思路。
4.1 提示词工程的魔力
-
续写模块的提示词 (
style_prompt)
我们的目标是为Llama 3设定一个清晰的“角色扮演”指令。一个好的角色指令应该包含:- 身份定义:你是谁?(“一位奇幻小说家”、“一位赛博朋克作家”)
- 任务描述:你要做什么?(“续写下面的故事”)
- 风格要求:你的作品是什么样的?(“文笔流畅,富有想象力”、“语言简洁、有力,充满科技感”)
- 视角限定:叙事视角是什么?(“以第三人称视角”)
赛博朋克风格示例分析:
"你是一位冷峻、锐利的赛博朋克故事作家...语言要简洁、有力...描绘一个霓虹闪烁、技术与腐朽并存的未来都市。"
这里的“冷峻、锐利”、“简洁、有力”、“霓虹闪烁、技术与腐朽”等词,都是在为AI的“思维”和“文笔”上“Buff”,引导它生成符合该风格的词汇和叙事节奏。 -
绘画模块的提示词 (
image_style_keywords)
AI绘画的提示词更像是在“施法”,需要精确的“咒语”。一个好的绘画提示词通常由几个部分拼接而成:- 核心内容:这部分由
keyword_extractor自动生成,如1man, tavern, rain。 - 艺术风格:定义整体画风,如
cyberpunk,ink wash painting。 - 艺术家风格:模仿特定艺术家的风格能快速获得高质量结果,如
by Syd Mead(赛博朋克概念艺术大师),by Greg Rutkowski(知名奇幻画师)。这是一种非常高效的“风格迁移”技巧。 - 媒介/画种:指明是油画、数码绘画还是水墨画,如
oil painting,digital painting。 - 通用质量词:如
masterpiece, best quality, cinematic,这些是社区总结出的、能有效提升画面精度的“万金油”词汇。
东方志怪风格示例分析:
"chinese mythology, dark fantasy, ink wash painting style, horror, mysterious, by Zdzisław Beksiński and Guweiz"
这里,chinese mythology和ink wash painting style定下了基调,dark fantasy和horror注入了氛围,而融合两位风格迥异的艺术家——波兰的超现实主义恐怖大师Beksiński和中国的数字艺术家Guweiz——则可能催生出一种既有古典水墨意蕴,又充满现代暗黑幻想的独特视觉效果。 - 核心内容:这部分由
第五部分:尾声 - 你的征途是星辰大海
5.1 总结回顾
如果你一步步跟随教程走到了这里,那么请给自己一个大大的赞!我们一起完成了一段非凡的旅程:从一个模糊的想法开始,我们设计了应用的蓝图,搭建了坚实的开发环境,并用代码将语言模型和图像模型这两大强大的AI能力“焊接”在了一起,最终创造出一个能将文字转化为图文并茂故事的实用工具。
在这个过程中,你已经掌握了:
- 一个完整AI应用的开发全流程。
- 如何使用
transformers和diffusers库来驾驭 Llama 3 和 Stable Diffusion。 - 通过精巧的Prompt设计,让同一个AI模型扮演不同角色,完成复杂任务链。
- 使用
gradio快速构建可交互的AI应用原型。
1万+



被折叠的 条评论
为什么被折叠?



