# AI绘画
# AI绘画模型:anime-illust-diffusion-xl

它这个模型有自己的使用方式,为了避免网站失效导致无法查看,我在这里也记录一份:

模型介绍(Chinese Part)

I 目录

在本介绍中,您将了解:

  1. 模型介绍(见 II 部分);

  2. 使用指南(见 III 部分);

  3. 训练参数(见 IV 部分);

  4. 触发词列表(见附录 A 部分)

II 模型介绍

动漫插画设计XL,或称 AIDXL 是一款专用于生成二次元插图的模型。它内置了 800 种以上(随着更新越来越多)的插画风格,依靠特定触发词(见附录 A 部分)触发。

优点:构图大胆,没有摆拍感,主体突出,没有过多繁杂的细节,认识很多动漫人物(依靠角色日文名拼音触发,例如,“ayanami rei”对应角色“绫波丽”,“kamado nezuko”对应角色“祢豆子”)。

III 使用指南(将与时俱进)

1 基本用法

1.1 提示词书写

  1. 使用触发词:使用附录 A 所提供的触发词来风格化图像。适合的触发词将 极大地 提高生成质量;

  2. 提示词标签化:使用标签化的提示词描述生成对象;

  3. 提示词排序:排序您的提示词将有助于模型理解词义。推荐的标签顺序:

    触发词(by xxx)->主角(1girl)->角色(frieren)->种族(elf)->构图(cowboy shot)->风格(impasto)->主题(fantasy)->主要环境(forest, day)->背景(gradient background)->动作(sitting)->表情(expressionless)->主要人物特征(white hair)->人体特征(twintails, green eyes, parted lip)->服饰(white dress)->服装配件(frills)->其他物品(magic wand)->次要环境(grass, sunshine)->美学(beautiful color, detailed, aesthetic)->质量(best quality)

  4. 负面提示词worst quality_,_ low quality_,_ lowres_,_ messy, abstract, ugly, disfigured, bad anatomy, deformed hands, fused fingers, signature, text, multi views

1.2 生成参数

  1. 分辨率:确保图像总分辨率(总分辨率=高度x宽度)围绕1024*1024且宽和高均为32的倍数。例如,832x1216 (3:2), 1216x832 (3:2), 以及 1024x1024 (1:1)。

  2. 不进行“Clip Skip”操作,即 Clip Skip = 1。

  3. 采样器步数:采用 “euler_ancester” 采样器(sampler),该组合在 webui 里称为 Euler A。在 7 CFG Scale 上采样 28 步。

  4. 仅需要使用模型本身,而不使用精炼器(Refiner)。

  5. 使用基底模型 vae 或 sdxl-vae。

2 特殊用法

2.1 泛风格化

0.7 版本归纳了若干相似插画画风,引入了泛风格触发词。泛风格触发词各代表一种常见动漫插画画风类别。

请注意,泛风格触发词并不一定符合其词义指代的美术含义,而是经过重新定义的特殊触发词。

2.2 角色

0.7 版本对强化训练了角色。部分角色触发词的还原度已经能够达到 lora 的效果,且能够很好地将角色概念与其本身的着装分离。

角色触发方式为 角色名 \(作品\)。例如,触发动画《赛博朋克:边缘行者》的女主角露西则使用 lucy \(cyberpunk\);触发游戏《原神》中的角色甘雨则使用 ganyu \(genshin impact\)。这里,“lucy” 和 “ganyu” 为角色名,“\(cyberpunk\)” 和 “\(genshin impact\)” 则为对应角色的作品出处,括号使用斜杠"\"转义以防止被解释为提示词加权。对于部分角色,出处并非必要。

角色触发词请参照 selected_tags.csv · SmilingWolf/wd-v1-4-convnext-tagger-v2 at main (huggingface.co)

在使用中,若仅靠单个角色触发词无法完全还原角色,则需要在提示词中添加该角色的主要特征。

角色触发词通常不会携带角色本身的着装特征,若要添加角色着装,则需要在提示词中添加衣物名。例如,游戏《碧蓝航线》中角色圣路易斯 ( st. louis \(luxurious wheels\) \(azur lane\) ) 的衣装触发可使用 silver evening gown, plunging neckline。类似地,您也能对任何角色添加其他角色的衣装标签。

2.3 质量标签

0.7 版本的质量和美学标签经过正式训练,在提示词中尾随它们将影响生成图像的质量。

0.7 版本正式训练并引入了质量标签,质量标签分为六个等级,由好到坏分别为:amazing quality, best quality, high quality, normal quality_,_ low qualityworst quality.

2.4 美学标签

0.7 版本起引入了美学标签,描述图像的特殊美学特征。

2.5 风格融合

您可以将一些样式合并到您的自定义样式中。 “合并”实际上意味着一次使用多种风格触发词。 例如,chun-li, amazing quality, (by yoneyama mai:0.9), (by chi4:0.8), by ask, by modare, (by ikky:0.9).

一些技巧:

  • 控制风格的权重和顺序来调整最终风格。

  • 尾随而非前置到提示词上。

3 注意事项

  1. 使用 SDXL 支持的 VAE 模型、文本嵌入(embeddings)模型和 Lora 模型。注意:sd-vae-ft-mse-original 不是支持 SDXL 的 vae;EasyNegative、badhandv4 等负面文本嵌入也不是支持 SDXL 的 embeddings;

  2. 对于 0.61 及以下版本:生成图像时,强烈推荐使用模型专用的负面文本嵌入(下载参见 Suggested Resources 栏),因其为模型特制,故对模型几乎仅有正面效果;

  3. 每个版本新增触发词将在当前版本效果相对较弱或不稳定。

IV 训练参数

以 SDXL1.0 为底模,使用大约 2w 张自己标注的图像在 5e-6 学习率,循环次数为 1 的余弦调度器上训练了约 100 期得到模型 A。之后在 2e-7 学习率,其余参数相同的条件下,训练得到模型 B。将模型 A 与 B 混合后得到 AIDXLv0.1 模型。

其他训练参数请参照英文版本的介绍。

V 特别鸣谢

算力赞助:感谢 @捏Ta 社区(捏Ta (nieta.art))提供的算力支持;

数据支持:感谢 @秋麒麟热茶KirinTea_Aki Creator Profile | Civitai) 和 @风吟Chenkin Creator Profile | Civitai)提供的大量数据支持;

没有它们就不会有 0.7 版本。

VI 更新日志

2023/08/08:AIDXL 使用与 AIDv2.10 完全相同的训练集进行训练,但表现优于 AIDv2.10。AIDXL 更聪明,能做到很多以 SD1.5 为底模型无法做到的事。它还能很好地区分不同概念,学习图像细节,处理对 SD1.5 来说难于登天的构图,几近完美地学习旧版 AID 无法完全掌握的风格。总的来说,它拥有比 SD1.5 更高的上限,我会继续更新 AIDXL。

2024/01/27:0.7 版本新增了大量内容,数据集大小是上一版本的两倍以上。

  1. 为了得到令人满意的标注,我尝试了很多新的标签处理算法,例如标签排序、标签分层随机化、角色特征分离等等。项目地址:Eugeoter/sd-dataset-manager (github.com)

  2. 为了使训练可控,且更加服从我的意愿,我基于 Kohya-ss 制作了特制的训练脚本;

  3. 为了掌控不同世代的模型的融合过程,我开发了一些启发式的模型融合算法;为了使模型达到足够的风格化,我放弃了通过融合文本编码器和UNET的OUT层来提高模型的稳定和美学,因为这会伤害模型的风格。

  4. 为了筛选和过滤数据,我训练了一个水印检测模型、一个图像分类模型、一个美学评分模型,来帮助我清洗数据。

VII 赞助我们

