我們很喜歡故事。講故事和進行其他形式的創作,既有挑戰性又能帶來成就感。不過,從空白頁面開始建立自製故事,有時可能會讓人感到困惑,甚至不知從何下手。人工智慧 (AI) 生成式模型是能幫助你擺脫空白頁面,並建立敘事結構的絕佳工具。
本教學課程將說明如何擴充 Wordcraft,這是由 Google People and AI Research team 建構的 AI 技術輔助故事編寫工具。這個網頁應用程式會使用 Gemini API 協助你建構故事,透過產生點子、撰寫部分故事內容,以及修改內容來加入更多細節,逐步完成故事。您可以修改 Wordcraft,讓 Wordcraft 更符合您自己的寫作風格,並建立新的寫作控制項,以便更好地支援工作流程。
如要觀看有關專案的影片總覽和擴充方式,以及開發人員提供的洞察資料,請參閱「AI 寫作助理 - 使用 Google AI 技術建構」一文。否則,您可以按照下方說明開始擴充專案。
專案設定
本操作說明將逐步引導您設定 Wordcraft 專案,以便進行開發和測試。您需要安裝必要軟體、從程式碼存放區複製專案、執行設定安裝作業,以及設定幾個環境變數。完成這些步驟後,您可以執行專案來測試設定。
安裝必要條件
Wordcraft 專案會使用 Node 和 npm 管理套件並執行應用程式。以下安裝說明適用於 Linux 主機。
如何安裝必要軟體:
- 請按照安裝說明安裝
node
和npm
。
複製及設定專案
請下載專案程式碼,並使用 npm
安裝指令下載必要的依附元件,然後設定專案。您需要使用 git 原始碼管控軟體,才能擷取專案原始碼。
如要下載及設定專案程式碼,請按照下列步驟操作:
- 使用下列指令複製 Git 存放區。
git clone https://github.com/PAIR-code/wordcraft
- 前往 Wordcraft 專案根目錄。
cd wordcraft/
- 執行安裝指令,下載依附元件並設定專案:
npm install
設定環境變數
設定 Wordcraft 程式碼專案執行所需的環境變數,特別是 Google Gemini API 金鑰。以下安裝操作說明適用於 Linux 主機。
如要設定環境變數,請按照下列步驟操作:
- 取得 Google Gemini API 金鑰,然後複製金鑰字串。
- 前往 Wordcraft 專案的根目錄。`
cd wordcraft/
- 將 API 金鑰設為環境變數。在 Linux 主機上,請使用下列指令。
touch .env echo "API_KEY="<YOUR_API_KEY>"" > .env
測試設定
您現在應該可以透過在裝置上執行 Wordcraft 來測試專案設定。這是選擇性步驟,但建議您採取。
如何測試安裝和設定:
- 前往 Wordcraft 專案根目錄。
cd wordcraft/
- 在開發模式中透過它執行專案:
npm run dev
- 在網路瀏覽器中前往 Wordcraft 使用者介面。特定地址會顯示在先前指令的輸出內容中,例如:
http://localhost:3000/
修改提示範例文字
Wordcraft 會根據每項寫作輔助作業的範例,為 AI 生成式模型建立提示,例如「start new story」和「generate text」指令。這些範例可引導生成式模型為故事產生文字,您可以修改操作的範例,讓輸出內容採用不同的模式或寫作風格。這種做法是讓 Wordcraft 以您想要的方式編寫的簡單方法。
以下範例說明如何修改 Wordcraft 中的 new_story
範例。這項修改的目標是指示 AI 生成模型使用內心獨白方法撰寫故事開頭,並採用更適合懸疑小說的風格。只要撰寫幾個這類故事的開頭,就能讓生成式模型遵循一般模式,產生不同主題的開頭。
如要修改 Wordcraft 中的新故事範例,請按照下列步驟操作:
- 開啟
wordcraft/app/context/json/new_story.json
檔案。 - 修改範例,同時保留 JSON 檔案的整體結構。以下是使用內心獨白風格修改的懸疑小說開頭範例。
[ { "topic": "scientist disappears and their research into a new technology is gone", "target": "I got the call from the chief early Tuesday morning, before I'd even had a second sip of coffee. Terrible timing. Something about a researcher disappearing from the local university. Unusual for the research lab to ask for assistance, so I headed over to main lab building." }, { "topic": "a young woman wakes up with no memory", "target": "An unfamiliar ceiling with harsh, white lights greeted my eyes as I opened them. I looked around. White walls, medical equipment, a hospital? Wait. Where am I? How did I get here?!" }, { "topic": "old man tries to recall an important task as his memories gradually fade away", "target": "What was I supposed to do today? Feels like it was important. I stared into the kitchen cabinet full of mismatched mugs, mirroring my own confusion. What was it? Like someone is...in danger? A chill shot down my spine, but the details skittered off and hid in some dark corner of my head." }, { "topic": "billionaire is found dead in a hotel room", "target": "People meet their end every day, some naturally, some unnaturally. After 17 years of working as a homicide detective in Seattle, I'd seen a lot more of the unnatural variety than most. Comes with the job, along with a hard-learned sense of what side of the line any given incident sat on. This...was murder." }, { "topic": "retired covert operative gets dragged back into an old mission", "target": "Steam rose gently off the cup of Earl Grey sitting in front of me as I sat at the cafe, pedestrians and light traffic rolling by. The city was slowly waking up around me and my perfect Paris morning routine was shaping up nicely. Then I noticed that old familiar and unwelcome tingling on the back of my neck. I was being watched." } ]
- 將變更儲存至 `new_story.json` 檔案。
如要測試經過修改的新故事作業,請按照下列步驟操作:
- 前往 Wordcraft 專案的根目錄。
cd wordcraft/
- 在開發模式下執行專案。如果應用程式已在執行,您可能需要停止應用程式並重新啟動。
npm run dev
- 在網路瀏覽器中前往 Wordcraft 使用者介面。特定地址會顯示在先前指令的輸出內容中,例如:
http://localhost:3000/
- 前往 Wordcraft 主選單,然後選取「Start a New Story」。
- 更新新故事提示或變更為您想要的內容,然後選取「開始新故事」。
您可以使用這項技巧修改 Wordcraft 中所有現有的劇本編寫控制項。嘗試更新 wordcraft/app/context/json/
目錄中的範例,變更其他故事控制項。
建立新的書寫控制項
Wordcraft 應用程式可擴充,因此您可以新增寫作控制項來協助自己,類似於應用程式右側「控制項」分頁中的「產生文字」或「重寫句子」按鈕。雖然進行這些修改需要花費更多心力,但您可以根據自己的工作流程和目標調整 Wordcraft 的功能。
以下範例修改會為 Wordcraft 建立新的字元控制項。您可以使用此元素,在故事中介紹新角色,並說明該角色的屬性。這個控制項的基礎與其他 Wordcraft 控制項相同,例如前面討論的「start new story」控制項。您可以建立 JSON 檔案,其中包含幾個範例,說明您希望如何引入字元。其餘的變更則是新增使用者介面和 AI 提示管理功能。
可建立樣本
請寫幾個範例,說明您希望生成式模型如何介紹角色。舉例來說,您想以旁白的方式描述角色,還是想透過主角的經歷介紹角色?以下範例採用後者做法,從主角的角度介紹新角色。您可以使用新的 JSON 檔案新增這些範例:
如要為新控制項新增範例:
- 建立
wordcraft/app/context/json/new_character.json
檔案。 - 在 JSON 檔案中建立範例。在這個範例中,每個範例都包含一個
character
說明欄位,代表提示文字,以及一個target
欄位,顯示預期輸出內容。[ { "character": "A character who is helpful and modest.", "target": "\"You lost, buddy?\" came a voice from behind me. Turning, I discovered a man dressed in a simple but presentable outfit. Small signs of age and loose threads hinted that these clothes, and the man himself, had seen better days." }, { "character": "A character who is attractive and devious.", "target": "Stepping out of the alley a little too quickly, I collided with something solidly muscular and surprisingly delicately scented. \"Sorry.\" I managed, regaining my balance. \"Easy there, buddy, you're gonna hurt yourself,\" came the reply from a man with an almost feline grace, further reinforced by a stare that reminded me of a hunting cat assessing its potential prey." }, { "character": "A character who is old and hesitant.", "target": "\"Excuse me. Do you know the way to the train station from here?\" I looked up from my phone to see a elderly woman in a threadbare coat, purse clutched with two hands in front of her. \"I-I'm supposed to meet my nephew there. Do... do you think you can help me?\"" }, { "character": "A character who is intelligent and aloof.", "target": "Bookish. That was my immediate reaction to this person I now saw in front of me. \"You're finally here. Did you read the notes I sent you?\" The voice sat squarely in between feminine and masculine intonation. \"No, of course you didn't.\" Dismissing my answer before I'd even formulated one. Annoyance immediately flushed through me." }, { "character": "A character who is clumsy and energetic.", "target": "\"Whoa!\" was the only warning I had before someone slammed into my back, almost knocking me off my feet. \"I'm so sorry! WOOO! These skates are a RUSH!\" The apology came from a rather loud redhead wearing rollerblades, dark glasses and a very beefy-looking pair of headphones. That explained the volume of the apology." } ]
- 將變更儲存至
new_character.json
檔案。
建立範例後,請修改 app/context/schema.ts
和 index.ts
檔案,以反映這個新字元控制項的提示內容。
如要將範例新增至 schema.ts
檔案,請按照下列步驟操作:
- 修改
wordcraft/app/context/schema.ts
檔案,加入新的字元範例資料結構。export const newStorySchema = z.object({ topic: z.string(), target: z.string(), }); // add the following: export const newCharacterSchema = z.object({ character: z.string(), target: z.string(), });
定義與這些新範例相關聯的作業類型。這類新類型可將提示範例連結至使用者介面和提示建構程式碼,您會在後續步驟中修改這些程式碼。
如何建立新的作業類型
- 修改
wordcraft/app/core/shared/types.ts
檔案,新增字元運算類型。export const enum OperationType { ... NEW_CHARACTER = 'NEW_CHARACTER', // add to list of types ... }
如要在 index.ts
檔案中註冊示例,請按照下列步驟操作:
- 在
wordcraft/app/context/index.ts
檔案中匯入新結構定義。import { continueSchema, ... newCharacterSchema // add new schema } from './schema';
- 將新的 JSON 檔案匯入為
newCharacterJson
。import newCharacterJson from './json/new_character.json';
- 在應用程式內容中註冊新的字元範例內容。
export class WordcraftContext { constructor() { ... this.registerExamples( OperationType.NEW_CHARACTER, newCharacterSchema, newCharacterJson ); ... }
- 匯出
NewCharacterExample
類型。export type NewCharacterExample = z.infer<typeof newCharacterSchema>;
建構使用者介面
建立並註冊內容產生範例後,您就可以為新控制項建立使用者介面。這個階段的主要工作是建立新的作業類別,然後將該類別註冊至 Wordcraft 應用程式的主程式碼。
如要建立新作業,請按照下列步驟操作:
- 在
wordcraft/app/core/operations/
目錄中,使用現有運算類別之一做為範本,建立新的運算類別。針對新的字元控制項,您可以複製new_story_operation.ts
類別,並將其重新命名為new_character_operation.ts
。 - 為類別命名,並藉由定義至少一個
OperationSite
值,指定控制項在使用者介面中顯示的時間。export class NewCharacterOperation extends ChoiceOperation { static override isAvailable(operationSite: OperationSite) { return ( operationSite === OperationSite.END_OF_SECTION || operationSite === OperationSite.EMPTY_SECTION ); }
- 設定作業的
id
。static override id = OperationType.NEW_CHARACTER;
- 更新
get
和run
函式,以反映結構定義參數的值。這段程式碼會處理從使用者介面取得提示文字,以便在 AI 提示中使用。private get character(): string { return NewCharacterOperation.controls.character.value; } async run() { const params = { character: this.character }; const choices = await this.getModel().newCharacter(params); this.setChoices(choices); }
- 更新使用者介面文字和說明。
static override getButtonLabel() { return 'introduce character'; } static override getDescription() { return 'Introduce a new character at the cursor.'; } static override controls = { character: new TextareaControl({ prefix: 'prompt', description: 'A prompt to introduce a new character.', value: 'A new character.', }), };
如要在 Wordcraft 應用程式中註冊新作業,請按照下列步驟操作:
- 在
wordcraft/app/core/operations/index.ts
檔案中,新增新作業的匯入作業。import {NewCharacterOperation} from './new_character_operation';
- 在同一個
index.ts
檔案中,為NewCharacterOperation
類別新增匯出作業。export { ... NewCharacterOperation, // add this class ... };
- 在
wordcraft/app/main.ts
檔案中,註冊新的作業。const operationsService = wordcraftCore.getService(OperationsService); operationsService.registerOperations( ... Operations.NewCharacterOperation, // add new operation ... );
建立提示處理程序
在建立新控制項的最後階段,您會建立程式碼,用於處理為 AI 生成式模型產生提示,以及處理回應。這項工作的重點是在 wordcraft/app/models/gemini/prompts/
目錄中建立提示處理常式,該常式會從使用者介面取得輸入內容,並組合要傳遞給生成式模型的提示。
如要為提示參數定義介面,請按照下列步驟操作:
- 在
wordcraft/app/core/shared/interfaces.ts
檔案中,新增介面,用於顯示新作業提示參數。export interface NewCharacterPromptParams { character: string; }
如要定義新作業的提示處理程序,請按照下列步驟操作:
- 在
wordcraft/app/models/gemini/prompts/
目錄中,使用現有作業類別之一做為範本,建立新的提示處理常式類別。針對新的字元控制項,您可以複製new_story.ts
類別,並將其重新命名為new_character.ts
,做為起點。 - 定義提示處理程序函式,並匯入
NewCharacterExample
類別。import { NewCharacterPromptParams } from '@core/shared/interfaces'; import { NewCharacterExample, WordcraftContext } from '../../../context'; import { OperationType } from '@core/shared/types'; import { GeminiModel } from '..'; export function makePromptHandler(model: GeminiModel, context: WordcraftContext) { ... }
- 建構
generatePrompt()
函式,取得 AI 模型提示的使用者介面輸入內容。function generatePrompt(character: string) { const prefix = "Here's a character description: "; const suffix = "Introduce this character in the story."; if (character.trim() === '') { return 'Introduce a new character to the story.'; } else { return `${prefix}${model.wrap(character)}\n${suffix}`; } }
- 建立
getPromptContext()
函式,將使用者介面輸入內容與範例回應組合,並建立完整提示。function getPromptContext() { const examples = context.getExampleData
( OperationType.NEW_CHARACTER ); let promptContext = model.getPromptPreamble(); examples.forEach((example) => { const { character, target } = example; const prompt = generatePrompt(character); promptContext += `${prompt} ${model.wrap(target)}\n\n`; }); return promptContext; }
如要整合新的字元提示處理常式,請按照下列步驟操作:
- 在
wordcraft/app/models/gemini/index.ts
檔案中,匯入新字元作業的提示處理常式。import {makePromptHandler as newCharacter} from './prompts/new_character';
- 為
newCharacter
提示處理常式新增覆寫定義。override newCharacter = this.makePromptHandler(newCharacter);
如要將提示參數與模型定義登錄:
- 在
wordcraft/app/models/model.ts
檔案中,為新的NewCharacterPromptParams
介面新增匯入內容。import { ... NewCharacterPromptParams, ... } from '@core/shared/interfaces';
- 將
newCharacter
提示參數新增至模型類別。async newCharacter(params: NewCharacterPromptParams): Promise<ModelResults> { throw new Error('Not yet implemented'); }
測試新書寫控制項
您應該可以透過 Wordcraft 介面測試新控制項。請務必先檢查程式碼是否有編譯錯誤,再繼續操作。
如要測試新的角色控制項,請按照下列步驟操作:
- 前往 Wordcraft 專案的根目錄。`
cd wordcraft/
- 在開發模式下執行專案:
npm run dev
- 在網路瀏覽器中前往 Wordcraft 使用者介面。特定地址會顯示在先前指令的輸出內容中,例如:
http://localhost:3000/
- 在 Wordcraft 應用程式中,建立新故事或開啟現有故事。
- 在故事編輯區域中,將游標移至故事結尾。右側的「控制項」分頁中應會顯示「引入角色」控制項。
- 在「introduce character」欄位中,輸入新角色的簡短說明,然後選取「introduce character」按鈕。
其他資源
如要進一步瞭解 Wordcraft 專案,請參閱程式碼存放區。您可以在這個提取要求中查看本教學課程中所述的變更。
正式版應用程式
如果您打算為大量使用者部署自訂版 Wordcraft,請注意,您使用 Google Gemini API 時可能會受到速率限制和其他使用限制。如果您考慮使用 Gemini API (例如 Docs Agent) 建構正式版應用程式,請參閱 Google Cloud Vertex AI 服務,進一步提升應用程式的可擴充性和可靠性。