1
import path from 'path';
4
import logger from '../logger';
5
import { getCache, isCacheEnabled } from '../cache';
6
import { runPython } from '../python/wrapper';
7
import { sha256 } from '../util';
16
interface PythonProviderConfig {
17
pythonExecutable?: string;
20
export class PythonProvider implements ApiProvider {
21
private config: PythonProviderConfig;
23
constructor(private scriptPath: string, private options?: ProviderOptions) {
24
this.id = () => options?.id ?? `python:${this.scriptPath}`;
25
this.config = options?.config ?? {};
29
return `python:${this.scriptPath}`;
32
async callApi(prompt: string, context?: CallApiContextParams): Promise<ProviderResponse> {
33
const absPath = path.resolve(path.join(this.options?.config.basePath || '', this.scriptPath));
34
logger.debug(`Computing file hash for script ${absPath}`);
35
const fileHash = sha256(fs.readFileSync(absPath, 'utf-8'));
36
const cacheKey = `python:${this.scriptPath}:${fileHash}:${prompt}:${JSON.stringify(
39
const cache = await getCache();
42
if (isCacheEnabled()) {
43
cachedResult = (await cache.get(cacheKey)) as string;
47
logger.debug(`Returning cached result for script ${absPath}`);
48
return JSON.parse(cachedResult);
50
const args = [prompt, this.options, context];
52
`Running python script ${absPath} with scriptPath ${this.scriptPath} and args: ${args.join(
56
const result = (await runPython(absPath, 'call_api', args, {
57
pythonExecutable: this.config.pythonExecutable,
62
if (!('output' in result) && !('error' in result)) {
64
'The Python script `call_api` function must return a dict with an `output` or `error` string',
67
if (isCacheEnabled()) {
68
await cache.set(cacheKey, JSON.stringify(result));