dev_writer 2025. 5. 17. 15:32

์•ˆ๋…•ํ•˜์„ธ์š” dev_writer์ž…๋‹ˆ๋‹ค.
 
์ด๋ฒˆ ์‹œ๊ฐ„์—๋Š” Spring AI ๊ณต์‹ ๋ฌธ์„œ ์ค‘ Chat Models์— ๋Œ€ํ•ด ๋ฒˆ์—ญํ•œ ๋‚ด์šฉ์„ ์ „๋‹ฌํ•ด ๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค.
 

Chat Memory

๋Œ€ํ˜• ์–ธ์–ด ๋ชจ๋ธ (LLM)์€ ์ƒํƒœ๋ฅผ ์ €์žฅํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ์ด์ „ ์ƒํ˜ธ์ž‘์šฉ์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ์œ ์ง€ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด๋Š” ์—ฌ๋Ÿฌ ์ƒํ˜ธ์ž‘์šฉ์— ๊ฑธ์ณ ๋ฌธ๋งฅ์ด๋‚˜ ์ƒํƒœ๋ฅผ ์œ ์ง€ํ•˜๊ณ ์ž ํ•  ๋•Œ ํ•œ๊ณ„๊ฐ€ ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด Spring AI๋Š” ์—ฌ๋Ÿฌ ์ƒํ˜ธ์ž‘์šฉ์— ๊ฑธ์ณ ์ •๋ณด๋ฅผ ์ €์žฅํ•˜๊ณ  ๋ถˆ๋Ÿฌ์˜ฌ ์ˆ˜ ์žˆ๋Š” ์ฑ„ํŒ… ๋ฉ”๋ชจ๋ฆฌ (chat memory) ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
 
ChatMemory ์ถ”์ƒํ™”๋Š” ๋‹ค์–‘ํ•œ ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ์ง€์›ํ•˜๊ธฐ ์œ„ํ•ด ์—ฌ๋Ÿฌ ์œ ํ˜•์˜ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค. ๋ฉ”์‹œ์ง€์˜ ์‹ค์ œ ์ €์žฅ์€ ChatMemoryRepository๊ฐ€ ๋‹ด๋‹นํ•˜๋ฉฐ, ์ด ์ปดํฌ๋„ŒํŠธ๋Š” ๋ฉ”์‹œ์ง€๋ฅผ ์ €์žฅํ•˜๊ณ  ๊ฒ€์ƒ‰ํ•˜๋Š” ์—ญํ• ๋งŒ ํ•ฉ๋‹ˆ๋‹ค. ์–ด๋–ค ๋ฉ”์‹œ์ง€๋ฅผ ์œ ์ง€ํ•˜๊ณ  ์–ธ์ œ ์ œ๊ฑฐํ• ์ง€๋Š” ChatMemory ๊ตฌํ˜„์ฒด๊ฐ€ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ์ตœ๊ทผ N๊ฐœ์˜ ๋ฉ”์‹œ์ง€๋งŒ ์œ ์ง€ํ•˜๊ฑฐ๋‚˜, ์ผ์ • ์‹œ๊ฐ„ ๋™์•ˆ๋งŒ ๋ฉ”์‹œ์ง€๋ฅผ ์œ ์ง€ํ•˜๊ฑฐ๋‚˜, ํ† ํฐ ์ˆ˜ ์ œํ•œ ๋‚ด์—์„œ๋งŒ ๋ฉ”์‹œ์ง€๋ฅผ ์œ ์ง€ํ•˜๋Š” ๋“ฑ์˜ ์ „๋žต์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.
 
๋ฉ”๋ชจ๋ฆฌ ์œ ํ˜•์„ ์„ ํƒํ•˜๊ธฐ ์ „์— chat memory์™€ chat history์˜ ์ฐจ์ด๋ฅผ ์ดํ•ดํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.

  • Chat Memory: ๋Œ€ํ˜• ์–ธ์–ด ๋ชจ๋ธ์ด ๋Œ€ํ™”๋ฅผ ํ†ตํ•ด ๋ฌธ๋งฅ ์ธ์‹์„ ์œ ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•˜๋Š” ์ •๋ณด์ž…๋‹ˆ๋‹ค.
  • Chat History: ์‚ฌ์šฉ์ž์™€ ๋ชจ๋ธ ๊ฐ„์— ์ฃผ๊ณ ๋ฐ›์€ ์ „์ฒด ๋ฉ”์‹œ์ง€ ๊ธฐ๋ก์ž…๋‹ˆ๋‹ค.

ChatMemory ์ถ”์ƒํ™”๋Š” ๋Œ€ํ™”์˜ ํ˜„์žฌ ๋ฌธ๋งฅ์— ๊ด€๋ จ๋œ ๋ฉ”์‹œ์ง€๋ฅผ ์ €์žฅํ•˜๊ณ  ๊ฒ€์ƒ‰ํ•˜๋Š”๋ฐ ์ค‘์ ์„ ๋‘ก๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ „์ฒด ๋Œ€ํ™” ๊ธฐ๋ก์„ ์ €์žฅํ•˜๋Š” ์šฉ๋„๋กœ๋Š” ์ ํ•ฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋ชจ๋“  ๋ฉ”์‹œ์ง€ ๊ธฐ๋ก์„ ์™„์ „ํžˆ ๋ณด์กดํ•  ํ•„์š”๊ฐ€ ์žˆ๋‹ค๋ฉด, Spring Data ๋“ฑ์„ ํ™œ์šฉํ•˜์—ฌ ํšจ์œจ์ ์ธ ์ €์žฅ ๋ฐ ์กฐํšŒ๊ฐ€ ๊ฐ€๋Šฅํ•œ ๋ณ„๋„์˜ ์ ‘๊ทผ ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.
 

