跳轉到主要內容
工程的博客

擁抱的臉和DeepSpeed微調大語言模型

容易應用和定製數十億美元的大型語言模型的參數

2023年3月20日 工程的博客

分享這篇文章

大型語言模型(llm)目前在聚光燈下ChatGPT的聳人聽聞的版本。很多人都想知道如何利用這樣的模型在自己的應用程序。然而,這僅僅是幾個比起進步的基於變壓器模型之一,許多其他的開放和現成的翻譯等任務,分類,和總結——不隻是聊天。

一個以前的博客探討了訪問這些模型的基礎上通過流行的磚擁抱的臉變形金剛的圖書館。現成的,pre-trained llm的樣子T5伯特適用於各種各樣的現實問題,沒有額外的數據或培訓。然而,有時是有價值的或必要的“微調”這些模型,以更好地執行特定的任務。

這個博客將探索簡單的微調T5家庭的語言模型,從最小到最大尺寸,專門為一個簡單的用例:構建一個產品評論概述從許多產品評論。它將使用擁抱在磚,包括它MLflow集成

它還將介紹微軟的DeepSpeed加快調整非常大的語言模型。不難調整甚至110億參數模型的磚——如果這是必要的!

問題:總結產品評論

假設您運行一個電子商務網站銷售相機產品。用戶在產品留下評論,你認為它會很高興凝結所有為客戶評論的產品到一個總結,而不是讓他們篩選一百評論。beplay体育app下载地址你收集了成千上萬的評論以及用戶提供的標題(這是一種“總結”的審查),想利用llm創建這些產品總結。

作為這樣一個數據集的替身,這個示例將使用亞馬遜客戶審查數據集包含1.3億產品評論從亞馬遜的客戶。beplay体育app下载地址感興趣的隻是評論的文本,標題,就“相機”的範疇,自然。

這個數據集的自由文本並不完全幹淨。為了模仿好,策劃數據集你的電子商務網站維護、加載數據,運用一些基本的清潔(有關詳細信息,請參閱伴隨筆記本),和把它寫成一個三角洲表。在這裏評論的長度是有限的(有些任意)到100令牌,一些很長的序列可以導致內存不足的錯誤。短序列是更快的微調,以犧牲當然的準確性;省略了一些評論文本。

