First commit.
This commit is contained in:
191
INNER_WORKING.md
Normal file
191
INNER_WORKING.md
Normal 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.
|
||||
Reference in New Issue
Block a user