๋น ๋ฅธ ์‹œ์ž‘

Spring AI๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ์ง์ ‘ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ChatMemory ๋นˆ์„ ์ž๋™ ๊ตฌ์„ฑํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ InMemoryChatMemoryRepository๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฉ”์‹œ์ง€๋ฅผ ์ €์žฅํ•˜๋ฉฐ, ๋Œ€ํ™” ๋‚ด์—ญ ๊ด€๋ฆฌ๋ฅผ ์œ„ํ•ด MessageWindowChatMemory ๊ตฌํ˜„์ฒด๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ Cassandra, JDBC, Neo4j ๋“ฑ ๋‹ค๋ฅธ ์ €์žฅ์†Œ๊ฐ€ ์ด๋ฏธ ๊ตฌ์„ฑ๋˜์–ด ์žˆ๋‹ค๋ฉด, Spring AI๋Š” ํ•ด๋‹น ์ €์žฅ์†Œ๋ฅผ ๋Œ€์‹  ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
 

@Autowired
ChatMemory chatMemory;

 
๋‹ค์Œ ์„น์…˜์—์„œ๋Š” Spring AI์—์„œ ์ œ๊ณตํ•˜๋Š” ๋‹ค์–‘ํ•œ ๋ฉ”๋ชจ๋ฆฌ ์œ ํ˜•๊ณผ ์ €์žฅ์†Œ(repository)์— ๋Œ€ํ•ด ๋” ์ž์„ธํžˆ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.
 

๋ฉ”๋ชจ๋ฆฌ ์œ ํ˜•

ChatMemory ์ถ”์ƒํ™”๋Š” ๋‹ค์–‘ํ•œ ์‚ฌ์šฉ ์‚ฌ๋ก€์— ๋งž์ถฐ ์—ฌ๋Ÿฌ ์ข…๋ฅ˜์˜ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋„๋ก ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. ๋ฉ”๋ชจ๋ฆฌ ์œ ํ˜• ์„ ํƒ์€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์„ฑ๋Šฅ๊ณผ ๋™์ž‘์— ํฐ ์˜ํ–ฅ์„ ๋ฏธ์น  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ์„น์…˜์—์„œ๋Š” Spring AI๊ฐ€ ๊ธฐ๋ณธ์ ์œผ๋กœ ์ œ๊ณตํ•˜๋Š” ๋ฉ”๋ชจ๋ฆฌ ์œ ํ˜•๋“ค๊ณผ ๊ทธ ํŠน์„ฑ์— ๋Œ€ํ•ด ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.
 

Message Window Chat Memory

MessageWindowChatMemory๋Š” ์ง€์ •๋œ ์ตœ๋Œ€ ๊ฐœ์ˆ˜๋งŒํผ์˜ ๋ฉ”์‹œ์ง€๋ฅผ ์œ ์ง€ํ•˜๋Š” ์Šฌ๋ผ์ด๋”ฉ ์œˆ๋„์šฐ ๋ฐฉ์‹์˜ ๋ฉ”๋ชจ๋ฆฌ์ž…๋‹ˆ๋‹ค. ๋ฉ”์‹œ์ง€ ์ˆ˜๊ฐ€ ์ตœ๋Œ€์น˜๋ฅผ ์ดˆ๊ณผํ•˜๋ฉด ์˜ค๋ž˜๋œ ๋ฉ”์‹œ์ง€๋ถ€ํ„ฐ ์ œ๊ฑฐ๋˜๋ฉฐ, ์‹œ์Šคํ…œ ๋ฉ”์‹œ์ง€๋Š” ๋ณด์กด๋ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ ์ตœ๋Œ€ ๋ฉ”์‹œ์ง€ ์ˆ˜๋Š” 20๊ฐœ์ž…๋‹ˆ๋‹ค.
 

MessageWindowChatMemory memory = MessageWindowChatMemory.builder()
    .maxMessages(10)
    .build();

 
์ด ๋ฉ”๋ชจ๋ฆฌ ์œ ํ˜•์€ Spring AI๊ฐ€ ChatMemory ๋นˆ์„ ์ž๋™ ๊ตฌ์„ฑํ•  ๋•Œ  ์‚ฌ์šฉํ•˜๋Š” ๊ธฐ๋ณธ๊ฐ’์ž…๋‹ˆ๋‹ค.
 

Memory Storage

Spring AI๋Š” ์ฑ„ํŒ… ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ €์žฅํ•˜๊ธฐ ์œ„ํ•œ ChatMemoryRepository ์ถ”์ƒํ™”๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ์ด ์„น์…˜์—์„œ๋Š” Spring AI๊ฐ€ ๊ธฐ๋ณธ์ ์œผ๋กœ ์ œ๊ณตํ•˜๋Š” ์ €์žฅ์†Œ(repository)๋“ค๊ณผ ๊ทธ ์‚ฌ์šฉ ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์„ค๋ช…ํ•˜๋ฉฐ, ํ•„์š”์— ๋”ฐ๋ผ ์ง์ ‘ ์ €์žฅ์†Œ๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
 

์ธ๋ฉ”๋ชจ๋ฆฌ ์ €์žฅ์†Œ (In-Memory Repository)

InMemoryChatMemoryRepository๋Š” ConcurrentHashMap์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ฉ”์‹œ์ง€๋ฅผ ๋ฉ”๋ชจ๋ฆฌ์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.
 
