.....
This commit is contained in:
parent
15b2c63e95
commit
c85996e453
@ -27,6 +27,9 @@ configurations {
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
|
||||
maven { url = uri("https://repo.spring.io/milestone") }
|
||||
|
||||
}
|
||||
|
||||
dependencies {
|
||||
@ -56,6 +59,13 @@ dependencies {
|
||||
// implementation(platform("com.google.cloud:libraries-bom: 26.55.0"))
|
||||
// implementation("com.google.cloud:google-cloud-apikeys")
|
||||
implementation ("com.google.maps:google-maps-services:2.2.0")
|
||||
// implementation ("org.springframework.ai:spring-ai-openai-spring-boot-starter:1.0.0-SNAPSHOT")
|
||||
// implementation ("org.springframework.ai:spring-ai-vertex-ai-gemini-spring-boot-starter:1.0.0-SNAPSHOT")
|
||||
// implementation("org.springframework.ai:spring-ai-ollama-spring-boot-starter:1.0.0-SNAPSHOT")
|
||||
implementation(platform("org.springframework.ai:spring-ai-bom:1.0.0-M6"))
|
||||
implementation("org.springframework.ai:spring-ai-ollama-spring-boot-starter:1.0.0-M6")
|
||||
implementation("org.springframework.ai:spring-ai-redis-store")
|
||||
|
||||
implementation ("org.slf4j:slf4j-simple:1.7.25")
|
||||
|
||||
implementation("io.jsonwebtoken:jjwt-api:0.11.5")
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
package kr.lunaticbum.back.lun.configs
|
||||
|
||||
import org.springframework.ai.ollama.api.OllamaApi
|
||||
import org.springframework.ai.ollama.api.OllamaOptions
|
||||
import org.springframework.beans.factory.annotation.Value
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
@ -27,6 +29,17 @@ class AppConfig : WebMvcConfigurer {
|
||||
registry.addInterceptor(authInterceptor())
|
||||
super.addInterceptors(registry)
|
||||
}
|
||||
|
||||
@Bean
|
||||
fun chatClient(): OllamaApi {
|
||||
return OllamaApi("https://lama.lunaticbum.kr")
|
||||
// .withDefaultOptions(
|
||||
// OllamaOptions.create()
|
||||
// .withModel("phi4:14b")
|
||||
// .withNumThread(5)
|
||||
// .withSeed(5)
|
||||
// .withTemperature(0.9f))
|
||||
}
|
||||
// @Bean
|
||||
// fun getProperty() : Map<String,String>{
|
||||
// println("telegramBotKey >>>> $telegramBotKey")
|
||||
|
||||
@ -15,9 +15,14 @@ import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kr.lunaticbum.back.lun.configs.GlobalEnvironment
|
||||
import kr.lunaticbum.back.lun.model.*
|
||||
import kr.lunaticbum.back.lun.service.Lama
|
||||
import kr.lunaticbum.back.lun.utils.LogService
|
||||
import org.jsoup.Jsoup
|
||||
import org.springframework.ai.chat.messages.UserMessage
|
||||
import org.springframework.ai.chat.prompt.Prompt
|
||||
import org.springframework.ai.ollama.api.OllamaApi
|
||||
import org.springframework.ai.ollama.api.OllamaOptions
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.beans.factory.annotation.Qualifier
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.http.MediaType
|
||||
import org.springframework.scheduling.annotation.Scheduled
|
||||
@ -25,6 +30,7 @@ import org.springframework.ui.ModelMap
|
||||
import org.springframework.web.bind.annotation.*
|
||||
import org.springframework.web.reactive.function.BodyInserters
|
||||
import org.springframework.web.reactive.function.client.WebClient
|
||||
import reactor.core.publisher.Mono
|
||||
import java.math.BigDecimal
|
||||
import java.math.RoundingMode
|
||||
import java.text.SimpleDateFormat
|
||||
@ -37,6 +43,7 @@ import java.util.prefs.Preferences
|
||||
@RequestMapping("/tlg")
|
||||
class Telegram {
|
||||
|
||||
|
||||
@Autowired
|
||||
lateinit var globalEvv : GlobalEnvironment
|
||||
|
||||
@ -89,6 +96,7 @@ class Telegram {
|
||||
comp = (word).plus(comp)
|
||||
return comp
|
||||
}
|
||||
|
||||
fun trimWithDecompString(comp : String) : String {
|
||||
var doubleIpmt = false
|
||||
var compressed : String? = comp
|
||||
@ -322,32 +330,32 @@ class Telegram {
|
||||
|
||||
} else if (req.reqMsg?.contains("검색") == true) {
|
||||
var originalQuery = req.reqMsg
|
||||
val gSearch = "https://www.googleapis.com/customsearch/v1?key=AIzaSyARLXyvmr_554tOy3UCh3naFlZQS3-qQQM&cx=207f328d3ad7242f2&q=${originalQuery?.replace("오늘", SimpleDateFormat("yyyMMdd").format(Date()))}&num=5&lr=kr"
|
||||
val gSearch = "https://www.google.com/search?q=${originalQuery?.replace("오늘", SimpleDateFormat("yyyMMdd").format(Date()))}&tbs=qdr%3Am"
|
||||
println("gSearch >>> ${gSearch}")
|
||||
WebClient.create().get()
|
||||
.uri(gSearch)
|
||||
.retrieve()
|
||||
.bodyToMono(GoogleSearchResult::class.java).timeout(Duration.ofMinutes(20L)).block()?.let { gsResult ->
|
||||
.bodyToMono(String::class.java).timeout(Duration.ofMinutes(20L)).block()?.let { gsResult ->
|
||||
println("gsearch result ==> ${Gson().toJson(gsResult)}")
|
||||
var additionalInfo = StringBuffer()
|
||||
gsResult.items?.forEach {
|
||||
additionalInfo.append("- 정보 출처 :").append(it.link).append("\n")
|
||||
try {
|
||||
Jsoup.connect(it.link).get().body().text().let {
|
||||
if (it.length > 1000) {
|
||||
additionalInfo.append("- 정보 내용 :").append(it.chunked(500).first()).append("\n")
|
||||
} else {
|
||||
additionalInfo.append("- 정보 내용 :").append(it).append("\n")
|
||||
}
|
||||
}
|
||||
} catch (e : Exception) {
|
||||
additionalInfo.append("- 정보 타이틀 : ").append(it.title).append("\n")
|
||||
additionalInfo.append("- 정보 요약 :").append(it.snippet).append("\n")
|
||||
println(it.link)
|
||||
e.printStackTrace()
|
||||
}
|
||||
additionalInfo.append("\n")
|
||||
}
|
||||
// gsResult.items?.forEach {
|
||||
// additionalInfo.append("- 정보 출처 :").append(it.link).append("\n")
|
||||
// try {
|
||||
// Jsoup.connect(it.link).get().body().text().let {
|
||||
// if (it.length > 1000) {
|
||||
// additionalInfo.append("- 정보 내용 :").append(it.chunked(500).first()).append("\n")
|
||||
// } else {
|
||||
// additionalInfo.append("- 정보 내용 :").append(it).append("\n")
|
||||
// }
|
||||
// }
|
||||
// } catch (e : Exception) {
|
||||
// additionalInfo.append("- 정보 타이틀 : ").append(it.title).append("\n")
|
||||
// additionalInfo.append("- 정보 요약 :").append(it.snippet).append("\n")
|
||||
// println(it.link)
|
||||
// e.printStackTrace()
|
||||
// }
|
||||
// additionalInfo.append("\n")
|
||||
// }
|
||||
println("additionalInfo >>> ${additionalInfo.toString()}")
|
||||
req.reqMsg = "질문 : " + originalQuery + "\n\n추가정보:" + "\n${additionalInfo.toString()} 위의 질문과 추가 정보를 고려하여 답변해주세요."
|
||||
|
||||
@ -415,6 +423,47 @@ class Telegram {
|
||||
}
|
||||
|
||||
|
||||
|
||||
// fun chatClient(): ChatClient {
|
||||
// return OllamaChatClient(OllamaApi("https://lama.lunaticbum.kr"))
|
||||
// .withDefaultOptions(
|
||||
// OllamaOptions.create()
|
||||
// .withModel("phi4:14b")
|
||||
// .withNumThread(5)
|
||||
// .withSeed(5)
|
||||
// .withTemperature(0.9f)
|
||||
// )
|
||||
// }
|
||||
@Autowired
|
||||
lateinit var lama : Lama
|
||||
|
||||
@ResponseBody
|
||||
@GetMapping("query/{path}")
|
||||
fun googleQueryTest(@PathVariable path: String): String {
|
||||
var originalQuery = path
|
||||
val gSearch = "https://psn.lunaticbum.kr/search?q=${originalQuery?.replace("오늘", SimpleDateFormat("yyyMMdd").format(Date()))}&language=auto&time_range=month&safesearch=0&categories=general&format=json"
|
||||
println("gSearch >>> ${gSearch}")
|
||||
var additionalInfo = StringBuffer()
|
||||
additionalInfo.append("참고자료")
|
||||
var idx = 0
|
||||
WebClient.create().get()
|
||||
.uri(gSearch)
|
||||
.retrieve()
|
||||
.bodyToMono(SearXng::class.java).timeout(Duration.ofMinutes(20L)).block()?.let { gsResult ->
|
||||
gsResult.results?.filter { it.score > 0.5}?.forEach {
|
||||
additionalInfo.append(idx).append(":").append(Gson().toJson(it))
|
||||
idx += 1
|
||||
}
|
||||
}
|
||||
|
||||
lama.generateResponse(query = originalQuery)
|
||||
return "TEST"
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
enum class LamaQueryType(val keywords : ArrayList<String>) {
|
||||
None(arrayListOf()),
|
||||
Search(arrayListOf("검색")),
|
||||
|
||||
26
src/main/kotlin/kr/lunaticbum/back/lun/model/SearXng.kt
Normal file
26
src/main/kotlin/kr/lunaticbum/back/lun/model/SearXng.kt
Normal file
@ -0,0 +1,26 @@
|
||||
package kr.lunaticbum.back.lun.model
|
||||
|
||||
|
||||
class SearXng {
|
||||
var query: String? = null
|
||||
var number_of_results: Int = 0
|
||||
var results: ArrayList<SearXngResult>? = null
|
||||
var answers: ArrayList<Any>? = null
|
||||
var corrections: ArrayList<Any>? = null
|
||||
var infoboxes: ArrayList<Any>? = null
|
||||
var suggestions: ArrayList<Any>? = null
|
||||
var unresponsive_engines: ArrayList<ArrayList<String>>? = null
|
||||
}
|
||||
class SearXngResult {
|
||||
var url: String? = null
|
||||
var title: String? = null
|
||||
var content: String? = null
|
||||
var thumbnail: Any? = null
|
||||
var engine: String? = null
|
||||
var template: String? = null
|
||||
var parsed_url: ArrayList<String>? = null
|
||||
var engines: ArrayList<String>? = null
|
||||
var positions: ArrayList<Int>? = null
|
||||
var score: Double = 0.0
|
||||
var category: String? = null
|
||||
}
|
||||
61
src/main/kotlin/kr/lunaticbum/back/lun/service/Lama.kt
Normal file
61
src/main/kotlin/kr/lunaticbum/back/lun/service/Lama.kt
Normal file
@ -0,0 +1,61 @@
|
||||
package kr.lunaticbum.back.lun.service
|
||||
|
||||
|
||||
import org.springframework.ai.chat.messages.UserMessage
|
||||
import org.springframework.ai.chat.prompt.Prompt
|
||||
import org.springframework.ai.document.Document
|
||||
import org.springframework.ai.ollama.OllamaChatModel
|
||||
import org.springframework.ai.ollama.api.OllamaApi
|
||||
import org.springframework.ai.vectorstore.SearchRequest
|
||||
import org.springframework.ai.vectorstore.VectorStore
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.beans.factory.annotation.Qualifier
|
||||
import org.springframework.stereotype.Service
|
||||
import java.util.stream.Collectors
|
||||
|
||||
|
||||
@Service
|
||||
class Lama {
|
||||
@Qualifier("chatClient")
|
||||
@Autowired
|
||||
private lateinit var chatClient: OllamaApi
|
||||
|
||||
@Autowired
|
||||
private lateinit var vectorStore: VectorStore
|
||||
|
||||
fun generateResponse(query: String?): String {
|
||||
println("On generateResponse :: find something")
|
||||
// 1. 유사 문서 검색
|
||||
|
||||
val relevantDocs = vectorStore.similaritySearch(
|
||||
SearchRequest.builder().query(query!!).topK(3).build()
|
||||
)
|
||||
|
||||
// 2. 프롬프트 구성
|
||||
val context = relevantDocs?.map { it.text }?.joinToString(separator = "\n")
|
||||
val prompt = """
|
||||
Context information is below.
|
||||
----
|
||||
$context
|
||||
----
|
||||
Given the context information and not prior knowledge, answer the query: $query
|
||||
\n한국어로 대답해줘
|
||||
""".trimIndent()
|
||||
|
||||
// 3. Ollama를 사용하여 응답 생성
|
||||
val response: OllamaApi.ChatResponse = chatClient.chat(OllamaApi.ChatRequest.Builder("phi4:14b").stream(false).format("json").messages(
|
||||
listOf(OllamaApi.Message.Builder(OllamaApi.Message.Role.USER).content(prompt).build())
|
||||
).build())
|
||||
println(response.message.content)
|
||||
println("On generateResponse :: END OF Answer")
|
||||
return response.message.content
|
||||
}
|
||||
|
||||
// 문서 추가 메소드
|
||||
fun addDocuments(documents: List<Document?>?) {
|
||||
documents?.let {
|
||||
vectorStore.add(it)
|
||||
}
|
||||
// vectorStore!!.add(documents)
|
||||
}
|
||||
}
|
||||
@ -62,5 +62,14 @@ spring.data.mongodb.option.min-heartbeat-frequency=500
|
||||
spring.data.mongodb.option.heartbeat-frequency=10000
|
||||
spring.data.mongodb.option.local-threshold=15
|
||||
|
||||
spring.ai.ollama.base-url=https://lama.lunaticbum.kr
|
||||
spring.ai.ollama.chat.options.model=phi4:14b
|
||||
|
||||
spring.data.redis.host=ollama.lunaticbum.kr
|
||||
spring.ai.vectorstore.redis.initialize-schema=true
|
||||
spring.ai.vectorstore.redis.index=spring-ai-redis-index
|
||||
spring.ai.vectorstore.redis.prefix=spring-ai-redis-embedding
|
||||
|
||||
|
||||
#>>>>>>> ab915d0a416c69708f1df1ad76d7a14c779c1f59
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user