Skip to content

Commit 77074d2

Browse files
authored
Merge branch 'main' into dependabot/gradle/ktor-version-3.4.0
2 parents 69a6b25 + 4a3e397 commit 77074d2

File tree

5 files changed

+57
-25
lines changed

5 files changed

+57
-25
lines changed

arc-assistants/src/main/kotlin/filters/MustFeature.kt

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,20 @@
44

55
package org.eclipse.lmos.arc.assistants.support.filters
66

7-
import org.eclipse.lmos.adl.server.agents.extensions.RESPONSE_GUIDE_RETRY_REASON
87
import org.eclipse.lmos.arc.agents.conversation.Conversation
98
import org.eclipse.lmos.arc.agents.conversation.ConversationMessage
109
import org.eclipse.lmos.arc.agents.dsl.AgentOutputFilter
1110
import org.eclipse.lmos.arc.agents.dsl.OutputFilterContext
1211
import org.eclipse.lmos.arc.agents.dsl.extensions.getCurrentUseCases
1312
import org.eclipse.lmos.arc.agents.dsl.extensions.llm
1413
import org.eclipse.lmos.arc.agents.dsl.get
15-
import org.eclipse.lmos.arc.agents.retry
1614
import org.eclipse.lmos.arc.core.getOrThrow
1715
import org.slf4j.LoggerFactory
1816