๊ธฐ๋ณธ์ ์œผ๋กœ ๋‹ค๋ฅธ ์ €์žฅ์†Œ๊ฐ€ ๊ตฌ์„ฑ๋˜์–ด ์žˆ์ง€ ์•Š์€ ๊ฒฝ์šฐ, Spring AI๋Š” InMemoryChatMemoryRepository ํƒ€์ž…์˜ ChatMemoryRepository ๋นˆ์„ ์ž๋™์œผ๋กœ ๊ตฌ์„ฑํ•˜์—ฌ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ์ง์ ‘ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

@Autowired
ChatMemoryRepository chatMemoryRepository;

 
๋งŒ์•ฝ InMemoryChatMemoryRepository๋ฅผ ์ˆ˜๋™์œผ๋กœ ์ƒ์„ฑํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด, ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ChatMemoryRepository repository = new InMemoryChatMemoryRepository();

 

JDBC ์ €์žฅ์†Œ (JdbcChatMemoryRepository)

JdbcChatMemoryRepository๋Š” ๋ฉ”์‹œ์ง€๋ฅผ ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ €์žฅํ•˜๊ธฐ ์œ„ํ•ด JDBC๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ธฐ๋ณธ ๊ตฌํ˜„์ฒด์ž…๋‹ˆ๋‹ค. ์—ฌ๋Ÿฌ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ๊ธฐ๋ณธ์ ์œผ๋กœ ์ง€์›ํ•˜๋ฉฐ, ์ฑ„ํŒ… ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์˜๊ตฌ์ ์œผ๋กœ ์ €์žฅํ•ด์•ผ ํ•˜๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค.
 
๋จผ์ €, ํ”„๋กœ์ ํŠธ์— ๋‹ค์Œ ์˜์กด์„ฑ์„ ์ถ”๊ฐ€ํ•˜์‹ญ์‹œ์˜ค:
 

Maven

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-starter-model-chat-memory-repository-jdbc</artifactId>
</dependency>

 

Gradle

dependencies {
    implementation 'org.springframework.ai:spring-ai-starter-model-chat-memory-repository-jdbc'
}

 
Spring AI๋Š” JdbcChatMemoryRepository์— ๋Œ€ํ•œ ์ž๋™ ๊ตฌ์„ฑ (auto-configuration)์„ ์ œ๊ณตํ•˜๋ฏ€๋กœ, ์ด๋ฅผ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ๋ฐ”๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

@Autowired
JdbcChatMemoryRepository chatMemoryRepository;

ChatMemory chatMemory = MessageWindowChatMemory.builder()
    .chatMemoryRepository(chatMemoryRepository)
    .maxMessages(10)
    .build();

 
์ง์ ‘ JdbcChatMemoryRepository๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด, JdbcTemplate ์ธ์Šคํ„ด์Šค์™€ JdbcChatMemoryRepositoryDialect๋ฅผ ์ œ๊ณตํ•˜์—ฌ ์ˆ˜๋™์œผ๋กœ ๊ตฌ์„ฑํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

ChatMemoryRepository chatMemoryRepository = JdbcChatMemoryRepository.builder()
    .jdbcTemplate(jdbcTemplate)
    .dialect(new PostgresChatMemoryDialect())
    .build();

ChatMemory chatMemory = MessageWindowChatMemory.builder()
    .chatMemoryRepository(chatMemoryRepository)
    .maxMessages(10)
    .build();

 

์ง€์›๋˜๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ฐ Dialect ์ถ”์ƒํ™”

Spring AI๋Š” dialect ์ถ”์ƒํ™”๋ฅผ ํ†ตํ•ด ์—ฌ๋Ÿฌ ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. ๋‹ค์Œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋“ค์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ์ง€์›๋ฉ๋‹ˆ๋‹ค:

  • PostgreSQL
  • MySQL / MariaDB
  • SQL Server
  • HSQLDB

JdbcChatMemoryRepositoryDialect.from(DataSource)๋ฅผ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ, JDBC URL์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์˜ฌ๋ฐ”๋ฅธ dialect๊ฐ€ ์ž๋™ ๊ฐ์ง€๋ฉ๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋Œ€ํ•œ ์ง€์›์„ ํ™•์žฅํ•˜๋ ค๋ฉด JdbcChatMemoryRepositoryDialect ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.
 

์„ค์ • ์†์„ฑ

์†์„ฑ ์„ค๋ช… ๊ธฐ๋ณธ๊ฐ’
spring.ai.chat.memory.repository.jdbc.initialize-schema ์Šคํ‚ค๋งˆ ์ดˆ๊ธฐํ™” ์‹œ์ ์„ ์ œ์–ดํ•ฉ๋‹ˆ๋‹ค. ๊ฐ€๋Šฅํ•œ ๊ฐ’: embedded(๊ธฐ๋ณธ๊ฐ’), always, never embedded
spring.ai.chat.memory.repository.jdbc.schema ์ดˆ๊ธฐํ™” ์‹œ ์‚ฌ์šฉํ•  ์Šคํ‚ค๋งˆ ์Šคํฌ๋ฆฝํŠธ์˜ ์œ„์น˜์ž…๋‹ˆ๋‹ค. classpath: URL๊ณผ @@platform@@ ํ”Œ๋ ˆ์ด์Šคํ™€๋”๋ฅผ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. classpath:org/springframework/ai/chat/memory/repository/jdbc/schema-@@platform@@.sql
spring.ai.chat.memory.repository.jdbc.platform @@platform@@ ํ”Œ๋ ˆ์ด์Šคํ™€๋”๊ฐ€ ์‚ฌ์šฉ๋  ๊ฒฝ์šฐ ์ดˆ๊ธฐํ™” ์Šคํฌ๋ฆฝํŠธ์—์„œ ์‚ฌ์šฉํ•  ํ”Œ๋žซํผ ์ด๋ฆ„์ž…๋‹ˆ๋‹ค. ์ž๋™ ๊ฐ์ง€๋จ

 

