์๋
ํ์ธ์ 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
'๐ ๊ณต์ ๋ฌธ์ ๋ฒ์ญ > Spring AI (2025 Renewal)' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Spring AI 2025 Renewal #8] Model Context Protocol (MCP) (0) | 2025.06.03 |
---|---|
[Spring AI 2025 Renewal #7] Tool Calling (4) | 2025.05.25 |
[Spring AI 2025 Renewal #5] Embedding Models & Audio Models & Moderation Models (0) | 2025.05.17 |
[Spring AI 2025 Renewal #4] Chat Models & Image Models (1) | 2025.04.12 |
[Spring AI 2025 Renewal #3] Advisors API (0) | 2025.04.06 |