11package org.evomaster.core.llm.service
22
3+ import com.fasterxml.jackson.core.type.TypeReference
4+ import com.fasterxml.jackson.databind.ObjectMapper
35import dev.langchain4j.model.chat.ChatModel
46import dev.langchain4j.model.chat.StreamingChatModel
57import org.evomaster.core.EMConfig
68import org.evomaster.core.config.ConfigProblemException
9+ import org.evomaster.core.llm.FieldInfo
10+ import org.evomaster.core.llm.LlmProvider
711import org.evomaster.core.llm.LlmSupport
12+ import org.evomaster.core.llm.Prompts
13+ import java.util.concurrent.ExecutorService
14+ import java.util.concurrent.Executors
815import java.util.concurrent.Future
916import javax.annotation.PostConstruct
1017import javax.inject.Inject
@@ -18,6 +25,8 @@ class LlmService {
1825
1926 private lateinit var syncModel: ChatModel
2027
28+ private lateinit var executor: ExecutorService
29+
2130 @PostConstruct
2231 private fun initService () {
2332
@@ -47,6 +56,13 @@ class LlmService {
4756 }catch (e: Exception ){
4857 throw ConfigProblemException (" Failed to connect and initialize the chosen LLM: ${e.message} " )
4958 }
59+
60+ val n = if (config.llmProvider == LlmProvider .OLLAMA ) 1 else config.llmThreads
61+ executor = Executors .newFixedThreadPool(n)
62+ }
63+
64+ fun shutdown () {
65+ executor.shutdown()
5066 }
5167
5268 private fun checkUsingLLM (){
@@ -64,4 +80,36 @@ class LlmService {
6480 fun chat (userMessage : String ) : String {
6581 return LlmSupport .chat(syncModel, " " , userMessage)
6682 }
83+
84+ fun askForNewExamples (fields : Collection <FieldInfo >, callback : (name: String , examples: Collection <String >) -> Unit ){
85+
86+ fields.toList()
87+ .sortedBy { it.name }
88+ .forEach { entry ->
89+ executor.submit { askForExamplesTask(entry.name, entry.description, callback) }
90+ }
91+ // here we do not wait... updates are done asynchronously
92+ }
93+
94+ private fun askForExamplesTask (
95+ name : String ,
96+ description : String? ,
97+ callback : (name: String , examples: Collection <String >) -> Unit
98+ ){
99+ val mapper = ObjectMapper ()
100+ val prompt = Prompts .getPromptForNameDescription(name, description)
101+ var result = LlmSupport .chat(syncModel, prompt.first, prompt.second)
102+ val list = try {
103+ mapper.readValue(result, object : TypeReference <List <String >>() {})
104+ } catch (e: Exception ) {
105+ try {
106+ val failed = Prompts .getPromptForFailedName(e.toString())
107+ result = LlmSupport .chat(syncModel, failed.first, failed.second)
108+ mapper.readValue(result, object : TypeReference <List <String >>() {})
109+ } catch (e: Exception ) {
110+ throw e
111+ }
112+ }
113+ callback(name, list)
114+ }
67115}
0 commit comments