์Šคํ‚ค๋งˆ ์ดˆ๊ธฐํ™”

์ž๋™ ๊ตฌ์„ฑ(auto-configuration)์€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‹œ์ž‘ ์‹œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ฒค๋”์— ๋งž๋Š” SQL ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ SPRING_AI_CHAT_MEMORY ํ…Œ์ด๋ธ”์„ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ ์Šคํ‚ค๋งˆ ์ดˆ๊ธฐํ™”๋Š” ๋‚ด์žฅํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค(H2, HSQL, Derby ๋“ฑ)์— ๋Œ€ํ•ด์„œ๋งŒ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.
 
์Šคํ‚ค๋งˆ ์ดˆ๊ธฐํ™” ๋™์ž‘์€ spring.ai.chat.memory.repository.jdbc.initialize-schema ์†์„ฑ์„ ํ†ตํ•ด ์ œ์–ดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

spring.ai.chat.memory.repository.jdbc.initialize-schema=embedded # Only for embedded DBs (default)
spring.ai.chat.memory.repository.jdbc.initialize-schema=always   # Always initialize
spring.ai.chat.memory.repository.jdbc.initialize-schema=never    # Never initialize (useful with Flyway/Liquibase)

 
์Šคํ‚ค๋งˆ ์Šคํฌ๋ฆฝํŠธ์˜ ์œ„์น˜๋ฅผ ์žฌ์ •์˜ํ•˜๋ ค๋ฉด ๋‹ค์Œ ์†์„ฑ์„ ์‚ฌ์šฉํ•˜์‹ญ์‹œ์˜ค:

spring.ai.chat.memory.repository.jdbc.schema=classpath:/custom/path/schema-mysql.sql

 

Dialect ํ™•์žฅ

์ƒˆ๋กœ์šด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์ง€์›ํ•˜๋ ค๋ฉด JdbcChatMemoryRepositoryDialect ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ , ๋ฉ”์‹œ์ง€๋ฅผ ์กฐํšŒ(select), ์‚ฝ์ž…(insert), ์‚ญ์ œ(delete) ํ•˜๊ธฐ ์œ„ํ•œ SQL์„ ์ œ๊ณตํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ดํ›„ ํ•ด๋‹น ์‚ฌ์šฉ์ž ์ •์˜ dialect๋ฅผ ๋ฆฌํฌ์ง€ํ„ฐ๋ฆฌ ๋นŒ๋”์— ์ „๋‹ฌํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

ChatMemoryRepository chatMemoryRepository = JdbcChatMemoryRepository.builder()
    .jdbcTemplate(jdbcTemplate)
    .dialect(new MyCustomDbDialect())
    .build();

 

CassandraChatMemoryRepository

CassandraChatMemoryRepository๋Š” Apache Cassandra๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฉ”์‹œ์ง€๋ฅผ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค. ๊ณ ๊ฐ€์šฉ์„ฑ, ๋‚ด๊ตฌ์„ฑ, ํ™•์žฅ์„ฑ ๋ฐ TTL (Time-To-Live) ๊ธฐ๋Šฅ์„ ํ™œ์šฉํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ์™€ ๊ฐ™์ด, ์ฑ„ํŒ… ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์˜๊ตฌ์ ์œผ๋กœ ์ €์žฅํ•ด์•ผ ํ•˜๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค.
 
CassandraChatMemoryRepository๋Š” ์‹œ๊ณ„์—ด ๊ธฐ๋ฐ˜ ์Šคํ‚ค๋งˆ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ณผ๊ฑฐ์˜ ๋ชจ๋“  ์ฑ„ํŒ… ์œˆ๋„์šฐ๋ฅผ ๊ธฐ๋กํ•˜๋ฏ€๋กœ, ๊ฑฐ๋ฒ„๋„Œ์Šค ๋ฐ ๊ฐ์‚ฌ (auditing) ๋ชฉ์ ์œผ๋กœ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด 3๋…„๊ณผ ๊ฐ™์€ ๊ฐ’์œผ๋กœ TTL์„ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์ด ๊ถŒ์žฅ๋ฉ๋‹ˆ๋‹ค.
 
CassandraChatMemoryRepository๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ๋จผ์ € ํ”„๋กœ์ ํŠธ์— ๋‹ค์Œ ์˜์กด์„ฑ์„ ์ถ”๊ฐ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
 

Maven

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-starter-model-chat-memory-repository-cassandra</artifactId>
</dependency>

 

Gradle

dependencies {
    implementation 'org.springframework.ai:spring-ai-starter-model-chat-memory-repository-cassandra'
}

 
Spring AI๋Š” CassandraChatMemoryRepository์— ๋Œ€ํ•œ ์ž๋™ ๊ตฌ์„ฑ์„ ์ œ๊ณตํ•˜๋ฏ€๋กœ, ์ด๋ฅผ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ๋ฐ”๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

@Autowired
CassandraChatMemoryRepository chatMemoryRepository;

ChatMemory chatMemory = MessageWindowChatMemory.builder()
    .chatMemoryRepository(chatMemoryRepository)
    .maxMessages(10)
    .build();

 
