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
22 changes: 22 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,28 @@ All notable changes to `chemflow-client` will be documented in this file.

## Unreleased

## 0.1.5

- Changed `chat3d(...)` to require `prompt` as a keyword argument and make `atoms` optional, so generation calls can use `chat3d(prompt="generate methane")`.
- Simplified the README examples for `chat3d(...)` and documented the public call signatures in a dedicated section.

## 0.1.4

- Fixed the README notebook widget image for PyPI by switching from a GitHub `blob` page URL to the raw GIF URL pinned to the release tag.

## 0.1.3

- Updated the README notebook widget image to use the GitHub-hosted URL so the animation renders correctly on PyPI.
- Simplified the notebook widget assistant placeholder text from `Thinking harder...` to `Thinking...`.

## 0.1.2

- Published the client and widget improvements that were previously tagged but not released to PyPI because of a package-version mismatch.
- Improved `ChemFlow3DClient` request preparation and response application so notebook background chats can reuse the same state transitions safely.
- Improved `Chat3DWidget` background chat handling to stay responsive and avoid applying results after the widget is closed.
- Improved ASE payload conversion for generated or empty structures so optional arrays, cell data, and periodic boundary flags are preserved more consistently.
- Expanded the public README examples for structure generation workflows and notebook usage.

## 0.1.0

- Initial public release.
Expand Down
52 changes: 43 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,11 @@ from chemflow_client import chat3d

atoms = molecule("H2O")
updated_atoms, text = chat3d(
atoms,
"change the H-O-H angle to 110 degrees",
)

generated_atoms, text = chat3d(
atoms=None,
prompt="generate methane",
prompt="change the H-O-H angle to 110 degrees",
atoms=atoms,
)
# or generate one directly.
generated_atoms, text = chat3d(prompt="generate methane")
```

## JupyterLab
Expand All @@ -57,7 +54,7 @@ widget
widget.get_atoms()
```

![JupyterLab widget demo](docs/assets/chemflow-widget-demo.gif)
![JupyterLab widget demo](https://raw.githubusercontent.com/SingletC/chemflow-client/v0.1.5/docs/assets/chemflow-widget-demo.gif)


## Configure
Expand All @@ -76,10 +73,47 @@ You can also pass configuration as arguments to `chat3d(...)` or `Chat3DWidget(.
from chemflow_client import Chat3DWidget, chat3d

updated_atoms, text = chat3d(
atoms=None,
prompt="generate methane",
api_key="cfsk_xxx",
)

widget = Chat3DWidget(api_key="cfsk_xxx")
```

## Call Signatures

### `chat3d(...)`

```python
chat3d(
*,
prompt: str,
atoms: Optional[Atoms] = None,
base_url: Optional[str] = None,
api_key: Optional[str] = None,
model: Optional[str] = None,
timeout: float = 300.0,
) -> Tuple[Atoms, str]
```

- `prompt`: Required keyword-only editing or generation instruction.
- `atoms`: Optional initial `ase.Atoms` structure.
- `base_url`, `api_key`, `model`, `timeout`: Optional client configuration overrides.
- Returns `(atoms, text)`.

### `Chat3DWidget(...)`

```python
Chat3DWidget(
atoms: Optional[Atoms] = None,
*,
base_url: Optional[str] = None,
api_key: Optional[str] = None,
model: Optional[str] = None,
timeout: float = 300.0,
)
```

- `atoms`: Optional initial `ase.Atoms` structure.
- `base_url`, `api_key`, `model`, `timeout`: Optional client configuration overrides.
- Returns a notebook widget instance backed by `ChemFlow3DClient`.
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "chemflow-client"
version = "0.1.0"
version = "0.1.5"
description = "Public Python client for ChemFlow 3D chat editing"
readme = "README.md"
requires-python = ">=3.9"
Expand Down
2 changes: 1 addition & 1 deletion src/chemflow_client/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def __init__(
transport=transport,
headers={
"X-ChemFlow-Api-Key": resolved_api_key,
"User-Agent": "chemflow-client/0.1.0",
"User-Agent": "chemflow-client/0.1.5",
"Accept": "application/json",
},
)
Expand Down
4 changes: 2 additions & 2 deletions src/chemflow_client/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,9 +122,9 @@ def __exit__(self, exc_type, exc, tb) -> None:


def chat3d(
atoms: Optional[Atoms],
prompt: str,
*,
prompt: str,
atoms: Optional[Atoms] = None,
base_url: Optional[str] = None,
api_key: Optional[str] = None,
model: Optional[str] = None,
Expand Down
2 changes: 1 addition & 1 deletion src/chemflow_client/widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ def _format_widget_error_message(error: Union[Exception, str]) -> str:

_WIDGET_ESM = r'''
const THREE_DMOL_URL = "https://cdn.jsdelivr.net/npm/3dmol@2.4.2/build/3Dmol-min.js";
const THINKING_PLACEHOLDER = "Thinking harder...";
const THINKING_PLACEHOLDER = "Thinking...";

async function ensure3Dmol() {
if (window.$3Dmol) {
Expand Down
11 changes: 5 additions & 6 deletions tests/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ def fake_chat3d(self, request):

atoms = Atoms(symbols=["H", "H"], positions=[[0.0, 0.0, 0.0], [0.0, 0.0, 0.74]])
updated_atoms, text = chat3d(
atoms,
"stretch the bond",
prompt="stretch the bond",
atoms=atoms,
base_url="http://localhost:8000",
api_key="cfsk_test_key",
)
Expand Down Expand Up @@ -68,8 +68,7 @@ def fake_chat3d(self, request):
monkeypatch.setattr("chemflow_client.api.ChemFlowApi.chat3d", fake_chat3d)

updated_atoms, text = chat3d(
None,
"generate methane",
prompt="generate methane",
api_key="cfsk_test_key",
)

Expand Down Expand Up @@ -217,8 +216,8 @@ def fake_chat3d(self, request):
monkeypatch.setattr("chemflow_client.api.ChemFlowApi.chat3d", fake_chat3d)

atoms, text = chat3d(
Atoms(symbols=["He"], positions=[[0.0, 0.0, 0.0]]),
"leave it as is",
prompt="leave it as is",
atoms=Atoms(symbols=["He"], positions=[[0.0, 0.0, 0.0]]),
)

assert atoms.get_chemical_symbols() == ["He"]
Expand Down
2 changes: 1 addition & 1 deletion tests/test_widget_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def test_format_widget_error_message_prefers_structured_message():


def test_widget_esm_uses_chat_thinking_placeholder_instead_of_waiting_banner():
assert "Thinking harder..." in _WIDGET_ESM
assert "Thinking..." in _WIDGET_ESM
assert "Waiting for ChemFlow response:" not in _WIDGET_ESM


Expand Down
Loading