如果您喜欢我们的工作,欢迎通过 Ko-fi(https://ko-fi.com/eugeai) 赞助我们,以支持我们的研究和开发,感谢您的支持!

Appendix / 附录

A. Special Trigger Words List / 特殊触发词列表

  • Art style trigger words: Click me

  • Painting style trigger words: flat color, clean color, celluloid, flat-pasto, thin-pasto, pseudo-impasto, impasto, realistic, photorealistic, cel shading, 3d

    • flat color: Flat colors, using lines to describe light and shadow

      平涂:平面色彩,使用线条和色块描述光影和层次

    • clean color: Style between flat color and flat-pasto. Simple and tidy coloring.

      具有简洁色彩的平涂,介于 flat color 和 flat-pasto 之间

    • celluloid: Anime coloring

      平涂赛璐璐:动漫着色

    • flat-pasto: Nearly flat color, using gradient color to describe lighting and shadow

      接近平面的色彩,使用渐变描述光影和层次

    • thin-pasto: Thin contour, using gradient and paint thickness to describe light, shadow and layers

      细轮廓勾线,使用渐变和颜料厚度描述光影和层次

    • pseudo-impasto:Use gradients and paint thickness to describe light, shadow and layers

      伪厚涂 / 半厚涂:使用渐变和颜料厚度描述光影和层次

    • impasto:Use paint thickness to describe light, shadow and gradation

      厚涂:使用颜料厚度描述光影和层次

    • realistic

      写实

    • photorealistic:Redefined to a style closer to the real world

      相片写实主义:重定义为接近真实世界的风格

    • cel shading: Anime 3D modeling style

      卡通渲染:二次元三维建模风格

    • 3d

  • Aesthetic trigger words:

    • beautiful

      美丽

    • aesthetic: slightly abstract artistic sense

      唯美:稍微抽象的艺术感

    • detailed

      细致

    • beautiful color: subtle use of color

      协调的色彩:精妙的用色

    • lowres

    • messy: messy composition or details

      杂乱:杂乱的构图或细节

  • Quality trigger words: amazing quality, best quality, high quality, low quality, worst quality

阅读全文 »

# AI绘画

这里用来记录比较好的结果:

约尔太太和🛏

tags:: #NSFW, #约尔太太 category:: Prompt

1
2
3
4
5
1girl,yor briar,medium breasts,open clothes,Pov mating press,1girl,1boy,pov,lying down,legs up,faceless male,cheating_(relationship),spreading legs,  
BREAK
tunamayo (dsasd751),very aesthetic,ultra-detailed,masterpiece,best quality,amazing quality,<lora:ZZZ_Emoji_style_ILv2:1>,
Negative prompt: worst quality,bad quality,bad detail,lowres,bad anatomy,watermark,deformed,bad hands,sketch,3d,realistic,white background,
Steps: 29, Sampler: DPM++ 2M, Schedule type: Karras, CFG scale: 7, Seed: 5116573, Size: 752x1040, Model hash: 89cb4ec0a9, Model: waiNSFWIllustrious_v120, Clip skip: 2, Lora hashes: "ZZZ_Emoji_style_ILv2: 20170a56d639", Version: v1.10.1

只能说这个底模太牛逼了,无需要复杂的提示词就能有非常好的效果

1
2
3
4
5
1girl,yor briar,medium breasts,open clothes,Pov mating press,1girl,1boy,pov,lying down,legs up,faceless male,cheating_(relationship),spreading legs,  
BREAK
tunamayo (dsasd751),very aesthetic,ultra-detailed,masterpiece,best quality,amazing quality,<lora:ZZZ_Emoji_style_ILv2:1>,
Negative prompt: worst quality,bad quality,bad detail,lowres,bad anatomy,watermark,deformed,bad hands,sketch,3d,realistic,white background,
Steps: 40, Sampler: Euler a, Schedule type: Automatic, CFG scale: 7, Seed: 5116573, Size: 832x1216, Model hash: 89cb4ec0a9, Model: waiNSFWIllustrious_v120, Clip skip: 2, Lora hashes: "ZZZ_Emoji_style_ILv2: 20170a56d639", Version: v1.10.1

另外一个,逆兔女郎,还不错

tags:: #逆兔女郎 category:: Prompt

1
2
3
masterpiece, very aesthetic, best quality, 1girl, skinny body, reverse_outfit, reverse_bunnysuit,  breasts, solo, navel,  animal_ears, female_pubic_hair, pubic_hair, rabbit_ears, shrug_(clothing), bowtie, bow, short_hair, fake_animal_ears, looking_at_viewer,  erected big nipples, pink nipples, holding candy, greedily looking on candy, nipple piercing, swooping medium tits, detailed tits, (puffy labia:1.4),  ((slim body)), fit slim, dynamic angle, unshaved pussy, trimmed pubic hair, slender legs, long legs, hipbone, skinny body, narrow waist, multiple boys, imminent group sex, thick penis, imminent gangbang, body grab, molested, aggressive grab, aggressive sex, rough sex, imminent sex,multiple penetration,double insertion,(gangbang, group sex, large cock, big dick,wear condom, hard pounding, deep penetration, groping, grabbing breasts, grabbing waist, pulling hair, pulling arms, hardcore ,wild sex, size difference, armpit sex, armpit fuck, used condoms everywhere)
Negative prompt: Female tongue, female tongue out, Neck grab, worst quality, low quality, displeasing, text, , watermark, bad anatomy, text, artist name, signature, hearts, deformed hands, missing finger, shiny skin,child,children
Steps: 40, CFG scale: 4, Sampler: Euler a, Seed: 2125656973, extra: [object Object], Size: 832x1216, nsfw: false, draft: false, width: 832, height: 1216, quantity: 2, workflow: txt2img, baseModel: Illustrious, Created Date: 2025-04-04T1504:42.1508795Z, Clip skip: 2

看向冰箱

1
2
3
4
5
masterpiece,best quality,amazing quality, solo, androgynous asian woman , looking at a refrigerator, refrigerator interior,  
from behind, bent over,
(flat cute color 0.9), thick thighs, small breasts , wide hips, highly detailed isometric kitchen, from below
Negative prompt: (lowres:1.2), (worst quality:1.4), (low quality:1.4), (bad anatomy:1.4), bad hands, jpeg artifacts, signature, watermark, text, logo, artist name, text censor
Steps: 20, CFG scale: 7, Sampler: Euler a, Seed: 803762383, Size: 1024x1536, Model: waiNSFWIllustrious_v120.safetensors, Model hash: 89CB4EC0A91D3626F65FB8EF187F9CBA92C74C3EA1123DE28291BDCCA25E7778

球鞋和黑裤袜

1
2
3
4
5
(fine fabric:1.1),1girl,skinny,((from below, extremely low angle)),feet,heel,bending over,pantyhose,(textured pantyhose:1.5),(shiny pantyhose:0.2),(dripping wet pantyhose:0.5),(fine fabric emphasis:1.2),(high detail texture:1.1),panties around knees,(((white sneakers))),pink panties down,panties off,puffy pussy,dripping wet pussy,pretty pussy,close up,pigeon-toed,from behind,feet together,wooden floor background,<lora:fine_fabric>,  
Negative prompt: lowres,bad anatomy,bad hands,text,error,missing fingers,extra digit,
fewer digits,cropped,worst quality,low quality,normal quality,jpeg artifacts,
signature,watermark,username,blurry,bad fee,front foot,
Steps: 35, Sampler: Euler a, Schedule type: Automatic, CFG scale: 4, Seed: 986852428, Size: 832x1216, Model hash: a810e710a2, Model: waiNSFWIllustrious_v130, Denoising strength: 0.7, Clip skip: 2, Hires upscale: 2, Hires upscaler: Latent, Lora hashes: "fine_fabric: 3c7a8e88d7ea", Version: v1.10.1

泳池里的女孩

1
2
3
masterpiece,best quality,amazing quality,very aesthetic,newest,depth of field,(blurred background),(dramatic lighting:0.1),masterpiece,best quality,very aesthetic,8k,masterpiece,best quality,masterpiece,best quality,8k,simple_background,half close-up,sexy pose,blushing,asian girl,small head,pretty girl,korean girl,((slim body)),(small breasts),LARGE AREOLAE,Erect nipples,LONG NIPPLES,(PUFFY NIPPLES:0.9),dynamic angle,dynamic pose,ear piercings,nsfw,portrait,girl,naked,in water,wet skin,<lora:Huge_perfect_nipples_concept_with_inverted:1>,<lora:long_nipples_addift:0.6>,  
Negative prompt: bad quality,worst quality,worst detail,censor,bad anatomy,duplicate hair shape,
Steps: 50, Sampler: Euler a, Schedule type: Automatic, CFG scale: 7, Seed: 253947270, Size: 832x1216, Model hash: a810e710a2, Model: waiNSFWIllustrious_v130, Clip skip: 2, Lora hashes: "Huge_perfect_nipples_concept_with_inverted: 8c1df68dbb3d, long_nipples_addift: 0bf97da89fc1", Version: v1.10.1

“覆面”系

1
2
3
4
embedding:lazypos,extreme sex,1girl,asian girl,korean girl,black hair,fit,slim,medium breasts,straight hair,blunt bangs,hair over one eye,long hair,red eyes,  
eyes crossed,torogao,spitroast,black choker,black jacket,open clothes,long sleeves,big eyes,(((penis over one eye, hetero, penis on face, 1penis, from above, partial side view, bed room, open mouth, tongue, saliva, blush))),head grab,large cock,hand on cock,hand squeezing testicles,grabbing balls,squeezing balls,cumshot,cum on hair,cum on face,cum on nose,((animated, bright colors, hentai)),<lora:kawafe:1>,
Negative prompt: duplicate hair shape,(highlights:0.3),
Steps: 50, Sampler: DPM++ 2M, Schedule type: Karras, CFG scale: 7, Seed: 673152417, Size: 832x1216, Model hash: a810e710a2, Model: waiNSFWIllustrious_v130, Clip skip: 2, Lora hashes: "kawafe: c81c37f55eb4", Version: v1.10.1

otintin画师,太好看了

这里的 croptop 是 短款上衣 covered nipples 非常对我的xp trembling,sweat,blush,motion lines,tiptoes,tongue out,saliva 这一串的效果非常好

1
2
3
masterpiece,best quality,newest,absurdres,highres,1girl,himekaidou_hatate,croptop,covered nipples,highleg thong,randoseru,thighhighs,outdoors,standing sex,sex from behind,against wall,bent over,grabbing another's hair,clothes pull,clothes aside,trembling,sweat,blush,motion lines,tiptoes,tongue out,saliva,solo focus,<lora:otintin>,  
Negative prompt: worst quality,bad quality,low quality,lowres,anatomical nonsense,artistic error,bad anatomy,blood,censored,monochrome,
Steps: 25, Sampler: DPM++ 2M SDE, Schedule type: Exponential, CFG scale: 4, Seed: 1869634766, Size: 832x1216, Model hash: a810e710a2, Model: waiNSFWIllustrious_v130, Clip skip: 2, Lora hashes: "otintin: d1d9268cc512", Version: v1.10.1

加了 zzz emoji 的风格让它的边缘线和手稳定点

1
2
3
masterpiece,best quality,newest,absurdres,highres,1girl,himekaidou_hatate,croptop,covered nipples,highleg thong,randoseru,thighhighs,outdoors,standing sex,sex from behind,against wall,bent over,grabbing another's hair,clothes pull,clothes aside,trembling,sweat,blush,motion lines,tiptoes,tongue out,saliva,solo focus,<lora:otintin:0.9>,<lora:ZZZ_Emoji_style_ILv2:0.2>,  
Negative prompt: worst quality,bad quality,low quality,lowres,anatomical nonsense,artistic error,bad anatomy,blood,censored,monochrome,
Steps: 25, Sampler: DPM++ 2M SDE, Schedule type: Exponential, CFG scale: 4, Seed: 1869634766, Size: 832x1216, Model hash: a810e710a2, Model: waiNSFWIllustrious_v130, Clip skip: 2, Lora hashes: "otintin: d1d9268cc512, ZZZ_Emoji_style_ILv2: 20170a56d639", Version: v1.10.1

埃及风格

1
2
3
masterpiece,best quality,newest,absurdres,highres,1girl,young,brunette,freckles,petite,slim,dancer,piercing,bridal gauntlets,thighhighs,choker,pelvic curtain,breast curtains,jewlery,outdoors,standing sex,sex from behind,against wall,bent over,grabbing another's hair,clothes pull,clothes aside,trembling,sweat,blush,motion lines,tiptoes,tongue out,saliva,solo focus,<lora:otintin:0.8>,<lora:fine_fabric:1>,<lora:ZZZ_Emoji_style_ILv2:0.4>,  
Negative prompt: worst quality,bad quality,low quality,lowres,anatomical nonsense,artistic error,bad anatomy,blood,censored,monochrome,
Steps: 50, Sampler: DPM++ 2M, Schedule type: Karras, CFG scale: 4, Seed: 126744804, Size: 832x1216, Model hash: a810e710a2, Model: waiNSFWIllustrious_v130, Clip skip: 2, Lora hashes: "otintin: d1d9268cc512, fine_fabric: 3c7a8e88d7ea, ZZZ_Emoji_style_ILv2: 20170a56d639", Version: v1.10.1

不知道为什么,这个丝袜质感的风格要么会过度涂抹要么质感其实也没有那么强。 不过总体来说还是非常棒的

画师_96YOTTEA 作为背景画师

注意看背景的印象派的绘画方式

1
2
3
masterpiece,best quality,newest,absurdres,highres,1girl,young,brunette,freckles,petite,slim,dancer,piercing,bridal gauntlets,thighhighs,choker,pelvic curtain,breast curtains,jewlery,outdoors,standing sex,sex from behind,against wall,bent over,grabbing another's hair,clothes pull,clothes aside,trembling,sweat,blush,motion lines,tiptoes,tongue out,saliva,solo focus,<lora:ZZZ_Emoji_style_ILv2:0.6>,<lora:96YOTTEA-WAI:0.6>,  
Negative prompt: worst quality,bad quality,low quality,lowres,anatomical nonsense,artistic error,bad anatomy,blood,censored,monochrome,
Steps: 50, Sampler: DPM++ 2M, Schedule type: Karras, CFG scale: 4, Seed: 126744804, Size: 832x1216, Model hash: a810e710a2, Model: waiNSFWIllustrious_v130, Clip skip: 2, Lora hashes: "ZZZ_Emoji_style_ILv2: 20170a56d639, 96YOTTEA-WAI: 7a6cdc714921", Version: v1.10.1

水池里的女孩

这其实也是一个画风对比

不加Lora

这一套提示词就算是不加lora也是非常好的画面效果 ### Choujiroo

这位画师本身是画那种更加平涂的画,但是在面对这种高清的场景也能让它表情和整体的质感看起来好很多

1
2
3
4
5
6
7
8
9
masterpiece,ultra-HD,cinematic lighting,photorealistic,impressionism (1.5),high detail,depth of field,(blurred background),(dramatic lighting),masterpiece,best quality,very aesthetic,8k,masterpiece,best quality,realistic,masterpiece,best quality,8k,  
simple_background,
half close-up,sexy pose,
blushing,asian girl,small head,pretty girl,korean girl,
((slim body)),(small breasts),areola,Dynamic angle,Dynamic pose,
ear piercings,Nswf,portrait,
girl,naked,in water,wet skin,<lora:Choujiroo-P6bv1a-Illu01:1>,
Negative prompt: Female tongue,female tongue out,Neck grab,worst quality,low quality,displeasing,text,watermark,bad anatomy,text,artist name,signature,hearts,deformed hands,missing finger,shiny skin,child,children,
Steps: 48, Sampler: Euler a, Schedule type: Automatic, CFG scale: 4, Seed: 989673675, Size: 832x1216, Model hash: a810e710a2, Model: waiNSFWIllustrious_v130, Clip skip: 2, Lora hashes: "Choujiroo-P6bv1a-Illu01: 0x3d18df523c", Version: v1.10.1

96YOTTEA-WAI

这个画师说实话有点鬼刀的味道了 也是厚涂印象风格

而且为了弥补这个风格会导致画面的边缘也变得模糊,可以加上万能的zzz_emoji_style,来将其边缘变得更加清晰,同时保留原本的风格。

1
2
3
4
5
6
7
8
9
masterpiece,ultra-HD,cinematic lighting,photorealistic,impressionism (1.5),high detail,depth of field,(blurred background),(dramatic lighting),masterpiece,best quality,very aesthetic,8k,masterpiece,best quality,realistic,masterpiece,best quality,8k,  
simple_background,
half close-up,sexy pose,
blushing,asian girl,small head,pretty girl,korean girl,
((slim body)),(small breasts),areola,Dynamic angle,Dynamic pose,
ear piercings,Nswf,portrait,
girl,naked,in water,wet skin,<lora:ZZZ_Emoji_style_ILv2:1.1>,<lora:96YOTTEA-WAI:0.8>,
Negative prompt: Female tongue,female tongue out,Neck grab,worst quality,low quality,displeasing,text,watermark,bad anatomy,text,artist name,signature,hearts,deformed hands,missing finger,shiny skin,child,children,
Steps: 48, Sampler: Euler a, Schedule type: Automatic, CFG scale: 4, Seed: 989673675, Size: 832x1216, Model hash: a810e710a2, Model: waiNSFWIllustrious_v130, Clip skip: 2, Lora hashes: "ZZZ_Emoji_style_ILv2: 20170a56d639, 96YOTTEA-WAI: 7a6cdc714921", Version: v1.10.1

不知道是为什么,好像它们都喜欢用这一套tag:

1
2
asian girl,small head,pretty girl,korean girl,
((slim body)),(small breasts),Dynamic angle,Dynamic pose,

模仿图片生成的机械娘

非常美丽。 直接复制粘贴图片就看在comfyUI中直接导出工作流。

1
(masterpiece, best quality, ultra-detailed), 1girl, petite body (158cm), (long straight black hair:1.3), slender eyes, (porcelain white skin with subtle mechanical texture:1.2), shy smile, (gentle yet dependent gaze:1.3), (engineer-style outfit:1.4) - white shirt with tie, brown tool skirt, (small gear-shaped accessories:1.2), (delicate repair marks on limbs:1.1), (soft mechanical glow on joints), standing beside vintage computer consoles, steampunk pipes and brass machinery in background, warm ambient lighting, holographic data panels floating nearby, (blend of organic and mechanical aesthetics:1.3),<otintin:0.8>,<zzz-emoji:0.5>

1
bad quality,worst quality,worst detail,censor,bad anatomy,duplicate hair shape,embedding:badhandv4, 

# hexo

Obsidian Annotator

黑曜石注释器

项目github

这是 Obsidian (https://obsidian.md) 的插件。它允许您打开和注释 PDF 和 EPUB 文件。

该插件基于 https://web.hypothes.is/,但经过修改后将注释存储在本地 markdown 文件中,而不是存储在 Internet 上。

Demonstration

示范

警告! 在上面的 gif 中,我使用 Dataview 语法来指定 annotation-target。如果你没有安装 dataview 插件,则必须在 frontmatter 中编写 annotation-target,如下所示:

1
2
3
---
annotation-target: https://arxiv.org/pdf/2104.13478.pdf
---

Getting Started

开始

将属性 annotation-target 添加到黑曜石便笺的 frontmatter 中,其值对应于 EPUB/PDF 文件的位置。该位置可以是 Vault 中的文件(如 Pdf/mypdf.pdf),也可以是联机文件(如 https://arxiv.org/pdf/2104.13478.pdf

然后,您可以在打开的注释窗格中,选择 “more options”(右上角的三个点),并且应该有一个新选项 “annotate” 可用。

该插件会自动尝试根据文件路径确定文件是 epub 还是 pdf,但如果这不起作用,您还可以添加属性 annotation-target-type 并手动指定它是 epub 还是 pdf

如果您安装了 dataview,则还可以使用 dataview 属性指定注释目标。在这种情况下,可以使用 obsidian 样式的链接来代替纯文本路径。

WARNING! Don't rename an original pdf or epub file! The plugin is going to lose the connection between annotations and file in that case.
警告!不要重命名原始 PDF 或 epub 文件!在这种情况下,插件将失去 annotation 和 file 之间的连接。

Annotating

注释 Annotation is self-explanatory. Select text with your mouse to get started.
注释是不言自明的。用鼠标选择文本以开始使用。

In the future, it would be nice to add colored highlights and image/region highlights. These features will have to be added to hypothes.is first, however. See these relevant issues: hypothesis/product-backlog#198, hypothesis/product-backlog#669
将来,添加彩色高光和图像/区域高光会很好。但是,必须先将这些功能添加到 hypothes.is 中。请参阅以下相关问题: hypothesis/product-backlog#198hypothesis/product-backlog#669

The annotations in markdown

markdown 中的注解

To return to the regular obsidian markdown editing mode, you can select more optionsOpen as MD. Each annotation has an associated quote block with a block reference. Be careful with modifying these blocks. Minor edits to PREFIX, HIGHLIGHT, and POSTFIX are typically ok. But if the edits are too major, hypothesis may no longer be able to identify the corresponding text.
要返回常规的 obsidian markdown 编辑模式,你可以选择 Open as MD更多选项 。每个注释都有一个带有块引用的关联 quote 块。修改这些块时要小心。对 PREFIX、HIGHLIGHT 和 POSTFIX 进行次要编辑通常是可以的。但是,如果编辑过于严重,假设可能无法再识别相应的文本。

The COMMENT region can be freely edited. (but ensure that it is still part of the quote block.)
COMMENT 区域可以自由编辑。(但请确保它仍然是 quote 块的一部分。

The TAGS region should consist of a comma-separated list of obsidian tags. (like #tag1, #tag2, #tag3)
TAGS 区域应由以逗号分隔的黑曜石标签列表组成。(如 #tag1、#tag2 #tag3

Dark Mode

深色模式

The plugin has built-in dark mode support. To toggle dark mode, select more optionsToggle Dark Mode while annotating. You can also tweak the dark mode behavior in the settings tab for the plugin.
该插件具有内置的暗模式支持。要切换深色模式,请在注释时选择更多选项 → Toggle Dark Mode(切换深色模式 )。您还可以在插件的 settings (设置) 选项卡中调整暗模式行为。

Linking to annotations

链接到注释

An obsidian link to an annotation block-reference will, when clicked, open the corresponding file and scroll to the associated highlight. If the file is already open in a pane, then the link will cause the existing pane to scroll instead.
单击指向注释块引用的黑曜石链接将打开相应的文件并滚动到关联的高亮显示。如果文件已在窗格中打开,则该链接将导致现有窗格滚动。

Contributing

贡献

Visit CONTRIBUTING.md for information on building from source or contribution improvements. To report a bug, ask a question or suggest an improvement for this plugin, you can create an issue.
请访问 CONTRIBUTING.md 以获取有关从源构建或贡献改进的信息。要报告错误、提出问题或建议此插件的改进,您可以创建一个问题

阅读全文 »

背景

在前端开发中,我们经常会遇到一些性能瓶颈,比如一些复杂的计算,或者一些需要大量计算的算法,这时候我们可以考虑使用WebAssembly来提高性能。

WebAssembly是一种新的低级字节码格式,可以在现代浏览器中运行,它可以让我们在浏览器中运行其他语言编写的代码,比如C、C++、Rust等。

Rust 因为其安全性可靠性以及高性能,以及跨平台的特性,非常适合用来编写WebAssembly模块。

1
2
3
4
5
6
7
### [Rust 和 WebAssembly 用例](https://developer.mozilla.org/zh-CN/docs/WebAssembly/Guides/Rust_to_Wasm#rust_%E5%92%8C_webassembly_%E7%94%A8%E4%BE%8B#rust_和_webassembly_用例)
Rust 和 WebAssembly 有两大主要用例:

- 构建完整应用——整个 Web 应用都基于 Rust 开发!
- 构建应用的组成部分——在现存的 JavaScript 前端中使用 Rust。

目前,Rust 团队正专注于第二种用例,因此我们也将着重介绍它。对于第一种用例,可以参阅 [`yew`](https://github.com/DenisKolodin/yew) 这类项目。

MDN网站上本身有一个简明的教程,用于介绍如何将Rust编写的程序打包为WebAssembly模块,然后在JavaScript中调用:编译 Rust 为 WebAssembly - WebAssembly | MDN

MDN这篇文章写的非常通俗易懂,基本上是面向于零基础的读者, 但是问题是,这篇文章里面仍然有很多容易踩的坑,所以说,我在这结合我自己的实践、以及所遇到的问题,来写一篇更加详细的教程。

所以说这篇文章的大部分内容将会和 MDN 的文章一致,但是我会对其的一些内容进行删改,以及添加一些我认为有必要的内容。

路径以及阶段性目标

在本教程中,我们将使用 Rust 的 npm 包构建工具 wasm-pack 来构建一个 npm 包。这个包只包含 WebAssembly 和 JavaScript 代码,以便包的用户无需安装 Rust 就能使用。他们甚至不需要知道这里包含 WebAssembly!

之后我们会使用 vite 框架来引入这个npm包,然后在前端项目中调用这个WebAssembly模块。

安装 Rust 环境

让我们看看安装 Rust 环境的所有必要步骤。

安装 Rust

前往 Install Rust 页面并跟随指示安装 Rust。这里会安装一个名为“rustup”的工具,这个工具能让你管理多个不同版本的 Rust。默认情况下,它会安装用于惯常 Rust 开发的 stable 版本 Rust Release。Rustup 会安装 Rust 的编译器 rustc、Rust 的包管理工具 cargo、Rust 的标准库 rust-std 以及一些有用的文档 rust-docs

备注: 需要注意,在安装完成后,你需要把 cargo 的 bin 目录添加到你系统的 PATH。一般来说它会自动添加,但需要你重启终端后才会生效。

wasm-pack

要构建我们的包,我们需要一个额外工具 wasm-pack。它会帮助我们把我们的代码编译成 WebAssembly 并制造出正确的 npm 包。使用下面的命令可以下载并安装它:

1
cargo install wasm-pack

可选:安装 Node.js 并获取 npm 账户

在这个例子中我们将会构建一个 npm 包,因此你需要确保安装 Node.js 和 npm 已经安装。

另外,我们将会把包发布到 npm 上,因此你还需要一个 npm 账号。它们是免费的。发布这个包并不是必须的,但是发布它非常简单,因此在本例中我们默认你会发布这个包。

这一步主要是为了,让你能够在本地测试你的WebAssembly模块,以及发布到npm上。之后其他的项目可以直接通过npm来同步更新你的WebAssembly模块,而无需手动操作。

Get npm! 页面按照说明下载并安装 Node.js 和 npm。在选择版本时,选择一个你喜欢的版本;本例不限定特定版本。

npm signup page 注册 npm 账户,并填写表格。

接下来,在命令行中运行 npm adduser:

1
2
3
4
> npm adduser
Username: yournpmusername
Password:
Email: (this IS public) you@example.com

你需要完善你的用户名,密码和邮箱。如果成功了,你将会看到:

1
Logged in as yournpmusername on https://registry.npmjs.org/.

在这里你可能会遇到两个问题: 1. 你被重定向到了 cnpm 而不是 npm 的网站。cnpm不支持公开账号的注册,它只允许你注册一个私人账号。

遇到这个问题是因为你之前可能遇到过 npm 无法安装某些模块的问题,之后在教程的指引下,使用了npmmirrow 淘宝镜像作为 npm 的源,当更改npm的源的时候,账号验证的源也会被设置为淘宝的镜像源。

解决方式有两个,一个是直接切换npm的源,但是这样,当你下次又有无法安装的而模块的时候,你又需要切换回来,最好的办法是自己手动指定一下登入账号使用的源:

1
npm login --registry http://registry.npmjs.com

  1. 密码和账号输入时无法确认是否输入正确且无法复制粘贴。

使用

1
npm login --username <username> --password <password> --email <email>

可以在命令行就指定这些参数,方便检查有无出错。 但是请注意请不要将这行命令添加到公开的文件里,以保护你的账号安全。

构建我们的 WebAssembly npm 包

万事俱备,来创建一个新的 Rust 包吧。打开你用来存放你私人项目的目录,做这些事:

1
2
$ cargo new --lib hello-wasm
Created library `hello-wasm` project

这里会在名为 hello-wasm 的子目录里创建一个新的库,里面有下一步之前你所需要的一切:

1
2
3
+-- Cargo.toml
+-- src
+-- lib.rs

首先,我们有一个 Cargo.toml 文件,这是我们配置构建的方式。如果你用过 Bundler 的 Gemfile 或者 npm 的 package.json,你应该会感到很熟悉。Cargo 的用法和它们类似。

接下来,Cargo 在 src/lib.rs 生成了一些 Rust 代码:

1
2
3
4
5
6
7
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
assert_eq!(2 + 2, 4);
}
}

我们完全不需要使用这些测试代码,所以继续吧,我们删掉它。

来写点 Rust 代码吧!

让我们在 src/lib.rs 写一些代码替换掉原来的:

1
2
3
4
5
6
7
8
9
10
11
12
13
extern crate wasm_bindgen;

use wasm_bindgen::prelude::*;

#[wasm_bindgen]
extern {
pub fn alert(s: &str);
}

#[wasm_bindgen]
pub fn greet(name: &str) {
alert(&format!("Hello, {}!", name));
}

上面是MDN给的代码,它在后面给出了每个部分的解释,你可以点击这里跳转到原文进行查看:来写点 Rust 代码吧!

不过我认为将注释和代码放在一起会更方便于参考,读者可以自行决定使用哪种方式。这里将会给出一个缺少部分细节的高级说明;如果想要了解更多 Rust 知识,请查看在线书籍 The Rust Programming Language

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
/*
第一行就像在说“哇 Rust,我们在用一个叫做 wasm_bindgen 的库”。
在 Rust 当中,库被称为“crates”,因为我们使用的是一个外部库,所以有 "extern"。
明白了吗? Cargo ships crates.
*/
extern crate wasm_bindgen;

/*第三行包括了一个将库中的代码引入到你的代码中的使用命令。
在这个情况下,将会引入 wasm_bindgen::prelude 的全部模块。
我们将在下一节中使用这些内容。 */
use wasm_bindgen::prelude::*;

/*
在 #[] 中的内容叫做 "属性",并以某种方式改变下面的语句。(其实有点类似于C#的属性)
#[wasm_bindgen] 后面跟着的语句是一个 extern,它将告诉 Rust 这下面的函数将由外部提供,我们想调用一些外部定义的函数。
而前面的这个属性标注告诉我们 这些函数将由 "wasm-bindgen" 来进行导入。(类似于 import {alert} from "wasm-bindgen")

这里的 alert 是 js 中的一个函数,它可以打开一个消息通知窗口,参数s为str类型,用于指示显示的内容。

当你想调用新的 JavaScript 函数时,你可以在这里写他们,wasm-bindgen 将负责为你设置一切。

并非一切都得到支持,但我们正在努力!
*/
#[wasm_bindgen]
extern {
pub fn alert(s: &str);
}

/*
这里的 #[wasm_bindgen] 和上面的类似,但是这里,#[wasm_bindgen] 后面 跟着的不再是 extern,而是 pub fn。

这代表我们希望能够在 JavaScript 中使用这个 Rust 函数。
这和 extern 正相反:我们并非引入函数,而是要把函数给外部世界使用。(类比到js里面就是 export {greet})

这个函数的名字是 greet,它需要一个参数,一个字符串(写作 &str)。
它调用了我们前面在 extern 块中引入的 alert 函数。
它传递了一个让我们串联字符串的 format! 宏的调用。

*/
#[wasm_bindgen]
pub fn greet(name: &str) {
/*
format! 在这里有两个参数,一个格式化字符串和一个要填入的变量。
格式化字符串是 "Hello, {}!" 部分。
它可以包含一个或多个 {},变量将会被填入其中。

传递的变量是 name,也就是这个函数的参数。
所以当我们调用 greet("Steve")时我们就能看到 "Hello, Steve!"。
*/
alert(&format!("Hello, {}!", name));
}

把我们的代码编译到 WebAssembly

为了能够正确的编译我们的代码,首先我们需要配置 Cargo.toml。打开这个文件,将内容改为如下所示:

Cargo.toml

1
2
3
4
5
6
7
8
9
10
11
12
13
[package]
name = "hello-wasm"
version = "0.1.0"
authors = ["Your Name <you@example.com>"]
description = "A sample project with wasm-pack"
license = "MIT/Apache-2.0"
repository = "https://github.com/yourgithubusername/hello-wasm"

[lib]
crate-type = ["cdylib"]

[dependencies]
wasm-bindgen = "0.2"

你需要改为自己的仓库,同时 Cargo 需要通过 git 来完善 authors 部分。

最重要的是添加底下的部分。第一个部分 — [lib] — 告诉 Rust 为我们的包建立一个 cdylib 版本;在本教程中我们不会讲解它的含义。有关更多信息,请参阅 CargoRust Linkage 文档。

第二个部分是 [dependencies] 部分。在这里我们告诉 Cargo 我们需要依赖哪个版本的 wasm-bindgen ;在这个例子中,它是 0.2.z 版本的 (不是 0.3.0 或者其他版本)。

构建包

现在我们已经完成了所有配置项,开始构建吧!在命令行输入以下命令:

1
wasm-pack build --scope mynpmusername

或者

1
wasm-pack build

上面的方式会附带你的签名。

这个命令将做一系列事情 (这会花一些时间,特别是当你第一次运行 wasm-pack)。想了解详细情况,查看这篇在 Mozilla Hacks 上的文章。简单来说,wasm-pack build 将做以下几件事:

  1. 将你的 Rust 代码编译成 WebAssembly。
  2. 在编译好的 WebAssembly 代码基础上运行 wasm-bindgen,生成一个 JavaScript 文件将 WebAssembly 文件包装成一个模块以便 npm 能够识别它。
  3. 创建一个 pkg 文件夹并将 JavaScript 文件和生成的 WebAssembly 代码移到其中。
  4. 读取你的 Cargo.toml 并生成相应的 package.json
  5. 复制你的 README.md (如果有的话) 到文件夹中。

最后的结果?你在 pkg 文件夹下有了一个 npm 包。

报错了?对咯!

教程的说明就截止到上面了,但是大概率,你报错了。

MDN的文章毕竟面对的是全球的开发者,但是在国内有一个比较烦的问题就是网络的访问,在执行wasm-pack build的时候,它会这样报错:

1
2
3
4
5
6
7
8
9
10
E:\_Project\Rust\hello-wasm>wasm-pack build
[INFO]: 🎯 Checking for the Wasm target...
[INFO]: 🌀 Compiling to Wasm...
warning: no edition set: defaulting to the 2015 edition while the latest is 2024
Compiling hello-wasm v0.1.0 (E:\_Project\Rust\hello-wasm)
Finished `release` profile [optimized] target(s) in 0.99s
Error: failed to download from https://github.com/WebAssembly/binaryen/releases/download/version_117/binaryen-version_117-x86_64-windows.tar.gz
To disable `wasm-opt`, add `wasm-opt = false` to your package metadata in your `Cargo.toml`.
Caused by: failed to download from https://github.com/WebAssembly/binaryen/releases/download/version_117/binaryen-version_117-x86_64-windows.tar.gz
To disable `wasm-opt`, add `wasm-opt = false` to your package metadata in your `Cargo.toml`.

这里它说是无法下载 wasm-opt 这个东西,但是实际上我直接通过链接是能够直接下载的,网上说更改代理能够解决问题,我这里没有尝试这种方式,但是我还是将这种方法贴在这里:

如果你尝试通过cargo 去提前下载好 wasm-opt 的话,就会遇到另外一个问题,它一会给你报错无法找到c++编译器,但是实际上我的电脑里面安装了vs2019,所以说实际上根本不应该存在这个问题。当我将vs2019的cl.exe添加到环境变量之后,它又会报错说无法找到clang,之后我又去llvm的官网下载了clang,但是它又报错说c++ 'algorithm' file not found,这个问题我解决不了,暂时也不知道是为什么,这让我浪费了很多时间。

对于新学者来说,最好的办法就是按照它的提示的后者,将wasm-opt = false添加到你的Cargo.toml文件中,这样就可以跳过这个步骤,直接编译你的WebAssembly模块。wasm-opt 是一个优化工具,它会对你的WebAssembly模块进行优化,但是实际上,这个优化工具并不是必须的,你可以直接跳过这个步骤,直接编译你的WebAssembly模块。

对了,还有一个问题,就是它虽然叫你需要在 package metadata 中添加wasm-opt = false,但是实际上,你并不知道在哪里添加,需要翻阅官方文档:Cargo.toml Configuration - Hello wasm-pack!

Cargo.toml 配置

wasm-pack 可以通过 Cargo.toml 中的 package.metadata.wasm-pack 键进行配置。 每个选项都有一个默认值,不是必需的。

共有三个配置文件:devprofilingrelease。 这些对应于传递给 wasm-pack build--dev--profiling--release 标志。

可用的配置选项及其默认值如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
[package.metadata.wasm-pack.profile.dev]
# Should `wasm-opt` be used to further optimize the wasm binary generated after
# the Rust compiler has finished? Using `wasm-opt` can often further decrease
# binary size or do clever tricks that haven't made their way into LLVM yet.
#
# Configuration is set to `false` by default for the dev profile, but it can
# be set to an array of strings which are explicit arguments to pass to
# `wasm-opt`. For example `['-Os']` would optimize for size while `['-O4']`
# would execute very expensive optimizations passes
wasm-opt = ['-O']

[package.metadata.wasm-pack.profile.dev.wasm-bindgen]
# Should we enable wasm-bindgen's debug assertions in its generated JS glue?
debug-js-glue = true
# Should wasm-bindgen demangle the symbols in the "name" custom section?
demangle-name-section = true
# Should we emit the DWARF debug info custom sections?
dwarf-debug-info = false

[package.metadata.wasm-pack.profile.profiling]
wasm-opt = ['-O']

[package.metadata.wasm-pack.profile.profiling.wasm-bindgen]
debug-js-glue = false
demangle-name-section = true
dwarf-debug-info = false

# `wasm-opt` is on by default in for the release profile, but it can be
# disabled by setting it to `false`
[package.metadata.wasm-pack.profile.release]
wasm-opt = false

[package.metadata.wasm-pack.profile.release.wasm-bindgen]
debug-js-glue = false
demangle-name-section = true
dwarf-debug-info = false

通过翻阅文档,我们知道,我们需要在package.metadata.wasm-pack.profile.release中添加wasm-opt = false,这样就可以跳过这个步骤了。 修改后的Cargo.toml文件如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[package]
name = "hello-wasm"
version = "0.1.0"
authors = ["Your Name <you@example.com>"]
description = "A sample project with wasm-pack"
license = "MIT/Apache-2.0"
repository = "https://github.com/yourgithubusername/hello-wasm"

[package.metadata.wasm-pack.profile.release]
wasm-opt = false

[lib]
crate-type = ["cdylib"]

[dependencies]
wasm-bindgen = "0.2"

对代码体积的一些说明

如果你检查生成的 WebAssembly 文件体积,它可能有几百 kB。我们没有让 Rust 去压缩生成的代码,从而大大减少生成包的体积。这和本次教程主题无关,但如果你想了解更多,查看 Rust WebAssembly 工作组文档上关于 减少 .wasm 体积 的说明。

把我们的包发布到 npm

把我们的新包发布到 npm registry:

1
2
cd pkg
npm publish --access=public

我们现在有了一个 npm 包,使用 Rust 编写,但已经被编译为 WebAssembly 了。 现在这个包已经可以被 JavaScript 使用了,而且使用它完全不需要用户安装 Rust;包中的代码是 WebAssembly 代码,而不是 Rust 源码!

在网站上使用我们的包

让我们建立一个使用我们包的网站!人们通过各种打包工具使用 npm 包,在本教程中,我们将使用 vite。它比其他某些打包工具要更为的便捷,但是你可以使用任何你喜欢的工具。

从这里开始,将会和MDN的教程有所不同,因为我没有使用webpack,而是使用vite,所以说这里将会给出使用vite的教程。

让我们离开pkg目录,并创建一个新目录site,尝试以下操作:

1
2
3
cd ../..
mkdir site
cd site

创建一个新文件 package.json,然后输入如下代码:

1
2
3
4
5
6
7
8
9
10
11
{
"scripts": {
"dev": "vite",
},
"dependencies": {
"@mynpmusername/hello-wasm": "^0.1.0",
"vite": "^2.6.0",
"vite-plugin-top-level-await": "^1.5.0",
"vite-plugin-wasm": "^3.4.1"
}
}

如果上面你并没有将自己的包发布到npm上,那么你需要手动将上一步生成的pkg文件夹拷贝到site文件夹下,然后在package.json中将dependencies中的@mynpmusername/hello-wasm改为file:./pkg

这样它将会从本地的pkg文件夹中引入你的WebAssembly模块。

如果上面你将自己的包发布到npm上了,那么请注意,你需要在依赖项部分的 @ 之后填写自己的用户名。

接下来,我们需要配置 Vite 来使用 WebAssembly。创建一个新文件 vite.config.js,并输入如下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
import { defineConfig } from 'vite'
import wasm from 'vite-plugin-wasm'
import topLevelAwait from 'vite-plugin-top-level-await'

export default defineConfig({
plugins: [
wasm(),
topLevelAwait()
],
optimizeDeps: {
exclude: ['hello_wasm'],
}
})

这里的optimizeDeps是为了解决一个问题,就是vite会将你的WebAssembly模块当作一个模块来处理,但是实际上它并不是一个模块,所以说我们需要将它排除在外,防止vite对它进行处理,使得模块找不到对应的文件。

vite-plugin-wasm 是一个 Vite 插件,它会帮助你加载 WebAssembly 模块。vite-plugin-top-level-await 是一个 Vite 插件,它会帮助你使用顶层 await。

接下来,我们需要一个 HTML 文件。创建一个index.html并写入如下内容:

1
2
3
4
5
6
7
8
9
10
11
12
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<title>hello-wasm example</title>
</head>
<body>
hello-wasm
<button id="testButton">Test Button</button>
<script type="module" src="./index.js"></script>
</body>
</html>

需要注意的是,MDN 里面使用的是<script src="./index.js"></script>,但是实际上,vite是不支持这种方式的,你需要使用<script type="module" src="./index.js"></script>这种方式来引入你的js文件。

这样的话,你可以在index.js中直接使用import {greet} from '@mynpmusername/hello-wasm'来引入你的WebAssembly模块,而不需要额外的处理。

现在我们来写index.js文件:

1
2
3
4
5
6
7
8
9
import * as wasm from "hello-wasm";

wasm.greet("WebAssembly");
//debug
console.debug("loaded");
document.querySelector("#testButton").addEventListener("click", () => {
console.debug("clicked button");
wasm.greet("WebAssembly");
});

加载后,它将从该模块调用greet函数,并传入字符串“WebAssembly”参数。注意这里看上去没有什么特别的,但是我们正在调用 Rust 代码!就 JavaScript 代码所知,这只是一个普通模块。

我们已经完成了所有的文件!让我们试一下:

1
2
npm install
npm run dev

这将启动一个 Web 服务器。访问 vite 给出的链接,比如,http://localhost:5178/ 你应该会在屏幕上看到一个内容为 Hello, WebAssembly! 的警告框。点击按钮时也会看到这个警告框。

我们已经成功地从 JavaScript 调用了 Rust,并从 Rust 调用了 JavaScript。

结论

本教程到此结束。希望你觉得它有用。

非常感谢来自 Rust 和 WebAssembly 社区的所有人,他们的工作使得这一切成为可能。 同样也非常感谢这位作者,他的文章非常通俗易懂,且提供了github上的代码仓库,让我们可以直接下载代码进行测试: 我使用 vue3 + WebAssembly 做了个文件校验网站,性能提升600%_vue webassembly-CSDN博客 jethroHuang/fast_hash

它的这里面还使用了worker来进一步提高性能,这里就不再赘述了,有兴趣的可以去看看。关于worker的内容,可以参考这篇文章:Web Workers API - Web APIs | MDN

阅读全文 »

# electron

Tauri 初体验:前途可期

之前一直苦恼于 electron 打包出来的体积太大,总是想要使其的体积更小,对于使用者更加友好。

最近发现了一个新的框架:Tauri,它是一个基于 Rust 的框架,可以将 Rust 代码编译成一个可执行文件,然后将这个可执行文件和前端代码打包成一个可执行文件。

本身我就对 Rust 比较感兴趣,所以就尝试了一下。

但是结果就是……Tauri的开发体验简直是糟糕。

简陋的开始

一开始使用一个简单的命令就可以创建一个基础的项目:

1
tauri create my-app

在选择了一些配置项之后,就可以运行这个项目了:

1
2
cd my-app
tauri dev

这个命令会启动一个开发服务器,然后打开一个窗口,显示你的应用。

一步步走到这里,一切都顺利,但是问题是:然后呢?

下面是它的文档的目录:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
-   快速开始

- [什么是 Tauri?](https://v2.tauri.org.cn/start/)
- [先决条件](https://v2.tauri.org.cn/start/prerequisites/)
- [创建项目](https://v2.tauri.org.cn/start/create-project/)
- 前端配置

- [概述](https://v2.tauri.org.cn/start/frontend/)
- [Leptos](https://v2.tauri.org.cn/start/frontend/leptos/)
- [Next.js](https://v2.tauri.org.cn/start/frontend/nextjs/)
- [Nuxt](https://v2.tauri.org.cn/start/frontend/nuxt/)
- [Qwik](https://v2.tauri.org.cn/start/frontend/qwik/)
- [SvelteKit](https://v2.tauri.org.cn/start/frontend/sveltekit/)
- [Trunk](https://v2.tauri.org.cn/start/frontend/trunk/)
- [Vite](https://v2.tauri.org.cn/start/frontend/vite/)

- 升级与迁移

- [概述](https://v2.tauri.org.cn/start/migrate/)
- [从 Tauri 1.0 升级](https://v2.tauri.org.cn/start/migrate/from-tauri-1/)
- [从 Tauri 2.0 Beta 升级](https://v2.tauri.org.cn/start/migrate/from-tauri-2-beta/)

在配置完前端(我使用的是vite)之后呢?让我们继续看看下面的非快速开始的内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
-   核心概念

- [概述](https://v2.tauri.org.cn/concept/)
- [Tauri 架构](https://v2.tauri.org.cn/concept/architecture/)
- [进程模型](https://v2.tauri.org.cn/concept/process-model/)
- [应用大小](https://v2.tauri.org.cn/concept/size/)
- 进程间通信

- [概述](https://v2.tauri.org.cn/concept/inter-process-communication/)
- [棕地模式](https://v2.tauri.org.cn/concept/inter-process-communication/brownfield/)
- [隔离模式](https://v2.tauri.org.cn/concept/inter-process-communication/isolation/)


- 安全性

- [概述](https://v2.tauri.org.cn/security/)
- [权限](https://v2.tauri.org.cn/security/permissions/)
- [命令作用域](https://v2.tauri.org.cn/security/scope/)
- [功能](https://v2.tauri.org.cn/security/capabilities/)
- [内容安全策略 (CSP)](https://v2.tauri.org.cn/security/csp/)
- [HTTP 标头 新](https://v2.tauri.org.cn/security/http-headers/)
- [Tauri 生态系统安全](https://v2.tauri.org.cn/security/ecosystem/)
- [应用程序生命周期威胁](https://v2.tauri.org.cn/security/lifecycle/)
- [未来工作](https://v2.tauri.org.cn/security/future/)
- [运行时权限](https://v2.tauri.org.cn/security/runtime-authority/)

- 开发

- [概述](https://v2.tauri.org.cn/develop/)
- [从 Rust 调用前端](https://v2.tauri.org.cn/develop/calling-frontend/)
- [从前端调用 Rust](https://v2.tauri.org.cn/develop/calling-rust/)
- [配置文件](https://v2.tauri.org.cn/develop/configuration-files/)
- [嵌入其他文件](https://v2.tauri.org.cn/develop/resources/)
- [嵌入外部二进制文件](https://v2.tauri.org.cn/develop/sidecar/)
- [状态管理](https://v2.tauri.org.cn/develop/state-management/)
- [更新依赖项](https://v2.tauri.org.cn/develop/updating-dependencies/)
- 调试

- [概述](https://v2.tauri.org.cn/develop/debug/)
- [CrabNebula DevTools 新](https://v2.tauri.org.cn/develop/debug/crabnebula-devtools/)
- [在 Neovim 中调试](https://v2.tauri.org.cn/develop/debug/neovim/)
- [在 JetBrains IDE 中调试](https://v2.tauri.org.cn/develop/debug/rustrover/)
- [在 VS Code 中调试](https://v2.tauri.org.cn/develop/debug/vscode/)

- 插件

- [概述](https://v2.tauri.org.cn/develop/plugins/)
- [移动插件开发](https://v2.tauri.org.cn/develop/plugins/develop-mobile/)

- 测试

- [概述](https://v2.tauri.org.cn/develop/tests/)
- [模拟 Tauri API](https://v2.tauri.org.cn/develop/tests/mocking/)
- WebDriver

- [概述](https://v2.tauri.org.cn/develop/tests/webdriver/)
- [持续集成](https://v2.tauri.org.cn/develop/tests/webdriver/ci/)
- 示例

- [设置](https://v2.tauri.org.cn/develop/tests/webdriver/example/)
- [Selenium](https://v2.tauri.org.cn/develop/tests/webdriver/example/selenium/)
- [WebdriverIO](https://v2.tauri.org.cn/develop/tests/webdriver/example/webdriverio/)

- 分发

- [概述](https://v2.tauri.org.cn/distribute/)
- ……后面略去

进程间通信这里,它在概述里面介绍了它使用的是类似于 IPC 的方式,但是问题是具体的调用方式在哪里呢?它没有举例子,而文档直到后面的 从 Rust 调用前端 才有介绍。

而且它也没讲解入口文件是哪个?主进程和渲染进程中主进程是在哪个文件中启动的?

模糊的文档

更为好笑的是:

1
import {invoke} from '@tauri-apps/api/tauri'

这个示例用的代码无法运行,因为它找不到这个模块。为什么找不到呢?因为它安装tauri的时候并不默认包含它的api,而是需要手动安装:

1
npm install @tauri-apps/api

欸,你认为这就结束了吗?不,它的文档也没有提到这个模块到底是哪里的,它在:

1
import {invoke} from '@tauri-apps/api/core'

这个模块中。而不是教程中的 @tauri-apps/api/tauri

初次之外,类似的事情还在文件系统上,在文档中它说:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 文件系统

[GitHub](https://github.com/tauri-apps/plugins-workspace/tree/v2/plugins/fs) [npm](https://npmjs.net.cn/package/@tauri-apps/plugin-fs) [crates.io](https://crates.io/crates/tauri-plugin-fs)

API 参考[](https://v2.tauri.org.cn/reference/javascript/fs/)[](https://docs.rs/tauri-plugin-fs)

访问文件系统。

## [支持的平台](https://v2.tauri.org.cn/plugin/file-system/#_top#supported-platforms)

_此插件需要 Rust 版本至少为 **1.77.2**_

| 平台 | 级别 | 注意 |
| --- | --- | --- |
| windows | | 通过 MSI 或 NSIS 安装在 `perMachine` 和 `both` 模式下的应用,需要在 `$RESOURCES` 文件夹中进行写入访问时需要管理员权限|
| linux | | 无法写入访问 `$RESOURCES` 文件夹|
| macos | | 无法写入访问 `$RESOURCES` 文件夹|
| android | | 默认情况下,访问权限仅限于应用程序文件夹 |
| ios | | 默认情况下,访问权限仅限于应用程序文件夹|

但是在另外一处,它说:

1
2
# 文件系统
fs模块可以使用 window.__TAURI__.fs 来访问文件系统。

但是实际上这种方式是无法使用的,因为它需要先安装 @tauri-apps/api/fs,而不是 @tauri-apps/plugin-fs

欸,但是 2.0 版本的 fs 模块已经被默认移除了,需要使用 plugin-fs。

## 缺失的功能

我写的程序为了优化性能,使用了creatlink而非copy,但是在tauri中并没有这个功能,所以我需要自己写一个rust后端来实现这个功能并且还需要处理多平台的问题,要么就是仍然使用 nodejs 作为依赖。

但是这样的话,tauri的优势就没有了,因为我还是需要依赖 nodejs。

……

总结

只能说未来可期,但是现在的体验真的是太差了,文档不全,不清晰,而且还有很多坑,不建议使用。

不过rust的编程的思路很有意思,虽然说编程的时候碍手碍脚的,但是因为其稳定性和性能,还是值得一试的。

阅读全文 »

# AI绘画
## Day 2:提示词与参数优化

学习目标:掌握提示词编写技巧,调整参数提升生成质量。 - 实践步骤: 1. 提示词公式:使用“主体+细节+风格+质量”结构(如“a knight in armor, detailed armor texture, dark fantasy style, 8k, masterpiece”)。 2. 权重控制:用(keyword:1.5)增强权重,[keyword]降低权重。 3. 参数调整: - 采样方法:推荐DPM++ 2M Karras(速度快且稳定)。 - 迭代步数:20-30步(平衡速度与质量)。 - 提示词相关性(CFG Scale):7-12(值越高越贴近描述,但可能过锐化)。 - 检验成果:生成一张符合复杂提示词描述的图片(如“科幻城市夜景,赛博朋克风格”)。

为此我研读了这本书,元素同典:确实不完全科学的魔导书

我会在另外一篇文章里面分享自己的 结合书本中的知识以的实战经历[[元素同典:确实不完全科学的魔导书 批注]]

预制提示词测试

这里,大佬给了一个非常棒的风格模板,后面加上想要的提示词大概率能出非常好的图像效果:

00086-1533094715.png

1
2
3
(masterpiece, extremely detailed 8k wallpaper,best quality),(best illumination, best shadow, extremely delicate and beautiful),dynamic angle,floating,finely detail,Depth of field (bloom),(shine),glinting stars,classic,(illustration),(painting),(sketch),1girl,solo,bare shoulders,medium breasts,areola,red eyes,beautiful detailed cold face,black hair,straight_hair,short hair,extremely delicate and beautiful girls,beautiful detailed eyes,(((rose))),cage,bandage,(red rope),  
Negative prompt: lowres,bad anatomy,bad hands,text,error,missing fingers,extra digit,fewer digits,cropped,worst quality,low quality,normal quality,jpeg artifacts,signature,watermark,username,blurry,sketches,EasyNegativeV2,badhandv4,
Steps: 18, Sampler: DPM++ 2M, Schedule type: Karras, CFG scale: 7, Seed: 1533094715, Size: 512x512, Model hash: 7f96a1a9ca, Model: anything-v5, Denoising strength: 0.7, Clip skip: 2, Hires upscale: 2, Hires upscaler: Latent, TI hashes: "EasyNegativeV2: 339cc9210f70, badhandv4: 5e40d722fc3d", Version: v1.10.1

迭代步数和采样方式对结果的影响

在控制同一个seed的情况下,我们可以用 X/Y参照来生成对比图像:

这里,我用提示词为:

1
masterpiece,1 girl,cute face,black short hair,red eyes,[SFW:(NSFW:1):0.1],
负面提示词为:
1
2
3
lowres,bad anatomy,bad hands,text,error,missing fingers,extra digit,
fewer digits,cropped,worst quality,low quality,normal quality,jpeg artifacts,
signature,watermark,username,blurry,bad fee,

镜头控制

close up、close shot、medium view、panorama 这几个镜头控制十分好用

吟唱方式

常见的吟唱方式有三种: 1. 字节式 ## 提示词的分割

语法功能

提示词

提示词是用于提示ai需要生成什么样式的图片的引导词,ai会根据你的提示词生成图片。

为什么提示词会有效我们可以从文生图的原理说起: SD等模型使用的都是让使用将一个带有若干个标签的图片,通过不断参杂噪声,让其变为一张纯噪声图作为正向过程让ai去学习,而这个参杂的过程在一定程度上是可逆的,所以说将ai通过这种方式得到的一系列参数求一个逆,我们就可以得到一个能够从一个噪声图生成为我们想要的图片的模型。

也就是说,提示词本质上就是一开始用来训练ai的图片上面带着的标签,了解训练ai的数据的来源,我们可以直到每个标签大概指的是什么意思:Danbooru: Anime Image Board

但是它们可能有的好用有的不好用,一般引用数大于2000的tag都能够出比较好的效果。

这里还有一些小伙伴们自己收集的比较好的tag资料: https://kdocs.cn/l/cre0TwbMkdx3 https://pan.baidu.com/s/11SE4uW0TiXqrHotBfT3hsQ?pwd=pdlk

然后这里是一些比较好的提示词组合,可以以此为范例: 元素法典 第二点五卷——Novel AI 元素魔法全收录 元素法典 第二卷——Novel AI 元素魔法全收录 等等

提示词 权重调整方法

权重控制在咒语中非常重要,这关系着你想要的东西是否合乎心意的获得了AI的重视。

最基础的权重控制为控制prompt在咒语中的位置。越靠前的词汇越受到重视。

权重控制可以通过对prompt加括号进行。() 或 {} 为加强权重,[] 为减弱权重,括号可以一次扩多个词条。(1girl:1.5)括号后对添加 ":1.5"是对词条直接赋予权重,数字即为权重大小。数字越大权重越大,默认1,通常为0-2之间。

目前在webui中()为对其中内容权重乘以1.1,[]为对其中内容除以1.1,而{}在webui版本中不生效。虽然多重括号也能生效,但是这种方法低效且不优雅,例如((((girl))))进行了4次括号,但是只对girl权重增加到了1.4641。

这里强烈推荐使用(prompt:权重数)的方式来进行权重调整。

比如,你可以在提示词中加入[],然后在括号中加入权重数,这样就可以对整个括号内的词条进行权重调整。

此外,webui还支持快速调节:选中一组词,然后按方向键上下(根据编译器版本不同可能是ctrl+方向键)可以直接完成权重调整。

权重调整的高阶技巧

除了上面的方法可以调整权重之外,还可以使用·

1
[from:to:step]
来配置阶段性的权重调整。

它可以在步数进行到 某一阶段时,将prompt 从 from 变成 to。

比如我个人觉得比较好用的一个是[SFW:NSFW:0.1] ,这样可以在推理的早些阶段,生成一个 SFW 的底图,之后,在经过了整体步数的 10% 之后,再转换为 NSFW 的图像。

这样可以保证擦边球的图像不会在早期就生成,而是在后期生成,从而保证了生成的图像的质量。

书写技巧

上面是单个词的方法,但是实际上我们需要的画面并不能使用寥寥几个词就能够描述,想要生成出好的效果,往往需要在多个方面去对于画面进行描述,对于画面中的元素进行控制,这就需要我们将多个提示词组合起来,构成一整句“咒语”。

三种常见的书写方式及其异同

这里直接引用 [[元素同典:确实不完全科学的魔导书.pdf]] 里面的原文了:

咏唱大致有着三种不同形式——最常见的直接咏唱、稍不常见的短句咏唱和堪称行为艺术一般的长咏唱。

假设要生成一个有着黄色头发、蓝色眼眸、白色上衣、红色裙子、黑色裤袜的全身坐姿二次元美少女,且强调服饰颜色,那么这三种咏唱分别看上去大概是这样的:

直接咏唱(pitch 式咏唱):

masterpiece, best quality, 1 girl, (blue eyes), (yellow hair), (white clothes), (red skirt), (black leggings), sitting, full body

短句咏唱(AND 强调咏唱):

masterpiece, best quality, 1 girl, (blue eyes) AND (yellow hair), (white clothes) AND (red skirt) AND (black leggings), sitting, full body

注意短句咏唱的 AND 必须是三个大写字母,AND 两侧的小括号是不必要的(但建议加上),这是一个专用语法,不过因为效果仍未明晰所以不单独介绍。此外,该语法并不能应用于所有采样方法,例如 DDIM 就不支持 AND,会导致报错。

这里似乎有点问题,大写“AND”会导致碎片化图片,但是小写“and”反而可以正常出图,估计是版本更新的问题

长咏唱(自然语言咏唱):

masterpiece, best quality, (1 girl with blue eyes and yellow hair wearing white clothes and red skirt with black leggings), sitting, full body

阅读全文 »

# AI绘画

Day 1:安装环境与基础生成

学习目标:完成Stable Diffusion本地部署,生成第一张AI图片。 - 实践步骤: 1. 下载秋葉整合包(解压密码:bilibili@秋葉aaaki),安装.NET依赖项,双击启动器一键运行。 2. 打开WebUI界面(默认地址http://127.0.0.1:7860),输入简单提示词(如“1 girl, masterpiece”),生成测试图。 3. 熟悉界面功能:模型切换、提示词输入区、生成参数(采样方法、迭代步数)。 - 检验成果:成功生成一张基础图片(如猫或人物)。 - 学习资料: - 秋葉整合包安装教程:CSDN博客。 - 界面功能速查表(见下文)。

阅读全文 »
0%