๋งŒ์•ฝ ์ง์ ‘ CassandraChatMemoryRepository๋ฅผ ์ƒ์„ฑํ•˜๋ ค๋ฉด, CassandraChatMemoryRepositoryConfig ์ธ์Šคํ„ด์Šค๋ฅผ ์ œ๊ณตํ•˜์—ฌ ์ˆ˜๋™์œผ๋กœ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ChatMemoryRepository chatMemoryRepository = CassandraChatMemoryRepository
    .create(CassandraChatMemoryConfig.builder().withCqlSession(cqlSession));

ChatMemory chatMemory = MessageWindowChatMemory.builder()
    .chatMemoryRepository(chatMemoryRepository)
    .maxMessages(10)
    .build();

 

์„ค์ • ์†์„ฑ

์†์„ฑ ์„ค๋ช… ๊ธฐ๋ณธ๊ฐ’
spring.cassandra.contactPoints ํด๋Ÿฌ์Šคํ„ฐ ๊ฒ€์ƒ‰์„ ์‹œ์ž‘ํ•  ํ˜ธ์ŠคํŠธ http://127.0.0.1
spring.cassandra.port Cassandra์— ์—ฐ๊ฒฐํ•  ๋„ค์ดํ‹ฐ๋ธŒ ํ”„๋กœํ† ์ฝœ ํฌํŠธ 9042
spring.cassandra.localDatacenter ์—ฐ๊ฒฐํ•  Cassandra ๋ฐ์ดํ„ฐ์„ผํ„ฐ datacenter1
spring.ai.chat.memory.cassandra.time-to-live Cassandra์— ์ €์žฅ๋œ ๋ฉ”์‹œ์ง€์˜ TTL(Time to Live)  
spring.ai.chat.memory.cassandra.keyspace Cassandra ํ‚ค์ŠคํŽ˜์ด์Šค springframework
spring.ai.chat.memory.cassandra.messages-column ๋ฉ”์‹œ์ง€๋ฅผ ์ €์žฅํ•  Cassandra ์ปฌ๋Ÿผ ์ด๋ฆ„ springframework
spring.ai.chat.memory.cassandra.table ์‚ฌ์šฉํ•  Cassandra ํ…Œ์ด๋ธ” ์ด๋ฆ„ ai_chat_memory
spring.ai.chat.memory.cassandra.initialize-schema ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‹œ์ž‘ ์‹œ ์Šคํ‚ค๋งˆ๋ฅผ ์ดˆ๊ธฐํ™”ํ• ์ง€ ์—ฌ๋ถ€ true

 

์Šคํ‚ค๋งˆ ์ดˆ๊ธฐํ™”

์ž๋™ ๊ตฌ์„ฑ์€ ai_chat_memory ํ…Œ์ด๋ธ”์„ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
์Šคํ‚ค๋งˆ ์ดˆ๊ธฐํ™”๋ฅผ ๋น„ํ™œ์„ฑํ™”ํ•˜๋ ค๋ฉด, spring.ai.chat.memory.repository.cassandra.initialize-schema ์†์„ฑ์„ false๋กœ ์„ค์ •ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.
 

Neo4j ChatMemoryRepository

Neo4jChatMemoryRepository๋Š” ์ฑ„ํŒ… ๋ฉ”์‹œ์ง€๋ฅผ ์†์„ฑ ๊ทธ๋ž˜ํ”„ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ๋…ธ๋“œ์™€ ๊ด€๊ณ„๋กœ ์ €์žฅํ•˜๊ธฐ ์œ„ํ•ด Neo4j๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ธฐ๋ณธ ๊ตฌํ˜„์ฒด์ž…๋‹ˆ๋‹ค. ์ด ์ €์žฅ์†Œ๋Š” Neo4j์˜ ๊ทธ๋ž˜ํ”„ ๊ธฐ๋Šฅ์„ ํ™œ์šฉํ•˜์—ฌ ์ฑ„ํŒ… ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ง€์†์ ์œผ๋กœ ์ €์žฅํ•˜๊ณ ์ž ํ•˜๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค.
 
๋จผ์ €, ํ”„๋กœ์ ํŠธ์— ๋‹ค์Œ ์˜์กด์„ฑ์„ ์ถ”๊ฐ€ํ•˜์‹ญ์‹œ์˜ค:
 

Maven

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-starter-model-chat-memory-repository-neo4j</artifactId>
</dependency>

 

Gradle

dependencies {
    implementation 'org.springframework.ai:spring-ai-starter-model-chat-memory-repository-neo4j'
}

 

Spring AI๋Š” Neo4jChatMemoryRepository์— ๋Œ€ํ•œ ์ž๋™ ๊ตฌ์„ฑ์„ ์ œ๊ณตํ•˜๋ฏ€๋กœ, ์ด๋ฅผ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ๋ฐ”๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

@Autowired
Neo4jChatMemoryRepository chatMemoryRepository;

ChatMemory chatMemory = MessageWindowChatMemory.builder()
    .chatMemoryRepository(chatMemoryRepository)
    .maxMessages(10)
    .build();

 
์ง์ ‘ Neo4jChatMemoryRepository๋ฅผ ์ƒ์„ฑํ•˜๋ ค๋ฉด, Neo4j Driver ์ธ์Šคํ„ด์Šค๋ฅผ ์ œ๊ณตํ•˜์—ฌ ์ˆ˜๋™์œผ๋กœ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ChatMemoryRepository chatMemoryRepository = Neo4jChatMemoryRepository.builder()
    .driver(driver)
    .build();

