lisonallen commited on
Commit
0cfce88
·
1 Parent(s): 5f71263

恢复AI图像生成功能,降级依赖以解决兼容性问题

Browse files
Files changed (2) hide show
  1. app.py +142 -138
  2. requirements.txt +6 -6
app.py CHANGED
@@ -12,7 +12,7 @@ logging.basicConfig(level=logging.INFO,
12
  stream=sys.stdout)
13
  logger = logging.getLogger(__name__)
14
 
15
- # 修复 Gradio JSON Schema 错误
16
  try:
17
  import gradio_client.utils
18
 
@@ -53,163 +53,170 @@ try:
53
  except Exception as e:
54
  logger.error(f"Failed to patch Gradio utils: {e}")
55
 
56
- # 创建一个简单的示例图像
57
- def create_dummy_image():
58
- logger.info("Creating dummy image")
59
- img = PILImage.new('RGB', (256, 256), color = (255, 100, 100))
60
- return img
61
-
62
- # 创建一个模拟图像生成器
63
- def create_mock_image(prompt):
64
- """当模型加载不成功时,创建一个带有提示词的简单图像"""
65
- logger.info(f"创建简单图像: {prompt}")
66
-
67
- # 创建一个基础图像
68
  img = PILImage.new('RGB', (512, 512), color=(240, 240, 250))
69
 
70
- # 在图像上写文字
71
  try:
72
  from PIL import ImageDraw, ImageFont
73
  draw = ImageDraw.Draw(img)
 
74
 
75
- # 尝试找一个合适的字体
76
- try:
77
- font = ImageFont.truetype("arial.ttf", 20)
78
- except:
79
- try:
80
- font = ImageFont.truetype("DejaVuSans.ttf", 20)
81
- except:
82
- font = ImageFont.load_default()
83
-
84
- # 添加提示文本
85
- text = f"提示词: {prompt}"
86
- draw.text((20, 20), text, fill=(0, 0, 0), font=font)
87
- draw.text((20, 60), "模型加载失败,显示占位图像", fill=(255, 0, 0), font=font)
88
 
89
  except Exception as e:
90
- logger.error(f"创建文字图像失败: {e}")
91
 
92
  return img
93
 
