chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,307 @@
|
||||
---
|
||||
search:
|
||||
exclude: true
|
||||
---
|
||||
# 고급 SQLite 세션
|
||||
|
||||
`AdvancedSQLiteSession`은 기본 `SQLiteSession`의 향상된 버전으로, 대화 분기, 상세 사용량 분석, 구조화된 대화 쿼리 등 고급 대화 관리 기능을 제공합니다.
|
||||
|
||||
## 기능
|
||||
|
||||
- **대화 분기**: 모든 사용자 메시지에서 대체 대화 경로를 생성
|
||||
- **사용량 추적**: 전체 JSON 세부 내역과 함께 턴별 상세 토큰 사용량 분석
|
||||
- **구조화된 쿼리**: 턴별 대화, 도구 사용 통계 등을 조회
|
||||
- **분기 관리**: 독립적인 분기 전환 및 관리
|
||||
- **메시지 구조 메타데이터**: 메시지 유형, 도구 사용, 대화 흐름 추적
|
||||
|
||||
## 빠른 시작
|
||||
|
||||
```python
|
||||
from agents import Agent, Runner
|
||||
from agents.extensions.memory import AdvancedSQLiteSession
|
||||
|
||||
# Create agent
|
||||
agent = Agent(
|
||||
name="Assistant",
|
||||
instructions="Reply very concisely.",
|
||||
)
|
||||
|
||||
# Create an advanced session
|
||||
session = AdvancedSQLiteSession(
|
||||
session_id="conversation_123",
|
||||
db_path="conversations.db",
|
||||
create_tables=True
|
||||
)
|
||||
|
||||
# First conversation turn
|
||||
result = await Runner.run(
|
||||
agent,
|
||||
"What city is the Golden Gate Bridge in?",
|
||||
session=session
|
||||
)
|
||||
print(result.final_output) # "San Francisco"
|
||||
|
||||
# IMPORTANT: Store usage data
|
||||
await session.store_run_usage(result)
|
||||
|
||||
# Continue conversation
|
||||
result = await Runner.run(
|
||||
agent,
|
||||
"What state is it in?",
|
||||
session=session
|
||||
)
|
||||
print(result.final_output) # "California"
|
||||
await session.store_run_usage(result)
|
||||
```
|
||||
|
||||
## 초기화
|
||||
|
||||
```python
|
||||
from agents.extensions.memory import AdvancedSQLiteSession
|
||||
|
||||
# Basic initialization
|
||||
session = AdvancedSQLiteSession(
|
||||
session_id="my_conversation",
|
||||
create_tables=True # Auto-create advanced tables
|
||||
)
|
||||
|
||||
# With persistent storage
|
||||
session = AdvancedSQLiteSession(
|
||||
session_id="user_123",
|
||||
db_path="path/to/conversations.db",
|
||||
create_tables=True
|
||||
)
|
||||
|
||||
# With custom logger
|
||||
import logging
|
||||
logger = logging.getLogger("my_app")
|
||||
session = AdvancedSQLiteSession(
|
||||
session_id="session_456",
|
||||
create_tables=True,
|
||||
logger=logger
|
||||
)
|
||||
```
|
||||
|
||||
### 매개변수
|
||||
|
||||
- `session_id` (str): 대화 세션의 고유 식별자
|
||||
- `db_path` (str | Path): SQLite 데이터베이스 파일 경로. 인메모리 저장소의 경우 기본값은 `:memory:`
|
||||
- `create_tables` (bool): 고급 테이블을 자동으로 생성할지 여부. 기본값은 `False`
|
||||
- `logger` (logging.Logger | None): 세션용 사용자 지정 로거. 기본값은 모듈 로거
|
||||
|
||||
## 사용량 추적
|
||||
|
||||
AdvancedSQLiteSession은 대화 턴별 토큰 사용량 데이터를 저장하여 상세한 사용량 분석을 제공합니다. **이는 각 에이전트 실행 후 `store_run_usage` 메서드가 호출되는지에 전적으로 의존합니다.**
|
||||
|
||||
### 사용량 데이터 저장
|
||||
|
||||
```python
|
||||
# After each agent run, store the usage data
|
||||
result = await Runner.run(agent, "Hello", session=session)
|
||||
await session.store_run_usage(result)
|
||||
|
||||
# This stores:
|
||||
# - Total tokens used
|
||||
# - Input/output token breakdown
|
||||
# - Request count
|
||||
# - Detailed JSON token information (if available)
|
||||
```
|
||||
|
||||
### 사용량 통계 조회
|
||||
|
||||
```python
|
||||
# Get session-level usage (all branches)
|
||||
session_usage = await session.get_session_usage()
|
||||
if session_usage:
|
||||
print(f"Total requests: {session_usage['requests']}")
|
||||
print(f"Total tokens: {session_usage['total_tokens']}")
|
||||
print(f"Input tokens: {session_usage['input_tokens']}")
|
||||
print(f"Output tokens: {session_usage['output_tokens']}")
|
||||
print(f"Total turns: {session_usage['total_turns']}")
|
||||
|
||||
# Get usage for specific branch
|
||||
branch_usage = await session.get_session_usage(branch_id="main")
|
||||
|
||||
# Get usage by turn
|
||||
turn_usage = await session.get_turn_usage()
|
||||
for turn_data in turn_usage:
|
||||
print(f"Turn {turn_data['user_turn_number']}: {turn_data['total_tokens']} tokens")
|
||||
if turn_data['input_tokens_details']:
|
||||
print(f" Input details: {turn_data['input_tokens_details']}")
|
||||
if turn_data['output_tokens_details']:
|
||||
print(f" Output details: {turn_data['output_tokens_details']}")
|
||||
|
||||
# Get usage for specific turn
|
||||
turn_2_usage = await session.get_turn_usage(user_turn_number=2)
|
||||
```
|
||||
|
||||
## 대화 분기
|
||||
|
||||
AdvancedSQLiteSession의 핵심 기능 중 하나는 모든 사용자 메시지에서 대화 분기를 생성하여 대체 대화 경로를 탐색할 수 있는 기능입니다.
|
||||
|
||||
### 분기 생성
|
||||
|
||||
```python
|
||||
# Get available turns for branching
|
||||
turns = await session.get_conversation_turns()
|
||||
for turn in turns:
|
||||
print(f"Turn {turn['turn']}: {turn['content']}")
|
||||
print(f"Can branch: {turn['can_branch']}")
|
||||
|
||||
# Create a branch from turn 2
|
||||
branch_id = await session.create_branch_from_turn(2)
|
||||
print(f"Created branch: {branch_id}")
|
||||
|
||||
# Create a branch with custom name
|
||||
branch_id = await session.create_branch_from_turn(
|
||||
2,
|
||||
branch_name="alternative_path"
|
||||
)
|
||||
|
||||
# Create branch by searching for content
|
||||
branch_id = await session.create_branch_from_content(
|
||||
"weather",
|
||||
branch_name="weather_focus"
|
||||
)
|
||||
```
|
||||
|
||||
### 분기 관리
|
||||
|
||||
```python
|
||||
# List all branches
|
||||
branches = await session.list_branches()
|
||||
for branch in branches:
|
||||
current = " (current)" if branch["is_current"] else ""
|
||||
print(f"{branch['branch_id']}: {branch['user_turns']} turns, {branch['message_count']} messages{current}")
|
||||
|
||||
# Switch between branches
|
||||
await session.switch_to_branch("main")
|
||||
await session.switch_to_branch(branch_id)
|
||||
|
||||
# Delete a branch
|
||||
await session.delete_branch(branch_id, force=True) # force=True allows deleting current branch
|
||||
```
|
||||
|
||||
### 분기 워크플로 예제
|
||||
|
||||
```python
|
||||
# Original conversation
|
||||
result = await Runner.run(agent, "What's the capital of France?", session=session)
|
||||
await session.store_run_usage(result)
|
||||
|
||||
result = await Runner.run(agent, "What's the weather like there?", session=session)
|
||||
await session.store_run_usage(result)
|
||||
|
||||
# Create branch from turn 2 (weather question)
|
||||
branch_id = await session.create_branch_from_turn(2, "weather_focus")
|
||||
|
||||
# Continue in new branch with different question
|
||||
result = await Runner.run(
|
||||
agent,
|
||||
"What are the main tourist attractions in Paris?",
|
||||
session=session
|
||||
)
|
||||
await session.store_run_usage(result)
|
||||
|
||||
# Switch back to main branch
|
||||
await session.switch_to_branch("main")
|
||||
|
||||
# Continue original conversation
|
||||
result = await Runner.run(
|
||||
agent,
|
||||
"How expensive is it to visit?",
|
||||
session=session
|
||||
)
|
||||
await session.store_run_usage(result)
|
||||
```
|
||||
|
||||
## 구조화된 쿼리
|
||||
|
||||
AdvancedSQLiteSession은 대화 구조와 내용을 분석하기 위한 여러 메서드를 제공합니다.
|
||||
|
||||
### 대화 분석
|
||||
|
||||
```python
|
||||
# Get conversation organized by turns
|
||||
conversation_by_turns = await session.get_conversation_by_turns()
|
||||
for turn_num, items in conversation_by_turns.items():
|
||||
print(f"Turn {turn_num}: {len(items)} items")
|
||||
for item in items:
|
||||
if item["tool_name"]:
|
||||
print(f" - {item['type']} (tool: {item['tool_name']})")
|
||||
else:
|
||||
print(f" - {item['type']}")
|
||||
|
||||
# Get tool usage statistics
|
||||
tool_usage = await session.get_tool_usage()
|
||||
for tool_name, count, turn in tool_usage:
|
||||
print(f"{tool_name}: used {count} times in turn {turn}")
|
||||
|
||||
# Find turns by content
|
||||
matching_turns = await session.find_turns_by_content("weather")
|
||||
for turn in matching_turns:
|
||||
print(f"Turn {turn['turn']}: {turn['content']}")
|
||||
```
|
||||
|
||||
### 메시지 구조
|
||||
|
||||
세션은 다음을 포함한 메시지 구조를 자동으로 추적합니다.
|
||||
|
||||
- 메시지 유형(사용자, 어시스턴트, tool_call 등)
|
||||
- 도구 호출의 도구 이름
|
||||
- 턴 번호 및 시퀀스 번호
|
||||
- 분기 연결
|
||||
- 타임스탬프
|
||||
|
||||
## 데이터베이스 스키마
|
||||
|
||||
AdvancedSQLiteSession은 두 개의 추가 테이블로 기본 SQLite 스키마를 확장합니다.
|
||||
|
||||
### message_structure 테이블
|
||||
|
||||
```sql
|
||||
CREATE TABLE message_structure (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
session_id TEXT NOT NULL,
|
||||
message_id INTEGER NOT NULL,
|
||||
branch_id TEXT NOT NULL DEFAULT 'main',
|
||||
message_type TEXT NOT NULL,
|
||||
sequence_number INTEGER NOT NULL,
|
||||
user_turn_number INTEGER,
|
||||
branch_turn_number INTEGER,
|
||||
tool_name TEXT,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (session_id) REFERENCES agent_sessions(session_id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (message_id) REFERENCES agent_messages(id) ON DELETE CASCADE
|
||||
);
|
||||
```
|
||||
|
||||
### turn_usage 테이블
|
||||
|
||||
```sql
|
||||
CREATE TABLE turn_usage (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
session_id TEXT NOT NULL,
|
||||
branch_id TEXT NOT NULL DEFAULT 'main',
|
||||
user_turn_number INTEGER NOT NULL,
|
||||
requests INTEGER DEFAULT 0,
|
||||
input_tokens INTEGER DEFAULT 0,
|
||||
output_tokens INTEGER DEFAULT 0,
|
||||
total_tokens INTEGER DEFAULT 0,
|
||||
input_tokens_details JSON,
|
||||
output_tokens_details JSON,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (session_id) REFERENCES agent_sessions(session_id) ON DELETE CASCADE,
|
||||
UNIQUE(session_id, branch_id, user_turn_number)
|
||||
);
|
||||
```
|
||||
|
||||
## 전체 예제
|
||||
|
||||
모든 기능을 종합적으로 보여 주는 [전체 예제](https://github.com/openai/openai-agents-python/tree/main/examples/memory/advanced_sqlite_session_example.py)를 확인하세요.
|
||||
|
||||
|
||||
## API 참조
|
||||
|
||||
- [`AdvancedSQLiteSession`][agents.extensions.memory.advanced_sqlite_session.AdvancedSQLiteSession] - 메인 클래스
|
||||
- [`Session`][agents.memory.session.Session] - 기본 세션 프로토콜
|
||||
@@ -0,0 +1,179 @@
|
||||
---
|
||||
search:
|
||||
exclude: true
|
||||
---
|
||||
# 암호화된 세션
|
||||
|
||||
`EncryptedSession`은 모든 세션 구현에 투명한 암호화를 제공하여, 오래된 항목의 자동 만료와 함께 대화 데이터를 보호합니다.
|
||||
|
||||
## 기능
|
||||
|
||||
- **투명한 암호화**: 모든 세션을 Fernet 암호화로 래핑합니다
|
||||
- **세션별 키**: HKDF 키 파생을 사용하여 세션마다 고유한 암호화를 적용합니다
|
||||
- **자동 만료**: TTL이 만료되면 오래된 항목을 조용히 건너뜁니다
|
||||
- **드롭인 대체**: 기존의 모든 세션 구현과 함께 작동합니다
|
||||
|
||||
## 설치
|
||||
|
||||
암호화된 세션에는 `encrypt` extra가 필요합니다:
|
||||
|
||||
```bash
|
||||
pip install openai-agents[encrypt]
|
||||
```
|
||||
|
||||
## 빠른 시작
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
from agents import Agent, Runner
|
||||
from agents.extensions.memory import EncryptedSession, SQLAlchemySession
|
||||
|
||||
async def main():
|
||||
agent = Agent("Assistant")
|
||||
|
||||
# Create underlying session
|
||||
underlying_session = SQLAlchemySession.from_url(
|
||||
"user-123",
|
||||
url="sqlite+aiosqlite:///:memory:",
|
||||
create_tables=True
|
||||
)
|
||||
|
||||
# Wrap with encryption
|
||||
session = EncryptedSession(
|
||||
session_id="user-123",
|
||||
underlying_session=underlying_session,
|
||||
encryption_key="your-secret-key-here",
|
||||
ttl=600 # 10 minutes
|
||||
)
|
||||
|
||||
result = await Runner.run(agent, "Hello", session=session)
|
||||
print(result.final_output)
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
```
|
||||
|
||||
## 구성
|
||||
|
||||
### 암호화 키
|
||||
|
||||
암호화 키는 Fernet 키이거나 임의의 문자열일 수 있습니다:
|
||||
|
||||
```python
|
||||
from agents.extensions.memory import EncryptedSession
|
||||
|
||||
# Using a Fernet key (base64-encoded)
|
||||
session = EncryptedSession(
|
||||
session_id="user-123",
|
||||
underlying_session=underlying_session,
|
||||
encryption_key="your-fernet-key-here",
|
||||
ttl=600
|
||||
)
|
||||
|
||||
# Using a raw string (will be derived to a key)
|
||||
session = EncryptedSession(
|
||||
session_id="user-123",
|
||||
underlying_session=underlying_session,
|
||||
encryption_key="my-secret-password",
|
||||
ttl=600
|
||||
)
|
||||
```
|
||||
|
||||
### TTL(time to live)
|
||||
|
||||
암호화된 항목이 유효한 기간을 설정합니다:
|
||||
|
||||
```python
|
||||
# Items expire after 1 hour
|
||||
session = EncryptedSession(
|
||||
session_id="user-123",
|
||||
underlying_session=underlying_session,
|
||||
encryption_key="secret",
|
||||
ttl=3600 # 1 hour in seconds
|
||||
)
|
||||
|
||||
# Items expire after 1 day
|
||||
session = EncryptedSession(
|
||||
session_id="user-123",
|
||||
underlying_session=underlying_session,
|
||||
encryption_key="secret",
|
||||
ttl=86400 # 24 hours in seconds
|
||||
)
|
||||
```
|
||||
|
||||
## 다양한 세션 유형과 함께 사용
|
||||
|
||||
### SQLite 세션과 함께 사용
|
||||
|
||||
```python
|
||||
from agents import SQLiteSession
|
||||
from agents.extensions.memory import EncryptedSession
|
||||
|
||||
# Create encrypted SQLite session
|
||||
underlying = SQLiteSession("user-123", "conversations.db")
|
||||
|
||||
session = EncryptedSession(
|
||||
session_id="user-123",
|
||||
underlying_session=underlying,
|
||||
encryption_key="secret-key"
|
||||
)
|
||||
```
|
||||
|
||||
### SQLAlchemy 세션과 함께 사용
|
||||
|
||||
```python
|
||||
from agents.extensions.memory import EncryptedSession, SQLAlchemySession
|
||||
|
||||
# Create encrypted SQLAlchemy session
|
||||
underlying = SQLAlchemySession.from_url(
|
||||
"user-123",
|
||||
url="postgresql+asyncpg://user:pass@localhost/db",
|
||||
create_tables=True
|
||||
)
|
||||
|
||||
session = EncryptedSession(
|
||||
session_id="user-123",
|
||||
underlying_session=underlying,
|
||||
encryption_key="secret-key"
|
||||
)
|
||||
```
|
||||
|
||||
!!! warning "고급 세션 기능"
|
||||
|
||||
`EncryptedSession`을 `AdvancedSQLiteSession` 같은 고급 세션 구현과 함께 사용할 때는 다음 사항에 유의하세요:
|
||||
|
||||
- `find_turns_by_content()` 같은 메서드는 메시지 콘텐츠가 암호화되어 있으므로 효과적으로 작동하지 않습니다
|
||||
- 콘텐츠 기반 검색은 암호화된 데이터에 대해 동작하므로 효과가 제한됩니다
|
||||
|
||||
|
||||
|
||||
## 키 파생
|
||||
|
||||
EncryptedSession은 HKDF(HMAC-based Key Derivation Function)를 사용하여 세션별로 고유한 암호화 키를 파생합니다:
|
||||
|
||||
- **마스터 키**: 제공한 암호화 키
|
||||
- **세션 솔트**: 세션 ID
|
||||
- **정보 문자열**: `"agents.session-store.hkdf.v1"`
|
||||
- **출력**: 32바이트 Fernet 키
|
||||
|
||||
이를 통해 다음이 보장됩니다:
|
||||
- 각 세션에는 고유한 암호화 키가 있습니다
|
||||
- 마스터 키 없이는 키를 파생할 수 없습니다
|
||||
- 서로 다른 세션 간에는 세션 데이터를 복호화할 수 없습니다
|
||||
|
||||
## 자동 만료
|
||||
|
||||
항목이 TTL을 초과하면 조회 중 자동으로 건너뜁니다:
|
||||
|
||||
```python
|
||||
# Items older than TTL are silently ignored
|
||||
items = await session.get_items() # Only returns non-expired items
|
||||
|
||||
# Expired items don't affect session behavior
|
||||
result = await Runner.run(agent, "Continue conversation", session=session)
|
||||
```
|
||||
|
||||
## API 참조
|
||||
|
||||
- [`EncryptedSession`][agents.extensions.memory.encrypt_session.EncryptedSession] - 기본 클래스
|
||||
- [`Session`][agents.memory.session.Session] - 기본 세션 프로토콜
|
||||
@@ -0,0 +1,711 @@
|
||||
---
|
||||
search:
|
||||
exclude: true
|
||||
---
|
||||
# 세션
|
||||
|
||||
Agents SDK는 여러 에이전트 실행 간 대화 기록을 자동으로 유지하는 기본 제공 세션 메모리를 제공하여, 턴 사이에 `.to_input_list()` 를 수동으로 처리할 필요를 없애줍니다.
|
||||
|
||||
세션은 특정 세션의 대화 기록을 저장하므로, 명시적인 수동 메모리 관리 없이도 에이전트가 컨텍스트를 유지할 수 있습니다. 이는 에이전트가 이전 상호작용을 기억해야 하는 채팅 애플리케이션이나 멀티턴 대화를 구축할 때 특히 유용합니다.
|
||||
|
||||
SDK가 클라이언트 측 메모리를 관리해 주기를 원할 때 세션을 사용하세요. 세션은 동일한 실행에서 `conversation_id`, `previous_response_id` 또는 `auto_previous_response_id` 와 함께 사용할 수 없습니다. OpenAI 서버 관리형 이어가기를 원한다면 세션을 그 위에 겹쳐 사용하지 말고 해당 메커니즘 중 하나를 선택하세요.
|
||||
|
||||
## 빠른 시작
|
||||
|
||||
```python
|
||||
from agents import Agent, Runner, SQLiteSession
|
||||
|
||||
# Create agent
|
||||
agent = Agent(
|
||||
name="Assistant",
|
||||
instructions="Reply very concisely.",
|
||||
)
|
||||
|
||||
# Create a session instance with a session ID
|
||||
session = SQLiteSession("conversation_123")
|
||||
|
||||
# First turn
|
||||
result = await Runner.run(
|
||||
agent,
|
||||
"What city is the Golden Gate Bridge in?",
|
||||
session=session
|
||||
)
|
||||
print(result.final_output) # "San Francisco"
|
||||
|
||||
# Second turn - agent automatically remembers previous context
|
||||
result = await Runner.run(
|
||||
agent,
|
||||
"What state is it in?",
|
||||
session=session
|
||||
)
|
||||
print(result.final_output) # "California"
|
||||
|
||||
# Also works with synchronous runner
|
||||
result = Runner.run_sync(
|
||||
agent,
|
||||
"What's the population?",
|
||||
session=session
|
||||
)
|
||||
print(result.final_output) # "Approximately 39 million"
|
||||
```
|
||||
|
||||
## 동일한 세션으로 인터럽트된 실행 재개
|
||||
|
||||
승인을 위해 실행이 일시 중지되는 경우, 재개된 턴이 동일한 저장된 대화 기록을 이어가도록 같은 세션 인스턴스(또는 같은 기반 저장소를 가리키는 다른 세션 인스턴스)로 재개하세요.
|
||||
|
||||
```python
|
||||
result = await Runner.run(agent, "Delete temporary files that are no longer needed.", session=session)
|
||||
|
||||
if result.interruptions:
|
||||
state = result.to_state()
|
||||
for interruption in result.interruptions:
|
||||
state.approve(interruption)
|
||||
result = await Runner.run(agent, state, session=session)
|
||||
```
|
||||
|
||||
## 핵심 세션 동작
|
||||
|
||||
세션 메모리가 활성화되면 다음과 같이 동작합니다.
|
||||
|
||||
1. **각 실행 전**: 러너가 세션의 대화 기록을 자동으로 조회하여 입력 항목 앞에 추가합니다.
|
||||
2. **각 실행 후**: 실행 중 생성된 모든 새 항목(사용자 입력, 어시스턴트 응답, 도구 호출 등)이 세션에 자동으로 저장됩니다.
|
||||
3. **컨텍스트 보존**: 동일한 세션으로 이어지는 각 실행에는 전체 대화 기록이 포함되어 에이전트가 컨텍스트를 유지할 수 있습니다.
|
||||
|
||||
이를 통해 `.to_input_list()` 를 수동으로 호출하고 실행 간 대화 상태를 관리할 필요가 없어집니다.
|
||||
|
||||
## 기록과 새 입력 병합 제어
|
||||
|
||||
세션을 전달하면 러너는 일반적으로 모델 입력을 다음과 같이 준비합니다.
|
||||
|
||||
1. 세션 기록(`session.get_items(...)` 에서 조회)
|
||||
2. 새 턴 입력
|
||||
|
||||
모델 호출 전에 이 병합 단계를 사용자 지정하려면 [`RunConfig.session_input_callback`][agents.run.RunConfig.session_input_callback] 을 사용하세요. 콜백은 두 개의 목록을 받습니다.
|
||||
|
||||
- `history`: 조회된 세션 기록(이미 입력 항목 형식으로 정규화됨)
|
||||
- `new_input`: 현재 턴의 새 입력 항목
|
||||
|
||||
모델에 전송할 최종 입력 항목 목록을 반환하세요.
|
||||
|
||||
콜백은 두 목록의 복사본을 받으므로 안전하게 변경할 수 있습니다. 반환된 목록은 해당 턴의 모델 입력을 제어하지만, SDK는 여전히 새 턴에 속한 항목만 지속 저장합니다. 따라서 이전 기록을 재정렬하거나 필터링해도 이전 세션 항목이 새 입력으로 다시 저장되지는 않습니다.
|
||||
|
||||
```python
|
||||
from agents import Agent, RunConfig, Runner, SQLiteSession
|
||||
|
||||
|
||||
def keep_recent_history(history, new_input):
|
||||
# Keep only the last 10 history items, then append the new turn.
|
||||
return history[-10:] + new_input
|
||||
|
||||
|
||||
agent = Agent(name="Assistant")
|
||||
session = SQLiteSession("conversation_123")
|
||||
|
||||
result = await Runner.run(
|
||||
agent,
|
||||
"Continue from the latest updates only.",
|
||||
session=session,
|
||||
run_config=RunConfig(session_input_callback=keep_recent_history),
|
||||
)
|
||||
```
|
||||
|
||||
세션이 항목을 저장하는 방식은 바꾸지 않으면서 기록에 대한 사용자 지정 가지치기, 재정렬 또는 선택적 포함이 필요할 때 사용하세요. 모델 호출 직전에 더 늦은 최종 처리 단계가 필요하다면 [에이전트 실행 가이드](../running_agents.md)의 [`call_model_input_filter`][agents.run.RunConfig.call_model_input_filter] 를 사용하세요.
|
||||
|
||||
## 조회 기록 제한
|
||||
|
||||
각 실행 전에 가져올 기록의 양을 제어하려면 [`SessionSettings`][agents.memory.SessionSettings] 를 사용하세요.
|
||||
|
||||
- `SessionSettings(limit=None)` (기본값): 사용 가능한 모든 세션 항목 조회
|
||||
- `SessionSettings(limit=N)`: 가장 최근 `N` 개 항목만 조회
|
||||
|
||||
[`RunConfig.session_settings`][agents.run.RunConfig.session_settings] 를 통해 실행별로 이를 적용할 수 있습니다.
|
||||
|
||||
```python
|
||||
from agents import Agent, RunConfig, Runner, SessionSettings, SQLiteSession
|
||||
|
||||
agent = Agent(name="Assistant")
|
||||
session = SQLiteSession("conversation_123")
|
||||
|
||||
result = await Runner.run(
|
||||
agent,
|
||||
"Summarize our recent discussion.",
|
||||
session=session,
|
||||
run_config=RunConfig(session_settings=SessionSettings(limit=50)),
|
||||
)
|
||||
```
|
||||
|
||||
세션 구현이 기본 세션 설정을 제공하는 경우, `RunConfig.session_settings` 는 해당 실행에 대해 `None` 이 아닌 값을 재정의합니다. 이는 긴 대화에서 세션의 기본 동작은 변경하지 않으면서 조회 크기를 제한하고 싶을 때 유용합니다.
|
||||
|
||||
## 메모리 작업
|
||||
|
||||
### 기본 작업
|
||||
|
||||
세션은 대화 기록 관리를 위한 여러 작업을 지원합니다.
|
||||
|
||||
```python
|
||||
from agents import SQLiteSession
|
||||
|
||||
session = SQLiteSession("user_123", "conversations.db")
|
||||
|
||||
# Get all items in a session
|
||||
items = await session.get_items()
|
||||
|
||||
# Add new items to a session
|
||||
new_items = [
|
||||
{"role": "user", "content": "Hello"},
|
||||
{"role": "assistant", "content": "Hi there!"}
|
||||
]
|
||||
await session.add_items(new_items)
|
||||
|
||||
# Remove and return the most recent item
|
||||
last_item = await session.pop_item()
|
||||
print(last_item) # {"role": "assistant", "content": "Hi there!"}
|
||||
|
||||
# Clear all items from a session
|
||||
await session.clear_session()
|
||||
```
|
||||
|
||||
### 수정을 위한 pop_item 사용
|
||||
|
||||
`pop_item` 메서드는 대화의 마지막 항목을 되돌리거나 수정하고 싶을 때 특히 유용합니다.
|
||||
|
||||
```python
|
||||
from agents import Agent, Runner, SQLiteSession
|
||||
|
||||
agent = Agent(name="Assistant")
|
||||
session = SQLiteSession("correction_example")
|
||||
|
||||
# Initial conversation
|
||||
result = await Runner.run(
|
||||
agent,
|
||||
"What's 2 + 2?",
|
||||
session=session
|
||||
)
|
||||
print(f"Agent: {result.final_output}")
|
||||
|
||||
# User wants to correct their question
|
||||
assistant_item = await session.pop_item() # Remove agent's response
|
||||
user_item = await session.pop_item() # Remove user's question
|
||||
|
||||
# Ask a corrected question
|
||||
result = await Runner.run(
|
||||
agent,
|
||||
"What's 2 + 3?",
|
||||
session=session
|
||||
)
|
||||
print(f"Agent: {result.final_output}")
|
||||
```
|
||||
|
||||
## 기본 제공 세션 구현
|
||||
|
||||
SDK는 다양한 사용 사례를 위한 여러 세션 구현을 제공합니다.
|
||||
|
||||
### 기본 제공 세션 구현 선택
|
||||
|
||||
아래의 상세 예제를 읽기 전에 시작점을 고르는 데 이 표를 사용하세요.
|
||||
|
||||
| 세션 유형 | 적합한 용도 | 참고 |
|
||||
| --- | --- | --- |
|
||||
| `SQLiteSession` | 로컬 개발 및 간단한 앱 | 기본 제공, 경량, 파일 기반 또는 인메모리 |
|
||||
| `AsyncSQLiteSession` | `aiosqlite` 기반 비동기 SQLite | 비동기 드라이버를 지원하는 확장 백엔드 |
|
||||
| `RedisSession` | 여러 워커/서비스 간 공유 메모리 | 저지연 분산 배포에 적합 |
|
||||
| `SQLAlchemySession` | 기존 데이터베이스를 사용하는 프로덕션 앱 | SQLAlchemy가 지원하는 데이터베이스와 함께 동작 |
|
||||
| `MongoDBSession` | 이미 MongoDB를 사용하거나 다중 프로세스 스토리지가 필요한 앱 | 비동기 pymongo; 순서 보장을 위한 원자적 시퀀스 카운터 |
|
||||
| `DaprSession` | Dapr 사이드카를 사용하는 클라우드 네이티브 배포 | 여러 상태 저장소와 TTL 및 일관성 제어 지원 |
|
||||
| `OpenAIConversationsSession` | OpenAI의 서버 관리형 스토리지 | OpenAI Conversations API 기반 기록 |
|
||||
| `OpenAIResponsesCompactionSession` | 자동 압축이 필요한 긴 대화 | 다른 세션 백엔드를 감싸는 래퍼 |
|
||||
| `AdvancedSQLiteSession` | SQLite와 분기/분석 | 더 많은 기능 세트; 전용 페이지 참조 |
|
||||
| `EncryptedSession` | 다른 세션 위에 암호화 + TTL 적용 | 래퍼; 먼저 하위 백엔드 선택 |
|
||||
|
||||
일부 구현에는 추가 세부 정보를 담은 전용 페이지가 있으며, 해당 하위 섹션에 링크되어 있습니다.
|
||||
|
||||
ChatKit용 Python 서버를 구현하는 경우, ChatKit의 스레드 및 항목 지속성을 위해 `chatkit.store.Store` 구현을 사용하세요. `SQLAlchemySession` 같은 Agents SDK 세션은 SDK 측 대화 기록을 관리하지만, ChatKit의 스토어를 그대로 대체할 수 있는 것은 아닙니다. [`chatkit-python` 의 ChatKit 데이터 스토어 구현 가이드](https://github.com/openai/chatkit-python/blob/main/docs/guides/respond-to-user-message.md#implement-your-chatkit-data-store)를 참조하세요.
|
||||
|
||||
### OpenAI Conversations API 세션
|
||||
|
||||
`OpenAIConversationsSession` 을 통해 [OpenAI의 Conversations API](https://platform.openai.com/docs/api-reference/conversations)를 사용하세요.
|
||||
|
||||
```python
|
||||
from agents import Agent, Runner, OpenAIConversationsSession
|
||||
|
||||
# Create agent
|
||||
agent = Agent(
|
||||
name="Assistant",
|
||||
instructions="Reply very concisely.",
|
||||
)
|
||||
|
||||
# Create a new conversation
|
||||
session = OpenAIConversationsSession()
|
||||
|
||||
# Optionally resume a previous conversation by passing a conversation ID
|
||||
# session = OpenAIConversationsSession(conversation_id="conv_123")
|
||||
|
||||
# Start conversation
|
||||
result = await Runner.run(
|
||||
agent,
|
||||
"What city is the Golden Gate Bridge in?",
|
||||
session=session
|
||||
)
|
||||
print(result.final_output) # "San Francisco"
|
||||
|
||||
# Continue the conversation
|
||||
result = await Runner.run(
|
||||
agent,
|
||||
"What state is it in?",
|
||||
session=session
|
||||
)
|
||||
print(result.final_output) # "California"
|
||||
```
|
||||
|
||||
### OpenAI Responses 압축 세션
|
||||
|
||||
Responses API(`responses.compact`)로 저장된 대화 기록을 압축하려면 `OpenAIResponsesCompactionSession` 을 사용하세요. 이 세션은 하위 세션을 감싸며, `should_trigger_compaction` 에 따라 각 턴 이후 자동으로 압축할 수 있습니다. `OpenAIConversationsSession` 을 이것으로 감싸지 마세요. 두 기능은 서로 다른 방식으로 기록을 관리합니다.
|
||||
|
||||
#### 일반적인 사용법(자동 압축)
|
||||
|
||||
```python
|
||||
from agents import Agent, Runner, SQLiteSession
|
||||
from agents.memory import OpenAIResponsesCompactionSession
|
||||
|
||||
underlying = SQLiteSession("conversation_123")
|
||||
session = OpenAIResponsesCompactionSession(
|
||||
session_id="conversation_123",
|
||||
underlying_session=underlying,
|
||||
)
|
||||
|
||||
agent = Agent(name="Assistant")
|
||||
result = await Runner.run(agent, "Hello", session=session)
|
||||
print(result.final_output)
|
||||
```
|
||||
|
||||
기본적으로 압축은 후보 임계값에 도달하면 각 턴 이후 실행됩니다.
|
||||
|
||||
`compaction_mode="previous_response_id"` 는 이미 Responses API 응답 ID로 턴을 체이닝하고 있을 때 가장 잘 동작합니다. `compaction_mode="input"` 은 대신 현재 세션 항목으로부터 압축 요청을 다시 구성합니다. 이는 응답 체인을 사용할 수 없거나 세션 내용을 신뢰할 수 있는 기준으로 삼고 싶을 때 유용합니다. 기본값인 `"auto"` 는 사용 가능한 가장 안전한 옵션을 선택합니다.
|
||||
|
||||
에이전트가 `ModelSettings(store=False)` 로 실행되는 경우, Responses API는 나중에 조회할 수 있도록 마지막 응답을 보관하지 않습니다. 이 무상태 구성에서는 기본 `"auto"` 모드가 `previous_response_id` 에 의존하지 않고 입력 기반 압축으로 폴백합니다. 전체 예제는 [`examples/memory/compaction_session_stateless_example.py`](https://github.com/openai/openai-agents-python/tree/main/examples/memory/compaction_session_stateless_example.py)를 참조하세요.
|
||||
|
||||
#### 스트리밍을 차단할 수 있는 자동 압축
|
||||
|
||||
압축은 세션 기록을 지우고 다시 쓰므로, SDK는 실행이 완료된 것으로 간주하기 전에 압축이 끝나기를 기다립니다. 스트리밍 모드에서는 압축 작업이 무거운 경우 마지막 출력 토큰 이후에도 `run.stream_events()` 가 몇 초 동안 열린 상태로 남아 있을 수 있습니다.
|
||||
|
||||
저지연 스트리밍이나 빠른 턴 전환을 원한다면 자동 압축을 비활성화하고 턴 사이(또는 유휴 시간)에 직접 `run_compaction()` 을 호출하세요. 자체 기준에 따라 언제 압축을 강제로 실행할지 결정할 수 있습니다.
|
||||
|
||||
```python
|
||||
from agents import Agent, Runner, SQLiteSession
|
||||
from agents.memory import OpenAIResponsesCompactionSession
|
||||
|
||||
underlying = SQLiteSession("conversation_123")
|
||||
session = OpenAIResponsesCompactionSession(
|
||||
session_id="conversation_123",
|
||||
underlying_session=underlying,
|
||||
# Disable triggering the auto compaction
|
||||
should_trigger_compaction=lambda _: False,
|
||||
)
|
||||
|
||||
agent = Agent(name="Assistant")
|
||||
result = await Runner.run(agent, "Hello", session=session)
|
||||
|
||||
# Decide when to compact (e.g., on idle, every N turns, or size thresholds).
|
||||
await session.run_compaction({"force": True})
|
||||
```
|
||||
|
||||
### SQLite 세션
|
||||
|
||||
SQLite를 사용하는 기본 경량 세션 구현입니다.
|
||||
|
||||
```python
|
||||
from agents import SQLiteSession
|
||||
|
||||
# In-memory database (lost when process ends)
|
||||
session = SQLiteSession("user_123")
|
||||
|
||||
# Persistent file-based database
|
||||
session = SQLiteSession("user_123", "conversations.db")
|
||||
|
||||
# Use the session
|
||||
result = await Runner.run(
|
||||
agent,
|
||||
"Hello",
|
||||
session=session
|
||||
)
|
||||
```
|
||||
|
||||
### 비동기 SQLite 세션
|
||||
|
||||
`aiosqlite` 기반 SQLite 지속성이 필요할 때 `AsyncSQLiteSession` 을 사용하세요.
|
||||
|
||||
```bash
|
||||
pip install aiosqlite
|
||||
```
|
||||
|
||||
```python
|
||||
from agents import Agent, Runner
|
||||
from agents.extensions.memory import AsyncSQLiteSession
|
||||
|
||||
agent = Agent(name="Assistant")
|
||||
session = AsyncSQLiteSession("user_123", db_path="conversations.db")
|
||||
result = await Runner.run(agent, "Hello", session=session)
|
||||
```
|
||||
|
||||
### Redis 세션
|
||||
|
||||
여러 워커 또는 서비스 간 공유 세션 메모리에는 `RedisSession` 을 사용하세요.
|
||||
|
||||
```bash
|
||||
pip install openai-agents[redis]
|
||||
```
|
||||
|
||||
```python
|
||||
from agents import Agent, Runner
|
||||
from agents.extensions.memory import RedisSession
|
||||
|
||||
agent = Agent(name="Assistant")
|
||||
session = RedisSession.from_url(
|
||||
"user_123",
|
||||
url="redis://localhost:6379/0",
|
||||
)
|
||||
result = await Runner.run(agent, "Hello", session=session)
|
||||
```
|
||||
|
||||
### SQLAlchemy 세션
|
||||
|
||||
SQLAlchemy가 지원하는 모든 데이터베이스를 사용하는 프로덕션 환경에 적합한 Agents SDK 세션 지속성입니다.
|
||||
|
||||
```python
|
||||
from agents.extensions.memory import SQLAlchemySession
|
||||
|
||||
# Using database URL
|
||||
session = SQLAlchemySession.from_url(
|
||||
"user_123",
|
||||
url="postgresql+asyncpg://user:pass@localhost/db",
|
||||
create_tables=True
|
||||
)
|
||||
|
||||
# Using existing engine
|
||||
from sqlalchemy.ext.asyncio import create_async_engine
|
||||
engine = create_async_engine("postgresql+asyncpg://user:pass@localhost/db")
|
||||
session = SQLAlchemySession("user_123", engine=engine, create_tables=True)
|
||||
```
|
||||
|
||||
자세한 문서는 [SQLAlchemy 세션](sqlalchemy_session.md)을 참조하세요.
|
||||
|
||||
### Dapr 세션
|
||||
|
||||
이미 Dapr 사이드카를 실행 중이거나 에이전트 코드를 변경하지 않고 여러 상태 저장소 백엔드 간에 이동할 수 있는 세션 스토리지를 원할 때 `DaprSession` 을 사용하세요.
|
||||
|
||||
```bash
|
||||
pip install openai-agents[dapr]
|
||||
```
|
||||
|
||||
```python
|
||||
from agents import Agent, Runner
|
||||
from agents.extensions.memory import DaprSession
|
||||
|
||||
agent = Agent(name="Assistant")
|
||||
|
||||
async with DaprSession.from_address(
|
||||
"user_123",
|
||||
state_store_name="statestore",
|
||||
dapr_address="localhost:50001",
|
||||
) as session:
|
||||
result = await Runner.run(agent, "Hello", session=session)
|
||||
print(result.final_output)
|
||||
```
|
||||
|
||||
참고:
|
||||
|
||||
- `from_address(...)` 는 Dapr 클라이언트를 생성하고 수명 주기를 관리합니다. 앱에서 이미 Dapr 클라이언트를 관리하고 있다면 `dapr_client=...` 로 `DaprSession(...)` 을 직접 생성하세요.
|
||||
- 기반 상태 저장소가 TTL을 지원하는 경우 오래된 세션 데이터가 자동으로 만료되도록 `ttl=...` 을 전달하세요.
|
||||
- 더 강한 쓰기 후 읽기 보장이 필요하면 `consistency=DAPR_CONSISTENCY_STRONG` 을 전달하세요.
|
||||
- Dapr Python SDK는 HTTP 사이드카 엔드포인트도 확인합니다. 로컬 개발에서는 `dapr_address` 에서 사용하는 gRPC 포트뿐 아니라 `--dapr-http-port 3500` 도 함께 지정해 Dapr를 시작하세요.
|
||||
- 로컬 컴포넌트와 문제 해결을 포함한 전체 설정 안내는 [`examples/memory/dapr_session_example.py`](https://github.com/openai/openai-agents-python/tree/main/examples/memory/dapr_session_example.py)를 참조하세요.
|
||||
|
||||
|
||||
### MongoDB 세션
|
||||
|
||||
이미 MongoDB를 사용하거나 수평 확장이 가능한 다중 프로세스 세션 스토리지가 필요한 애플리케이션에는 `MongoDBSession` 을 사용하세요.
|
||||
|
||||
```bash
|
||||
pip install openai-agents[mongodb]
|
||||
```
|
||||
|
||||
```python
|
||||
from agents import Agent, Runner
|
||||
from agents.extensions.memory import MongoDBSession
|
||||
|
||||
agent = Agent(name="Assistant")
|
||||
|
||||
# Create from URI — owns the client and closes it when session.close() is called
|
||||
session = MongoDBSession.from_uri(
|
||||
"user-123",
|
||||
uri="mongodb://localhost:27017",
|
||||
database="agents",
|
||||
)
|
||||
result = await Runner.run(agent, "Hello", session=session)
|
||||
print(result.final_output)
|
||||
await session.close()
|
||||
```
|
||||
|
||||
참고:
|
||||
|
||||
- `from_uri(...)` 는 `AsyncMongoClient` 를 생성하고 수명 주기를 관리하며, `session.close()` 시 닫습니다. 애플리케이션에서 이미 클라이언트를 관리하고 있다면 `client=...` 로 `MongoDBSession(...)` 을 직접 생성하세요. 이 경우 `session.close()` 는 아무 작업도 하지 않으며 수명 주기는 호출자에게 남아 있습니다.
|
||||
- 다른 변경 없이 `mongodb+srv://user:password@cluster.example.mongodb.net` URI를 `from_uri(...)` 에 전달하여 [MongoDB Atlas](https://www.mongodb.com/products/platform)에 연결하세요.
|
||||
- 두 개의 컬렉션이 사용되며, 두 이름 모두 `sessions_collection=` (기본값 `agent_sessions`) 및 `messages_collection=` (기본값 `agent_messages`) 로 구성할 수 있습니다. 인덱스는 처음 사용할 때 자동으로 생성됩니다. 각 메시지 문서는 단조 증가하는 `seq` 카운터를 포함하여 동시 작성자와 프로세스 간 순서를 보존합니다.
|
||||
- 첫 실행 전에 연결을 확인하려면 `await session.ping()` 을 사용하세요.
|
||||
|
||||
### 고급 SQLite 세션
|
||||
|
||||
대화 분기, 사용량 분석, 구조화된 쿼리를 지원하는 향상된 SQLite 세션입니다.
|
||||
|
||||
```python
|
||||
from agents.extensions.memory import AdvancedSQLiteSession
|
||||
|
||||
# Create with advanced features
|
||||
session = AdvancedSQLiteSession(
|
||||
session_id="user_123",
|
||||
db_path="conversations.db",
|
||||
create_tables=True
|
||||
)
|
||||
|
||||
# Automatic usage tracking
|
||||
result = await Runner.run(agent, "Hello", session=session)
|
||||
await session.store_run_usage(result) # Track token usage
|
||||
|
||||
# Conversation branching
|
||||
await session.create_branch_from_turn(2) # Branch from turn 2
|
||||
```
|
||||
|
||||
자세한 문서는 [고급 SQLite 세션](advanced_sqlite_session.md)을 참조하세요.
|
||||
|
||||
### 암호화된 세션
|
||||
|
||||
모든 세션 구현을 위한 투명한 암호화 래퍼입니다.
|
||||
|
||||
```python
|
||||
from agents.extensions.memory import EncryptedSession, SQLAlchemySession
|
||||
|
||||
# Create underlying session
|
||||
underlying_session = SQLAlchemySession.from_url(
|
||||
"user_123",
|
||||
url="sqlite+aiosqlite:///conversations.db",
|
||||
create_tables=True
|
||||
)
|
||||
|
||||
# Wrap with encryption and TTL
|
||||
session = EncryptedSession(
|
||||
session_id="user_123",
|
||||
underlying_session=underlying_session,
|
||||
encryption_key="your-secret-key",
|
||||
ttl=600 # 10 minutes
|
||||
)
|
||||
|
||||
result = await Runner.run(agent, "Hello", session=session)
|
||||
```
|
||||
|
||||
자세한 문서는 [암호화된 세션](encrypted_session.md)을 참조하세요.
|
||||
|
||||
### 기타 세션 유형
|
||||
|
||||
기본 제공 옵션이 몇 가지 더 있습니다. `examples/memory/` 및 `extensions/memory/` 아래의 소스 코드를 참조하세요.
|
||||
|
||||
## 운영 패턴
|
||||
|
||||
### 세션 ID 명명
|
||||
|
||||
대화를 정리하는 데 도움이 되는 의미 있는 세션 ID를 사용하세요.
|
||||
|
||||
- 사용자 기반: `"user_12345"`
|
||||
- 스레드 기반: `"thread_abc123"`
|
||||
- 컨텍스트 기반: `"support_ticket_456"`
|
||||
|
||||
### 메모리 지속성
|
||||
|
||||
- 임시 대화에는 인메모리 SQLite(`SQLiteSession("session_id")`) 사용
|
||||
- 지속 대화에는 파일 기반 SQLite(`SQLiteSession("session_id", "path/to/db.sqlite")`) 사용
|
||||
- `aiosqlite` 기반 구현이 필요할 때는 비동기 SQLite(`AsyncSQLiteSession("session_id", db_path="...")`) 사용
|
||||
- 공유 저지연 세션 메모리에는 Redis 기반 세션(`RedisSession.from_url("session_id", url="redis://...")`) 사용
|
||||
- SQLAlchemy가 지원하는 기존 데이터베이스가 있는 프로덕션 시스템에는 SQLAlchemy 기반 세션(`SQLAlchemySession("session_id", engine=engine, create_tables=True)`) 사용
|
||||
- 이미 MongoDB를 사용하거나 다중 프로세스, 수평 확장 가능한 세션 스토리지가 필요한 애플리케이션에는 MongoDB 세션(`MongoDBSession.from_uri("session_id", uri="mongodb://localhost:27017")`) 사용
|
||||
- 기본 제공 텔레메트리, 트레이싱, 데이터 격리와 함께 30개 이상의 데이터베이스 백엔드를 지원하는 프로덕션 클라우드 네이티브 배포에는 Dapr 상태 저장소 세션(`DaprSession.from_address("session_id", state_store_name="statestore", dapr_address="localhost:50001")`) 사용
|
||||
- OpenAI Conversations API에 기록을 저장하고 싶다면 OpenAI가 호스팅하는 스토리지(`OpenAIConversationsSession()`) 사용
|
||||
- 투명한 암호화와 TTL 기반 만료로 모든 세션을 감싸려면 암호화된 세션(`EncryptedSession(session_id, underlying_session, encryption_key)`) 사용
|
||||
- 더 고급 사용 사례에는 다른 프로덕션 시스템(예: Django)을 위한 사용자 지정 세션 백엔드 구현 고려
|
||||
|
||||
### 여러 세션
|
||||
|
||||
```python
|
||||
from agents import Agent, Runner, SQLiteSession
|
||||
|
||||
agent = Agent(name="Assistant")
|
||||
|
||||
# Different sessions maintain separate conversation histories
|
||||
session_1 = SQLiteSession("user_123", "conversations.db")
|
||||
session_2 = SQLiteSession("user_456", "conversations.db")
|
||||
|
||||
result1 = await Runner.run(
|
||||
agent,
|
||||
"Help me with my account",
|
||||
session=session_1
|
||||
)
|
||||
result2 = await Runner.run(
|
||||
agent,
|
||||
"What are my charges?",
|
||||
session=session_2
|
||||
)
|
||||
```
|
||||
|
||||
### 세션 공유
|
||||
|
||||
```python
|
||||
# Different agents can share the same session
|
||||
support_agent = Agent(name="Support")
|
||||
billing_agent = Agent(name="Billing")
|
||||
session = SQLiteSession("user_123")
|
||||
|
||||
# Both agents will see the same conversation history
|
||||
result1 = await Runner.run(
|
||||
support_agent,
|
||||
"Help me with my account",
|
||||
session=session
|
||||
)
|
||||
result2 = await Runner.run(
|
||||
billing_agent,
|
||||
"What are my charges?",
|
||||
session=session
|
||||
)
|
||||
```
|
||||
|
||||
## 전체 예제
|
||||
|
||||
세션 메모리가 동작하는 방식을 보여주는 전체 예제입니다.
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
from agents import Agent, Runner, SQLiteSession
|
||||
|
||||
|
||||
async def main():
|
||||
# Create an agent
|
||||
agent = Agent(
|
||||
name="Assistant",
|
||||
instructions="Reply very concisely.",
|
||||
)
|
||||
|
||||
# Create a session instance that will persist across runs
|
||||
session = SQLiteSession("conversation_123", "conversation_history.db")
|
||||
|
||||
print("=== Sessions Example ===")
|
||||
print("The agent will remember previous messages automatically.\n")
|
||||
|
||||
# First turn
|
||||
print("First turn:")
|
||||
print("User: What city is the Golden Gate Bridge in?")
|
||||
result = await Runner.run(
|
||||
agent,
|
||||
"What city is the Golden Gate Bridge in?",
|
||||
session=session
|
||||
)
|
||||
print(f"Assistant: {result.final_output}")
|
||||
print()
|
||||
|
||||
# Second turn - the agent will remember the previous conversation
|
||||
print("Second turn:")
|
||||
print("User: What state is it in?")
|
||||
result = await Runner.run(
|
||||
agent,
|
||||
"What state is it in?",
|
||||
session=session
|
||||
)
|
||||
print(f"Assistant: {result.final_output}")
|
||||
print()
|
||||
|
||||
# Third turn - continuing the conversation
|
||||
print("Third turn:")
|
||||
print("User: What's the population of that state?")
|
||||
result = await Runner.run(
|
||||
agent,
|
||||
"What's the population of that state?",
|
||||
session=session
|
||||
)
|
||||
print(f"Assistant: {result.final_output}")
|
||||
print()
|
||||
|
||||
print("=== Conversation Complete ===")
|
||||
print("Notice how the agent remembered the context from previous turns!")
|
||||
print("Sessions automatically handles conversation history.")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
```
|
||||
|
||||
## 사용자 지정 세션 구현
|
||||
|
||||
[`Session`][agents.memory.session.Session] 프로토콜을 따르는 클래스를 만들어 자체 세션 메모리를 구현할 수 있습니다.
|
||||
|
||||
```python
|
||||
from agents.memory.session import SessionABC
|
||||
from agents.items import TResponseInputItem
|
||||
from typing import List
|
||||
|
||||
class MyCustomSession(SessionABC):
|
||||
"""Custom session implementation following the Session protocol."""
|
||||
|
||||
def __init__(self, session_id: str):
|
||||
self.session_id = session_id
|
||||
# Your initialization here
|
||||
|
||||
async def get_items(self, limit: int | None = None) -> List[TResponseInputItem]:
|
||||
"""Retrieve conversation history for this session."""
|
||||
# Your implementation here
|
||||
pass
|
||||
|
||||
async def add_items(self, items: List[TResponseInputItem]) -> None:
|
||||
"""Store new items for this session."""
|
||||
# Your implementation here
|
||||
pass
|
||||
|
||||
async def pop_item(self) -> TResponseInputItem | None:
|
||||
"""Remove and return the most recent item from this session."""
|
||||
# Your implementation here
|
||||
pass
|
||||
|
||||
async def clear_session(self) -> None:
|
||||
"""Clear all items for this session."""
|
||||
# Your implementation here
|
||||
pass
|
||||
|
||||
# Use your custom session
|
||||
agent = Agent(name="Assistant")
|
||||
result = await Runner.run(
|
||||
agent,
|
||||
"Hello",
|
||||
session=MyCustomSession("my_session")
|
||||
)
|
||||
```
|
||||
|
||||
## 커뮤니티 세션 구현
|
||||
|
||||
커뮤니티에서 추가 세션 구현을 개발했습니다.
|
||||
|
||||
| 패키지 | 설명 |
|
||||
|---------|-------------|
|
||||
| [openai-django-sessions](https://pypi.org/project/openai-django-sessions/) | Django가 지원하는 모든 데이터베이스(PostgreSQL, MySQL, SQLite 등)를 위한 Django ORM 기반 세션 |
|
||||
|
||||
세션 구현을 만들었다면 이곳에 추가할 수 있도록 문서 PR을 자유롭게 제출해 주세요!
|
||||
|
||||
## API 참조
|
||||
|
||||
자세한 API 문서는 다음을 참조하세요.
|
||||
|
||||
- [`Session`][agents.memory.session.Session] - 프로토콜 인터페이스
|
||||
- [`OpenAIConversationsSession`][agents.memory.OpenAIConversationsSession] - OpenAI Conversations API 구현
|
||||
- [`OpenAIResponsesCompactionSession`][agents.memory.openai_responses_compaction_session.OpenAIResponsesCompactionSession] - Responses API 압축 래퍼
|
||||
- [`SQLiteSession`][agents.memory.sqlite_session.SQLiteSession] - 기본 SQLite 구현
|
||||
- [`AsyncSQLiteSession`][agents.extensions.memory.async_sqlite_session.AsyncSQLiteSession] - `aiosqlite` 기반 비동기 SQLite 구현
|
||||
- [`RedisSession`][agents.extensions.memory.redis_session.RedisSession] - Redis 기반 세션 구현
|
||||
- [`SQLAlchemySession`][agents.extensions.memory.sqlalchemy_session.SQLAlchemySession] - SQLAlchemy 기반 구현
|
||||
- [`MongoDBSession`][agents.extensions.memory.mongodb_session.MongoDBSession] - MongoDB 기반 세션 구현
|
||||
- [`DaprSession`][agents.extensions.memory.dapr_session.DaprSession] - Dapr 상태 저장소 구현
|
||||
- [`AdvancedSQLiteSession`][agents.extensions.memory.advanced_sqlite_session.AdvancedSQLiteSession] - 분기와 분석을 지원하는 향상된 SQLite
|
||||
- [`EncryptedSession`][agents.extensions.memory.encrypt_session.EncryptedSession] - 모든 세션을 위한 암호화 래퍼
|
||||
@@ -0,0 +1,80 @@
|
||||
---
|
||||
search:
|
||||
exclude: true
|
||||
---
|
||||
# SQLAlchemy 세션
|
||||
|
||||
`SQLAlchemySession`은 SQLAlchemy를 사용해 프로덕션 환경에서 사용할 수 있는 세션 구현을 제공하며, 세션 저장소로 SQLAlchemy가 지원하는 모든 데이터베이스(PostgreSQL, MySQL, SQLite 등)를 사용할 수 있습니다.
|
||||
|
||||
## 설치
|
||||
|
||||
SQLAlchemy 세션에는 `sqlalchemy` extra가 필요합니다.
|
||||
|
||||
```bash
|
||||
pip install openai-agents[sqlalchemy]
|
||||
```
|
||||
|
||||
## 빠른 시작
|
||||
|
||||
### 데이터베이스 URL 사용
|
||||
|
||||
가장 간단하게 시작하는 방법입니다.
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
from agents import Agent, Runner
|
||||
from agents.extensions.memory import SQLAlchemySession
|
||||
|
||||
async def main():
|
||||
agent = Agent("Assistant")
|
||||
|
||||
# Create session using database URL
|
||||
session = SQLAlchemySession.from_url(
|
||||
"user-123",
|
||||
url="sqlite+aiosqlite:///:memory:",
|
||||
create_tables=True
|
||||
)
|
||||
|
||||
result = await Runner.run(agent, "Hello", session=session)
|
||||
print(result.final_output)
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
```
|
||||
|
||||
### 기존 엔진 사용
|
||||
|
||||
기존 SQLAlchemy 엔진이 있는 애플리케이션의 경우:
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
from agents import Agent, Runner
|
||||
from agents.extensions.memory import SQLAlchemySession
|
||||
from sqlalchemy.ext.asyncio import create_async_engine
|
||||
|
||||
async def main():
|
||||
# Create your database engine
|
||||
engine = create_async_engine("postgresql+asyncpg://user:pass@localhost/db")
|
||||
|
||||
agent = Agent("Assistant")
|
||||
session = SQLAlchemySession(
|
||||
"user-456",
|
||||
engine=engine,
|
||||
create_tables=True
|
||||
)
|
||||
|
||||
result = await Runner.run(agent, "Hello", session=session)
|
||||
print(result.final_output)
|
||||
|
||||
# Clean up
|
||||
await engine.dispose()
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
```
|
||||
|
||||
|
||||
## API 참조
|
||||
|
||||
- [`SQLAlchemySession`][agents.extensions.memory.sqlalchemy_session.SQLAlchemySession] - 주요 클래스
|
||||
- [`Session`][agents.memory.session.Session] - 기본 세션 프로토콜
|
||||
Reference in New Issue
Block a user