ChatMemory chatMemory = MessageWindowChatMemory.builder()
    .chatMemoryRepository(chatMemoryRepository)
    .maxMessages(10)
    .build();

 

์„ค์ • ์†์„ฑ

์†์„ฑ ์„ค๋ช… ๊ธฐ๋ณธ๊ฐ’
spring.ai.chat.memory.repository.neo4j.sessionLabel ๋Œ€ํ™” ์„ธ์…˜์„ ์ €์žฅํ•˜๋Š” ๋…ธ๋“œ์˜ ๋ ˆ์ด๋ธ” Session
spring.ai.chat.memory.repository.neo4j.messageLabel ๋ฉ”์‹œ์ง€๋ฅผ ์ €์žฅํ•˜๋Š” ๋…ธ๋“œ์˜ ๋ ˆ์ด๋ธ” Message
spring.ai.chat.memory.repository.neo4j.toolCallLabel ๋„๊ตฌ ํ˜ธ์ถœ(์˜ˆ: Assistant ๋ฉ”์‹œ์ง€ ๋‚ด)์„ ์ €์žฅํ•˜๋Š” ๋…ธ๋“œ์˜ ๋ ˆ์ด๋ธ” ToolCall
spring.ai.chat.memory.repository.neo4j.metadataLabel ๋ฉ”์‹œ์ง€ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๋Š” ๋…ธ๋“œ์˜ ๋ ˆ์ด๋ธ” Metadata
spring.ai.chat.memory.repository.neo4j.toolResponseLabel ๋„๊ตฌ ์‘๋‹ต์„ ์ €์žฅํ•˜๋Š” ๋…ธ๋“œ์˜ ๋ ˆ์ด๋ธ” ToolResponse
spring.ai.chat.memory.repository.neo4j.mediaLabel ๋ฉ”์‹œ์ง€์™€ ์—ฐ๊ด€๋œ ๋ฏธ๋””์–ด๋ฅผ ์ €์žฅํ•˜๋Š” ๋…ธ๋“œ์˜ ๋ ˆ์ด๋ธ” Media

 

์ธ๋ฑ์Šค ์ดˆ๊ธฐํ™” (Index Initialization)

Neo4j ์ €์žฅ์†Œ๋Š” ์„ฑ๋Šฅ ์ตœ์ ํ™”๋ฅผ ์œ„ํ•ด ๋Œ€ํ™” ID(conversation ID)์™€ ๋ฉ”์‹œ์ง€ ์ธ๋ฑ์Šค(message index)์— ๋Œ€ํ•œ ์ธ๋ฑ์Šค๋ฅผ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž ์ •์˜ ๋ ˆ์ด๋ธ”(custom labels)์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ, ํ•ด๋‹น ๋ ˆ์ด๋ธ”์— ๋Œ€ํ•ด์„œ๋„ ์ธ๋ฑ์Šค๊ฐ€ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค. ๋ณ„๋„์˜ ์Šคํ‚ค๋งˆ ์ดˆ๊ธฐํ™”๋Š” ํ•„์š”ํ•˜์ง€ ์•Š์ง€๋งŒ, ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ Neo4j ์ธ์Šคํ„ด์Šค์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋„๋ก ์„ค์ •๋˜์–ด ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

Memory in Chat Client

ChatClient API๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ, ์—ฌ๋Ÿฌ ์ƒํ˜ธ์ž‘์šฉ์— ๊ฑธ์ณ ๋Œ€ํ™” ๋ฌธ๋งฅ์„ ์œ ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ChatMemory ๊ตฌํ˜„์ฒด๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
 
Spring AI๋Š” ํ•„์š”์— ๋”ฐ๋ผ ๋ฉ”๋ชจ๋ฆฌ ๋™์ž‘์„ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ๋„๋ก ๋ช‡ ๊ฐ€์ง€ ๊ธฐ๋ณธ ์ œ๊ณต Advisor๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
 

์ฃผ์˜
ํ˜„์žฌ ํˆด ํ˜ธ์ถœ(tool call)์„ ์ˆ˜ํ–‰ํ•  ๋•Œ LLM๊ณผ ์ฃผ๊ณ ๋ฐ›๋Š” ์ค‘๊ฐ„ ๋ฉ”์‹œ์ง€๋“ค์€ ๋ฉ”๋ชจ๋ฆฌ์— ์ €์žฅ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด๋Š” ํ˜„์žฌ ๊ตฌํ˜„์˜ ์ œํ•œ ์‚ฌํ•ญ์ด๋ฉฐ, ํ–ฅํ›„ ๋ฆด๋ฆฌ์Šค์—์„œ ๊ฐœ์„ ๋  ์˜ˆ์ •์ž…๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๋ฉ”์‹œ์ง€ ์ €์žฅ์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ ์‚ฌ์šฉ์ž ์ œ์–ดํ˜• ๋„๊ตฌ ์‹คํ–‰(User Controlled Tool Execution) ๊ด€๋ จ ์ง€์นจ์„ ์ฐธ์กฐํ•˜์‹ญ์‹œ์˜ค.
  • MessageChatMemoryAdvisor: ์ฃผ์–ด์ง„ ChatMemory ๊ตฌํ˜„์ฒด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋Œ€ํ™” ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ๊ฐ ์ƒํ˜ธ์ž‘์šฉ ์‹œ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ๋Œ€ํ™” ์ด๋ ฅ์„ ๊ฐ€์ ธ์™€ ๋ฉ”์‹œ์ง€ ์ปฌ๋ ‰์…˜ ํ˜•ํƒœ๋กœ ํ”„๋กฌํ”„ํŠธ์— ํฌํ•จ์‹œํ‚ต๋‹ˆ๋‹ค.
  • PromptChatMemoryAdvisor: ์ฃผ์–ด์ง„ ChatMemory ๊ตฌํ˜„์ฒด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋Œ€ํ™” ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ๊ฐ ์ƒํ˜ธ์ž‘์šฉ ์‹œ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ๋Œ€ํ™” ์ด๋ ฅ์„ ๊ฐ€์ ธ์™€ ์‹œ์Šคํ…œ ํ”„๋กฌํ”„ํŠธ์— ์ผ๋ฐ˜ ํ…์ŠคํŠธ ํ˜•์‹์œผ๋กœ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.
  • VectorStoreChatMemoryAdvisor: ์ฃผ์–ด์ง„ VectorStore ๊ตฌํ˜„์ฒด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋Œ€ํ™” ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ๊ฐ ์ƒํ˜ธ์ž‘์šฉ ์‹œ ๋ฒกํ„ฐ ์ €์žฅ์†Œ์—์„œ ๋Œ€ํ™” ์ด๋ ฅ์„ ๊ฒ€์ƒ‰ํ•˜์—ฌ ์‹œ์Šคํ…œ ๋ฉ”์‹œ์ง€์— ์ผ๋ฐ˜ ํ…์ŠคํŠธ๋กœ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, MessageWindowChatMemory๋ฅผ MessageChatMemoryAdvisor์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

