# 参数对照表 `AdvancedParams` 用 `adp` 代替,名称变动的原则是和 Fooocus 进行统一: | Fooocus-API | FooocusAPI | 备注 | |------------------------------------------|--------------------------------------|---------------------| | prompt | prompt | | | negative_prompt | negative_prompt | | | style_selections | style_selections | | | performance_selection | performance_selection | | | aspect_ratios_selection | aspect_ratios_selection | | | image_number | image_number | | | image_seed | image_seed | | | sharpness | sharpness | | | guidance_scale | guidance_scale | | | base_model_name | base_model_name | | | refiner_model_name | refiner_model_name | | | refiner_switch | refiner_switch | | | loras | loras | 传入格式相同,都是 Lora 对象列表 | | | input_image_checkbox | 可以忽略,它总是为 True | | | current_tab | 可以忽略,根据参数会自动判断 | | uov_method | uov_method | | | **input_image** | **uov_input_image** | 使用 Fooocus 的变量名称 | | outpaint_selections | outpaint_selections | | | **input_image** | **inpaint_input_image** | 使用 Fooocus 的变量名称 | | inpaint_additional_prompt | inpaint_additional_prompt | | | **input_mask** | **inpaint_mask_image_upload** | 使用 Fooocus 的变量名称 | | adp.disable_preview | disable_preview | | | adp.disable_intermediate_results | disable_intermediate_results | | | adp.disable_seed_increment | disable_seed_increment | | | adp.black_out_nsfw | black_out_nsfw | | | adp.adm_scaler_positive | adm_scaler_positive | | | adp.adm_scaler_negative | adm_scaler_negative | | | adp.adm_scaler_end | adm_scaler_end | | | adp.adaptive_cfg | adaptive_cfg | | | adp.clip_skip | clip_skip | | | adp.sampler_name | sampler_name | | | adp.scheduler_name | scheduler_name | | | adp.vae_name | vae_name | | | adp.overwrite_step | overwrite_step | | | adp.overwrite_switch | overwrite_switch | | | adp.overwrite_width | overwrite_width | | | adp.overwrite_height | overwrite_height | | | adp.overwrite_vary_strength | overwrite_vary_strength | | | adp.overwrite_upscale_strength | overwrite_upscale_strength | | | adp.mixing_image_prompt_and_vary_upscale | mixing_image_prompt_and_vary_upscale | | | adp.mixing_image_prompt_and_inpaint | mixing_image_prompt_and_inpaint | | | adp.debugging_cn_preprocessor | debugging_cn_preprocessor | | | adp.skipping_cn_preprocessor | skipping_cn_preprocessor | | | adp.canny_low_threshold | canny_low_threshold | | | adp.canny_high_threshold | canny_high_threshold | | | adp.refiner_swap_method | refiner_swap_method | | | adp.controlnet_softness | controlnet_softness | | | adp.freeu_enabled | freeu_enabled | | | adp.freeu_b1 | freeu_b1 | | | adp.freeu_b2 | freeu_b2 | | | adp.freeu_s1 | freeu_s1 | | | adp.freeu_s2 | freeu_s2 | | | adp.debugging_inpaint_preprocessor | debugging_inpaint_preprocessor | | | adp.inpaint_disable_initial_latent | inpaint_disable_initial_latent | | | adp.inpaint_engine | inpaint_engine | | | adp.inpaint_strength | inpaint_strength | | | adp.inpaint_respective_field | inpaint_respective_field | | | adp.inpaint_mask_upload_checkbox | inpaint_mask_upload_checkbox | | | adp.invert_mask_checkbox | invert_mask_checkbox | | | adp.inpaint_erode_or_dilate | inpaint_erode_or_dilate | | | **image_prompts** | **controlnet_image** | 只是属性名称变更 | | | generate_image_grid | 新增,这是个测试选项,建议默认 | | outpaint_distance_left | outpaint_distance | 这四个属性合并为了一个属性 | | outpaint_distance_right | | 可以通过一个列表传递这四个值 | | outpaint_distance_top | | 例如:[100, 50, 0, 0] | | outpaint_distance_bottom | | 方向是:左, 上, 右, 下 | | **upscale_value** | **upscale_multiple** | 属性名变更 | | | preset | 新增,可以通过该属性指定使用的预设 | | | stream_output | 新增流式输出,类似 LLM 的流式输出 | | **save_meta** | **save_metadata_to_images** | | | **meta_scheme** | **metadata_scheme** | | | **save_extension** | **output_format** | | | save_name | | 移除,不支持自定义文件名 | | read_wildcards_in_order | read_wildcards_in_order | | | require_base64 | require_base64 | 该参数后续可能会被移除 | | async_process | async_process | | | webhook_url | webhook_url | | 简单说来就是 - 将所有 `AdvancedParams` 平移到上一级 - 修改部分参数名 - `input_image` -> `inpaint_input_image` - `inpaint_mask` -> `inpaint_mask_image_upload` - `input_image` -> `uov_input_image` - `image_prompts` -> `controlnet_image` - `upscale_value` -> `upscale_value` - `save_meta` -> `upscale_multiple` - `meta_scheme` -> `save_metadata_to_images` - `save_extension` -> `output_format` - 移除部分参数名 - `save_name` - 增加部分参数 - `input_image_checkbox` - `current_tab` - `generate_image_grid` - `preset` - `stream_output` - 合并部分参数 - `outpaint_distance_left,right,top,bottom` 四个参数合并为 `outpaint_distance` ## 三种返回示例 ### 异步任务 在参数中指定 `async_process` 为 `True` ```python import requests import json endpoint = "http://127.0.0.1:7866/v1/engine/generate/" params = { "prompt": "", "negative_prompt": "", "performance_selection": "Lightning", "async_process": True, "webhook_url": "" } res = requests.post( url=endpoint, data=json.dumps(params), timeout=60 ) print(res.json()) ``` 输出如下: ```python {'id': -1, 'task_id': '85c10c81e9e2482d90a64c3704137d3a', 'req_params': {}, 'in_queue_mills': -1, 'start_mills': -1, 'finish_mills': -1, 'task_status': 'pending', 'progress': -1, 'preview': '', 'webhook_url': '', 'result': []} ``` 你可以通过 `task_id` 访问 `http://127.0.0.1:7866/tasks/{task_id}` 获取任务信息,如果该任务正在执行,返回信息中会包含 `preview` 返回数据示例: ```python # 未开始 { "id": -1, "in_queue_mills": 1720085748199, "finish_mills": null, "progress": null, "result": null, "req_params": { # 完整的请求参数 ... }, "task_id": "85c10c81e9e2482d90a64c3704137d3a", "start_mills": null, "task_status": null, "webhook_url": "" } # 执行中 { "id": -1, "task_id": "85c10c81e9e2482d90a64c3704137d3a", "req_params": { ... }, "in_queue_mills": 1720086131653, "start_mills": 1720086131865, "finish_mills": -1, "task_status": "running", "progress": 18, "preview": "a long text", "webhook_url": "", "result": [] } # 已完成 { "id": 71, "in_queue_mills": 1720085748199, "finish_mills": 1720085770046, "progress": 100, "result": [ "http://127.0.0.1:7866/outputs/2024-07-04/2024-07-04_17-36-09_5201.png" ], "req_params": { ... }, "task_id": "85c10c81e9e2482d90a64c3704137d3a", "start_mills": 1720085748425, "task_status": "finished", "webhook_url": "" } ``` ### 流式输出 这是一个类似 LLM 流式输出的方式,你会持续收到来自服务器的信息,直到结束,参照上面的示例: ```python import requests import json endpoint = "http://127.0.0.1:7866/v1/engine/generate/" params = { "prompt": "", "negative_prompt": "", "performance_selection": "Lightning", "stream_output": True, "webhook_url": "" } res = requests.post( url=endpoint, data=json.dumps(params), stream=True, timeout=60 ) for line in res.iter_lines(): if line: print(line.decode('utf-8')) ``` 你会获得类似下面的输出: ```python data: {"progress": 2, "preview": null, "message": "Loading models ...", "images": []} data: data: {"progress": 13, "preview": null, "message": "Preparing task 1/1 ...", "images": []} data: data: {"progress": 13, "preview": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASAAAA...", 'message': 'Sampling step 1/4, image 1/1 ...', 'images': []} data: data: {"progress": 34, "preview": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASAAAA...", 'message': 'Sampling step 2/4, image 1/1 ...', 'images': []} data: data: {"progress": 56, "preview": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASAAAA...", 'message': 'Sampling step 3/4, image 1/1 ...', 'images': []} data: data: {"progress": 78, "preview": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASAAAA...", 'message': 'Sampling step 4/4, image 1/1 ...', 'images': []} data: data: {"progress": 100, "preview": null, "message": "Saving image 1/1 to system ...", "images": []} data: data: {"progress": 100, "preview": null, "message": "Finished", "images": ["http://10.0.0.245:7866/outputs/2024-07-05/2024-07-05_09-31-10_1752.png"]} data: ``` 我们在稍微修改下: ```python import requests import json endpoint = "http://127.0.0.1:7866/v1/engine/generate/" params = { "prompt": "", "negative_prompt": "", "performance_selection": "Lightning", "stream_output": True, "webhook_url": "" } res = requests.post( url=endpoint, data=json.dumps(params), stream=True, timeout=60 ) for line in res.iter_lines(chunk_size=8192): line = line.decode('utf-8').split('\n')[0] try: json_data = json.loads(line[6:]) if json_data["preview"] is not None: json_data["preview"] = "data:image/png;base64,iVBORw0KGgoAAAANSU..." except json.decoder.JSONDecodeError: continue print(json_data) ``` 然后你就得到了一系列类似这样的输出: ```python {'progress': 13, 'preview': None, 'message': 'Preparing task 1/1 ...', 'images': []} {'progress': 13, 'preview': 'data:image/png;base64,iVBORw0KGgoAAAANSU...', 'message': 'Sampling step 1/4, image 1/1 ...', 'images': []} {'progress': 34, 'preview': 'data:image/png;base64,iVBORw0KGgoAAAANSU...', 'message': 'Sampling step 2/4, image 1/1 ...', 'images': []} {'progress': 56, 'preview': 'data:image/png;base64,iVBORw0KGgoAAAANSU...', 'message': 'Sampling step 3/4, image 1/1 ...', 'images': []} {'progress': 78, 'preview': 'data:image/png;base64,iVBORw0KGgoAAAANSU...', 'message': 'Sampling step 4/4, image 1/1 ...', 'images': []} {'progress': 100, 'preview': None, 'message': 'Saving image 1/1 to system ...', 'images': []} {'progress': 100, 'preview': None, 'message': 'Finished', 'images': ['http://10.0.0.245:7866/outputs/2024-07-05/2024-07-05_10-02-22_2536.png']} ``` 这还挺适合前端套壳用的(可惜我完全搞不懂前端,要不高低套一个),比如我用 AI 生成了一个 [example.html](./docs/example.html) ,服务启动后点击 `Generate` 按钮,你就会得到一个有预览、有进度的生成过程。 ### 二进制输出 这个就简单了,它就是返回一张图片,不过需要在请求时将 `async_process` 和 `stream_output` 同时指定为 `false`,此时 `image_number` 强制为 `1` ```python import requests import json from PIL import Image from io import BytesIO import matplotlib.pyplot as plt endpoint = "http://127.0.0.1:7866/v1/engine/generate/" params = { "prompt": "", "negative_prompt": "", "performance_selection": "Lightning", "async_process": False, "stream_output": False, "webhook_url": "" } res = requests.post( url=endpoint, data=json.dumps(params), timeout=60 ) image_stream = BytesIO(res.content) image = Image.open(image_stream) plt.imshow(image) plt.show() ``` # 任务查询 和 [Fooocus-API](https://github.com/mrhan1993/Fooocus-API) 不同的是历史记录的保存将是自动进行的,没有保留开关。数据库使用 `SQLite3` 并存放在 `outputs/db.sqlite3` 中。同时吸取了上次的教训,极大简化了表结构,将请求参数作为 JSON 存放在 `req_params` 字段。为了降低读写,仅在任务进入队列时和完成后进行数据库操作。其仅作为生成记录使用,任务状态的追踪会在内存中完成。 此外,该版本会保留输入图像,上传的图像会计算哈希值并保存在 `inputs` 目录,数据库中的 `req_params` 会将图片参数替换为 `url` 信息进行保存,这意味着更完整的历史记录保存,无论是文生图还是图生图又或者是其他 ## /tasks 这是个复合接口,但其返回格式是固定的,该接口总是会返回下面格式的 JSON 数据,无论参数如何指定 ```python { "history": [], "current": [], # 尽管是个列表,但其中不会超过一个元素。 "pending": [] } ``` 所有的元素其格式都是和数据库中的 scheme 匹配的,除了 `current` 会多一个 `preview` ,比如下图: ![](./assets/tasks.png) 该接口还支持更加精细的用法,参考下面的示例: > 该接口返回格式总是固定的,不管参数如何调整 ```shell curl http://localhost:7866/tasks?query=current # 仅返回当前任务,query 参数还可以指定的值为 'all', 'pending', 'history' curl http://localhost:7866/tasks?query=history&page=3&page_size=5 # history 和 pending 支持分页和页面大小 curl http://localhost:7866/tasks?query=history&start_at=2024-07-03T12:22:30 # 你可以指定一个时间范围进行查询,这会返回该时间段的所有记录。时间格式是 ISO8601,如果你不指定 end_at 则截止当前时间 curl http://localhost:7866/tasks?query=history&start_at=2024-07-03T12:22:30&action=delete # 删除指定时间范围的任务,数据库记录和生成文件。目前仅支持这一种删除方法(不会删除 input 文件)。 curl http://localhost:7866/tasks/38ba92b188a64233a7336218cd902865 # 这会返回该任务的信息,但它只是一个字典。相当于从上面列表中取出指定 task_id 的任务,如果它刚好是当前任务,那它也会包含 preview ```