LLM summarizers by example

A summarizer turns a group of LLM tool calls into deterministic inspector views. Summarizers are subclasses of GtLToolCallsSummarizer Object << #GtLToolCallsSummarizer slots: { #originalToolCalls . #summarizerSpecification }; tag: 'Summaries'; package: 'Gt4LlmCore' and are shown on GtLMessagesGroup GtLGroup << #GtLMessagesGroup slots: {}; tag: 'Core'; package: 'Gt4LlmCore' .

messagesGroupWithToolAndExampleSummaries
	<gtExample>
	| group toolCall toolMessage exampleWithResult singleStatus wrappedSingle exampleMethod |
	group := GtLMessagesGroup new.
	exampleMethod := self class >> #exampleStatusSuccess.

	toolCall := GtLFunctionToolCall new
		name: 'exampleMethodRun';
		arguments: (Dictionary new
			at: 'exampleReference' put: 'GtLToolCallsSummarizerExamples>>exampleStatusSuccess';
			yourself);
		yourself.

	exampleWithResult := exampleMethod gtExample asExampleWithResult.

	singleStatus := GtLExampleWithResultStatus new.
	singleStatus
		instVarNamed: 'exampleWithResult' put: exampleWithResult;
		objectId: nil.

	wrappedSingle := GtLWrappedObjectModel new
		name: 'example';
		model: singleStatus;
		yourself.

	toolCall result: wrappedSingle.
	toolMessage := GtLToolMessage new
		toolCall: toolCall;
		output: wrappedSingle;
		yourself.

	group add: toolMessage.
	group add: (GtLToolMessage new
		toolCall: (GtLFunctionToolCall new
			name: 'lookupClass';
			arguments: (Dictionary new at: 'className' put: 'Object'; yourself);
			yourself);
		output: wrappedSingle;
		yourself).

	self assert: group relevantToolCallsSummarizers size equals: 2.
	self assert: (group toolCallsSummarizers allSatisfy: [ :each | each class inheritsFrom: GtLToolCallsSummarizer ]).
	^ group
    

A summarizer defines a concise text through GtLToolCallsSummarizer>>#summaryText summaryText ^ self subclassResponsibility and one or more <gtView> views. The default summary view is GtLToolCallsSummarizer>>#gtSummaryFor: gtSummaryFor: aView <gtView> ^ aView textEditor title: 'Summary'; priority: 5; text: [ self summaryText asRopedText ] .

Concrete summarizers select relevant tool calls and compute domain objects from them. For example, GtLCodeChangesToolCallsSummarizer GtLToolCallsSummarizer << #GtLCodeChangesToolCallsSummarizer slots: { #relevantToolCalls . #codeChanges }; tag: 'Summaries'; package: 'Gt4LlmCore' summarizes code-modifying tool calls and exposes views such as GtLCodeChangesToolCallsSummarizer>>#gtPackageChangeHistoriesFor: gtPackageChangeHistoriesFor: aView <gtView> <gtLlmView> ^ aView forward title: 'Changes by package'; priority: 16; object: [ self packageChangeHistories ]; view: #gtViewHistoriesFor:; actionButtonIcon: BrGlamorousVectorIcons inspect tooltip: 'Inspect summarizer' action: [ :aButton | aButton phlow spawnObject: self ] and GtLCodeChangesToolCallsSummarizer>>#gtCodeChangesFor: gtCodeChangesFor: aView <gtView> ^ aView forward title: 'Code changes'; priority: 21.1; object: [ self codeChanges ]; view: #gtCodeChangesFor:; actionButtonIcon: BrGlamorousVectorIcons inspect tooltip: 'Inspect summarizer' action: [ :aButton | aButton phlow spawnObject: self ]; actionUpdateButton .

packageChangeHistoriesForClassCreationAndRemoval
	<gtExample>
	<after: #cleanupCreatedClasses>
	| group summarizer packageHistories classHistory |
	
	group := self messagesGroupWithExecutedClassCreationAndRemoval.
	summarizer := group toolCallsSummarizers 
		detect: [ :each | each class = GtLCodeChangesToolCallsSummarizer ].
	
	packageHistories := summarizer packageChangeHistories.
	
	self assert: packageHistories isNotEmpty.
	
	"Find the package containing the temporary class"
	classHistory := packageHistories classHistories items 
		detect: [ :ch | ch targetClassName = 'GtLTemporarySummarizerExampleClass' ] 
		ifNone: [ nil ].
	self assert: classHistory isNotNil.
	self assert: classHistory hasNoEffect description: 'Class was created and then removed, so it should have no effect'.
	
	^ packageHistories
    

Use examples to explain summarizers from the produced objects outward. Build a messages group, inspect its "Tool call summarizers" view, then inspect an individual summarizer and its derived views. Keep the views deterministic and focused on stable summary data.