Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ jobs:
os: [ubuntu-latest, macos-latest, windows-latest]
python-version: ["3.10", "3.11", "3.12", "3.13"]
runs-on: ${{ matrix.os }}
env:
OPENAI_API_KEY: dummy_value_for_tests # Dummy value
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ wheels/

# Development files
.coverage
.coverage.*
.env
*.pdf

Expand Down
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/)

## [0.6.0]
### Added
- Commands for `assistants list` and `assistants clean`
- Added CLI commands for `assistants list` and `assistants clean`
- Automatic cleanup of any extra assistants in user account when initiating chat
- Added docstrings for undocumented functions
- Test case coverage for most OpenAI chat and vector store operations [#15](https://github.com/jbencina/vecsync/issues/15)

### Changed
- Updated CLI chat command to `vs chat`
Expand Down
16 changes: 10 additions & 6 deletions src/vecsync/chat/clients/openai.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ def on_message_delta(self, delta, snapshot):
def on_message_done(self, message):
# Append citations at the end of the response
text = self.formatter.get_references(self.annotations, self.files)
self.queue.put(text)
if len(text) > 0:
self.queue.put(text)
self.active = False

def consume_queue(self, timeout: float = 1.0):
Expand Down Expand Up @@ -102,14 +103,17 @@ class OpenAIClient:
store_name : str
The name of the vector store to use for this client. The named assistant will
be created in the form of "vecsync-{store_name}".

settings_path : str | None
The path to the settings file. If None, the default settings file will be used.
This is used to store the thread ID for the current conversation.
"""

def __init__(self, store_name: str):
def __init__(self, store_name: str, settings_path: str | None = None):
self.client = OpenAI()
self.store_name = store_name
self.assistant_name = f"vecsync-{store_name}"
self.connected = False
self.settings_path = settings_path

def connect(self):
"""Connect to the OpenAI API and load the assistant and thread.
Expand Down Expand Up @@ -156,7 +160,7 @@ def _get_thread_id(self) -> str:
str
The thread ID for the current conversation.
"""
settings = Settings()
settings = Settings(path=self.settings_path)

# TODO: Ideally we would grab the thread ID from OpenAI but there doesn't seem to be
# a way to do that. So we are storing it in the settings file for now.
Expand Down Expand Up @@ -232,7 +236,7 @@ def _create_assistant(self) -> str:
model="gpt-4o-mini",
)

settings = Settings()
settings = Settings(path=self.settings_path)
del settings["openai_thread_id"]

print(f"🖥️ Assistant created: {assistant.name}")
Expand All @@ -253,7 +257,7 @@ def _create_thread(self) -> str:

thread = self.client.beta.threads.create()
print(f"💬 Conversation started: {thread.id}")
settings = Settings()
settings = Settings(path=self.settings_path)
settings["openai_thread_id"] = thread.id
return thread.id

Expand Down
2 changes: 1 addition & 1 deletion src/vecsync/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ def sync(source: str):
f"Saved: {result.files_saved} | Deleted: {result.files_deleted} | Skipped: {result.files_skipped} ",
"yellow",
)
cprint(f"Remote count: {result.updated_count}", "yellow")
cprint(f"Remote count: {result.remote_count}", "yellow")
cprint(f"Duration: {result.duration:.2f} seconds", "yellow")


Expand Down
2 changes: 1 addition & 1 deletion src/vecsync/cli/sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,5 @@ def sync(source: str):
f"Saved: {result.files_saved} | Deleted: {result.files_deleted} | Skipped: {result.files_skipped} ",
"yellow",
)
cprint(f"Remote count: {result.updated_count}", "yellow")
cprint(f"Remote count: {result.remote_count}", "yellow")
cprint(f"Duration: {result.duration:.2f} seconds", "yellow")
2 changes: 1 addition & 1 deletion src/vecsync/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class SettingData(BaseModel):


class Settings:
def __init__(self, path: str | None = None):
def __init__(self, path: Path | None = None):
self.file = path or Path(user_config_dir("vecsync")) / "settings.json"

if not self.file.exists():
Expand Down
9 changes: 5 additions & 4 deletions src/vecsync/store/openai.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class SyncOperationResult(BaseModel):
files_saved: int
files_deleted: int
files_skipped: int
updated_count: int
remote_count: int
duration: float


Expand Down Expand Up @@ -88,8 +88,9 @@ def _delete_files(self, files_to_remove: list[str]) -> set[str]:
removed_file_ids = []
for file_id in tqdm(files_to_remove):
self.client.vector_stores.files.delete(vector_store_id=self.store.id, file_id=file_id)
self.client.files.delete(file_id=file_id)
removed_file_ids.append(file_id)
result = self.client.files.delete(file_id=file_id)
if result.deleted:
removed_file_ids.append(file_id)

return set(removed_file_ids)

Expand Down Expand Up @@ -147,6 +148,6 @@ def sync(self, files: list[Path]):
files_saved=len(files_to_upload),
files_deleted=len(files_to_remove),
files_skipped=len(duplicate_file_names),
updated_count=len(existing_vector_file_ids | files_to_attach),
remote_count=len(existing_vector_file_ids | files_to_attach),
duration=duration,
)
Loading