defclean_text(文本,max_tokens):approx_tokens =0清洗=”“片段split_regex.split(文本):approx_tokens + =len(fragment.split (”“))如果(approx_tokens > max_tokens):打破清洗+ =片段返回cleaned.strip ()@udf (“字符串”)defclean_review_udf(審查):返回clean_text(審查,One hundred.)camera_reviews_df.select (“product_id”,“review_body”,“review_headline”)。\樣品(0.1種子=42)。\withColumn (“review_body”clean_review_udf (“review_body”))。\withColumn (“review_headline”clean_summary_udf (“review_headline”))。\過濾器(”(review_body) > 0長度和長度(review_headline) > 0 ")。\寫。格式(“δ”).save (“/ tmp /…/審查/清洗”)
review_body review_headline
好相機的價格。 五顆星
我不高興,電纜下車。需要一個更強的近 兩顆星

好相機的價格。注意,240,480年933相機進來,所以這不是那麼清晰。我所需要的工作啊,我真希望我就會知道這之前我買了它。

沒有好的相機,鋒利先前的模型

我真的非常喜歡這些貼紙。他們立即和他們的預期。我喜歡所有的設計。 我真的非常喜歡這些貼紙
不要試圖用一個汽車充電器充電線或適配器插頭!它會消耗電池。 警告!不要給這些與…

這是更好的。從這裏開始,然後看看大語言模型可以處理這些數據。

快速地總結與t5-small

T5(Text-to-Text傳輸變壓器)是一個通用llm從穀歌的家庭。它是有用的在總結等許多任務,分類,和翻譯,在幾個大小來自“小”(~ 60 m參數)相當大(~ 11 b參數)。這些尺寸越來越強大,也越來越昂貴的發揮。這些llm處理的一個重要主題是“保持簡單”。使用模型如果他們足夠小,並開始用現成的資源。推理與大模型花費的時間和成本,所以延遲和預算約束可能意味著更大的模型從一開始是不可能的。

以前的博客展示了如何輕鬆地應用T5火花和擁抱的臉,同樣的可以在這裏發生。目前還不清楚,它將工作做好開箱即用的數據集,將很快看到,因為輸入文本和輸出文本很短。回顧,一些新的元素:

os.environ [“TRANSFORMERS_CACHE”]=“緩存/ dbfs /…/ /高頻”summarizer_pipeline =管道(“摘要”,模型=“t5-small”記號賦予器=“t5-small”num_beams =10)summarizer_broadcast = sc.broadcast (summarizer_pipeline)@pandas_udf (“字符串”)defsummarize_review(評論):管= summarizer_broadcast.value ((總結:“+評論).to_list (), batch_size =8截斷=真正的)返回pd.Series ([s [“summary_text”]年代管)camera_reviews_df = spark.read。格式(“δ”).load (“/ tmp /…/審查/清洗”)顯示器(camera_reviews_df.withColumn (“摘要”,summarize_review (“review_body”).select (“review_body”,“摘要”).limit (10))
review_body 總結
好相機的價格。 偉大的相機相機的價格。專業攝影師的相機是一個很好的選擇。它是世界上最好的相機。
我不高興,電纜下車。需要一個更強的近 我不高興,電纜下車。需要一個更強更接近電纜。請點擊這裏查看所有最新的電視新聞。
好相機的價格。注意,240,480年933相機進來,所以這不是那麼清晰。我所需要的工作啊,我真希望我就會知道這之前我買了它。 933相機的240,所以這並不是那麼清晰。我希望我知道這之前我買了它。
我真的非常喜歡這些貼紙。他們立即和他們的預期。我喜歡所有的設計。 貼紙是及時和他們的預期。我喜歡所有的設計和設計。貼紙是一個偉大的除了貼紙。
不要試圖用一個汽車充電器充電線或適配器插頭!它會消耗電池。 不要試圖用一個汽車充電器充電線或適配器插頭。它會消耗電池。如果你想充電,這是一個好主意。

不壞幾行代碼,執行幾分鍾——這甚至不需要一個GPU。結果看起來可信的簡明總結回顧。然而,股票模型掙紮有點過於簡短的回顧總結,甚至在前兩個摘要有點太遠了!這表明需要一些微調。

上麵的清單中強調了一些有用的使用技巧:

  • TRANSFORMERS_CACHE環境變量設置為一個位置/ dbfs,下載模型隻有一次和重用在許多工作和集群
  • 廣播管道幫助火花有效轉移和分享它,而不是必要的,但是對於較大的模型是非常重要的
  • 使用熊貓udf與火花高效流程整個批次的輸入
  • 從一個小模型t5-small和工作需要
  • 摘要管道有幾個設置,一些是有用的了解:
    • min_new_tokens鼓勵輸出不會太短;這是使用下麵生成再總結更多的文本;這將是以後使用
    • num_beams可以提高輸出的質量,嚐試更多的可能性,更多的計算成本

到目前為止,這並不新鮮。然而,這樣做的目的是總結所有檢查每個產品。這很容易引發;聚合文本的評論總結:

summarizer_pipeline =管道(“摘要”,模型=“t5-small”記號賦予器=“t5-small”num_beams =10min_new_tokens =50)summarizer_broadcast = sc.broadcast (summarizer_pipeline)@pandas_udf (“字符串”)defsummarize_review(評論):管= summarizer_broadcast.value ((總結:“+評論).to_list (), batch_size =8截斷=真正的)返回pd.Series ([s [“summary_text”]年代管)review_by_product_df = camera_reviews_df.groupBy (“product_id”)。\gg (collect_list (“review_body”).alias (“review_array”),計數(“*”).alias (“n”))。\過濾器(“n > = 10”)。\選擇(“product_id”,“n”concat_ws (”“坳(“review_array”).alias (“評論”))。\withColumn (“摘要”summarize_review (“評論”))顯示器(review_by_product_df.select (“評論”,“摘要”).limit (10))

這裏是一個例子的輸出,總複習截斷簡潔:

評論 總結
這個項目沒有問題。其所有功能完美的工作。我建議這個項目對於任何想要黑白照片。這台相機不是我的預期,這是更輕,似乎有點脆弱,但它是在非常好的條件和很快到來,就像發送方的廣告。這是一個非常容易使用的相機和我很高興我有學習,但電影我開發的第一個角色的質量並不好。 相機對於攝影的學生購買。它很快到來,就像發送方的廣告。考慮到電池的價格很低,這台相機需要工作很難找到,或者賣方應該指定的信息。

有趣的,但很明顯,總結不是很好。兩個下一個邏輯步驟將在一個更大的模型,這些模型或微調。以下部分將嚐試。

現成的微調

微調僅僅意味著進一步培訓pre-trained模型的新數據,以改善其性能在一個特定的任務。模型像T5都被訓練去做許多事情看起來像轉換到另一個序列的一個單詞。這裏,應該做一件事:變換許多產品評論回顧總結。這就像總結任務,T5,我們隻希望它調整總結已經更好地適應實際的評估數據。這是不一樣的培訓從頭T5架構。不僅會花費很長的時間,但是它將失去所有的相關學習語言pre-trained T5模型已經。

上麵的例子而簡單,相對於發生的事情的複雜性,因為它重用現有的模型,和所有的研究數據和計算能力去創造它。然而,微調模型培訓,即使對經驗豐富的從業者,這不是簡單的寫PyTorch或Tensorflow代碼需要繼續培訓過程。

幸運的是,這些開放源碼模型往往會有培訓或調整代碼。不幸的是對於筆記本用戶來說,他們通常是Python腳本,而不是筆記本。這不是一個問題在磚,甚至筆記本電腦可以執行shell命令,腳本從git回購,或任何一種交互式地網絡終端

獲得微調腳本

事實上,擁抱的臉提供了一些方便微調的腳本在T5工作模型,通過教練的API。它將明顯後來為什麼使用這些腳本是有利的,即使它似乎有點尷尬的考慮。複用現有的解決方案是一個偉大的方式開始迅速。

首先,克隆擁抱臉Github庫在磚作為回購。隻有克隆總結的例子,而不是整個回購,使用稀疏校驗模式:

回購的磚

這run_summarization的副本。py腳本。也很好隻是複製粘貼run_summarization.py成任何你喜歡的回購。

一個小改變是必要的。腳本檢查變壓器庫版本匹配它期望什麼。這源付款預計源安裝變壓器。你可以添加% pip安裝git + https://github.com/huggingface/transformers而不是改變這個文件,但它也可能可以拆卸檢查。刪除行閱讀check_min_version (“……dev0”)從你的副本。

環境設置

在任何地方,使用這些腳本需要一些設置。在磚運行時12.2毫升(GPU -這肯定會需要一個GPU !):

  • 安裝必要的庫,不是已經在運行時:
    % pip安裝'變形金剛> = 4.26.0 '數據集評估rouge-score
  • 設置環境變量連接磚的主持MLflow跟蹤服務器擁抱的臉的MLflow集成:
    os.environ [“DATABRICKS_TOKEN”]=dbutils.notebook.entry_point。\.apiToken .getContext .notebook getDbutils () () () ()。得到()os.environ [“DATABRICKS_HOST”]=“https://”+spark.conf.get (“spark.databricks.workspaceUrl”)os.environ [“MLFLOW_EXPERIMENT_NAME”]=“/用戶/…/ fine-tuning-t5”os.environ [“MLFLOW_FLATTEN_PARAMS”]=“真正的”

一個現代GPU容易處理t5-small微調。有利於使用最近的安培架構GPU像NVIDIA的A10或A100這些模型。例如,在AWS,這可能是g5實例類型。比A100s a10可能更容易獲得。

這樣的腳本通常希望本地輸入文件;在這裏,優化腳本希望CSV文件(文本、總結)對。沒有問題;分布式存儲與/ dbfs看起來像本地文件。隻是寫出來作為一對增量數據集的訓練和驗證文件:

train_df val_df = camera_reviews_cleaned_df.randomSplit ([0.9,0.1),種子=42)train_df.toPandas () .to_csv (“dbfs /…/ camera_reviews_train.csv”指數=)val_df.toPandas () .to_csv (“dbfs /…/ camera_reviews_val.csv”指數=)

調整微調

實際微調然後運行腳本。這幾乎是虎頭蛇尾。

%上海出口DATABRICKS_TOKEN& &出口DATABRICKS_HOST& &出口MLFLOW_EXPERIMENT_NAME& &出口MLFLOW_FLATTEN_PARAMS=真正的& &python \/工作空間/回購//摘要/run_summarization.py\——model_name_or_path t5-small \——do_train \——do_eval \——train_file dbfs /…/審查/ camera_reviews_train。csv \——validation_file dbfs /…/審查/ camera_reviews_val。csv \——source_prefix”總結:“\——output_dir / dbfs /……/審查/t5-small-summary \——optim adafactor \——num_train_epochs 8 \——bf16 \——per_device_train_batch_size 64 \——per_device_eval_batch_size 64 \——predict_with_generate \——run_name“t5-small-fine-tune-reviews”

腳本的參數太多了封麵,但值得注意的幾項:

  • 出口的環境變量允許MLflow集成工作
  • source_prefix:“總結:“幫助T5理解數據的文本摘要
  • optim:Adafactor優化器是沒有嚴格要求,但其減少內存使用後,調優較大的模型是很重要的
  • bf16:允許更快的16位浮點運算使用bfloat16類型,它保留了更多的數字範圍。這就要求現代安培gpu。
  • num_train_epochs:微調不需要盡可能多的時代從頭開始訓練,所以少數時代可以好
  • per_device_train_batch_size:這一重要參數控製批量大小。在任何訓練,大型批量大小可以排氣GPU內存。微調時這將是一個關鍵問題較大的模型,但是大值64應該可以與短序列數據集,和對現代gpu 24 gb或更多的內存。您的裏程將發生顯著的變化。

這需要大約一個小時A10 GPU,例如,花費幾美元。在訓練(之後),MLflow記錄培訓指標,如損失的步驟:

A10 GPU

看來,雖然訓練可以開始一段時間,8時代大約reconverge已經足夠。有更多的捕獲(eval指標、模型)或可以捕獲(檢查點,TensorBoard日誌);的更多細節見附帶的筆記本如何MLflow追蹤模型,甚至可以作為一個REST API部署它。

TensorBoard

你可以找到更多的指標自動記錄與模型,胭脂指標評估質量的總結。這可能是有用的在決定怎麼做調整,這個指標給出了一個更有意義的照片比損失結果的質量。

就是這樣!你調整一個T5模型磚使用開放的、現成的模型和工具。結果呢,他們改善嗎?就重新運行總結管道上麵所描述的那樣,“t5-small”替換為您的模型的輸出路徑:

summarizer_tuned =管道(“摘要”,\模型=“dbfs /…/審查/ t5-small-summary”,\記號賦予器=“dbfs /…/審查/ t5-small-summary”,\num_beams =10min_new_tokens =50)
評論 總結
這個項目沒有問題。其所有功能完美的工作。我建議這個項目對於任何想要黑白照片。這台相機不是我的預期,這是更輕,似乎有點脆弱,但它是在非常好的條件和很快到來,就像發送方的廣告。這是一個非常容易使用的相機和我很高興我有學習,但電影我開發的第一個角色的質量並不好。 好相機,好價格,好運輸,偉大的客戶服務-偉大的價格好的產品易於使用和易於使用的——就像我預期的那麼好,正是我需要的!

文字看起來更像一個評論標題,如預期。它缺少一些深度也許!這甚至可以變成了一個REST API幾次點擊。

值得思考延遲如果考慮REST API。需要多長時間來回應總結?如果延遲是很重要的,那麼在GPU執行是很重要的。事實證明,僅運行一個總結大約需要480 ms。

更複雜的總結,值得嚐試一個更大的T5模型。

擴大與DeepSpeed t5-large

當擴大到一個更大的模型很少更改t5-large一樣,盡管模型是一個數量級,在770 m參數與60 m。事實上,在上麵運行調整腳本應該改變:

  • 切換到多個gpu - 4 A10 gpu例如,而不是1
  • 指定t5-large
  • 減少對12批大小

一個更大的模型需要更多的硬件,意味著更少的可以適用於GPU。正確的批量大小可以是困難的,部分原因是序列長度不均勻,有時長。這就是為什麼數據準備有限長度的回顧和總結。腳本也有選項max_source_length手動截斷輸入。規模較小的輸入可以幫助,但是,根據具體問題,它可能損害模型通過任意刪除輸入的質量。

是你重新運行這些變化,你會發現它的工作原理。每個時代也需要2個小時。成本不再僅僅是幾美元,但更像90美元的8時代。出於這個原因,就需要仔細思考時代的數量。例如,運行4時代似乎並沒有導致更高的損失在上麵的圖中,因此,有人可能會合理地運行4時代當調優,至少開始。人們總是可以恢複一個檢查站和培訓進一步如果需要。

進入DeepSpeed

也變得很重要的利用比什麼工具例如擁抱麵臨更複雜的並行化提供了開箱即用的。幸運的是,再次開放源碼有一些答案。微軟的DeepSpeed可以加速現有深度學習培訓和推理工作,很少或根本沒有變化,通過實施一係列複雜的優化。特別感興趣的是零,一組優化,試圖減少內存使用量。全部細節和論文,看到DeepSpeed網站。

DeepSpeed可以自動優化微調使用擁抱臉的教練API的工作,並提供替代腳本運行現有的微調腳本。這是一個原因,重用現成的培訓腳本是有利的。

使用DeepSpeed,安裝的包,以及加速。建議從源代碼安裝它,雖然安裝包發布的作品:% pip安裝…git + https://github.com/microsoft/DeepSpeed加速

相同的執行DeepSpeed看起來隻有略有不同:

%上海出口DATABRICKS_TOKEN& &出口DATABRICKS_HOST& &出口MLFLOW_EXPERIMENT_NAME& &出口MLFLOW_FLATTEN_PARAMS=真正的& &deepspeed \/工作空間/回購//run_summarization.py\——deepspeed /工作區/回購/ . . / ds_config_zero2_no_offload_adafactor。json \——model_name_or_path t5-large \——do_train \——do_eval \——train_file / dbfs /…/ camera_reviews_train。csv \——validation_file / dbfs /…/ camera_reviews_val。csv \——source_prefix”總結:“\——output_dir / dbfs /……/ t5-large-summary-ds \——optim adafactor \——num_train_epochs 4 \——gradient_checkpointing \——bf16 \——per_device_train_batch_size 20 \——per_device_eval_batch_size 20 \——predict_with_generate \——run_name“t5-large-fine-tune-reviews-ds”

python是deepspeed運動員腳本所取代。它還需要一個配置文件的路徑。探索該文件中的選項的範圍,盡管它是合理的開始默認的“零階段2”配置微小的變化。例如,當前的設置需要兩個編輯:

  • 顯式地啟用bf16(正常和禁用float16 / fp16支持)
  • 刪除優化配置,讓它使用Adafactor而不是AdamW。Adafactor需要更少的內存,是任何大型模型微調時一個不錯的選擇

DeepSpeed可以添加更多的改進:

  • 向前gradient_checkpointing:發布一些大型的中間結果,重新計算他們向後傳球;節省內存的成本計算
  • 種每設備批量大小可以20(如果需要可能會更高)。注意4 gpu,有效批大小現在4 x 20 = 80。

批量大小成為一個重要的優化問題。批量大小每設備,因為它通常是調整個人GPU內存限製多少一個GPU可以處理。更大的批量大小增加吞吐量——如果他們不排氣GPU內存!最大的批處理大小取決於幾個因素,包括GPU內存大小的輸入序列,最大的層模型的大小,優化器設置,等等。一般來說,它必須是一些試驗和錯誤。

有時過分大的批量大小也是有問題的培訓。然而,非常大的語言模型,這個問題通常是尋找適合一些,或者,批到每個設備的內存。記住,至少是重要的有效批大小(x種每設備批量大小的設備數量),隨著批量大小對繁殖的結果很重要。

這滴執行時間更像40分鍾/時代。大約3倍也便宜3倍,意味著這個調優可能成本更像30美元。這將變得越來越寶貴的時間以天,數百甚至數千美元的成本。

GPU度量的改進是可見的,就像這些神經節指標從磚集群:

沒有DeepSpeed:

磚集群

DeepSpeed:

磚集群

總結如何看這個模型嗎?

評論 總結
這個項目沒有問題。其所有功能完美的工作。我建議這個項目對於任何想要黑白照片。這台相機不是我的預期,這是更輕,似乎有點脆弱,但它是在非常好的條件和很快到來,就像發送方的廣告。這是一個非常容易使用的相機和我很高興我有學習,但電影我開發的第一個角色的質量並不好。 偉大的相機,偉大的條件如新。它需要驚人的照片和易於處理和使用。偉大的攝影類的相機和到目前為止與質量的照片,我很高興了。偉大的賣方處理!

簡潔,或許更好,因為它現在提供一些準確的詳細審查文本。模型的延遲在單一GPU現在大約3秒,可能已經給暫停如果考慮進一步擴展到更大的模型。一個可能會停止,但也可以規模最大的T5模型。

超大尺寸:微調t5-11b

最大的T5模型t5-11b,,你猜,110億參數,t5-large超過14倍。微調是仍然可能在一台機器上,盡管在雲中可用最大的類型,用同樣的方法。

%上海出口DATABRICKS_TOKEN& &出口DATABRICKS_HOST& &出口MLFLOW_EXPERIMENT_NAME& &出口MLFLOW_FLATTEN_PARAMS=真正的& &deepspeed \/工作空間/回購//run_summarization.py\——deepspeed / Workspace /回購/…/ ds_config_zero3_adafactor。json \——model_name_or_path t5-11b \——do_train \——do_eval \——train_file / dbfs /…/ camera_reviews_train。csv \——validation_file / dbfs /…/ camera_reviews_val。csv \——source_prefix”總結:“\——output_dir / dbfs /……/ t5-11b-summary \——optim adafactor \——num_train_epochs 1 \——gradient_checkpointing \——bf16 \——per_device_train_batch_size 8 \——per_device_eval_batch_size 8 \——predict_with_generate \——run_name“t5-11b-fine-tune-reviews”

這是一個龐大的任務,實際上,讓這個完整的合理的時間需要更多的變化:

  • 一個8-GPU機器內存400 gb +
  • 1培訓時代(或更少)
  • 每批設備大小8(有效批大小8×8 = 64)
  • 完整的“零第三階段”優化分區,其中包括完整的參數,參數卸載啟用

它工作,但是對於這個數據集大小和輸入,一個時代大約需要1.8才能完成。成本將接近每個時代數百美元。這當然可以是進一步調整,但給人一種計算預期的規模。這個例子的目的,隻是微調幾百步時代的(1%)產生了這樣的總結:

評論 總結
這個項目沒有問題。其所有功能完美的工作。我建議這個項目對於任何想要黑白照片。這台相機不是我的預期,這是更輕,似乎有點脆弱,但它是在非常好的條件和很快到來,就像發送方的廣告。這是一個非常容易使用的相機和我很高興我有學習,但電影我開發的第一個角色的質量並不好。 好相機攝影類! !我很滿意我的購買。送貨很快,我收到相機後幾天購買。我在黑白膠片攝影類和到目前為止結果很高興我的第一卷膠卷

這是一個更好的總結,定性。對於這個問題,不太可能是值得的時間和成本,然而,即使這是完全可能的。即使在調整成本和時間是可以接受的,推理成本和時間可能不是。例如,推理與GPU t5-11b可能需要幾十秒,那可能是太慢了。對於大多數問題,這種規模或更小的就足夠了,但是超大規模調整方便。

結論和未來方向

大語言模型是一係列的業務問題,強大的新工具和開源的按原樣可以應用,容易,使用開源工具,在磚上。微調這些大型語言模型可以同樣簡單的開源工具;不需要手工編寫工具。甚至在磚筆記本的腳本是沒有問題。這些簡單的方法擴大尺寸滿足幾乎任何現實世界的問題。

快速實驗的結果與微調各種大小的T5,沿著數量級資源需求調整和運行推理:

T5大小 例子總結 調整時間 優化成本 推理延遲
t5-small
60 m參數
沒有調整
相機對於攝影的學生購買。它很快到來,就像發送方的廣告。考慮到電池的價格很低,這台相機需要工作很難找到,或者賣方應該指定的信息。 n /一個 n /一個 100年代的女士
t5-small
60 m參數
微調
好相機,好價格,好運輸,偉大的客戶服務-偉大的價格好的產品易於使用和易於使用的——就像我預期的那麼好,正是我需要的! 一個小時 10美元的年代 100年代的女士
t5-large
770的參數
微調
偉大的相機,偉大的條件如新。它需要驚人的照片和易於處理和使用。偉大的攝影類的相機和到目前為止與質量的照片,我很高興了。偉大的賣方處理! 幾個小時 100年代
t5-11b
11 b參數
微調
好相機攝影類! !我很滿意我的購買。送貨很快,我收到相機後幾天購買。我在黑白膠片攝影類和到目前為止結果很高興我的第一卷膠卷 1000年代 10秒

然而,總會有需要更多的情況下,甚至需要更多的資源比最大的機器提供。更多的工作,這些工具可以適應集群在磚的機器,是未來博客的主題。

試試這個磚!導入該筆記本電腦存檔在一個存儲庫中。

免費試著磚

相關的帖子

看到所有工程的博客的帖子
Baidu
map