ChatMemory chatMemory = MessageWindowChatMemory.builder().build();

ChatClient chatClient = ChatClient.builder(chatModel)
    .defaultAdvisors(MessageChatMemoryAdvisor.builder(chatMemory).build())
    .build();

 
ChatClient๋ฅผ ํ†ตํ•ด ํ˜ธ์ถœ์ด ์ˆ˜ํ–‰๋˜๋ฉด, MessageChatMemoryAdvisor๊ฐ€ ์ž๋™์œผ๋กœ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ์ง€์ •๋œ ๋Œ€ํ™” ID๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ๋Œ€ํ™” ์ด๋ ฅ์ด ์กฐํšŒ๋ฉ๋‹ˆ๋‹ค.

String conversationId = "007";

chatClient.prompt()
    .user("Do I have license to code?")
    .advisors(a -> a.param(ChatMemory.CONVERSATION_ID, conversationId))
    .call()
    .content();

 

PromptChatMemoryAdvisor

์ปค์Šคํ…€ ํ…œํ”Œ๋ฆฟ
PromptChatMemoryAdvisor๋Š” ๊ฒ€์ƒ‰๋œ ๋Œ€ํ™” ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์‹œ์Šคํ…œ ๋ฉ”์‹œ์ง€์— ๋ณด๊ฐ•ํ•˜๊ธฐ ์œ„ํ•ด ๊ธฐ๋ณธ ํ…œํ”Œ๋ฆฟ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ด ๋™์ž‘์€ .promptTemplate() ๋นŒ๋” ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ์‚ฌ์šฉ์ž ์ง€์ • PromptTemplate ๊ฐ์ฒด๋ฅผ ์ œ๊ณตํ•จ์œผ๋กœ์จ ์ปค์Šคํ„ฐ๋งˆ์ด์ง• ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
 

์ฐธ๊ณ 
์—ฌ๊ธฐ์—์„œ ์ œ๊ณตํ•˜๋Š” PromptTemplate์€ ์–ด๋“œ๋ฐ”์ด์ €๊ฐ€ ๊ฒ€์ƒ‰๋œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์‹œ์Šคํ…œ ๋ฉ”์‹œ์ง€์™€ ๊ฒฐํ•ฉํ•˜๋Š” ๋ฐฉ์‹์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” .templateRenderer()๋ฅผ ํ†ตํ•ด ChatClient์— ์„ค์ •ํ•˜๋Š” TemplateRenderer์™€๋Š” ๊ตฌ๋ณ„๋ฉ๋‹ˆ๋‹ค. ํ›„์ž๋Š” ์–ด๋“œ๋ฐ”์ด์ €๊ฐ€ ์‹คํ–‰๋˜๊ธฐ ์ „์— ์‚ฌ์šฉ์ž/์‹œ์Šคํ…œ ํ”„๋กฌํ”„ํŠธ์˜ ์ดˆ๊ธฐ ์ฝ˜ํ…์ธ  ๋ Œ๋”๋ง ๋ฐฉ์‹์— ์˜ํ–ฅ์„ ์ค๋‹ˆ๋‹ค. ํด๋ผ์ด์–ธํŠธ ์ˆ˜์ค€์˜ ํ…œํ”Œ๋ฆฟ ๋ Œ๋”๋ง์— ๋Œ€ํ•ด์„œ๋Š” ChatClient Prompt Templates ํ•ญ๋ชฉ์„ ์ฐธ๊ณ ํ•˜์‹ญ์‹œ์˜ค.

 
์‚ฌ์šฉ์ž ์ง€์ • PromptTemplate์€ ์–ด๋–ค TemplateRenderer ๊ตฌํ˜„์ฒด๋“  ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ(๊ธฐ๋ณธ๊ฐ’์€ StringTemplate ์—”์ง„ ๊ธฐ๋ฐ˜์˜ StPromptTemplate), ๋‹ค์Œ ๋‘ ๊ฐœ์˜ ํ”Œ๋ ˆ์ด์Šคํ™€๋”๋ฅผ ๋ฐ˜๋“œ์‹œ ํฌํ•จํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค:

  • instructions: ์›๋ณธ ์‹œ์Šคํ…œ ๋ฉ”์‹œ์ง€๋ฅผ ์ „๋‹ฌ๋ฐ›๊ธฐ ์œ„ํ•œ ํ”Œ๋ ˆ์ด์Šคํ™€๋”
  • memory: ๊ฒ€์ƒ‰๋œ ๋Œ€ํ™” ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ „๋‹ฌ๋ฐ›๊ธฐ ์œ„ํ•œ ํ”Œ๋ ˆ์ด์Šคํ™€๋”

 