1917
/**
2018
* An [AgentOutputFilter] that extracts "MUST" instructions from processed use cases and verifies compliance.
2119
*/
22-
class MustFeature(private val keyword: String = "MUST", private val retryMax: Int = 3) : AgentOutputFilter {
20+
class MustFeature(private val keyword: String = "MUST") : AgentOutputFilter {
2321

2422
private val log = LoggerFactory.getLogger(this::class.java)
2523

@@ -144,7 +142,7 @@ class MustFeature(private val keyword: String = "MUST", private val retryMax: In
144142
return message
145143
}
146144

147-
log.warn("MustFeature verification failed: $verificationResult")
145+
log.warn("MustFeature verification failed for: ${message.content}")
148146
val fixedResponse = verificationResult.substringAfter("Fixed Response:")
149147
.trim()
150148
.replace("```", "")
@@ -155,12 +153,6 @@ class MustFeature(private val keyword: String = "MUST", private val retryMax: In
155153
return message.update(fixedResponse)
156154
}
157155

158-
context.retry(
159-
max = retryMax,
160-
details = mapOf("error" to "The following instructions must be followed: $instructionsText"),
161-
reason = RESPONSE_GUIDE_RETRY_REASON
162-
)
163-
164156
return message
165157
}
166158
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2+
//
3+
// SPDX-License-Identifier: Apache-2.0
4+
5+
package org.eclipse.lmos.arc.assistants.support.filters
6+
7+
import org.eclipse.lmos.arc.agents.conversation.ConversationMessage
8+
import org.eclipse.lmos.arc.agents.dsl.AgentOutputFilter
9+
import org.eclipse.lmos.arc.agents.dsl.OutputFilterContext
10+
import org.eclipse.lmos.arc.agents.dsl.extensions.getCurrentUseCases
11+
import org.eclipse.lmos.arc.assistants.support.usecases.toUseCases
12+
13+
14+
class StaticResponseFeature : AgentOutputFilter {
15+
16+
override suspend fun filter(
17+
message: ConversationMessage,
18+
context: OutputFilterContext
19+
): ConversationMessage {
20+
val currentUseCaseId = context.getCurrentUseCases()?.currentUseCaseId
21+
context.getCurrentUseCases()?.processedUseCaseMap?.get(currentUseCaseId)?.let { uc ->
22+
val solution = uc.toUseCases().first().solution.joinToString("\n").trim()
23+
if ((solution.startsWith("\"") || solution.startsWith("- \"")) && solution.endsWith("\"")) {
24+
return message.update(solution.substringAfter("\"").substringBeforeLast("\""))
25+
}
26+
}
27+
return message
28+
}
29+
}

arc-assistants/src/main/kotlin/usecases/UseCaseFormatter.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@ suspend fun List<UseCase>.formatToString(
6161
temp.append("#### Solution\n")
6262
useCase.fallbackSolution.output(allConditions, temp, codeBlockProcessor)
6363
}
64+
if (outputOptions.outputSolution != false && useCase.context.isNotEmpty()) {
65+
temp.append("#### Context\n")
66+
useCase.context.output(allConditions, temp, codeBlockProcessor)
67+
}
6468
if (useCase.examples.isNotEmpty() && outputOptions.outputExamples != false) {
6569
temp.append("#### Examples\n")
6670
useCase.examples.split("\n").take(exampleLimit).forEach { example ->

arc-assistants/src/main/kotlin/usecases/UseCaseParser.kt

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ fun String.toUseCases(): List<UseCase> {
2020

2121
forEachLine { line ->
2222
if (line.trimStart().startsWith("#")) {
23-
if (line.contains("# UseCase") || line.contains("# Case")) {
23+
if (line.contains("# UseCase") || line.contains("# Case") || line.contains("# Skill")) {
2424
currentUseCase?.let { useCases.add(it) }
2525
val (lineWithoutConditions, conditions) = line.parseConditions()
2626
val useCaseHeader = lineWithoutConditions.substringAfter(":").trim()
@@ -46,6 +46,7 @@ fun String.toUseCases(): List<UseCase> {
4646
line.contains("# Fallback") -> FALLBACK_SOLUTION
4747
line.contains("# Step") -> STEPS
4848
line.contains("# Example") -> EXAMPLES
49+
line.contains("# Context") -> CONTEXT
4950
else -> error("Unknown UseCase section: ${line.trim()}")
5051
}
5152
return@forEachLine
@@ -62,6 +63,10 @@ fun String.toUseCases(): List<UseCase> {
6263
goal = (currentUseCase?.goal ?: emptyList()) + line.asConditional(),
6364
)
6465

66+
CONTEXT -> currentUseCase?.copy(
67+
context = (currentUseCase?.context ?: emptyList()) + line.asConditional(),
68+
)
69+
6570
STEPS -> currentUseCase?.copy(steps = (currentUseCase?.steps ?: emptyList()) + line.asConditional())
6671
EXAMPLES -> currentUseCase?.copy(examples = (currentUseCase?.examples ?: "") + line)
6772
DESCRIPTION -> currentUseCase?.copy(
@@ -202,6 +207,7 @@ enum class Section {
202207
FALLBACK_SOLUTION,
203208
STEPS,
204209
EXAMPLES,
210+
CONTEXT,
205211
}
206212

207213
@Serializable
@@ -219,6 +225,7 @@ data class UseCase(
219225
val goal: List<Conditional> = emptyList(),
220226
val subUseCase: Boolean = false,
221227
val category: String? = null,
228+
val context: List<Conditional> = emptyList(),
222229
) {
223230
fun matches(allConditions: Set<String>, input: String? = null): Boolean = conditions.matches(allConditions, input)
224231

@@ -294,20 +301,20 @@ fun Set<String>.matches(conditions: Set<String>, input: String? = null): Boolean
294301
conditions
295302
}
296303
return isEmpty() || (
297-
positiveConditionals().all { allConditions.contains(it) } &&
298-
negativeConditionals().none { allConditions.contains(it) } &&
299-
orConditionals().all { ors ->
300-
ors.any {
301-
if (it.startsWith("!")) {
302-
!allConditions.contains(
303-
it.removePrefix("!").trim(),
304-
)
305-
} else {
306-
allConditions.contains(it.trim())
304+
positiveConditionals().all { allConditions.contains(it) } &&
305+
negativeConditionals().none { allConditions.contains(it) } &&
306+
orConditionals().all { ors ->
307+
ors.any {
308+
if (it.startsWith("!")) {
309+
!allConditions.contains(
310+
it.removePrefix("!").trim(),
311+
)
312+
} else {
313+
allConditions.contains(it.trim())
314+
}
315+
}
307316
}
308-
}
309-
}
310-
)
317+
)
311318
}
312319

313320
/**

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,4 @@ org.gradle.dependency.verification=lenient
1212
#org.gradle.configuration-cache=true
1313
#org.gradle.configuration-cache.problems=warn
1414
org.gradle.configureondemand=true
15-
version=0.214.0-SNAPSHOT
15+
version=0.216.0-SNAPSHOT

0 commit comments

Comments
 (0)