First commit.

This commit is contained in:
2025-11-18 11:02:39 +01:00
parent e57266f93d
commit d4c4ccfc18
16 changed files with 874 additions and 1 deletions

191
INNER_WORKING.md Normal file
View File

@@ -0,0 +1,191 @@
# Node.js Python Binding Class Documentation
## Overview
This project provides a Node.js interface (`python_bindings.js`) to interact with a Python backend. The Python backend exposes an API via a Controller class (`controller.py`) and communicates with Node.js via JSON messages over stdin/stdout using `python-shell` in Node.js.
The Node.js class `Bindings` wraps the interaction with the Python process and exposes asynchronous methods mapped dynamically to Python Controller methods. It supports property setting/getting, method calling with parameters, and streaming partial results via callbacks.
---
## Files and Components
### 1. `index.js`
- Entry point example illustrating usage of the `ChatModel` (the default export from `python_bindings.js`).
- Shows setting properties, calling methods, receiving streamed messages, and proper shutdown.
- This file is intended for customization by users for their use case.
Example usage:
```js
import ChatModel from "./python_bindings.js";
const chat = new ChatModel({ "model": "something" });
await chat.setProperty("tokenizer", 123);
const modelResponse = await chat.getModelPath();
console.log(modelResponse); // { model: "something" }
const tokenizerResponse = await chat.getTokenizer();
console.log(tokenizerResponse); // { tokenizer: 123 }
let response = await chat.increment({ by: 5 });
console.log("Incremented counter:", response.counter);
chat.onMessage(function(data) {
console.log(data); // receives streamed partial results
});
chat.testStream();
chat.end();
```
---
### 2. `python_bindings.js`
- Implements `Bindings` class which manages the Python subprocess using `python-shell`.
- Sends JSON-formatted method calls with parameters to Python.
- Receives JSON responses asynchronously.
- Supports streaming JSON messages prefixed with `__STREAM__`.
- Uses Proxy to dynamically route method calls to Python backend methods.
- Provides:
- `.setProperty(name, value)` to set Python controller properties.
- `.getProperty(name)` to get Python controller properties.
- `.onMessage(callback)` to register streaming data callback.
- `.end()` to gracefully end the Python subprocess.
Key methods:
- `callMethod(method, ...args)`: sends a method call to Python and returns a promise resolving to the response.
- `processSendQueue()`: ensures requests are sent sequentially.
- `onMessage(callback)`: sets a callback for streaming partial data.
---
### 3. `python/controller.py`
- Defines `Controller` class that inherits from `BaseController`.
- Implements backend logic called by Node.js methods.
- Example methods:
- `getModelPath(params)`
- `getTokenizer(params)`
- `increment(params)`
- `reset(params)`
- `testStream(params)` — emits streaming partial data via `self.send()`.
---
### 4. `python/basecontroller.py`
- Provides base class with common controller features:
- `setProperty(params)`: sets attributes dynamically on controller.
- `getProperty(params)`: gets attributes dynamically.
- `send(data)`: sends partial streaming data through injected stream function.
- `set_stream_func(stream_func)`: used to inject the stream callback for `send()`.
---
### 5. `python/router.py`
- Acts as the Python message router.
- Reads JSON messages from `stdin`, calls the appropriate `Controller` method, and writes JSON responses to `stdout`.
- Supports streaming partial responses with the `__STREAM__` prefix.
- Handles unknown methods gracefully by returning error JSON.
---
### 6. `python/index.py`
- Runs the `Router` instance when executed as a script.
- This is the Python entry point for the subprocess.
---
### 7. `router.js`
- Alternative Node.js approach (not used directly by `Bindings`).
- Spawns a Python process per method call.
- Supports streaming messages.
- More suited for stateless or separate process calls.
---
## How It Works (Workflow)
1. **Initialization**
- `Bindings` starts a persistent Python subprocess running `python/index.py` via `python-shell`.
- The Python process reads JSON messages from stdin and sends JSON responses on stdout.
2. **Method Calls**
- Node.js sends JSON messages with `{ method: "methodName", params: { ... } }`.
- Python calls the matching method in `Controller` class with params.
- Python sends back `{ result: ... }` or `{ error: ... }`.
3. **Streaming**
- Python can send partial results during long-running methods using the injected `send()` function.
- These partial messages are prefixed with `__STREAM__` so Node.js can route them to the streaming callback.
4. **Dynamic Proxy**
- The `Bindings` class uses a JavaScript Proxy to make any method call on the object automatically send the request to Python and return a Promise with the result.
5. **Property Setting/Getting**
- Properties like `model` and `tokenizer` can be set or fetched through dedicated calls or via `.setProperty()`.
6. **Shutdown**
- Calling `.end()` ends the Python process cleanly.
---
## Usage Summary
- Import `Bindings` or `ChatModel`.
- Instantiate with initial properties if desired.
- Call any controller method asynchronously on the instance.
- Use `.onMessage()` to handle streamed data.
- Call `.end()` to terminate the backend.
---
## Notes for Customization
- Edit `controller.py` to add your own Python logic and methods.
- Update `index.js` for your application-specific flow.
- Ensure Python methods return JSON serializable objects.
- Implement streaming with `send()` and handle it in Node.js via `.onMessage()`.
---
## Example
```js
import ChatModel from "./python_bindings.js";
const chat = new ChatModel({ model: "gpt" });
await chat.setProperty("tokenizer", 42);
const info = await chat.getModelPath();
console.log(info); // { model: "gpt" }
chat.onMessage(data => {
console.log("Streamed partial data:", data);
});
await chat.testStream();
await chat.end();
```
---
This documentation provides a comprehensive understanding of the binding class design and usage to integrate Python backend logic into a Node.js environment efficiently.