# 
        Layer
    
A Layer is simply a list of Units grouped together in a stage of execution for the purposes of organization and shared configuration (e.g., sharing a model + inference parameters with .via will apply to all Units in the Layer). This container allows you to quickly re-organize and scale up Units in an ensemble, round-robin, or other arbitrary configurations.
By default, a Layer propagates information through a judge system in a feedforward fashion with the Units of a subsequent Layer receive the output of a previous Layer's Units in a fully-connected fashion; furthermore, Units within a Layer are fully independent of one another.
from verdict import Layer
from verdict.common.judge import JudgeUnit
from verdict.transform import MeanPoolUnit
ensemble = Layer(JudgeUnit(), 3).via('gpt-4o', temperature=0.8) \
    >> MeanPoolUnit("score") 
    
However, it is possible to customize Unit behavior both within a Layer (using keyword inner=) and between current and subsequent Layers (using keyword outer=). Below are common instances of how Units can be stitched together from Layer to Layer. Using the inner='chain' keyword, we can stitch together subsequent JudgeUnit's within the Layer.
from verdict.schema import Schema, Field
from verdict.scale import DiscreteScale
class JudgeRoundRobinUnit(JudgeUnit):
    class InputSchema(Schema):
        explanation: str = Field(default="")
round_robin = Layer(
    JudgeRoundRobinUnit(DiscreteScale((1, 5)), explanation=True).prompt("""
        Rate how funny this joke is.
        {source.joke}
        Consider the previous Judge's explanation to produce your own judgement
        {input.explanation}
""")
, 3, inner='chain').via('gpt-4o', temperature=0.8) \
    >> MeanPoolUnit("score") 
    
Perhaps we only want to output the final Judge's score. Of course, you can simply reference the final previous.judge[2].score using the Previous keyword in a subsequent Prompt. We also can also use the last keyword.
from verdict import Unit
round_robin = Layer(
    JudgeRoundRobinUnit()
, 3, inner='chain', outer='last') \
    >> Unit() # dummy Unit for demonstration 
    
We can also customize the root/leaf node indices that are used to connect Layers.
from verdict.common.conversational import ConversationalUnit
from verdict.common.judge import JudgeUnit
conversation = Layer([
    ConversationalUnit(role_name='Proponent'),
    ConversationalUnit(role_name='Opponent')
], 3, inner='chain', outer='broadcast').with_leaf([1, 3, 5]) \
    >> Layer(JudgeUnit(), 3) 
    
        # 
        Usage
    
 
    
        # 
        Unraveling
    
By default, a Layer takes a single primitive (i.e., Unit/Layer/Block); however, you can also pass a list of primitives to a Layer and it will be unraveled appropriately.
