您好,登錄后才能下訂單哦!
本篇內容介紹了“適合面向ChatGPT編程的架構源碼分析”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
我們前面爬蟲的需求呢,有些平臺說因為引起爭議,所以不讓發,好吧,那我們換個需求,本來那個例子也不好擴展了。最近AI畫圖也是比較火的,那么我們來試試做個程序幫我們生成AI畫圖的prompt。
首先講一下AI話題的prompt的關鍵要素,大部分的AI畫圖都是有一個個由逗號分割的關鍵字,也叫subject,類似下面這樣:
a cute cat, smile, running, look_at_viewer, full_body, side_view,
然后還有negative prompt,就是你不想出現的關鍵字,跟上面的寫法一樣,只是寫下來表示不希望它畫出來的,比如我們想畫一堆貓的圖片,不想出現狗,不想出現人,我們可以這么寫:
dog, human,
這樣大概率就不會出現狗和人了(當然也不一定,懂得都懂)。
那么說干就干,開始之前要了解一下領域知識。
首先是關鍵字,在這個需求里只是基礎知識,沒有什么難的,大概有下面幾條規則:
內容,這些關鍵字呢,說是關鍵字,其實你寫一句話也沒人管你。簡化處理,我們這里就只用詞和短語。另外,空格可以用下劃線代替,這樣可能會避免被分詞,具體我也不確定,沒有深入研究。但是這個不重要,可以完全看成兩種關鍵字去排列組合好了。
關鍵字是可以有權重的,通常的表達方式是:
(a cute cat:1.5)
這個很重要,通常我們想嘗試好的方式,需要給每個關鍵字設置權重。
LoRA,英文全稱Low-Rank Adaptation of Large Language Models,直譯為大語言模型的低階適應,這是微軟的研究人員為了解決大語言模型微調而開發的一項技術,在我們這個場景下就是我們多了一種關鍵字,這種關鍵字大概是這么寫:
<lora:wanostyle_2_offset:1>, monkey d luffy,
它多了一些尖括號,也有權重,同時他會被其他關鍵字觸發,比如上面這個就可以畫個海賊王風格的路飛出來。
但總的來說,對關鍵字本身的建模影響不大
接著我們來了解一下排列組合的邏輯,這個將是我們的關鍵難點。
在這個領域,影響生成的因素主要有幾個:
模型
sample
step
寬高
seed
negative prompt
prompt
在prompt中我們的關鍵字還可以根據使用目的分類,比如于生成畫面風格的、用于生成背景的、用于生成人物的、用于成表情的等等
在prompt中,關鍵字的擺放順序有時候還會造成點不同。
還有更復雜的Control Net,這個例子里我們先不考慮。
生成的時候,某些關鍵字要獲得最好的效果,可能自己對模型、sample以及其他關鍵字的存在和權重都有自己的要求,比某關鍵字在某模型下權重為0.3,而在另一個模型下權重需要0.7。比如路飛會帶草帽,那么這個人物出現的時候,必須配上帽的關鍵字才對味,而其他的人物就不要跟草帽組合了,又浪時間又沒有意義。所以組合上要考慮各種因素之間的互斥和強依賴等場景。
好,這大概是一個比較復雜的需求了。回到上篇文章遺留的問題,聊聊當我們面對一個比較復雜的需求,而且我們接下來要用ChatGPT把它實現的時候,我們應該怎么設計架構。
在這個需求里,我們首先要知道,這類AI都是有REST API的,比如說stable diffusion WebUI,就有一個自己的API,他們的API接受一個固定格式的JSON,其結構大概是這個樣子:
{ "prompt": "", "negative_prompt": "", "controlnet_input_image": [], "controlnet_mask": [], "controlnet_module": "", "controlnet_model": "", "controlnet_weight": 1, "controlnet_resize_mode": "Scale to Fit (Inner Fit)", "controlnet_lowvram": true, "controlnet_processor_res": 512, "controlnet_threshold_a": 64, "controlnet_threshold_b": 64, "controlnet_guidance": 1, "controlnet_guessmode": true, "enable_hr": false, "denoising_strength": 0.5, "hr_scale": 1.5, "hr_upscale": "Latent", "seed": -1, "subseed": -1, "subseed_strength": -1, "sampler_index": "", "batch_size": 1, "n_iter": 1, "steps": 20, "cfg_scale": 7, "width": 512, "height": 512, "restore_faces": true, "override_settings": {}, "override_settings_restore_afterwards": true }
那么這就是類似他們的意圖描述,可以把它看成一種DSL。
而在我們這個領域里,我們要做的是排列組合,那么對于排列組合,我們要設計我們排列組合的意圖描述,這可以看成另一種DSL,這種DSL只作簡單排列組合,不做復雜的互斥和強依賴邏輯的計算,其結構可能是這個樣子:
- base_share_composite_intentions: base: steps: 10 batch_size: 1 width: 512 height: 512 cfg_scale: 7 sampler: "Euler a" seed: -1 restore_faces: true output_folder: output/txt2img file_full_name_strategy: date_seed_name_strategy sd_host: http://localhost:7860 negative_prompt: a dog poly: - template_prompt: template: > a cat, ${ view_angle } ${ portrait } ${ facial_expressions } ${ pose } meta: - view_angle: - side_view, - front_view, portrait: - full body, facial_expressions: - (smile:1.5), - (smile:1.2), - smile, pose: "" - view_angle: - front_view, portrait: - "" facial_expressions: - smile, pose: - run, - jump, - rolling, steps: 20
然后在這個DSL之上,我們可以再做一個DSL,這個DSL用于處理復雜的互斥和強依賴邏輯的計算,前面說了那么多,真正這個地方到底有多復雜我也想不清楚。那干脆,搞個模板引擎來吧,這就什么都能干了,慢慢搞明白了再封裝。最終其結構可能是這個樣子:
<% const randomNum = Math.floor(Math.random() * 900000000) + 100000000; var intention = { is_override_settings: true, seed: randomNum, } %> <% var status = { charas:{ values_of_chara_$ref: [ "cats.yml#Abyssinian", "cats.yml#cats_in_boots", ], current_chara_index: 0, next_chara(){ this.current_chara_index++; } }, themes:{ values_of_theme: [ { $ref: "outdoor" }, ], current_theme_index: 0, next_theme(){ this.current_theme_index++; }, reset_theme(){ this.current_theme_index = 0; } } } %> <% common_theme_file = "common/chara_based_themes.yml" %> <% while (status.charas.current_chara_index < status.charas.values_of_chara_$ref.length) { %> - base_share_composite_intentions: common: theme: base: steps: 20 batch_size: 1 width: 512 height: 512 cfg_scale: 7 sampler: "DPM++ 2M Karras" seed: <%- intention.seed %> restore_faces: false output_folder: output/txt2img file_full_name_strategy: date_seed_name_strategy sd_host: http://localhost:7860 <% if(intention.is_override_settings){ %> override_settings: CLIP_stop_at_last_layers: 2 eta_noise_seed_delta: 31337 <%}%> negative_prompt: > dog, human, bad anatomy, EasyNegative,paintings, sketches, (worst quality:2), (low quality:2), (normal quality:2), lowres, normal quality, poly: <% while (status.themes.current_theme_index < status.themes.values_of_theme.length) { %> - $p_ref: $ref: "<%-common_theme_file%>#<%- status.themes.values_of_theme[status.themes.current_theme_index].$ref%>" params: base_prompt_features: $p_ref: $ref: <%- status.charas.values_of_chara_$ref[status.charas.current_chara_index] %> params: is_full_chara: true chara_weight: 0.2 pose: sit facial_expressions: (smile:1.1),(open mouth), - $p_ref: $ref: "<%-common_theme_file%>#<%- status.themes.values_of_theme[status.themes.current_theme_index].$ref%>" params: base_prompt_features: $p_ref: $ref: <%- status.charas.values_of_chara_$ref[status.charas.current_chara_index] %> params: is_full_chara: true chara_weight: 0.6 pose: run facial_expressions: (smile:1.2),(closed mouth), <% status.themes.next_theme(); %> <% } %> <% status.themes.reset_theme(); %> <% status.charas.next_chara(); %> <% } %>
于是我們有了三個DSL,他們層層轉換,最終驅動AI畫圖。那么我們的程序可能就會是下面這個樣子:
可以看出,這樣我們就得到了大名鼎鼎的管道架構,經常使用Linux/Unix命令行的人,可能已經體會過管道架構恐怖的擴展能力,這次我們只能說,是Linux/Unix哲學再一次展現出威力。
我們之前講了,ChatGPT可以快速寫出一些小程序,但是長一點的總是會出錯,那么其實除了從規模上進行分解將任務復雜度降低之外,通過抽象建立分層的DSL也是一種降低復雜度的方案。
說到分層,其實從另一個角度看,我們這個架構也是一個分層架構。
可以看到,我們可以輕易地替換調用不同REST API的代碼以做到對于不同AI的適配,實現了隔離。
同理,不但意圖執行可以切換,意圖描述也可以跟著切換:
既可以有技術維度上的擴展,也可以有業務維度上的擴展:
所以從這個角度來說,每一個管段,都是可以看作是一層。
而到這還不算完,具體在執行的時候,可能受環境的影響,可能受上層意圖影響等等,總之是需要進行每一層的路徑選擇的。這種選擇,可能是由另一個引擎來完成的。那么最終我們的架構的完整形態他可能是這個樣子的:
當然其運行視圖可能是這樣的:
到此,我們得到了我們架構比較完整的形態,他是一個集成了管道架構和分層架構,在一個派發引擎的支撐下的一個類分層神經網絡的結構。
“適合面向ChatGPT編程的架構源碼分析”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。