VectorStoreChatMemoryAdvisor

์ปค์Šคํ…€ ํ…œํ”Œ๋ฆฟ

VectorStoreChatMemoryAdvisor๋Š” ๊ฒ€์ƒ‰๋œ ๋Œ€ํ™” ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์‹œ์Šคํ…œ ๋ฉ”์‹œ์ง€์— ๋ณด๊ฐ•ํ•˜๊ธฐ ์œ„ํ•ด ๊ธฐ๋ณธ ํ…œํ”Œ๋ฆฟ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ด ๋™์ž‘์€ .promptTemplate() ๋นŒ๋” ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ์‚ฌ์šฉ์ž ์ง€์ • PromptTemplate ๊ฐ์ฒด๋ฅผ ์ œ๊ณตํ•จ์œผ๋กœ์จ ์ปค์Šคํ„ฐ๋งˆ์ด์ง• ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
 

์ฐธ๊ณ 
์—ฌ๊ธฐ์„œ ์ œ๊ณตํ•˜๋Š” PromptTemplate์€ ์–ด๋“œ๋ฐ”์ด์ €๊ฐ€ ๊ฒ€์ƒ‰๋œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์‹œ์Šคํ…œ ๋ฉ”์‹œ์ง€์™€ ๊ฒฐํ•ฉํ•˜๋Š” ๋ฐฉ์‹์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ChatClient ์ž์ฒด์— ์„ค์ •ํ•˜๋Š” TemplateRenderer (์˜ˆ: .templateRenderer() ์‚ฌ์šฉ)์™€๋Š” ๋‹ค๋ฆ…๋‹ˆ๋‹ค. ํ›„์ž๋Š” ์–ด๋“œ๋ฐ”์ด์ €๊ฐ€ ์‹คํ–‰๋˜๊ธฐ ์ „์— ์‚ฌ์šฉ์ž/์‹œ์Šคํ…œ ํ”„๋กฌํ”„ํŠธ์˜ ์ดˆ๊ธฐ ์ฝ˜ํ…์ธ  ๋ Œ๋”๋ง ๋ฐฉ์‹์— ์˜ํ–ฅ์„ ์ค๋‹ˆ๋‹ค. ํด๋ผ์ด์–ธํŠธ ์ˆ˜์ค€์˜ ํ…œํ”Œ๋ฆฟ ๋ Œ๋”๋ง์— ๋Œ€ํ•ด์„œ๋Š” ChatClient Prompt Templates ํ•ญ๋ชฉ์„ ์ฐธ๊ณ ํ•˜์‹ญ์‹œ์˜ค.

 
์‚ฌ์šฉ์ž ์ง€์ • PromptTemplate์€ ์–ด๋–ค TemplateRenderer ๊ตฌํ˜„์ฒด๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ(๊ธฐ๋ณธ๊ฐ’์€ StringTemplate ์—”์ง„ ๊ธฐ๋ฐ˜์˜ StPromptTemplate), ๋‹ค์Œ ๋‘ ๊ฐœ์˜ ํ”Œ๋ ˆ์ด์Šคํ™€๋”๋ฅผ ๋ฐ˜๋“œ์‹œ ํฌํ•จํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค:

  • instructions: ์›๋ณธ ์‹œ์Šคํ…œ ๋ฉ”์‹œ์ง€๋ฅผ ์ „๋‹ฌ๋ฐ›๊ธฐ ์œ„ํ•œ ์šฉ๋„
  • long_term_memory: ๊ฒ€์ƒ‰๋œ ๋Œ€ํ™” ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ „๋‹ฌ๋ฐ›๊ธฐ ์œ„ํ•œ ์šฉ๋„

 

Memory in Chat Model

ChatClient ๋Œ€์‹  ChatModel์„ ์ง์ ‘ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ, ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

// ๋ฉ”๋ชจ๋ฆฌ ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ
ChatMemory chatMemory = MessageWindowChatMemory.builder().build();
String conversationId = "007";

// ์ฒซ ๋ฒˆ์งธ ์ƒํ˜ธ์ž‘์šฉ
UserMessage userMessage1 = new UserMessage("My name is James Bond");
chatMemory.add(conversationId, userMessage1);
ChatResponse response1 = chatModel.call(new Prompt(chatMemory.get(conversationId)));
chatMemory.add(conversationId, response1.getResult().getOutput());

// ๋‘ ๋ฒˆ์งธ ์ƒํ˜ธ์ž‘์šฉ
UserMessage userMessage2 = new UserMessage("What is my name?");
chatMemory.add(conversationId, userMessage2);
ChatResponse response2 = chatModel.call(new Prompt(chatMemory.get(conversationId)));
chatMemory.add(conversationId, response2.getResult().getOutput());

// ์‘๋‹ต์—๋Š” "James Bond"๊ฐ€ ํฌํ•จ๋  ๊ฒƒ์ž„

 

Reference