목차
1. File Search 기능 개요
2. 기본 준비: 파일 업로드 함수 만들기
3. 파일 객체 생성과 file_id 이해하기
4. Vector Store 생성하기
5. Vector Store에 파일 연결하기
6. File Search로 문서 기반 질문하기
7. 응답 확인과 response.output_text
8. 종합 코드 예제
1. File Search 기능 개요
File Search 도구는 사용자가 업로드한 문서를 모델이 검색해서 답변에 활용할 수 있게 해주는 기능이다.
그 과정은 다음과 같다.
File 객체 생성(업로드) → 벡터 스토어 생성 → 파일을 벡터 스토어에 연결
File Search는 단순히 파일을 첨부하는 기능이 아니라, 먼저 파일을 OpenAI 서버에 업로드하여 file_id를 생성하고, 이후 벡터 스토어(Vector Store)를 생성한 뒤 해당 파일을 저장소에 연결하여 검색 가능 상태로 만드는 구조로 동작한다.
특히 벡터 스토어에 파일을 추가하는 과정은 새로운 업로드가 아니라, 이미 업로드된 파일을 file_id를 통해 연결하는 과정이라는 점이 중요하다.
이 구조를 이해하면 Web Search와 File Search의 차이도 명확해진다.
Web Search가 외부 웹 정보를 찾는 기능이라면, File Search는 내가 업로드한 문서 내부에서 필요한 정보를 검색하는 기능이라고 보면 된다.
2. 기본 준비: 파일 업로드 함수 만들기
File Search를 사용하기 위해서는 먼저 문서를 OpenAI 서버에 업로드해야 한다.
아래 함수는 입력된 경로가 URL인지 로컬 파일인지 구분하여 파일을 업로드하는 역할을 한다.
import requests
from io import BytesIO
def create_file(client, file_path):
# URL 파일 처리
if file_path.startswith("http://") or file_path.startswith("https://"):
response = requests.get(file_path)
file_content = BytesIO(response.content)
file_name = file_path.split("/")[-1]
file_tuple = (file_name, file_content)
result = client.files.create(
file=file_tuple,
purpose="assistants"
)
# 로컬 파일 처리
else:
with open(file_path, "rb") as file_content:
result = client.files.create(
file=file_content,
purpose="assistants"
)
print(result.id)
return result.id
이 함수의 핵심은 입력값이 URL인지 로컬 경로인지 구분해서 파일을 업로드한다는 점이다.
URL이면 먼저 requests.get()으로 파일 내용을 받아오고, 로컬 경로면 open(..., "rb")로 바이너리 모드에서 파일을 읽는다.
이후 client.files.create()로 파일 객체를 만들고, 그 결과로 반환된 id를 저장한다. 이 file_id가 나중에 벡터 스토어에 파일을 연결할 때 사용된다. OpenAI 문서에서도 벡터 스토어 파일 생성은 기존 File 객체를 벡터 스토어에 붙이는 방식으로 설명한다.
| requests.get() | URL에 있는 파일 다운로드 |
| BytesIO | 메모리 안에서 파일처럼 다루기 위한 객체 |
| open(..., "rb") | 로컬 파일을 바이너리 모드로 읽기 |
| client.files.create() | OpenAI에 파일 업로드 |
| result.id | 업로드된 파일의 고유 ID |
3. 파일 객체 생성과 file_id 이해하기
다음 코드는 앞에서 만든 create_file() 함수를 사용하여 실제 파일을 업로드하는 부분이다.
file_id = create_file(client, './howto-sockets.pdf')
file_id는 단순한 문자열이 아니라, OpenAI 서버에 업로드된 파일을 식별하는 고유 값이다.
이 값은 이후 벡터 스토어에 파일을 연결할 때 반드시 필요하며, File Search 기능 전반에서 핵심적인 참조 기준으로 사용된다.
File Search에서는 파일 자체를 직접 전달하지 않는다.
대신, 한 번 업로드된 파일을 file_id를 통해 참조하는 방식으로 동작한다.
즉, 파일의 실제 내용은 서버에 저장되고, 이후 모든 작업은 file_id를 기준으로 이루어진다.
따라서 파일을 반복해서 전달하는 구조가 아니라, file_id를 통해 동일한 파일을 재사용하는 구조라고 이해할 수 있다.
4. Vector Store 생성하기
다음 단계는 파일을 검색 가능한 지식 저장소에 넣기 위한 벡터 스토어(Vector Store)를 생성하는 것이다.
vector_store = client.vector_stores.create(
name="know_base"
)
| client.vector_stores.create() | 벡터 스토어 생성 |
| name | 저장소 이름 |
| vector_store.id | 생성된 저장소의 고유 ID |
벡터 스토어는 쉽게 말해 문서 검색을 위한 저장소이다.
File Search는 개별 파일 하나를 직접 검색하는 방식이 아니라, 여러 파일을 벡터 스토어에 모아두고 해당 저장소를 대상으로 검색을 수행하는 구조로 동작한다.
File Search에서 모델은 단일 파일이 아니라, 벡터 스토어 단위로 문서를 검색한다.
따라서 벡터 스토어는 단순 저장 공간이 아니라, 검색을 수행하기 위한 기준 단위 역할을 한다.
5. Vector Store에 파일 연결하기
벡터 스토어를 생성했다면, 이제 업로드한 파일을 해당 저장소에 연결해야 한다.
client.vector_stores.files.create(
vector_store_id=vector_store.id,
file_id=file_id
)
이 코드는 업로드된 파일을 특정 벡터 스토어에 연결하는 역할을 한다.
여기서 중요한 점은 다음 두 값을 함께 전달한다는 것이다.
- vector_store_id → 어떤 저장소에 넣을 것인지
- file_id → 어떤 파일을 연결할 것인지
즉, 이미 업로드된 파일을 선택하여 특정 저장소에 포함시키는 과정이라고 이해할 수 있다.
이 단계는 파일을 새로 업로드하는 과정이 아니라, 이미 업로드된 파일을 벡터 스토어에 연결하는 과정이다.
따라서 File Search의 흐름은 다음과 같이 구분할 수 있다.
- 파일 업로드 → file_id 생성
- 벡터 스토어 생성
- 파일 연결 → 검색 가능 상태로 전환
벡터 스토어에 연결된 파일은 처리 상태를 가지며, 일반적으로 다음과 같이 구분된다.
- in_progress → 처리 중
- completed → 검색 가능 상태
- failed → 처리 실패
특히 completed 상태가 되어야 File Search에서 정상적으로 검색할 수 있다.
따라서 실제 서비스에서는 파일을 연결한 직후 바로 질문하기보다는, 파일 상태가 completed인지 확인하는 과정을 추가하는 것이 안정적이다.
file_list = client.vector_stores.files.list(
vector_store_id=vector_store.id
)
print(file_list)
6. File Search로 문서 기반 질문하기
이제 실제로 모델에게 문서 내용을 바탕으로 질문할 수 있다.
question = '파이썬 코드로 소켓을 만드는 방법을 간단하게 설명해줘'
response = client.responses.create(
model='gpt-5.2',
input=question,
tools=[
{
'type': 'file_search',
'vector_store_ids': [vector_store.id]
}
]
)
여기서 핵심은 tools 안의 이 부분이다.
{
'type': 'file_search',
'vector_store_ids': [vector_store.id]
}
- 외부 웹이 아닌 지정된 벡터 스토어 내부 문서를 먼저 검색한 뒤 그 결과를 기반으로 답변을 생성하라
즉, File Search의 핵심은 다음 두 가지이다.
- type: "file_search" → 파일 검색 기능 활성화
- vector_store_ids → 어떤 저장소를 검색할지 지정
| client.responses.create() | 모델에게 질문 요청 |
| model | 사용할 모델 |
| input | 사용자 질문 |
| tools | 모델이 사용할 도구 목록 |
| type: "file_search" | 파일 검색 기능 활성화 |
| vector_store_ids | 검색 대상 벡터 스토어 지정 |
7. 응답 확인과 response.output_text
최종 결과는 아래처럼 확인할 수 있다.
print(response.output_text)
응답 객체 전체를 확인하고 싶다면 다음과 같이 사용할 수 있다.
print(dict(response))
이 코드를 통해 다음과 같은 정보를 확인할 수 있다.
- 어떤 도구(file_search)가 사용되었는지
- 내부 응답 구조
- 추가 메타데이터
1. 파일 처리 상태 확인
벡터 스토어에 연결된 파일은 다음과 같은 상태를 가진다.
- in_progress → 처리 중
- completed → 검색 가능
- failed → 처리 실패
파일이 completed 상태가 되기 전에 검색을 수행하면 정상적인 결과가 나오지 않을 수 있다.
따라서 실제 서비스에서는 파일 상태를 확인한 뒤 검색을 수행하는 흐름이 필요하다.
2. 여러 파일 처리 (배치)
여러 개의 파일을 처리하는 경우, 배치(batch) 방식으로 업로드 및 상태 관리를 수행할 수 있다.
이를 통해 여러 파일의 처리 상태를 한 번에 확인할 수 있으며, 대규모 문서 처리에 유리하다.
3. 검색 결과 제어
File Search는 다음과 같은 옵션을 통해 검색 결과를 조정할 수 있다.
- max_num_results → 검색 결과 개수 제한
- ranking_options → 결과 정렬 방식
- score_threshold → 최소 유사도 기준
이를 활용하면 보다 정확한 검색 결과를 얻을 수 있다.
8. 종합 코드 예제
아래는 전체 흐름을 정리한 코드이다.
response.output_text는 File Search를 통해 문서를 검색한 뒤 생성된 최종 답변이며, 실제 서비스에서는 파일 상태 확인과 검색 옵션 설정을 함께 고려하는 것이 중요하다.
from dotenv import load_dotenv
import os
import requests
from io import BytesIO
from openai import OpenAI
# 환경 설정
load_dotenv()
client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
# 파일 업로드 함수
def create_file(client, file_path):
if file_path.startswith("http://") or file_path.startswith("https://"):
response = requests.get(file_path)
file_content = BytesIO(response.content)
file_name = file_path.split("/")[-1]
file_tuple = (file_name, file_content)
result = client.files.create(
file=file_tuple,
purpose="assistants"
)
else:
with open(file_path, "rb") as file_content:
result = client.files.create(
file=file_content,
purpose="assistants"
)
return result.id
# 파일 업로드
file_id = create_file(client, "./howto-sockets.pdf")
# 벡터 스토어 생성
vector_store = client.vector_stores.create(
name="know_base"
)
# 파일 연결
client.vector_stores.files.create(
vector_store_id=vector_store.id,
file_id=file_id
)
# 질문
question = "파이썬 코드로 소켓을 만드는 방법을 간단하게 설명해줘"
# File Search 실행
response = client.responses.create(
model="gpt-5.2",
input=question,
tools=[
{
"type": "file_search",
"vector_store_ids": [vector_store.id]
}
]
)
# 결과 출력
print(response.output_text)
'머신러닝&딥러닝' 카테고리의 다른 글
| OpenAI Web Search 완전 정리 (코드 + 구조 + 실전 활용) (0) | 2026.03.24 |
|---|---|
| Function Calling 완전 정리 – GPT를 API·DB와 연결하는 방법 (1) | 2026.03.24 |
| OpenAI API 사용법 정리 (Responses API, Chat Completions 차이, 요청 구조) (0) | 2026.03.23 |
| 머신러닝 & 딥러닝 기초 33편 | 모델 저장과 로드 (joblib, pickle, Keras) (0) | 2026.03.21 |
| 머신러닝 & 딥러닝 기초 32편 | 딥러닝 - CNN, RNN, Transformer (0) | 2026.03.20 |