94
- # 使用简单的文本生成器
95
- def text_to_image(prompt):
96
- """一个非常简单的基于规则的文本到图像生成器"""
97
- logger.info(f"使用简单规则生成图像: {prompt}")
98
-
99
- # 创建基础图像
100
- img = PILImage.new('RGB', (512, 512), color=(240, 240, 250))
101
-
102
- # 尝试分析提示词内容
103
- color = (100, 100, 200) # 默认蓝色
104
-
105
- # 简单的颜色匹配
106
- color_words = {
107
- 'red': (200, 50, 50),
108
- 'blue': (50, 50, 200),
109
- 'green': (50, 200, 50),
110
- 'yellow': (200, 200, 50),
111
- 'purple': (150, 50, 150),
112
- 'orange': (220, 140, 20),
113
- 'pink': (255, 150, 200),
114
- 'black': (30, 30, 30),
115
- 'white': (240, 240, 240),
116
- 'gray': (128, 128, 128),
117
- }
118
-
119
- # 检查提示词中是否包含颜色
120
- prompt_lower = prompt.lower()
121
- for color_word, rgb in color_words.items():
122
- if color_word in prompt_lower:
123
- color = rgb
124
- break
125
-
126
- # 创建一个简单的图形
127
- from PIL import ImageDraw
128
- draw = ImageDraw.Draw(img)
129
-
130
- # 根据提示词选择不同的绘制方式
131
- if any(animal in prompt_lower for animal in ['cat', 'kitty', 'kitten']):
132
- # 画一个简单的猫
133
- draw.ellipse((156, 156, 356, 306), fill=color) # 头
134
- draw.ellipse((196, 176, 246, 226), fill=(255, 255, 255)) # 左眼
135
- draw.ellipse((266, 176, 316, 226), fill=(255, 255, 255)) # 右眼
136
- draw.ellipse((211, 191, 231, 211), fill=(0, 0, 0)) # 左眼球
137
- draw.ellipse((281, 191, 301, 211), fill=(0, 0, 0)) # 右眼球
138
- draw.polygon([(256, 256), (236, 246), (276, 246)], fill=(255, 100, 150)) # 鼻子
139
- draw.line([(256, 256), (256, 286)], fill=(0, 0, 0), width=2) # 鼻线
140
- draw.arc((206, 256, 306, 336), 0, 180, fill=(0, 0, 0), width=2) # 嘴
141
- # 猫耳朵
142
- draw.polygon([(206, 156), (156, 76), (246, 126)], fill=color)
143
- draw.polygon([(306, 156), (356, 76), (266, 126)], fill=color)
144
-
145
- elif any(landscape in prompt_lower for landscape in ['landscape', 'mountain', 'sunset', 'nature']):
146
- # 画一个简单的风景
147
- # 天空
148
- sky_color = (100, 150, 250)
149
- if 'sunset' in prompt_lower:
150
- sky_color = (250, 150, 100)
151
- draw.rectangle([(0, 0), (512, 300)], fill=sky_color)
152
-
153
- # 太阳/月亮
154
- if 'sunset' in prompt_lower or 'sun' in prompt_lower:
155
- draw.ellipse((400, 50, 480, 130), fill=(255, 200, 50))
156
- elif 'night' in prompt_lower or 'moon' in prompt_lower:
157
- draw.ellipse((400, 50, 480, 130), fill=(240, 240, 240))
158
-
159
- # 山
160
- draw.polygon([(0, 300), (200, 100), (400, 300)], fill=(100, 100, 100))
161
- draw.polygon([(100, 300), (300, 50), (500, 300)], fill=(80, 80, 80))
162
-
163
- # 地面
164
- ground_color = (100, 200, 100)
165
- if 'desert' in prompt_lower:
166
- ground_color = (240, 220, 180)
167
- elif 'snow' in prompt_lower or 'winter' in prompt_lower:
168
- ground_color = (240, 240, 250)
169
- draw.rectangle([(0, 300), (512, 512)], fill=ground_color)
170
-
171
- else:
172
- # 默认绘制一些简单的几何图形
173
- draw.rectangle([(106, 106), (406, 406)], outline=(0, 0, 0), width=2)
174
- draw.ellipse((156, 156, 356, 356), fill=color)
175
- draw.polygon([(256, 106), (406, 406), (106, 406)], fill=(color[0]//2, color[1]//2, color[2]//2))
176
 
177
- # 添加提示词文本
178
  try:
179
- font = ImageFont.load_default()
180
- draw.text((10, 10), f"提示词: {prompt}", fill=(0, 0, 0), font=font)
181
- draw.text((10, 30), "由简单规则生成", fill=(100, 100, 100), font=font)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
182
  except Exception as e:
183
- logger.error(f"添加文字失败: {e}")
 
 
 
 
 
 
 
 
 
184
 
185
- return img
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
186
 
187
- # 生成图像函数
188
  def generate_image(prompt):
189
- # 如果提示为空,使用默认提示
190
  if not prompt or prompt.strip() == "":
191
  prompt = "a beautiful landscape"
192
  logger.info(f"输入为空,使用默认提示词: {prompt}")
193
 
194
  logger.info(f"收到提示词: {prompt}")
195
 
196
- # 不再尝试加载AI模型,直接使用规则生成器
197
- logger.info("使用规则生成器代替AI模型")
198
- return text_to_image(prompt)
 
 
 
 
 
 
199
 
200
  # 创建Gradio界面
201
  def create_demo():
202
- # 创建界面
203
- demo = gr.Interface(
204
- fn=generate_image,
205
- inputs=gr.Textbox(label="输入提示词(例如:猫、风景、日落)"),
206
- outputs=gr.Image(type="pil", label="生成的图像"),
207
- title="简易文本到图像生成器",
208
- description="输入文本描述,生成相应的图像(使用规则生成器,不依赖AI模型)",
209
- examples=["a cute cat", "beautiful sunset", "mountain landscape", "red circle"],
210
- cache_examples=False,
211
- flagging_mode=None
212
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
213
  return demo
214
 
215
  # 创建演示界面
@@ -219,13 +226,10 @@ demo = create_demo()
219
  if __name__ == "__main__":
220
  try:
221
  logger.info("启动Gradio界面...")
222
- # 使用最小配置
223
  demo.launch(
224
- server_name="0.0.0.0",
225
- show_api=False, # 禁用API
226
- share=False, # 不创建公共链接
227
- debug=False, # 禁用调试模式
228
- quiet=True # 减少日志输出
229
  )
230
  except Exception as e:
231
  logger.error(f"启动失败: {e}")
 
12
  stream=sys.stdout)
13
  logger = logging.getLogger(__name__)
14
 
15
+ # 补丁修复 Gradio JSON Schema 错误
16
  try:
17
  import gradio_client.utils
18
 
 
53
  except Exception as e:
54
  logger.error(f"Failed to patch Gradio utils: {e}")
55
 
56
+ # 创建一个备用图像
57
+ def create_backup_image(prompt=""):
58
+ logger.info(f"创建备用图像: {prompt}")
 
 
 
 
 
 
 
 
 
59
  img = PILImage.new('RGB', (512, 512), color=(240, 240, 250))
60
 
 
61
  try:
62
  from PIL import ImageDraw, ImageFont
63
  draw = ImageDraw.Draw(img)
64
+ font = ImageFont.load_default()
65
 
66
+ draw.text((20, 20), f"提示词: {prompt}", fill=(0, 0, 0), font=font)
67
+ draw.text((20, 60), "模型加载失败,无法生成图像", fill=(255, 0, 0), font=font)
 
 
 
 
 
 
 
 
 
 
 
68
 
69
  except Exception as e:
70
+ logger.error(f"创建备用图像时出错: {e}")
71
 
72
  return img
73
 
74
+ # 预加载 AI 模型
75
+ model = None
76
+
77
+ def load_model():
78
+ global model
79
+ if model is not None:
80
+ return model
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81
 
 
82
  try:
83
+ logger.info("开始加载AI模型...")
84
+
85
+ # 延迟导入,确保所有依赖都已正确安装
86
+ import torch
87
+ from diffusers import StableDiffusionPipeline
88
+
89
+ # 使用较低版本的模型
90
+ model_id = "CompVis/stable-diffusion-v1-4"
91
+
92
+ # 设置加载参数
93
+ load_options = {
94
+ "revision": "fp16" if torch.cuda.is_available() else None,
95
+ "torch_dtype": torch.float16 if torch.cuda.is_available() else torch.float32,
96
+ "safety_checker": None
97
+ }
98
+
99
+ logger.info(f"使用模型: {model_id}")
100
+ pipe = StableDiffusionPipeline.from_pretrained(model_id, **load_options)
101
+
102
+ # 转移到适当的设备
103
+ device = "cuda" if torch.cuda.is_available() else "cpu"
104
+ pipe = pipe.to(device)
105
+
106
+ # 优化
107
+ if torch.cuda.is_available():
108
+ pipe.enable_attention_slicing()
109
+
110
+ logger.info("AI模型加载成功")
111
+ model = pipe
112
+ return model
113
  except Exception as e:
114
+ logger.error(f"AI模型加载失败: {e}")
115
+ return None
116
+
117
+ # AI 图像生成函数
118
+ def generate_ai_image(prompt, seed=None):
119
+ # 尝试加载模型
120
+ pipe = load_model()
121
+ if pipe is None:
122
+ logger.error("AI模型不可用")
123
+ return None
124
 
125
+ try:
126
+ logger.info(f"使用AI生成图像: {prompt}")
127
+
128
+ # 设置生成参数
129
+ if seed is None:
130
+ seed = random.randint(0, 2147483647)
131
+
132
+ # 确定正确的设备
133
+ generator = torch.Generator("cuda" if torch.cuda.is_available() else "cpu").manual_seed(seed)
134
+
135
+ # 生成图像
136
+ image = pipe(
137
+ prompt=prompt,
138
+ guidance_scale=7.5,
139
+ num_inference_steps=5, # 降低步数以加快速度
140
+ generator=generator,
141
+ height=512,
142
+ width=512
143
+ ).images[0]
144
+
145
+ # 清理缓存
146
+ if torch.cuda.is_available():
147
+ torch.cuda.empty_cache()
148
+
149
+ logger.info(f"AI图像生成成功,种子: {seed}")
150
+ return image
151
+
152
+ except Exception as e:
153
+ logger.error(f"AI图像生成失败: {e}")
154
+ return None
155
 
156
+ # 入口点函数 - 处理请求并生成图像
157
  def generate_image(prompt):
158
+ # 处理空提示
159
  if not prompt or prompt.strip() == "":
160
  prompt = "a beautiful landscape"
161
  logger.info(f"输入为空,使用默认提示词: {prompt}")
162
 
163
  logger.info(f"收到提示词: {prompt}")
164
 
165
+ # 尝试使用AI生成
166
+ image = generate_ai_image(prompt)
167
+
168
+ # 检查结果
169
+ if image is not None:
170
+ return image
171
+ else:
172
+ logger.warning("使用备用生成器")
173
+ return create_backup_image(prompt)
174
 
175
  # 创建Gradio界面
176
  def create_demo():
177
+ with gr.Blocks(title="AI 文本到图像生成器") as demo:
178
+ gr.Markdown("# AI 文本到图像生成器")
179
+ gr.Markdown("输入文本描述,AI将为你生成相应的图像。")
180
+
181
+ with gr.Row():
182
+ with gr.Column(scale=3):
183
+ # 输入区域
184
+ prompt_input = gr.Textbox(
185
+ label="输入提示词",
186
+ placeholder="描述你想要的图像,例如:一只可爱的猫,日落下的山脉...",
187
+ lines=2
188
+ )
189
+ generate_button = gr.Button("生成图像", variant="primary")
190
+
191
+ # 示例
192
+ gr.Examples(
193
+ examples=[
194
+ "a cute cat sitting on a windowsill",
195
+ "beautiful sunset over mountains",
196
+ "an astronaut riding a horse in space",
197
+ "a fantasy castle on a floating island"
198
+ ],
199
+ inputs=prompt_input
200
+ )
201
+
202
+ # 输出区域
203
+ with gr.Column(scale=5):
204
+ output_image = gr.Image(label="生成的图像", type="pil")
205
+
206
+ # 绑定按钮事件
207
+ generate_button.click(
208
+ fn=generate_image,
209
+ inputs=prompt_input,
210
+ outputs=output_image
211
+ )
212
+
213
+ # 也绑定Enter键提交
214
+ prompt_input.submit(
215
+ fn=generate_image,
216
+ inputs=prompt_input,
217
+ outputs=output_image
218
+ )
219
+
220
  return demo
221
 
222
  # 创建演示界面
 
226
  if __name__ == "__main__":
227
  try:
228
  logger.info("启动Gradio界面...")
 
229
  demo.launch(
230
+ server_name="0.0.0.0",
231
+ show_api=False,
232
+ share=False
 
 
233
  )
234
  except Exception as e:
235
  logger.error(f"启动失败: {e}")
requirements.txt CHANGED
@@ -1,8 +1,8 @@
1
- accelerate==0.21.0
2
- diffusers==0.18.0
3
- huggingface-hub==0.14.1
4
- torch==2.0.1
5
- transformers==4.30.2
6
  safetensors==0.3.1
7
  gradio==3.24.1
8
- Pillow==10.0.0
 
1
+ accelerate==0.15.0
2
+ diffusers==0.14.0
3
+ huggingface-hub==0.13.3
4
+ torch==1.13.1
5
+ transformers==4.26.0
6
  safetensors==0.3.1
7
  gradio==3.24.1
8
+ Pillow==9.5.0