π± Gemini Portrait
It turns Face + Body + Form + Makeup into one character that stays the same character
- face
- body
- form
- cloth
- makeup
- response
- traits
Gemini Portrait is the node the rest of the character family exists to feed. On its own it's a single text-to-prompt generator: give it a text_prompt, an identity (FEMININE or MASCULINE), a framing (headshot, portrait, medium shot, wide shot, full body shot), and it returns a polished character description. But the actual workflow the pack is built around wires the specialized nodes into its five optional inputs - face from Gemini Face, body from Gemini Body, form from Gemini Form, makeup from Gemini Makeup, cloth from the pack's cloth node. Portrait combines them into one property list, hands that list to Gemini, and gets back a single, cohesive character prompt that's specific about the face, the physique and the styling all at once.
That's the whole point, and it's the same problem the KB's character-consistency essay keeps circling: diffusion models have no memory of "this character," so the only way to keep a face and build stable across two different images is to nail it down in words. Portrait is a structured way to do that - every run can feed the same specs in and get a description that names the same cheekbones, the same eye color, the same abs. It's the hub of the π± Artha-Gemini pack (category Artha/LLM/GEMINI), and it has three modes, which is where most people get confused.
The three modes
- Parameters only (
use_imageoff): the property list from your connected nodes is sent to Gemini with no reference image. If the list is empty, the node returns an empty response - Portrait is useless on its own; it wants its children. - Extraction (
use_imageon,reconstructoff): the image is the authority. Gemini reads the photo and describes the character from it, ignoring your connected specs entirely. - Reconstruction (
use_imageon,reconstructon): the image is the base, but your connected specs override it. If the photo's eyes are green and your Face node says blue, blue wins, and any spec you didn't provide gets added from the image. This is the mode for "start from a reference, but my character spec is final."
seed (default 0) is threaded through the API call for reproducible descriptions, and framing is baked into the system instruction - "optimize the prompt for a [framing] framed photo" - so the output length and detail adapt to a headshot versus a full body shot.
Outputs
Two STRING wires, and they behave differently:
response- the finished character description, ready to drop into your text encoder or a prompter node.traits- the raw property list (the- FACE β¦,- BODY β¦lines) that was sent to Gemini. Useful for inspecting exactly what the model was told, and for reusing the spec without re-picking all the dropdowns.
Install & gotchas
Shared pack install:
cd ComfyUI/custom_nodes
git clone https://github.com/Cyrostar/Artha-Gemini
cd Artha-Gemini
pip install -r requirements.txt
Restart ComfyUI, or grab it from ComfyUI Manager (search "Artha-Gemini"). No models to download - the actual model is Google's Gemini, reached over the API, so you need a key from Google AI Studio, and every run is a billed call.
The traps: Portrait calls the API in all three modes, so there's no free path here - budget for it. image is a file dropdown (upload or pick from ComfyUI/input), not an IMAGE socket. And keep your key out of the api_key widget - it's plain text in the workflow JSON; api.json (gemini_api_key) or a GEMINI_API_KEY env var is cleaner. Finally, remember the cloth input expects the pack's cloth output (type ARTHACLOTH) - the character side has five children, not four, and Portrait is where they all meet. If your output reads thin, check which of the five wires you actually connected.
Inputs (16)
| Name | Type | Default | Description |
|---|---|---|---|
| text_prompt | STRING | Construct a prompt describing a character in detail. | β |
| identity | COMBO | FEMININE | 2 options: FEMININE, MASCULINE |
| framing | COMBO | portrait | 5 options: headshot, portrait, medium shot, wide shot, full body shot |
| api_key | STRING | API key will be visible in plain text. Consider adding your api to the api.json located inside this custom node folder. | |
| model | COMBO | gemini-2.5-flash | 5 options: gemini-2.5-pro, gemini-2.5-flash, gemini-2.5-flash-lite, gemini-2.0-flash, gemini-2.0-flash-lite |
| max_tokens | INT | 50001β8192 | For Gemini models, a token is equivalent to about 4 characters. 100 tokens is equal to about 60-80 English words. |
| temperature | FLOAT | 0.70β2 | A temperature of 0 means only the most likely tokens are selected, and there's no randomness. Conversely, a high temperature injects a high degree of randomness into the tokens selected by the model, leading to more unexpected, surprising model responses. |
| seed | INT | 00β18446744073709550000 | β |
| use_image | BOOLEAN | false | β |
| reconstruct | BOOLEAN | false | β |
| image | COMBO | 1 options: example.png | |
| faceopt | ARTHAFACE | β | |
| bodyopt | ARTHABODY | β | |
| formopt | ARTHAFORM | β | |
| clothopt | ARTHACLOTH | β | |
| makeupopt | ARTHAMAKEUP | β |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| response | STRING | β |
| traits | STRING | β |