diff --git a/configs/sd-concepts.txt b/configs/sd-concepts.txt new file mode 100644 index 0000000000..969f628c4f --- /dev/null +++ b/configs/sd-concepts.txt @@ -0,0 +1,803 @@ +sd-concepts-library/001glitch-core +sd-concepts-library/2814-roth +sd-concepts-library/3d-female-cyborgs +sd-concepts-library/4tnght +sd-concepts-library/80s-anime-ai +sd-concepts-library/80s-anime-ai-being +sd-concepts-library/852style-girl +sd-concepts-library/8bit +sd-concepts-library/8sconception +sd-concepts-library/Aflac-duck +sd-concepts-library/Akitsuki +sd-concepts-library/Atako +sd-concepts-library/Exodus-Styling +sd-concepts-library/RINGAO +sd-concepts-library/a-female-hero-from-the-legend-of-mir +sd-concepts-library/a-hat-kid +sd-concepts-library/a-tale-of-two-empires +sd-concepts-library/aadhav-face +sd-concepts-library/aavegotchi +sd-concepts-library/abby-face +sd-concepts-library/abstract-concepts +sd-concepts-library/accurate-angel +sd-concepts-library/agm-style-nao +sd-concepts-library/aj-fosik +sd-concepts-library/alberto-mielgo +sd-concepts-library/alex-portugal +sd-concepts-library/alex-thumbnail-object-2000-steps +sd-concepts-library/aleyna-tilki +sd-concepts-library/alf +sd-concepts-library/alicebeta +sd-concepts-library/alien-avatar +sd-concepts-library/alisa +sd-concepts-library/all-rings-albuns +sd-concepts-library/altvent +sd-concepts-library/altyn-helmet +sd-concepts-library/amine +sd-concepts-library/amogus +sd-concepts-library/anders-zorn +sd-concepts-library/angus-mcbride-style +sd-concepts-library/animalve3-1500seq +sd-concepts-library/anime-background-style +sd-concepts-library/anime-background-style-v2 +sd-concepts-library/anime-boy +sd-concepts-library/anime-girl +sd-concepts-library/anyXtronXredshift +sd-concepts-library/anya-forger +sd-concepts-library/apex-wingman +sd-concepts-library/apulian-rooster-v0-1 +sd-concepts-library/arcane-face +sd-concepts-library/arcane-style-jv +sd-concepts-library/arcimboldo-style +sd-concepts-library/armando-reveron-style +sd-concepts-library/armor-concept +sd-concepts-library/arq-render +sd-concepts-library/art-brut +sd-concepts-library/arthur1 +sd-concepts-library/artist-yukiko-kanagai +sd-concepts-library/arwijn +sd-concepts-library/ashiok +sd-concepts-library/at-wolf-boy-object +sd-concepts-library/atm-ant +sd-concepts-library/atm-ant-2 +sd-concepts-library/axe-tattoo +sd-concepts-library/ayush-spider-spr +sd-concepts-library/azura-from-vibrant-venture +sd-concepts-library/ba-shiroko +sd-concepts-library/babau +sd-concepts-library/babs-bunny +sd-concepts-library/babushork +sd-concepts-library/backrooms +sd-concepts-library/bad_Hub_Hugh +sd-concepts-library/bada-club +sd-concepts-library/baldi +sd-concepts-library/baluchitherian +sd-concepts-library/bamse +sd-concepts-library/bamse-og-kylling +sd-concepts-library/bee +sd-concepts-library/beholder +sd-concepts-library/beldam +sd-concepts-library/belen +sd-concepts-library/bella-goth +sd-concepts-library/belle-delphine +sd-concepts-library/bert-muppet +sd-concepts-library/better-collage3 +sd-concepts-library/between2-mt-fade +sd-concepts-library/birb-style +sd-concepts-library/black-and-white-design +sd-concepts-library/black-waifu +sd-concepts-library/bloo +sd-concepts-library/blue-haired-boy +sd-concepts-library/blue-zombie +sd-concepts-library/blue-zombiee +sd-concepts-library/bluebey +sd-concepts-library/bluebey-2 +sd-concepts-library/bobs-burgers +sd-concepts-library/boissonnard +sd-concepts-library/bonzi-monkey +sd-concepts-library/borderlands +sd-concepts-library/bored-ape-textual-inversion +sd-concepts-library/boris-anderson +sd-concepts-library/bozo-22 +sd-concepts-library/breakcore +sd-concepts-library/brittney-williams-art +sd-concepts-library/bruma +sd-concepts-library/brunnya +sd-concepts-library/buddha-statue +sd-concepts-library/bullvbear +sd-concepts-library/button-eyes +sd-concepts-library/canadian-goose +sd-concepts-library/canary-cap +sd-concepts-library/cancer_style +sd-concepts-library/captain-haddock +sd-concepts-library/captainkirb +sd-concepts-library/car-toy-rk +sd-concepts-library/carasibana +sd-concepts-library/carlitos-el-mago +sd-concepts-library/carrascharacter +sd-concepts-library/cartoona-animals +sd-concepts-library/cat-toy +sd-concepts-library/centaur +sd-concepts-library/cgdonny1 +sd-concepts-library/cham +sd-concepts-library/chandra-nalaar +sd-concepts-library/char-con +sd-concepts-library/character-pingu +sd-concepts-library/cheburashka +sd-concepts-library/chen-1 +sd-concepts-library/child-zombie +sd-concepts-library/chillpill +sd-concepts-library/chonkfrog +sd-concepts-library/chop +sd-concepts-library/christo-person +sd-concepts-library/chuck-walton +sd-concepts-library/chucky +sd-concepts-library/chungus-poodl-pet +sd-concepts-library/cindlop +sd-concepts-library/collage-cutouts +sd-concepts-library/collage14 +sd-concepts-library/collage3 +sd-concepts-library/collage3-hubcity +sd-concepts-library/cologne +sd-concepts-library/color-page +sd-concepts-library/colossus +sd-concepts-library/command-and-conquer-remastered-cameos +sd-concepts-library/concept-art +sd-concepts-library/conner-fawcett-style +sd-concepts-library/conway-pirate +sd-concepts-library/coop-himmelblau +sd-concepts-library/coraline +sd-concepts-library/cornell-box +sd-concepts-library/cortana +sd-concepts-library/covid-19-rapid-test +sd-concepts-library/cow-uwu +sd-concepts-library/cowboy +sd-concepts-library/crazy-1 +sd-concepts-library/crazy-2 +sd-concepts-library/crb-portraits +sd-concepts-library/crb-surrealz +sd-concepts-library/crbart +sd-concepts-library/crested-gecko +sd-concepts-library/crinos-form-garou +sd-concepts-library/cry-baby-style +sd-concepts-library/crybaby-style-2-0 +sd-concepts-library/csgo-awp-object +sd-concepts-library/csgo-awp-texture-map +sd-concepts-library/cubex +sd-concepts-library/cumbia-peruana +sd-concepts-library/cute-bear +sd-concepts-library/cute-cat +sd-concepts-library/cute-game-style +sd-concepts-library/cyberpunk-lucy +sd-concepts-library/dabotap +sd-concepts-library/dan-mumford +sd-concepts-library/dan-seagrave-art-style +sd-concepts-library/dark-penguin-pinguinanimations +sd-concepts-library/darkpenguinanimatronic +sd-concepts-library/darkplane +sd-concepts-library/david-firth-artstyle +sd-concepts-library/david-martinez-cyberpunk +sd-concepts-library/david-martinez-edgerunners +sd-concepts-library/david-moreno-architecture +sd-concepts-library/daycare-attendant-sun-fnaf +sd-concepts-library/ddattender +sd-concepts-library/degods +sd-concepts-library/degodsheavy +sd-concepts-library/depthmap +sd-concepts-library/depthmap-style +sd-concepts-library/design +sd-concepts-library/detectivedinosaur1 +sd-concepts-library/diaosu-toy +sd-concepts-library/dicoo +sd-concepts-library/dicoo2 +sd-concepts-library/dishonored-portrait-styles +sd-concepts-library/disquieting-muses +sd-concepts-library/ditko +sd-concepts-library/dlooak +sd-concepts-library/doc +sd-concepts-library/doener-red-line-art +sd-concepts-library/dog +sd-concepts-library/dog-django +sd-concepts-library/doge-pound +sd-concepts-library/dong-ho +sd-concepts-library/dong-ho2 +sd-concepts-library/doose-s-realistic-art-style +sd-concepts-library/dq10-anrushia +sd-concepts-library/dr-livesey +sd-concepts-library/dr-strange +sd-concepts-library/dragonborn +sd-concepts-library/dreamcore +sd-concepts-library/dreamy-painting +sd-concepts-library/drive-scorpion-jacket +sd-concepts-library/dsmuses +sd-concepts-library/dtv-pkmn +sd-concepts-library/dullboy-caricature +sd-concepts-library/duranduran +sd-concepts-library/durer-style +sd-concepts-library/dyoudim-style +sd-concepts-library/early-mishima-kurone +sd-concepts-library/eastward +sd-concepts-library/eddie +sd-concepts-library/edgerunners-style +sd-concepts-library/edgerunners-style-v2 +sd-concepts-library/el-salvador-style-style +sd-concepts-library/elegant-flower +sd-concepts-library/elspeth-tirel +sd-concepts-library/eru-chitanda-casual +sd-concepts-library/erwin-olaf-style +sd-concepts-library/ettblackteapot +sd-concepts-library/explosions-cat +sd-concepts-library/eye-of-agamotto +sd-concepts-library/f-22 +sd-concepts-library/facadeplace +sd-concepts-library/fairy-tale-painting-style +sd-concepts-library/fairytale +sd-concepts-library/fang-yuan-001 +sd-concepts-library/faraon-love-shady +sd-concepts-library/fasina +sd-concepts-library/felps +sd-concepts-library/female-kpop-singer +sd-concepts-library/fergal-cat +sd-concepts-library/filename-2 +sd-concepts-library/fileteado-porteno +sd-concepts-library/final-fantasy-logo +sd-concepts-library/fireworks-over-water +sd-concepts-library/fish +sd-concepts-library/flag-ussr +sd-concepts-library/flatic +sd-concepts-library/floral +sd-concepts-library/fluid-acrylic-jellyfish-creatures-style-of-carl-ingram-art +sd-concepts-library/fnf-boyfriend +sd-concepts-library/fold-structure +sd-concepts-library/fox-purple +sd-concepts-library/fractal +sd-concepts-library/fractal-flame +sd-concepts-library/fractal-temple-style +sd-concepts-library/frank-frazetta +sd-concepts-library/franz-unterberger +sd-concepts-library/freddy-fazbear +sd-concepts-library/freefonix-style +sd-concepts-library/furrpopasthetic +sd-concepts-library/fursona +sd-concepts-library/fzk +sd-concepts-library/galaxy-explorer +sd-concepts-library/ganyu-genshin-impact +sd-concepts-library/garcon-the-cat +sd-concepts-library/garfield-pizza-plush +sd-concepts-library/garfield-pizza-plush-v2 +sd-concepts-library/gba-fe-class-cards +sd-concepts-library/gba-pokemon-sprites +sd-concepts-library/geggin +sd-concepts-library/ggplot2 +sd-concepts-library/ghost-style +sd-concepts-library/ghostproject-men +sd-concepts-library/gibasachan-v0 +sd-concepts-library/gim +sd-concepts-library/gio +sd-concepts-library/giygas +sd-concepts-library/glass-pipe +sd-concepts-library/glass-prism-cube +sd-concepts-library/glow-forest +sd-concepts-library/goku +sd-concepts-library/gram-tops +sd-concepts-library/green-blue-shanshui +sd-concepts-library/green-tent +sd-concepts-library/grifter +sd-concepts-library/grisstyle +sd-concepts-library/grit-toy +sd-concepts-library/gt-color-paint-2 +sd-concepts-library/gta5-artwork +sd-concepts-library/guttestreker +sd-concepts-library/gymnastics-leotard-v2 +sd-concepts-library/half-life-2-dog +sd-concepts-library/handstand +sd-concepts-library/hanfu-anime-style +sd-concepts-library/happy-chaos +sd-concepts-library/happy-person12345 +sd-concepts-library/happy-person12345-assets +sd-concepts-library/harley-quinn +sd-concepts-library/harmless-ai-1 +sd-concepts-library/harmless-ai-house-style-1 +sd-concepts-library/hd-emoji +sd-concepts-library/heather +sd-concepts-library/henjo-techno-show +sd-concepts-library/herge-style +sd-concepts-library/hiten-style-nao +sd-concepts-library/hitokomoru-style-nao +sd-concepts-library/hiyuki-chan +sd-concepts-library/hk-bamboo +sd-concepts-library/hk-betweenislands +sd-concepts-library/hk-bicycle +sd-concepts-library/hk-blackandwhite +sd-concepts-library/hk-breakfast +sd-concepts-library/hk-buses +sd-concepts-library/hk-clouds +sd-concepts-library/hk-goldbuddha +sd-concepts-library/hk-goldenlantern +sd-concepts-library/hk-hkisland +sd-concepts-library/hk-leaves +sd-concepts-library/hk-market +sd-concepts-library/hk-oldcamera +sd-concepts-library/hk-opencamera +sd-concepts-library/hk-peach +sd-concepts-library/hk-phonevax +sd-concepts-library/hk-streetpeople +sd-concepts-library/hk-vintage +sd-concepts-library/hoi4 +sd-concepts-library/hoi4-leaders +sd-concepts-library/homestuck-sprite +sd-concepts-library/homestuck-troll +sd-concepts-library/hours-sentry-fade +sd-concepts-library/hours-style +sd-concepts-library/hrgiger-drmacabre +sd-concepts-library/huang-guang-jian +sd-concepts-library/huatli +sd-concepts-library/huayecai820-greyscale +sd-concepts-library/hub-city +sd-concepts-library/hubris-oshri +sd-concepts-library/huckleberry +sd-concepts-library/hydrasuit +sd-concepts-library/i-love-chaos +sd-concepts-library/ibere-thenorio +sd-concepts-library/ic0n +sd-concepts-library/ie-gravestone +sd-concepts-library/ikea-fabler +sd-concepts-library/illustration-style +sd-concepts-library/ilo-kunst +sd-concepts-library/ilya-shkipin +sd-concepts-library/im-poppy +sd-concepts-library/ina-art +sd-concepts-library/indian-watercolor-portraits +sd-concepts-library/indiana +sd-concepts-library/ingmar-bergman +sd-concepts-library/insidewhale +sd-concepts-library/interchanges +sd-concepts-library/inuyama-muneto-style-nao +sd-concepts-library/irasutoya +sd-concepts-library/iridescent-illustration-style +sd-concepts-library/iridescent-photo-style +sd-concepts-library/isabell-schulte-pv-pvii-3000steps +sd-concepts-library/isabell-schulte-pviii-1-image-style +sd-concepts-library/isabell-schulte-pviii-1024px-1500-steps-style +sd-concepts-library/isabell-schulte-pviii-12tiles-3000steps-style +sd-concepts-library/isabell-schulte-pviii-4-tiles-1-lr-3000-steps-style +sd-concepts-library/isabell-schulte-pviii-4-tiles-3-lr-5000-steps-style +sd-concepts-library/isabell-schulte-pviii-4tiles-500steps +sd-concepts-library/isabell-schulte-pviii-4tiles-6000steps +sd-concepts-library/isabell-schulte-pviii-style +sd-concepts-library/isometric-tile-test +sd-concepts-library/jacqueline-the-unicorn +sd-concepts-library/james-web-space-telescope +sd-concepts-library/jamie-hewlett-style +sd-concepts-library/jamiels +sd-concepts-library/jang-sung-rak-style +sd-concepts-library/jetsetdreamcastcovers +sd-concepts-library/jin-kisaragi +sd-concepts-library/jinjoon-lee-they +sd-concepts-library/jm-bergling-monogram +sd-concepts-library/joe-mad +sd-concepts-library/joe-whiteford-art-style +sd-concepts-library/joemad +sd-concepts-library/john-blanche +sd-concepts-library/johnny-silverhand +sd-concepts-library/jojo-bizzare-adventure-manga-lineart +sd-concepts-library/jos-de-kat +sd-concepts-library/junji-ito-artstyle +sd-concepts-library/kaleido +sd-concepts-library/kaneoya-sachiko +sd-concepts-library/kanovt +sd-concepts-library/kanv1 +sd-concepts-library/karan-gloomy +sd-concepts-library/karl-s-lzx-1 +sd-concepts-library/kasumin +sd-concepts-library/kawaii-colors +sd-concepts-library/kawaii-girl-plus-object +sd-concepts-library/kawaii-girl-plus-style +sd-concepts-library/kawaii-girl-plus-style-v1-1 +sd-concepts-library/kay +sd-concepts-library/kaya-ghost-assasin +sd-concepts-library/ki +sd-concepts-library/kinda-sus +sd-concepts-library/kings-quest-agd +sd-concepts-library/kiora +sd-concepts-library/kira-sensei +sd-concepts-library/kirby +sd-concepts-library/klance +sd-concepts-library/kodakvision500t +sd-concepts-library/kogatan-shiny +sd-concepts-library/kogecha +sd-concepts-library/kojima-ayami +sd-concepts-library/koko-dog +sd-concepts-library/kuvshinov +sd-concepts-library/kysa-v-style +sd-concepts-library/laala-character +sd-concepts-library/larrette +sd-concepts-library/lavko +sd-concepts-library/lazytown-stephanie +sd-concepts-library/ldr +sd-concepts-library/ldrs +sd-concepts-library/led-toy +sd-concepts-library/lego-astronaut +sd-concepts-library/leica +sd-concepts-library/leif-jones +sd-concepts-library/lex +sd-concepts-library/liliana +sd-concepts-library/liliana-vess +sd-concepts-library/liminal-spaces-2-0 +sd-concepts-library/liminalspaces +sd-concepts-library/line-art +sd-concepts-library/line-style +sd-concepts-library/linnopoke +sd-concepts-library/liquid-light +sd-concepts-library/liqwid-aquafarmer +sd-concepts-library/lizardman +sd-concepts-library/loab-character +sd-concepts-library/loab-style +sd-concepts-library/lofa +sd-concepts-library/logo-with-face-on-shield +sd-concepts-library/lolo +sd-concepts-library/looney-anime +sd-concepts-library/lost-rapper +sd-concepts-library/lphr-style +sd-concepts-library/lucario +sd-concepts-library/lucky-luke +sd-concepts-library/lugal-ki-en +sd-concepts-library/luinv2 +sd-concepts-library/lula-13 +sd-concepts-library/lumio +sd-concepts-library/lxj-o4 +sd-concepts-library/m-geo +sd-concepts-library/m-geoo +sd-concepts-library/madhubani-art +sd-concepts-library/mafalda-character +sd-concepts-library/magic-pengel +sd-concepts-library/malika-favre-art-style +sd-concepts-library/manga-style +sd-concepts-library/marbling-art +sd-concepts-library/margo +sd-concepts-library/marty +sd-concepts-library/marty6 +sd-concepts-library/mass +sd-concepts-library/masyanya +sd-concepts-library/masyunya +sd-concepts-library/mate +sd-concepts-library/matthew-stone +sd-concepts-library/mattvidpro +sd-concepts-library/maurice-quentin-de-la-tour-style +sd-concepts-library/maus +sd-concepts-library/max-foley +sd-concepts-library/mayor-richard-irvin +sd-concepts-library/mechasoulall +sd-concepts-library/medazzaland +sd-concepts-library/memnarch-mtg +sd-concepts-library/metagabe +sd-concepts-library/meyoco +sd-concepts-library/meze-audio-elite-headphones +sd-concepts-library/midjourney-style +sd-concepts-library/mikako-method +sd-concepts-library/mikako-methodi2i +sd-concepts-library/miko-3-robot +sd-concepts-library/milady +sd-concepts-library/mildemelwe-style +sd-concepts-library/million-live-akane-15k +sd-concepts-library/million-live-akane-3k +sd-concepts-library/million-live-akane-shifuku-3k +sd-concepts-library/million-live-spade-q-object-3k +sd-concepts-library/million-live-spade-q-style-3k +sd-concepts-library/minecraft-concept-art +sd-concepts-library/mishima-kurone +sd-concepts-library/mizkif +sd-concepts-library/moeb-style +sd-concepts-library/moebius +sd-concepts-library/mokoko +sd-concepts-library/mokoko-seed +sd-concepts-library/monster-girl +sd-concepts-library/monster-toy +sd-concepts-library/monte-novo +sd-concepts-library/moo-moo +sd-concepts-library/morino-hon-style +sd-concepts-library/moxxi +sd-concepts-library/msg +sd-concepts-library/mtg-card +sd-concepts-library/mtl-longsky +sd-concepts-library/mu-sadr +sd-concepts-library/munch-leaks-style +sd-concepts-library/museum-by-coop-himmelblau +sd-concepts-library/muxoyara +sd-concepts-library/my-hero-academia-style +sd-concepts-library/my-mug +sd-concepts-library/mycat +sd-concepts-library/mystical-nature +sd-concepts-library/naf +sd-concepts-library/nahiri +sd-concepts-library/namine-ritsu +sd-concepts-library/naoki-saito +sd-concepts-library/nard-style +sd-concepts-library/naruto +sd-concepts-library/natasha-johnston +sd-concepts-library/nathan-wyatt +sd-concepts-library/naval-portrait +sd-concepts-library/nazuna +sd-concepts-library/nebula +sd-concepts-library/ned-flanders +sd-concepts-library/neon-pastel +sd-concepts-library/new-priests +sd-concepts-library/nic-papercuts +sd-concepts-library/nikodim +sd-concepts-library/nissa-revane +sd-concepts-library/nixeu +sd-concepts-library/noggles +sd-concepts-library/nomad +sd-concepts-library/nouns-glasses +sd-concepts-library/obama-based-on-xi +sd-concepts-library/obama-self-2 +sd-concepts-library/og-mox-style +sd-concepts-library/ohisashiburi-style +sd-concepts-library/oleg-kuvaev +sd-concepts-library/olli-olli +sd-concepts-library/on-kawara +sd-concepts-library/one-line-drawing +sd-concepts-library/onepunchman +sd-concepts-library/onzpo +sd-concepts-library/orangejacket +sd-concepts-library/ori +sd-concepts-library/ori-toor +sd-concepts-library/orientalist-art +sd-concepts-library/osaka-jyo +sd-concepts-library/osaka-jyo2 +sd-concepts-library/osrsmini2 +sd-concepts-library/osrstiny +sd-concepts-library/other-mother +sd-concepts-library/ouroboros +sd-concepts-library/outfit-items +sd-concepts-library/overprettified +sd-concepts-library/owl-house +sd-concepts-library/painted-by-silver-of-999 +sd-concepts-library/painted-by-silver-of-999-2 +sd-concepts-library/painted-student +sd-concepts-library/painting +sd-concepts-library/pantone-milk +sd-concepts-library/paolo-bonolis +sd-concepts-library/party-girl +sd-concepts-library/pascalsibertin +sd-concepts-library/pastelartstyle +sd-concepts-library/paul-noir +sd-concepts-library/pen-ink-portraits-bennorthen +sd-concepts-library/phan +sd-concepts-library/phan-s-collage +sd-concepts-library/phc +sd-concepts-library/phoenix-01 +sd-concepts-library/pineda-david +sd-concepts-library/pink-beast-pastelae-style +sd-concepts-library/pintu +sd-concepts-library/pion-by-august-semionov +sd-concepts-library/piotr-jablonski +sd-concepts-library/pixel-mania +sd-concepts-library/pixel-toy +sd-concepts-library/pjablonski-style +sd-concepts-library/plant-style +sd-concepts-library/plen-ki-mun +sd-concepts-library/pokemon-conquest-sprites +sd-concepts-library/pool-test +sd-concepts-library/poolrooms +sd-concepts-library/poring-ragnarok-online +sd-concepts-library/poutine-dish +sd-concepts-library/princess-knight-art +sd-concepts-library/progress-chip +sd-concepts-library/puerquis-toy +sd-concepts-library/purplefishli +sd-concepts-library/pyramidheadcosplay +sd-concepts-library/qpt-atrium +sd-concepts-library/quiesel +sd-concepts-library/r-crumb-style +sd-concepts-library/rahkshi-bionicle +sd-concepts-library/raichu +sd-concepts-library/rail-scene +sd-concepts-library/rail-scene-style +sd-concepts-library/ralph-mcquarrie +sd-concepts-library/ransom +sd-concepts-library/rayne-weynolds +sd-concepts-library/rcrumb-portraits-style +sd-concepts-library/rd-chaos +sd-concepts-library/rd-paintings +sd-concepts-library/red-glasses +sd-concepts-library/reeducation-camp +sd-concepts-library/reksio-dog +sd-concepts-library/rektguy +sd-concepts-library/remert +sd-concepts-library/renalla +sd-concepts-library/repeat +sd-concepts-library/retro-girl +sd-concepts-library/retro-mecha-rangers +sd-concepts-library/retropixelart-pinguin +sd-concepts-library/rex-deno +sd-concepts-library/rhizomuse-machine-bionic-sculpture +sd-concepts-library/ricar +sd-concepts-library/rickyart +sd-concepts-library/rico-face +sd-concepts-library/riker-doll +sd-concepts-library/rikiart +sd-concepts-library/rikiboy-art +sd-concepts-library/rilakkuma +sd-concepts-library/rishusei-style +sd-concepts-library/rj-palmer +sd-concepts-library/rl-pkmn-test +sd-concepts-library/road-to-ruin +sd-concepts-library/robertnava +sd-concepts-library/roblox-avatar +sd-concepts-library/roy-lichtenstein +sd-concepts-library/ruan-jia +sd-concepts-library/russian +sd-concepts-library/s1m-naoto-ohshima +sd-concepts-library/saheeli-rai +sd-concepts-library/sakimi-style +sd-concepts-library/salmonid +sd-concepts-library/sam-yang +sd-concepts-library/sanguo-guanyu +sd-concepts-library/sas-style +sd-concepts-library/scarlet-witch +sd-concepts-library/schloss-mosigkau +sd-concepts-library/scrap-style +sd-concepts-library/scratch-project +sd-concepts-library/sculptural-style +sd-concepts-library/sd-concepts-library-uma-meme +sd-concepts-library/seamless-ground +sd-concepts-library/selezneva-alisa +sd-concepts-library/sem-mac2n +sd-concepts-library/senneca +sd-concepts-library/seraphimmoonshadow-art +sd-concepts-library/sewerslvt +sd-concepts-library/she-hulk-law-art +sd-concepts-library/she-mask +sd-concepts-library/sherhook-painting +sd-concepts-library/sherhook-painting-v2 +sd-concepts-library/shev-linocut +sd-concepts-library/shigure-ui-style +sd-concepts-library/shiny-polyman +sd-concepts-library/shrunken-head +sd-concepts-library/shu-doll +sd-concepts-library/shvoren-style +sd-concepts-library/sims-2-portrait +sd-concepts-library/singsing +sd-concepts-library/singsing-doll +sd-concepts-library/sintez-ico +sd-concepts-library/skyfalls +sd-concepts-library/slm +sd-concepts-library/smarties +sd-concepts-library/smiling-friend-style +sd-concepts-library/smooth-pencils +sd-concepts-library/smurf-style +sd-concepts-library/smw-map +sd-concepts-library/society-finch +sd-concepts-library/sorami-style +sd-concepts-library/spider-gwen +sd-concepts-library/spritual-monsters +sd-concepts-library/stable-diffusion-conceptualizer +sd-concepts-library/star-tours-posters +sd-concepts-library/stardew-valley-pixel-art +sd-concepts-library/starhavenmachinegods +sd-concepts-library/sterling-archer +sd-concepts-library/stretch-re1-robot +sd-concepts-library/stuffed-penguin-toy +sd-concepts-library/style-of-marc-allante +sd-concepts-library/summie-style +sd-concepts-library/sunfish +sd-concepts-library/super-nintendo-cartridge +sd-concepts-library/supitcha-mask +sd-concepts-library/sushi-pixel +sd-concepts-library/swamp-choe-2 +sd-concepts-library/t-skrang +sd-concepts-library/takuji-kawano +sd-concepts-library/tamiyo +sd-concepts-library/tangles +sd-concepts-library/tb303 +sd-concepts-library/tcirle +sd-concepts-library/teelip-ir-landscape +sd-concepts-library/teferi +sd-concepts-library/tela-lenca +sd-concepts-library/tela-lenca2 +sd-concepts-library/terraria-style +sd-concepts-library/tesla-bot +sd-concepts-library/test +sd-concepts-library/test-epson +sd-concepts-library/test2 +sd-concepts-library/testing +sd-concepts-library/thalasin +sd-concepts-library/thegeneral +sd-concepts-library/thorneworks +sd-concepts-library/threestooges +sd-concepts-library/thunderdome-cover +sd-concepts-library/thunderdome-covers +sd-concepts-library/ti-junglepunk-v0 +sd-concepts-library/tili-concept +sd-concepts-library/titan-robot +sd-concepts-library/tnj +sd-concepts-library/toho-pixel +sd-concepts-library/tomcat +sd-concepts-library/tonal1 +sd-concepts-library/tony-diterlizzi-s-planescape-art +sd-concepts-library/towerplace +sd-concepts-library/toy +sd-concepts-library/toy-bonnie-plush +sd-concepts-library/toyota-sera +sd-concepts-library/transmutation-circles +sd-concepts-library/trash-polka-artstyle +sd-concepts-library/travis-bedel +sd-concepts-library/trigger-studio +sd-concepts-library/trust-support +sd-concepts-library/trypophobia +sd-concepts-library/ttte +sd-concepts-library/tubby +sd-concepts-library/tubby-cats +sd-concepts-library/tudisco +sd-concepts-library/turtlepics +sd-concepts-library/type +sd-concepts-library/ugly-sonic +sd-concepts-library/uliana-kudinova +sd-concepts-library/uma +sd-concepts-library/uma-clean-object +sd-concepts-library/uma-meme +sd-concepts-library/uma-meme-style +sd-concepts-library/uma-style-classic +sd-concepts-library/unfinished-building +sd-concepts-library/urivoldemort +sd-concepts-library/uzumaki +sd-concepts-library/valorantstyle +sd-concepts-library/vb-mox +sd-concepts-library/vcr-classique +sd-concepts-library/venice +sd-concepts-library/vespertine +sd-concepts-library/victor-narm +sd-concepts-library/vietstoneking +sd-concepts-library/vivien-reid +sd-concepts-library/vkuoo1 +sd-concepts-library/vraska +sd-concepts-library/w3u +sd-concepts-library/walter-wick-photography +sd-concepts-library/warhammer-40k-drawing-style +sd-concepts-library/waterfallshadow +sd-concepts-library/wayne-reynolds-character +sd-concepts-library/wedding +sd-concepts-library/wedding-HandPainted +sd-concepts-library/werebloops +sd-concepts-library/wheatland +sd-concepts-library/wheatland-arknight +sd-concepts-library/wheelchair +sd-concepts-library/wildkat +sd-concepts-library/willy-hd +sd-concepts-library/wire-angels +sd-concepts-library/wish-artist-stile +sd-concepts-library/wlop-style +sd-concepts-library/wojak +sd-concepts-library/wojaks-now +sd-concepts-library/wojaks-now-now-now +sd-concepts-library/xatu +sd-concepts-library/xatu2 +sd-concepts-library/xbh +sd-concepts-library/xi +sd-concepts-library/xidiversity +sd-concepts-library/xioboma +sd-concepts-library/xuna +sd-concepts-library/xyz +sd-concepts-library/yb-anime +sd-concepts-library/yerba-mate +sd-concepts-library/yesdelete +sd-concepts-library/yf21 +sd-concepts-library/yilanov2 +sd-concepts-library/yinit +sd-concepts-library/yoji-shinkawa-style +sd-concepts-library/yolandi-visser +sd-concepts-library/yoshi +sd-concepts-library/youpi2 +sd-concepts-library/youtooz-candy +sd-concepts-library/yuji-himukai-style +sd-concepts-library/zaney +sd-concepts-library/zaneypixelz +sd-concepts-library/zdenek-art +sd-concepts-library/zero +sd-concepts-library/zero-bottle +sd-concepts-library/zero-suit-samus +sd-concepts-library/zillertal-can +sd-concepts-library/zizigooloo +sd-concepts-library/zk +sd-concepts-library/zoroark diff --git a/configs/stable-diffusion/v1-inference.yaml b/configs/stable-diffusion/v1-inference.yaml index d872404f2c..ca1ae1e35d 100644 --- a/configs/stable-diffusion/v1-inference.yaml +++ b/configs/stable-diffusion/v1-inference.yaml @@ -32,7 +32,7 @@ model: placeholder_strings: ["*"] initializer_words: ['sculpture'] per_image_tokens: false - num_vectors_per_token: 1 + num_vectors_per_token: 8 progressive_words: False unet_config: diff --git a/configs/stable-diffusion/v1-inpainting-inference.yaml b/configs/stable-diffusion/v1-inpainting-inference.yaml index f0b470e417..2d25b8a4e6 100644 --- a/configs/stable-diffusion/v1-inpainting-inference.yaml +++ b/configs/stable-diffusion/v1-inpainting-inference.yaml @@ -32,7 +32,7 @@ model: placeholder_strings: ["*"] initializer_words: ['sculpture'] per_image_tokens: false - num_vectors_per_token: 1 + num_vectors_per_token: 8 progressive_words: False unet_config: diff --git a/ldm/generate.py b/ldm/generate.py index bbc2cc5078..2ca6baaa28 100644 --- a/ldm/generate.py +++ b/ldm/generate.py @@ -39,6 +39,7 @@ from ldm.invoke.conditioning import get_uc_and_c_and_ec from ldm.invoke.model_cache import ModelCache from ldm.invoke.seamless import configure_model_padding from ldm.invoke.txt2mask import Txt2Mask, SegmentedGrayscale +from ldm.invoke.concepts_lib import Concepts def fix_func(orig): if hasattr(torch.backends, 'mps') and torch.backends.mps.is_available(): @@ -858,6 +859,12 @@ class Generate: self.model_name = model_name return self.model + def load_concepts(self,concepts:list[str]): + self.model.embedding_manager.load_concepts(concepts, self.precision=='float32' or self.precision=='autocast') + + def concept_lib(self)->Concepts: + return self.model.embedding_manager.concepts_library + def correct_colors(self, image_list, reference_image_path, diff --git a/ldm/invoke/CLI.py b/ldm/invoke/CLI.py index 310c1a1fe3..d5687602d9 100644 --- a/ldm/invoke/CLI.py +++ b/ldm/invoke/CLI.py @@ -15,6 +15,7 @@ from ldm.invoke.args import Args, metadata_dumps, metadata_from_png, dream_cmd_f from ldm.invoke.pngwriter import PngWriter, retrieve_metadata, write_metadata from ldm.invoke.image_util import make_grid from ldm.invoke.log import write_log +from ldm.invoke.concepts_lib import Concepts from omegaconf import OmegaConf from pathlib import Path import pyparsing @@ -62,6 +63,12 @@ def main(): if not os.path.isabs(opt.conf): opt.conf = os.path.normpath(os.path.join(Globals.root,opt.conf)) + if opt.embeddings: + if not os.path.isabs(opt.embedding_path): + embedding_path = os.path.normpath(os.path.join(Globals.root,opt.embedding_path)) + else: + embedding_path = None + # load the infile as a list of lines if opt.infile: try: @@ -81,7 +88,7 @@ def main(): conf = opt.conf, model = opt.model, sampler_name = opt.sampler_name, - embedding_path = opt.embedding_path, + embedding_path = embedding_path, full_precision = opt.full_precision, precision = opt.precision, gfpgan=gfpgan, @@ -138,6 +145,7 @@ def main_loop(gen, opt): # changing the history file midstream when the output directory is changed. completer = get_completer(opt, models=list(model_config.keys())) set_default_output_dir(opt, completer) + add_embedding_terms(gen, completer) output_cntr = completer.get_current_history_length()+1 # os.pathconf is not available on Windows @@ -215,7 +223,7 @@ def main_loop(gen, opt): set_default_output_dir(opt,completer) # try to relativize pathnames - for attr in ('init_img','init_mask','init_color','embedding_path'): + for attr in ('init_img','init_mask','init_color'): if getattr(opt,attr) and not os.path.exists(getattr(opt,attr)): basename = getattr(opt,attr) path = os.path.join(opt.outdir,basename) @@ -298,6 +306,7 @@ def main_loop(gen, opt): if use_prefix is not None: prefix = use_prefix postprocessed = upscaled if upscaled else operation=='postprocess' + opt.prompt = triggers_to_concepts(gen, opt.prompt) # to avoid the problem of non-unique concept triggers filename, formatted_dream_prompt = prepare_image_metadata( opt, prefix, @@ -341,6 +350,8 @@ def main_loop(gen, opt): last_results.append([path, seed]) if operation == 'generate': + # load any from the SD concepts library + opt.prompt = concepts_to_triggers(gen, opt.prompt) catch_ctrl_c = infile is None # if running interactively, we catch keyboard interrupts opt.last_operation='generate' try: @@ -416,6 +427,7 @@ def do_command(command:str, gen, opt:Args, completer) -> tuple: elif command.startswith('!switch'): model_name = command.replace('!switch ','',1) gen.set_model(model_name) + add_embedding_terms(gen, completer) completer.add_history(command) operation = None @@ -489,6 +501,19 @@ def do_command(command:str, gen, opt:Args, completer) -> tuple: command = '-h' return command, operation +def concepts_to_triggers(gen, prompt:str)->str: + concepts = re.findall('<([^>]+)>',prompt) + if not concepts: + return prompt + gen.load_concepts(concepts) + return gen.concept_lib().replace_concepts_with_triggers(prompt) + +def triggers_to_concepts(gen,prompt:str)->str: + concepts = re.findall('<([^>]+)>',prompt) + if not concepts: + return prompt + return gen.concept_lib().replace_triggers_with_concepts(prompt) + def set_default_output_dir(opt:Args, completer:Completer): ''' If opt.outdir is relative, we add the root directory to it @@ -790,7 +815,13 @@ def invoke_ai_web_server_loop(gen, gfpgan, codeformer, esrgan): except KeyboardInterrupt: pass - +def add_embedding_terms(gen,completer): + ''' + Called after setting the model, updates the autocompleter with + any terms loaded by the embedding manager. + ''' + completer.add_embedding_terms(gen.model.embedding_manager.list_terms()) + def split_variations(variations_string) -> list: # shotgun parsing, woo parts = [] diff --git a/ldm/invoke/args.py b/ldm/invoke/args.py index 5d60153a60..330220b7ea 100644 --- a/ldm/invoke/args.py +++ b/ldm/invoke/args.py @@ -92,6 +92,7 @@ import shlex import copy import base64 import functools +import warnings import ldm.invoke.pngwriter from ldm.invoke.globals import Globals from ldm.invoke.prompt_parser import split_weighted_subprompts @@ -116,7 +117,7 @@ PRECISION_CHOICES = [ # is there a way to pick this up during git commits? APP_ID = 'invoke-ai/InvokeAI' -APP_VERSION = 'v2.1.2' +APP_VERSION = 'v2.2.0' class ArgFormatter(argparse.RawTextHelpFormatter): # use defined argument order to display usage @@ -174,8 +175,9 @@ class Args(object): print(f'>> Initialization file {initfile} found. Loading...') sysargs.insert(0,f'@{initfile}') else: - print(f'>> Initialization file {initfile} not found. Creating a new one...') - self._create_init_file(initfile) + from ldm.invoke.CLI import emergency_model_reconfigure + emergency_model_reconfigure() + sys.exit(-1) self._arg_switches = self._arg_parser.parse_args(sysargs) return self._arg_switches except Exception as e: @@ -546,9 +548,18 @@ class Args(object): help='generate a grid' ) render_group.add_argument( + '--embedding_directory', '--embedding_path', + dest='embedding_path', + default='embeddings', type=str, - help='Path to a pre-trained embedding manager checkpoint - can only be set on command line', + help='Path to a directory containing .bin and/or .pt files, or a single .bin/.pt file. You may use subdirectories. (default is ROOTDIR/embeddings)' + ) + render_group.add_argument( + '--embeddings', + action=argparse.BooleanOptionalAction, + default=True, + help='Enable embedding directory (default). Use --no-embeddings to disable.', ) render_group.add_argument( '--enable_image_debugging', diff --git a/ldm/invoke/concepts_lib.py b/ldm/invoke/concepts_lib.py new file mode 100644 index 0000000000..6d1100d8b3 --- /dev/null +++ b/ldm/invoke/concepts_lib.py @@ -0,0 +1,151 @@ +""" +Query and install embeddings from the HuggingFace SD Concepts Library +at https://huggingface.co/sd-concepts-library. + +The interface is through the Concepts() object. +""" +import os +import re +import traceback +from urllib import request, error as ul_error +from huggingface_hub import HfFolder, hf_hub_url, ModelSearchArguments, ModelFilter, HfApi +from ldm.invoke.globals import Globals + +class Concepts(object): + def __init__(self, root=None): + ''' + Initialize the Concepts object. May optionally pass a root directory. + ''' + self.root = root or Globals.root + self.hf_api = HfApi() + self.concept_list = None + self.concepts_loaded = dict() + self.triggers = dict() # concept name to trigger phrase + self.concept_names = dict() # trigger phrase to concept name + self.match_trigger = re.compile('(<[\w\-]+>)') + self.match_concept = re.compile('<([\w\-]+)>') + + def list_concepts(self)->list: + ''' + Return a list of all the concepts by name, without the 'sd-concepts-library' part. + ''' + if self.concept_list is not None: + return self.concept_list + try: + models = self.hf_api.list_models(filter=ModelFilter(model_name='sd-concepts-library/')) + self.concept_list = [a.id.split('/')[1] for a in models] + except Exception as e: + print(' ** WARNING: Hugging Face textual inversion concepts libraries could not be loaded. The error was {str(e)}.') + print(' ** You may load .bin and .pt file(s) manually using the --embedding_directory argument.') + return self.concept_list + + def get_concept_model_path(self, concept_name:str)->str: + ''' + Returns the path to the 'learned_embeds.bin' file in + the named concept. Returns None if invalid or cannot + be downloaded. + ''' + return self.get_concept_file(concept_name.lower(),'learned_embeds.bin') + + def concept_to_trigger(self, concept_name:str)->str: + ''' + Given a concept name returns its trigger by looking in the + "token_identifier.txt" file. + ''' + if concept_name in self.triggers: + return self.triggers[concept_name] + file = self.get_concept_file(concept_name, 'token_identifier.txt', local_only=True) + if not file: + return None + with open(file,'r') as f: + trigger = f.readline() + trigger = trigger.strip() + self.triggers[concept_name] = trigger + self.concept_names[trigger] = concept_name + return trigger + + def trigger_to_concept(self, trigger:str)->str: + ''' + Given a trigger phrase, maps it to the concept library name. + Only works if concept_to_trigger() has previously been called + on this library. There needs to be a persistent database for + this. + ''' + concept = self.concept_names.get(trigger,None) + return f'<{concept}>' if concept else f'{trigger}' + + def replace_triggers_with_concepts(self, prompt:str)->str: + ''' + Given a prompt string that contains tags, replace these + tags with the concept name. The reason for this is so that the + concept names get stored in the prompt metadata. There is no + controlling of colliding triggers in the SD library, so it is + better to store the concept name (unique) than the concept trigger + (not necessarily unique!) + ''' + def do_replace(match)->str: + return self.trigger_to_concept(match.group(1)) or f'<{match.group(1)}>' + return self.match_trigger.sub(do_replace, prompt) + + def replace_concepts_with_triggers(self, prompt:str)->str: + ''' + Given a prompt string that contains tags, replace + these tags with the appropriate trigger. + ''' + def do_replace(match)->str: + return self.concept_to_trigger(match.group(1)) or f'<{match.group(1)}>' + return self.match_concept.sub(do_replace, prompt) + + def get_concept_file(self, concept_name:str, file_name:str='learned_embeds.bin' , local_only:bool=False)->str: + if not self.concept_is_downloaded(concept_name) and not local_only: + self.download_concept(concept_name) + path = os.path.join(self._concept_path(concept_name), file_name) + return path if os.path.exists(path) else None + + def concept_is_downloaded(self, concept_name)->bool: + concept_directory = self._concept_path(concept_name) + return os.path.exists(concept_directory) + + def download_concept(self,concept_name)->bool: + repo_id = self._concept_id(concept_name) + dest = self._concept_path(concept_name) + + access_token = HfFolder.get_token() + header = [("Authorization", f'Bearer {access_token}')] if access_token else [] + opener = request.build_opener() + opener.addheaders = header + request.install_opener(opener) + + os.makedirs(dest, exist_ok=True) + succeeded = True + + bytes = 0 + def tally_download_size(chunk, size, total): + nonlocal bytes + if chunk==0: + bytes += total + + print(f'>> Downloading {repo_id}...',end='') + try: + for file in ('README.md','learned_embeds.bin','token_identifier.txt','type_of_concept.txt'): + url = hf_hub_url(repo_id, file) + request.urlretrieve(url, os.path.join(dest,file),reporthook=tally_download_size) + except ul_error.HTTPError as e: + if e.code==404: + print(f'This concept is not known to the Hugging Face library. Generation will continue without the concept.') + else: + print(f'Failed to download {concept_name}/{file} ({str(e)}. Generation will continue without the concept.)') + os.rmdir(dest) + return False + except ul_error.URLError as e: + print(f'ERROR: {str(e)}. This may reflect a network issue. Generation will continue without the concept.') + os.rmdir(dest) + return False + print('...{:.2f}Kb'.format(bytes/1024)) + return succeeded + + def _concept_id(self, concept_name:str)->str: + return f'sd-concepts-library/{concept_name}' + + def _concept_path(self, concept_name:str)->str: + return os.path.join(self.root,'models','sd-concepts-library',concept_name) diff --git a/ldm/invoke/model_cache.py b/ldm/invoke/model_cache.py index 645a6fd4da..26630d1db2 100644 --- a/ldm/invoke/model_cache.py +++ b/ldm/invoke/model_cache.py @@ -206,7 +206,7 @@ class ModelCache(object): if not os.path.isabs(weights): weights = os.path.normpath(os.path.join(Globals.root,weights)) # scan model - self._scan_model(model_name, weights) + self.scan_model(model_name, weights) print(f'>> Loading {model_name} from {weights}') @@ -288,7 +288,7 @@ class ModelCache(object): if self._has_cuda(): torch.cuda.empty_cache() - def _scan_model(self, model_name, checkpoint): + def scan_model(self, model_name, checkpoint): # scan model print(f'>> Scanning Model: {model_name}') scan_result = scan_file_path(checkpoint) diff --git a/ldm/invoke/prompt_parser.py b/ldm/invoke/prompt_parser.py index 42c83188aa..3e26dcca89 100644 --- a/ldm/invoke/prompt_parser.py +++ b/ldm/invoke/prompt_parser.py @@ -646,13 +646,13 @@ def split_weighted_subprompts(text, skip_normalize=False)->list: # usually tokens have '' to indicate end-of-word, # but for readability it has been replaced with ' ' def log_tokenization(text, model, display_label=None): - tokens = model.cond_stage_model.tokenizer._tokenize(text) + tokens = model.cond_stage_model.tokenizer.tokenize(text) tokenized = "" discarded = "" usedTokens = 0 totalTokens = len(tokens) for i in range(0, totalTokens): - token = tokens[i].replace('', 'x` ') + token = tokens[i].replace('', ' ') # alternate color s = (usedTokens % 6) + 1 if i < model.cond_stage_model.max_length: diff --git a/ldm/invoke/readline.py b/ldm/invoke/readline.py index e0b0c7689b..86b15c3a16 100644 --- a/ldm/invoke/readline.py +++ b/ldm/invoke/readline.py @@ -12,6 +12,7 @@ import os import re import atexit from ldm.invoke.args import Args +from ldm.invoke.concepts_lib import Concepts # ---------------readline utilities--------------------- try: @@ -84,6 +85,7 @@ IMG_FILE_COMMANDS=( '--init_color[=\s]', '--embedding_path[=\s]', ) + path_regexp = '(' + '|'.join(IMG_PATH_COMMANDS+IMG_FILE_COMMANDS) + ')\s*\S*$' weight_regexp = '(' + '|'.join(WEIGHT_COMMANDS) + ')\s*\S*$' text_regexp = '(' + '|'.join(TEXT_PATH_COMMANDS) + ')\s*\S*$' @@ -98,6 +100,7 @@ class Completer(object): self.linebuffer = None self.auto_history_active = True self.extensions = None + self.concepts = Concepts().list_concepts() return def complete(self, text, state): @@ -122,6 +125,9 @@ class Completer(object): elif re.search('(-S\s*|--seed[=\s])\d*$',buffer): self.matches= self._seed_completions(text,state) + elif re.search('<[\w-]*$',buffer): + self.matches= self._concept_completions(text,state) + # looking for a model elif re.match('^'+'|'.join(MODEL_COMMANDS),buffer): self.matches= self._model_completions(text, state) @@ -257,6 +263,22 @@ class Completer(object): matches.sort() return matches + def add_embedding_terms(self, terms:list[str]): + self.concepts = Concepts().list_concepts() + self.concepts.extend(terms) + + def _concept_completions(self, text, state): + partial = text[1:] # this removes the leading '<' + if len(partial) == 0: + return self.concepts # whole dump - think if user wants this! + + matches = list() + for concept in self.concepts: + if concept.startswith(partial): + matches.append(f'<{concept}>') + matches.sort() + return matches + def _model_completions(self, text, state): m = re.search('(!switch\s+)(\w*)',text) if m: diff --git a/ldm/modules/embedding_manager.py b/ldm/modules/embedding_manager.py index 18688708f9..239fd346ab 100644 --- a/ldm/modules/embedding_manager.py +++ b/ldm/modules/embedding_manager.py @@ -1,14 +1,15 @@ +import os.path from cmath import log import torch from torch import nn import sys +from ldm.invoke.concepts_lib import Concepts from ldm.data.personalized import per_img_token_list from transformers import CLIPTokenizer from functools import partial - -DEFAULT_PLACEHOLDER_TOKEN = ['*'] +from picklescan.scanner import scan_file_path PROGRESSIVE_SCALE = 2000 @@ -43,7 +44,6 @@ def get_bert_token_for_string(tokenizer, string): def get_embedding_for_clip_token(embedder, token): return embedder(token.unsqueeze(0))[0, 0] - class EmbeddingManager(nn.Module): def __init__( self, @@ -58,6 +58,8 @@ class EmbeddingManager(nn.Module): super().__init__() self.embedder = embedder + self.concepts_library=Concepts() + self.concepts_loaded = dict() self.string_to_token_dict = {} self.string_to_param_dict = nn.ParameterDict() @@ -149,68 +151,55 @@ class EmbeddingManager(nn.Module): placeholder_string ].to(device) - if ( - self.max_vectors_per_token == 1 - ): # If there's only one vector per token, we can do a simple replacement - placeholder_idx = torch.where( - tokenized_text == placeholder_token.to(device) + if self.progressive_words: + self.progressive_counter += 1 + max_step_tokens = ( + 1 + self.progressive_counter // PROGRESSIVE_SCALE ) - embedded_text[placeholder_idx] = placeholder_embedding - else: # otherwise, need to insert and keep track of changing indices - if self.progressive_words: - self.progressive_counter += 1 - max_step_tokens = ( - 1 + self.progressive_counter // PROGRESSIVE_SCALE - ) - else: - max_step_tokens = self.max_vectors_per_token + else: + max_step_tokens = self.max_vectors_per_token - num_vectors_for_token = min( - placeholder_embedding.shape[0], max_step_tokens - ) + num_vectors_for_token = min( + placeholder_embedding.shape[0], max_step_tokens + ) - if torch.cuda.is_available(): - placeholder_rows, placeholder_cols = torch.where( - tokenized_text == placeholder_token.to(device) - ) - else: - placeholder_rows, placeholder_cols = torch.where( - tokenized_text == placeholder_token - ) + placeholder_rows, placeholder_cols = torch.where( + tokenized_text == placeholder_token.to(tokenized_text.device) + ) - if placeholder_rows.nelement() == 0: - continue + if placeholder_rows.nelement() == 0: + continue - sorted_cols, sort_idx = torch.sort( - placeholder_cols, descending=True - ) - sorted_rows = placeholder_rows[sort_idx] + sorted_cols, sort_idx = torch.sort( + placeholder_cols, descending=True + ) + sorted_rows = placeholder_rows[sort_idx] - for idx in range(len(sorted_rows)): - row = sorted_rows[idx] - col = sorted_cols[idx] + for idx in range(sorted_rows.shape[0]): + row = sorted_rows[idx] + col = sorted_cols[idx] - new_token_row = torch.cat( - [ - tokenized_text[row][:col], - placeholder_token.repeat(num_vectors_for_token).to( - device - ), - tokenized_text[row][col + 1 :], - ], - axis=0, - )[:n] - new_embed_row = torch.cat( - [ - embedded_text[row][:col], - placeholder_embedding[:num_vectors_for_token], - embedded_text[row][col + 1 :], - ], - axis=0, - )[:n] + new_token_row = torch.cat( + [ + tokenized_text[row][:col], + placeholder_token.repeat(num_vectors_for_token).to( + device + ), + tokenized_text[row][col + 1 :], + ], + axis=0, + )[:n] + new_embed_row = torch.cat( + [ + embedded_text[row][:col], + placeholder_embedding[:num_vectors_for_token], + embedded_text[row][col + 1 :], + ], + axis=0, + )[:n] - embedded_text[row] = new_embed_row - tokenized_text[row] = new_token_row + embedded_text[row] = new_embed_row + tokenized_text[row] = new_token_row return embedded_text @@ -223,29 +212,98 @@ class EmbeddingManager(nn.Module): ckpt_path, ) - def load(self, ckpt_path, full=True): + def load_concepts(self, concepts:list[str], full=True): + bin_files = list() + for concept_name in concepts: + if concept_name in self.concepts_loaded: + continue + else: + bin_file = self.concepts_library.get_concept_model_path(concept_name) + if not bin_file: + continue + bin_files.append(bin_file) + self.concepts_loaded[concept_name]=True + self.load(bin_files, full) + + def list_terms(self) -> list[str]: + return self.concepts_loaded.keys() + + def load(self, ckpt_paths, full=True): + if len(ckpt_paths) == 0: + return + if type(ckpt_paths) != list: + ckpt_paths = [ckpt_paths] + ckpt_paths = self._expand_directories(ckpt_paths) + for c in ckpt_paths: + self._load(c,full) + # remember that we know this term and don't try to download it again from the concepts library + # note that if the concept name is also provided and different from the trigger term, they + # both will be stored in this dictionary + for term in self.string_to_param_dict.keys(): + term = term.strip('<').strip('>') + self.concepts_loaded[term] = True + print(f'>> Current embedding manager terms: {", ".join(self.string_to_param_dict.keys())}') + + def _expand_directories(self, paths:list[str]): + expanded_paths = list() + for path in paths: + if os.path.isfile(path): + expanded_paths.append(path) + elif os.path.isdir(path): + for root, _, files in os.walk(path): + for name in files: + expanded_paths.append(os.path.join(root,name)) + return [x for x in expanded_paths if os.path.splitext(x)[1] in ('.pt','.bin')] + + def _load(self, ckpt_path, full=True): + + scan_result = scan_file_path(ckpt_path) + if scan_result.infected_files == 1: + print(f'\n### Security Issues Found in Model: {scan_result.issues_count}') + print('### For your safety, InvokeAI will not load this embed.') + return + ckpt = torch.load(ckpt_path, map_location='cpu') # Handle .pt textual inversion files if 'string_to_token' in ckpt and 'string_to_param' in ckpt: - self.string_to_token_dict = ckpt["string_to_token"] - self.string_to_param_dict = ckpt["string_to_param"] + filename = os.path.basename(ckpt_path) + token_str = '.'.join(filename.split('.')[:-1]) # filename excluding extension + if len(ckpt["string_to_token"]) > 1: + print(f">> {ckpt_path} has >1 embedding, only the first will be used") + + string_to_param_dict = ckpt['string_to_param'] + embedding = list(string_to_param_dict.values())[0] + self.add_embedding(token_str, embedding, full) # Handle .bin textual inversion files from Huggingface Concepts # https://huggingface.co/sd-concepts-library else: for token_str in list(ckpt.keys()): - token = get_clip_token_for_string(self.embedder.tokenizer, token_str) - self.string_to_token_dict[token_str] = token - ckpt[token_str] = torch.nn.Parameter(ckpt[token_str]) - - self.string_to_param_dict.update(ckpt) + embedding = ckpt[token_str] + self.add_embedding(token_str, embedding, full) + def add_embedding(self, token_str, embedding, full): + if token_str in self.string_to_param_dict: + print(f">> Embedding manager refusing to overwrite already-loaded term '{token_str}'") + return if not full: - for key, value in self.string_to_param_dict.items(): - self.string_to_param_dict[key] = torch.nn.Parameter(value.half()) + embedding = embedding.half() + if len(embedding.shape) == 1: + embedding = embedding.unsqueeze(0) - print(f'Added terms: {", ".join(self.string_to_param_dict.keys())}') + num_tokens_added = self.embedder.tokenizer.add_tokens(token_str) + current_embeddings = self.embedder.transformer.resize_token_embeddings(None) + current_token_count = current_embeddings.num_embeddings + new_token_count = current_token_count + num_tokens_added + self.embedder.transformer.resize_token_embeddings(new_token_count) + + token = get_clip_token_for_string(self.embedder.tokenizer, token_str) + self.string_to_token_dict[token_str] = token + self.string_to_param_dict[token_str] = torch.nn.Parameter(embedding) + + def has_embedding_for_token(self, token_str): + return token_str in self.string_to_token_dict def get_embedding_norms_squared(self): all_params = torch.cat( diff --git a/main.py b/main.py index 60c091891c..6f56962cd4 100644 --- a/main.py +++ b/main.py @@ -188,10 +188,6 @@ def get_parser(**parser_kwargs): default='', help='Initialize embedding manager from a checkpoint', ) - parser.add_argument( - '--placeholder_tokens', type=str, nargs='+', default=['*'], - help='Placeholder token which will be used to denote the concept in future prompts') - parser.add_argument( '--init_word', type=str, @@ -722,14 +718,9 @@ if __name__ == '__main__': config.model.params.personalization_config.params.embedding_manager_ckpt = ( opt.embedding_manager_ckpt ) - config.model.params.personalization_config.params.placeholder_tokens = ( - opt.placeholder_tokens - ) if opt.init_word: - config.model.params.personalization_config.params.initializer_words[ - 0 - ] = opt.init_word + config.model.params.personalization_config.params.initializer_words = [opt.init_word] if opt.actual_resume: model = load_model_from_config(config, opt.actual_resume) diff --git a/scripts/configure_invokeai.py b/scripts/configure_invokeai.py old mode 100755 new mode 100644 index 4e55ed2ffd..fd7a009e66 --- a/scripts/configure_invokeai.py +++ b/scripts/configure_invokeai.py @@ -602,8 +602,8 @@ def initialize_rootdir(root:str,yes_to_all:bool=False): print(f'\nYou may change the chosen directories at any time by editing the --root and --outdir options in "{Globals.initfile}",') print(f'You may also change the runtime directory by setting the environment variable INVOKEAI_ROOT.\n') - - for name in ['models','configs']: + + for name in ('models','configs','embeddings'): os.makedirs(os.path.join(root,name), exist_ok=True) for src in (['configs']): dest = os.path.join(root,src) @@ -634,7 +634,15 @@ def initialize_rootdir(root:str,yes_to_all:bool=False): # ''' ) - + else: + print(f'Updating the initialization file at "{init_file}".\n') + with open(init_file,'r') as infile, open(f'{init_file}.tmp','w') as outfile: + for line in infile.readlines(): + if not line.startswith('--root') and not line.startswith('--outdir'): + outfile.write(line) + outfile.write(f'--root="{root}"\n') + outfile.write(f'--outdir="{outputs}"\n') + os.replace(f'{init_file}.tmp',init_file) #------------------------------------- class ProgressBar(): @@ -710,5 +718,3 @@ def main(): #------------------------------------- if __name__ == '__main__': main() - - diff --git a/scripts/merge_embeddings.py b/scripts/merge_embeddings.py index 97bfa6a8c6..f419116fe9 100644 --- a/scripts/merge_embeddings.py +++ b/scripts/merge_embeddings.py @@ -1,6 +1,6 @@ from ldm.modules.encoders.modules import FrozenCLIPEmbedder, BERTEmbedder from ldm.modules.embedding_manager import EmbeddingManager -from ldm.modules.globals import Globals +from ldm.invoke.globals import Globals import argparse, os from functools import partial