English | 한국어
LinkLog
Flutter + Supabase 기반 사용자 정의 RAG 빌더
나만의 지식 베이스를 구축하고, AI에게 질문하세요.
Screenshots
아키텍처
LinkLog는 레이어 분리 및 유지보수성을 극대화한 Flutter 안티 그래비티 아키텍처를 기반으로 설계되었습니다.
┌─────────────────────────────────────────────────────────────┐
│ Presentation Layer │
│ (Riverpod ViewModels & Screen Widgets) │
└──────────────────────────────┬──────────────────────────────┘
▼
┌─────────────────────────────────────────────────────────────┐
│ Domain Layer │
│ (Pure Dart Entities & Usecase Logic) │
└──────────────────────────────┬──────────────────────────────┘
▼
┌─────────────────────────────────────────────────────────────┐
│ Data Layer │
│ (Supabase DTOs & Repository Implementations) │
└──────────────────────────────┴─────────────────────────────┘
주요 기능
| 기능 | 설명 |
|---|---|
| API 설정 | Supabase URL/Key, OpenAI Key를 flutter_secure_storage로 안전하게 저장 |
| 문서 업로드 | 텍스트 입력 → text-embedding-3-small 벡터화 → Supabase 저장 |
| RAG 채팅 | 질문 벡터화 → cosine similarity 검색 → GPT-4o-mini 답변 생성 |
| 문서 관리 | 등록된 문서 목록 조회 및 삭제 |
시작하기
1. Supabase 설정
Supabase 프로젝트를 생성한 뒤, SQL Editor에서 아래 스크립트를 실행하세요:
-- pgvector 확장 활성화
create extension if not exists vector with schema extensions;
-- documents 테이블 생성
create table if not exists public.documents (
id bigserial primary key,
content text not null,
metadata text,
embedding vector(1536),
created_at timestamptz default now()
);
-- 검색 성능 인덱스
create index if not exists documents_embedding_idx
on public.documents
using ivfflat (embedding vector_cosine_ops)
with (lists = 100);
-- 유사도 검색 함수
create or replace function public.match_documents(
query_embedding vector(1536),
match_count int default 5,
match_threshold float default 0.7
)
returns table (
id bigint,
content text,
metadata text,
similarity float
)
language plpgsql
as $$
begin
return query
select
d.id, d.content, d.metadata,
1 - (d.embedding <=> query_embedding) as similarity
from public.documents d
where 1 - (d.embedding <=> query_embedding) > match_threshold
order by d.embedding <=> query_embedding
limit match_count;
end;
$$;
-- RLS 정책
alter table public.documents enable row level security;
create policy "Allow public read" on public.documents for select using (true);
create policy "Allow public insert" on public.documents for insert with check (true);
create policy "Allow public delete" on public.documents for delete using (true);
전체 SQL 파일:
supabase_setup.sql
2. 앱 실행
git clone https://github.com/kimdzhekhon/Link_log.git
cd Link_log
flutter pub get
flutter run
3. 앱 설정
- 설정 탭에서 Supabase URL, Anon Key, OpenAI API Key 입력
- 문서 탭에서 지식 베이스용 텍스트 추가
- 채팅 탭에서 질문 입력 → AI 답변 확인
기술 스택
| 구분 | 기술 |
|---|---|
| Frontend | Flutter, Material 3 |
| 상태 관리 | flutter_riverpod |
| 보안 저장소 | flutter_secure_storage |
| Database | Supabase (PostgreSQL + pgvector) |
| AI | OpenAI text-embedding-3-small, GPT-4o-mini |
| 통신 | http (REST API) |
프로젝트 구조
lib/
├── main.dart # 앱 진입점, 네비게이션
├── providers/
│ └── providers.dart # Riverpod 상태 관리
├── services/
│ ├── secure_storage_service.dart # API 키 암호화 저장
│ ├── supabase_service.dart # Supabase CRUD & RPC
│ └── openai_service.dart # 임베딩 & Chat Completion
└── views/
├── settings_view.dart # API 설정 UI
├── document_view.dart # 문서 업로드/관리 UI
└── chat_view.dart # RAG 채팅 UI
라이선스
MIT License