navada-edge-cli 3.5.6 → 3.5.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/agent.js +44 -15
- package/lib/knowledge.py +197 -0
- package/package.json +1 -1
package/lib/agent.js
CHANGED
|
@@ -14,6 +14,19 @@ const config = require('./config');
|
|
|
14
14
|
// NAVADA Edge Agent — personality + tools + routing
|
|
15
15
|
// ---------------------------------------------------------------------------
|
|
16
16
|
|
|
17
|
+
// Strip markdown formatting for clean terminal output
|
|
18
|
+
function cleanOutput(text) {
|
|
19
|
+
if (typeof text !== 'string') return text;
|
|
20
|
+
return text
|
|
21
|
+
.replace(/\*\*(.+?)\*\*/g, '$1') // **bold** → plain
|
|
22
|
+
.replace(/\*(.+?)\*/g, '$1') // *italic* → plain
|
|
23
|
+
.replace(/__(.+?)__/g, '$1') // __underline__ → plain
|
|
24
|
+
.replace(/^#{1,6}\s+/gm, '') // ### headers → plain
|
|
25
|
+
.replace(/---+/g, '') // horizontal rules → remove
|
|
26
|
+
.replace(/\s--\s/g, ' ') // spaced -- → space
|
|
27
|
+
.replace(/--/g, ', '); // remaining -- → comma
|
|
28
|
+
}
|
|
29
|
+
|
|
17
30
|
const IDENTITY = {
|
|
18
31
|
name: 'NAVADA Edge',
|
|
19
32
|
role: 'AI Infrastructure Agent',
|
|
@@ -30,12 +43,13 @@ You also connect to the NAVADA Edge Network (4 nodes via Tailscale VPN):
|
|
|
30
43
|
- mcp_call: access 18 MCP tools on the ASUS server
|
|
31
44
|
- docker_registry: manage the private Docker registry
|
|
32
45
|
- send_email / generate_image: communications and AI image generation
|
|
33
|
-
- founder_info:
|
|
46
|
+
- founder_info: ALWAYS use this tool when asked about Lee Akpareva, his career, education, projects, or NAVADA's founder. It has his full CV. Never guess about Lee, always call this tool.
|
|
34
47
|
When users ask you to DO something — DO IT. Use write_file to create files. Use shell to run commands. Never say "I can't" when you have a tool for it.
|
|
35
48
|
When asked to generate diagrams — use write_file to create Mermaid (.mmd), SVG, or HTML files. You can also use python_exec with matplotlib/graphviz for complex diagrams.
|
|
36
49
|
When asked to create, edit, or delete files — use the file tools directly. You are a terminal agent with FULL access.
|
|
37
50
|
PLATFORM: This machine runs ` + (process.platform === 'win32' ? `Windows. Use Windows paths. Desktop = ${fs.existsSync(path.join(os.homedir(), 'OneDrive', 'Desktop')) ? path.join(os.homedir(), 'OneDrive', 'Desktop') : path.join(os.homedir(), 'Desktop')}. Home = ${os.homedir()}.` : `${process.platform}. Home = ${os.homedir()}.`) + `
|
|
38
|
-
Keep responses short. Code blocks when needed. No fluff
|
|
51
|
+
Keep responses short. Code blocks when needed. No fluff.
|
|
52
|
+
FORMATTING: Never use markdown formatting like **bold**, *italic*, ### headers, or -- dashes. Write plain text only. This is a terminal, not a web page.`,
|
|
39
53
|
founder: {
|
|
40
54
|
name: 'Leslie (Lee) Akpareva',
|
|
41
55
|
title: 'Principal AI Consultant & Founder, NAVADA Edge Network',
|
|
@@ -328,8 +342,21 @@ const localTools = {
|
|
|
328
342
|
},
|
|
329
343
|
|
|
330
344
|
founderInfo: {
|
|
331
|
-
description: '
|
|
332
|
-
execute: () =>
|
|
345
|
+
description: 'Answer questions about Lee Akpareva, founder of NAVADA Edge, using his full CV and career history',
|
|
346
|
+
execute: (question) => {
|
|
347
|
+
try {
|
|
348
|
+
const knowledgePath = path.join(__dirname, 'knowledge.py');
|
|
349
|
+
const py = process.platform === 'win32' ? 'python' : 'python3';
|
|
350
|
+
const openaiKey = config.get('openaiKey') || process.env.OPENAI_API_KEY || '';
|
|
351
|
+
const output = execFileSync(py, [knowledgePath, question || 'Who is Lee Akpareva?'], {
|
|
352
|
+
timeout: 30000, encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'],
|
|
353
|
+
env: { ...process.env, OPENAI_API_KEY: openaiKey },
|
|
354
|
+
});
|
|
355
|
+
return output.trim();
|
|
356
|
+
} catch (e) {
|
|
357
|
+
return `Error: ${e.stderr?.trim() || e.message}`;
|
|
358
|
+
}
|
|
359
|
+
},
|
|
333
360
|
},
|
|
334
361
|
};
|
|
335
362
|
|
|
@@ -443,7 +470,7 @@ function streamFreeTier(endpoint, messages) {
|
|
|
443
470
|
const delta = parsed.choices?.[0]?.delta;
|
|
444
471
|
// Grok-3-mini streams reasoning_content first, then content — skip reasoning
|
|
445
472
|
if (delta?.reasoning_content && !delta?.content) continue;
|
|
446
|
-
const text = delta?.content || '';
|
|
473
|
+
const text = cleanOutput(delta?.content || '');
|
|
447
474
|
if (text) {
|
|
448
475
|
process.stdout.write(text);
|
|
449
476
|
fullContent += text;
|
|
@@ -523,8 +550,9 @@ function streamAnthropic(key, messages, tools, system) {
|
|
|
523
550
|
|
|
524
551
|
case 'content_block_delta':
|
|
525
552
|
if (event.delta?.type === 'text_delta') {
|
|
526
|
-
|
|
527
|
-
|
|
553
|
+
const clean = cleanOutput(event.delta.text);
|
|
554
|
+
process.stdout.write(clean);
|
|
555
|
+
currentText += clean;
|
|
528
556
|
} else if (event.delta?.type === 'input_json_delta') {
|
|
529
557
|
const last = contentBlocks[contentBlocks.length - 1];
|
|
530
558
|
if (last?.type === 'tool_use') last.input += event.delta.partial_json;
|
|
@@ -616,8 +644,9 @@ function streamOpenAI(key, messages, model = 'gpt-4o') {
|
|
|
616
644
|
if (finish) finishReason = finish;
|
|
617
645
|
|
|
618
646
|
if (delta?.content) {
|
|
619
|
-
|
|
620
|
-
|
|
647
|
+
const clean = cleanOutput(delta.content);
|
|
648
|
+
process.stdout.write(clean);
|
|
649
|
+
fullContent += clean;
|
|
621
650
|
}
|
|
622
651
|
|
|
623
652
|
// Accumulate tool calls
|
|
@@ -696,7 +725,7 @@ function streamGemini(key, messages, model = 'gemini-2.0-flash') {
|
|
|
696
725
|
if (!data) continue;
|
|
697
726
|
try {
|
|
698
727
|
const parsed = JSON.parse(data);
|
|
699
|
-
const text = parsed.candidates?.[0]?.content?.parts?.[0]?.text || '';
|
|
728
|
+
const text = cleanOutput(parsed.candidates?.[0]?.content?.parts?.[0]?.text || '');
|
|
700
729
|
if (text) {
|
|
701
730
|
process.stdout.write(text);
|
|
702
731
|
fullContent += text;
|
|
@@ -732,7 +761,7 @@ function openAITools() {
|
|
|
732
761
|
{ name: 'python_pip', description: 'Install a Python package via pip.', parameters: { type: 'object', properties: { package: { type: 'string', description: 'Package name' } }, required: ['package'] } },
|
|
733
762
|
{ name: 'python_script', description: 'Run a Python script file.', parameters: { type: 'object', properties: { path: { type: 'string', description: 'Path to .py file' } }, required: ['path'] } },
|
|
734
763
|
{ name: 'sandbox_run', description: 'Run code in an isolated sandbox with syntax highlighting. Supports javascript, python, typescript.', parameters: { type: 'object', properties: { code: { type: 'string' }, language: { type: 'string', description: 'javascript, python, or typescript' } }, required: ['code'] } },
|
|
735
|
-
{ name: 'founder_info', description: '
|
|
764
|
+
{ name: 'founder_info', description: 'Answer questions about Lee Akpareva (founder of NAVADA Edge) using his full CV and career history. Always use this tool when asked about Lee, his career, experience, education, or projects.', parameters: { type: 'object', properties: { question: { type: 'string', description: 'The question about Lee' } }, required: ['question'] } },
|
|
736
765
|
];
|
|
737
766
|
return defs.map(d => ({ type: 'function', function: d }));
|
|
738
767
|
}
|
|
@@ -985,8 +1014,8 @@ async function chat(userMessage, conversationHistory = []) {
|
|
|
985
1014
|
},
|
|
986
1015
|
{
|
|
987
1016
|
name: 'founder_info',
|
|
988
|
-
description: '
|
|
989
|
-
input_schema: { type: 'object', properties: {} },
|
|
1017
|
+
description: 'Answer questions about Lee Akpareva (founder of NAVADA Edge) using his full CV and career history. Always use this tool when asked about Lee, his career, experience, education, certifications, or projects.',
|
|
1018
|
+
input_schema: { type: 'object', properties: { question: { type: 'string', description: 'The question about Lee' } }, required: ['question'] },
|
|
990
1019
|
},
|
|
991
1020
|
];
|
|
992
1021
|
|
|
@@ -1065,7 +1094,7 @@ async function executeTool(name, input) {
|
|
|
1065
1094
|
displayOutput(result);
|
|
1066
1095
|
return result.error ? `Error (exit ${result.exitCode}): ${result.error}` : result.output;
|
|
1067
1096
|
}
|
|
1068
|
-
case 'founder_info': return localTools.founderInfo.execute();
|
|
1097
|
+
case 'founder_info': return localTools.founderInfo.execute(input.question);
|
|
1069
1098
|
default: return `Unknown tool: ${name}`;
|
|
1070
1099
|
}
|
|
1071
1100
|
} catch (e) {
|
|
@@ -1250,7 +1279,7 @@ async function grokChat(userMessage, conversationHistory = []) {
|
|
|
1250
1279
|
|
|
1251
1280
|
// Extract final text
|
|
1252
1281
|
const content = response?.choices?.[0]?.message?.content || '';
|
|
1253
|
-
return content || 'No response.';
|
|
1282
|
+
return cleanOutput(content) || 'No response.';
|
|
1254
1283
|
}
|
|
1255
1284
|
|
|
1256
1285
|
async function fallbackChat(msg) {
|
package/lib/knowledge.py
ADDED
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
"""
|
|
2
|
+
NAVADA Edge Knowledge Skill — answers questions about Lee Akpareva accurately.
|
|
3
|
+
Called by the CLI agent as a Python subprocess. Uses OpenAI for natural responses
|
|
4
|
+
grounded in factual CV data. No hallucination.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import sys
|
|
8
|
+
import json
|
|
9
|
+
import os
|
|
10
|
+
|
|
11
|
+
KNOWLEDGE = """
|
|
12
|
+
LESLIE (LEE) AKPAREVA
|
|
13
|
+
Principal AI Consultant | Program Director | ML Engineer
|
|
14
|
+
Phone: 07935237704 | Email: leeakpareva@hotmail.com | Web: www.navada-lab.space
|
|
15
|
+
|
|
16
|
+
Senior technology leader and practising ML engineer with 17+ years delivering large-scale digital transformation across insurance, finance, healthcare, aviation, logistics, and e-commerce. Combines MBA-level commercial acumen with hands-on AI engineering, training custom models on GPU infrastructure, designing multi-agent architectures, and deploying production-grade systems that drive measurable P&L impact.
|
|
17
|
+
|
|
18
|
+
Equally comfortable presenting ROI cases to C-suite stakeholders and debugging CUDA memory allocation in a GPU terminal. Track record of owning programme budgets up to 5M GBP, leading cross-functional teams of 30+, and translating AI capability into benefits realisation across underwriting, claims, operations, and commercial functions.
|
|
19
|
+
|
|
20
|
+
Engineering workflow runs on Paperspace (paperspace.com) for GPU-accelerated model training and inference, with Railway (railway.com) providing persistent compute for production APIs, scheduled automation, and cron-based orchestration.
|
|
21
|
+
|
|
22
|
+
CORE COMPETENCIES
|
|
23
|
+
Leadership: Programme Governance, Portfolio Management, C-Suite Engagement, Vendor Management, Risk & Compliance
|
|
24
|
+
AI/ML: PyTorch, Hugging Face, LangChain, QLoRA Fine-Tuning, RAG Pipelines, Computer Vision (YOLO), Azure AI Foundry, OpenAI, FastAPI, Docker, CI/CD
|
|
25
|
+
Commercial: P&L Ownership, Benefits Realisation, ROI & NPV Modelling, Cost Optimisation, Investment Prioritisation
|
|
26
|
+
|
|
27
|
+
PROFESSIONAL EXPERIENCE (chronological, most recent first)
|
|
28
|
+
|
|
29
|
+
1. Principal Azure AI Solution Consultant | Generali UK | November 2024 to Present
|
|
30
|
+
Hired directly by the COO to define and lead AI strategy across the UK business. Sole technical architect and lead developer for enterprise AI, responsible for the full ML lifecycle from model selection through fine-tuning to production deployment.
|
|
31
|
+
- Established the AI Centre of Excellence, defining operating model, governance frameworks, and technical standards for AI delivery on Azure AI Foundry
|
|
32
|
+
- Designed and implemented multi-agent architectures integrating LangChain, Azure OpenAI, and vector databases (PostgreSQL/Pinecone) for production RAG pipelines
|
|
33
|
+
- Led model evaluation and fine-tuning initiatives, executing QLoRA adapter training on Qwen and Llama models using Hugging Face transformers and PEFT on cloud GPU infrastructure
|
|
34
|
+
- Built end-to-end ML training pipelines including dataset curation, hyperparameter optimisation, loss curve analysis, and inference endpoint deployment via FastAPI
|
|
35
|
+
- Trained custom LoRA adapters for domain-specific image generation using Stable Diffusion, supporting brand and marketing use cases
|
|
36
|
+
- Deployed computer vision prototypes using YOLOv8 for document classification and visual inspection workflows
|
|
37
|
+
- Created reusable AI reference architecture now adopted as the blueprint for all new AI initiatives, reducing concept-to-POC time by 60%
|
|
38
|
+
- Delivered AI prototypes for legal, claims, and operations teams, demonstrating measurable reduction in manual review time and improved knowledge retrieval
|
|
39
|
+
- Authored and delivered internal AI enablement programme including workshops, notebooks, and technical guides to upskill 50+ staff on RAG, LLM orchestration, and ML operations
|
|
40
|
+
- Built secure API layers with JWT/OAuth, rate limiting, and Azure Key Vault integration maintaining enterprise compliance and data protection standards
|
|
41
|
+
|
|
42
|
+
2. Program Director | Informa Markets | October 2023 to September 2024
|
|
43
|
+
Accountable for strategy, P&L, and delivery of two new digital products within the global food portfolio. Led a cross-functional European team of 27 across engineering, data science, product, UX, and operations.
|
|
44
|
+
- Took two digital propositions from concept to launch-ready state
|
|
45
|
+
- Managed programme financials including resource allocation, cost forecasting, and investment trade-off analysis
|
|
46
|
+
- Defined and executed go-to-market strategies for digital product launches across multiple European regions
|
|
47
|
+
- Introduced data-driven decision-making into portfolio management
|
|
48
|
+
- Oversaw regulatory compliance, risk management, and governance across multi-jurisdiction delivery
|
|
49
|
+
|
|
50
|
+
3. Commercial Program Manager | Farfetch | December 2022 to August 2023
|
|
51
|
+
- Led commercial technology programmes for the luxury fashion marketplace
|
|
52
|
+
- Owned programme financials and benefits tracking, reporting directly to senior leadership
|
|
53
|
+
- Coordinated platform initiatives supporting 2.3B GBP GMV marketplace operations
|
|
54
|
+
|
|
55
|
+
4. Blockchain Program Manager | DHL Express | May 2022 to December 2022
|
|
56
|
+
- Managed blockchain and emerging technology programmes for the global logistics leader
|
|
57
|
+
- Led cross-functional teams evaluating distributed ledger solutions for supply chain transparency and shipment verification
|
|
58
|
+
- Developed business cases and ROI models for blockchain integration across European operations
|
|
59
|
+
|
|
60
|
+
5. Product / Project Lead | Shutterstock | November 2021 to May 2022
|
|
61
|
+
6. DeFi & Blockchain Program Lead | Bumper (DeFi Protocol) | September 2021 to November 2021
|
|
62
|
+
7. Project Manager | Millbrook Healthcare | March 2021 to May 2021
|
|
63
|
+
8. Agile Project Consultant | NHSX (NHS Digital) | October 2020 to December 2020
|
|
64
|
+
9. Project Manager | Springer Nature | March 2020 to October 2020
|
|
65
|
+
10. Platform Manager | Opus Energy | June 2019 to December 2019
|
|
66
|
+
11. Digital Project Manager | Centrica (British Gas) | April 2018 to June 2019
|
|
67
|
+
12. Project Manager | Wesleyan Bank | October 2017 to April 2018
|
|
68
|
+
13. Manager | Avis Budget Group | October 2016 to October 2017
|
|
69
|
+
14. Business Program Manager | Wonga | May 2016 to October 2016
|
|
70
|
+
15. Project Manager | British Airways | November 2015 to April 2016
|
|
71
|
+
16. Agile PM / Scrum Master | Flybe | May 2015 to November 2015
|
|
72
|
+
17. Technical Project Manager | Expedia Inc | October 2014 to May 2015
|
|
73
|
+
18. Project Manager | Powa Technology | April 2014 to October 2014
|
|
74
|
+
19. Implementation Manager | Polarisoft | August 2013 to April 2014
|
|
75
|
+
|
|
76
|
+
PERSONAL PROJECTS & TECHNICAL RESEARCH
|
|
77
|
+
- Custom LLM Fine-Tuning: Trained domain-specific language models using QLoRA on cloud GPU (NVIDIA A4000). Built 85-example curated datasets, iterated across 3 model versions, resolved base model hallucination through progressive LoRA rank scaling
|
|
78
|
+
- Stable Diffusion LoRA Training: Created custom image generation adapters for brand-consistent AI imagery
|
|
79
|
+
- Computer Vision: Deployed YOLOv8 object detection models with real-time inference. Live: computervisionbylee.streamlit.app
|
|
80
|
+
- RAVEN Terminal: AI-powered code learning platform. Live: raventerminal.xyz
|
|
81
|
+
- Medical AI: Evaluated OpenBioLLM-8B for healthcare automation, clinical triage and drug discovery
|
|
82
|
+
- ALEX: Multi-modal autonomous agent combining cloud GPU inference with Raspberry Pi edge deployment. Live: alexnavada.xyz
|
|
83
|
+
- RAG & Vector Search: Built retrieval-augmented generation pipelines using ChromaDB, LangChain, and sentence-transformers
|
|
84
|
+
- Robotics & IoT: Raspberry Pi-powered robots including PiCrawler spider robot with computer vision, servo calibration, and MediaPipe gesture control
|
|
85
|
+
- Full-Stack AI Applications: End-to-end Next.js, FastAPI, Vercel, and Railway deployments. Portfolio: navada.space
|
|
86
|
+
- GPU ML Lab: Full ML engineering workstation on Paperspace A4000. Publicly shareable: navada-lab.space
|
|
87
|
+
- Hugging Face Contributor: Publishing models and datasets on huggingface.co/Navada25
|
|
88
|
+
- NAVADA Edge Network: Distributed AI home server (4 nodes, 25+ Docker containers, Tailscale VPN mesh)
|
|
89
|
+
- NAVADA Edge SDK + CLI: npm packages for network access (navada-edge-sdk, navada-edge-cli)
|
|
90
|
+
- WorldMonitor: OSINT intelligence dashboard
|
|
91
|
+
- Lucas CTO: Autonomous infrastructure agent on EC2
|
|
92
|
+
|
|
93
|
+
EDUCATION
|
|
94
|
+
- MBA (Master of Business Administration) | Northumbria University | 2016 to 2017
|
|
95
|
+
- MSc Project Management | Northumbria University | 2013 to 2015
|
|
96
|
+
- Fashion Design & Art Direction | Central Saint Martins, UAL | 2020
|
|
97
|
+
- LLB Law (Hons) | Brunel University | 2007 to 2010
|
|
98
|
+
|
|
99
|
+
CERTIFICATIONS
|
|
100
|
+
AI & Cloud: Azure AI Engineer, Azure Data Scientist, AWS Solutions Architect, Google Cloud Associate, Python Expert (Meta), IBM Full Stack Developer
|
|
101
|
+
Blockchain: Certified Blockchain Architect, Smart Contract Developer, DeFi Expert, Cryptocurrency Expert (Blockchain Council)
|
|
102
|
+
Project Management: PRINCE2 Practitioner, Certified Scrum Master, SAFe, ITIL, Project Risk Management (Oxford), Strategic Planning & Foresight (Oxford)
|
|
103
|
+
Security: CISM (Certified Information Security Manager), ISEB Business Analysis, Foundation in Software Testing
|
|
104
|
+
|
|
105
|
+
TECHNICAL STACK
|
|
106
|
+
ML & AI: PyTorch, Hugging Face Transformers, Diffusers, PEFT, TRL, BitsAndBytes, LangChain, CrewAI, OpenAI, Anthropic, YOLO, Whisper, Gradio, Streamlit
|
|
107
|
+
Languages: Python, TypeScript, JavaScript, SQL
|
|
108
|
+
Cloud & DevOps: Azure AI Foundry, AWS, GCP, Docker, Vercel, Railway, Paperspace GPU, GitHub Actions
|
|
109
|
+
Web & API: Next.js, React, FastAPI, Flask, Node.js, Tailwind CSS
|
|
110
|
+
Data: PostgreSQL, ChromaDB, Pinecone, Redis, Oracle, pandas, NumPy, scikit-learn
|
|
111
|
+
Hardware: Raspberry Pi, Arduino, PiCrawler, servo control, MediaPipe, edge deployment
|
|
112
|
+
|
|
113
|
+
REFERENCES
|
|
114
|
+
Nisha Chopra (Mastercard UK), Natasha Berrow (Informa Markets), Abs Oshinowo (Google UK)
|
|
115
|
+
"""
|
|
116
|
+
|
|
117
|
+
SYSTEM_PROMPT = """You are an accurate knowledge assistant for NAVADA Edge. You answer questions about Lee Akpareva using ONLY the factual data provided below.
|
|
118
|
+
|
|
119
|
+
Rules:
|
|
120
|
+
- Only state facts from the provided knowledge. Never invent or guess.
|
|
121
|
+
- If the answer is not in the knowledge, say "I don't have that specific detail."
|
|
122
|
+
- Be concise and natural. No markdown formatting, no bold, no headers, no dashes.
|
|
123
|
+
- Speak in third person about Lee unless the question is directed at Lee himself.
|
|
124
|
+
|
|
125
|
+
KNOWLEDGE:
|
|
126
|
+
""" + KNOWLEDGE
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def ask(question, api_key=None):
|
|
130
|
+
"""Answer a question using OpenAI grounded in Lee's CV data."""
|
|
131
|
+
key = api_key or os.environ.get("OPENAI_API_KEY", "")
|
|
132
|
+
if not key:
|
|
133
|
+
# Fall back to simple keyword search
|
|
134
|
+
return search_local(question)
|
|
135
|
+
|
|
136
|
+
try:
|
|
137
|
+
import urllib.request
|
|
138
|
+
import ssl
|
|
139
|
+
|
|
140
|
+
body = json.dumps({
|
|
141
|
+
"model": "gpt-4o-mini",
|
|
142
|
+
"messages": [
|
|
143
|
+
{"role": "system", "content": SYSTEM_PROMPT},
|
|
144
|
+
{"role": "user", "content": question}
|
|
145
|
+
],
|
|
146
|
+
"temperature": 0.2,
|
|
147
|
+
"max_tokens": 500
|
|
148
|
+
}).encode()
|
|
149
|
+
|
|
150
|
+
req = urllib.request.Request(
|
|
151
|
+
"https://api.openai.com/v1/chat/completions",
|
|
152
|
+
data=body,
|
|
153
|
+
headers={
|
|
154
|
+
"Content-Type": "application/json",
|
|
155
|
+
"Authorization": f"Bearer {key}"
|
|
156
|
+
}
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
ctx = ssl.create_default_context()
|
|
160
|
+
with urllib.request.urlopen(req, timeout=30, context=ctx) as resp:
|
|
161
|
+
data = json.loads(resp.read())
|
|
162
|
+
return data["choices"][0]["message"]["content"]
|
|
163
|
+
except Exception as e:
|
|
164
|
+
# Fall back to local search on API failure
|
|
165
|
+
return search_local(question)
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
def search_local(question):
|
|
169
|
+
"""Simple keyword search fallback when no API key available."""
|
|
170
|
+
q = question.lower()
|
|
171
|
+
lines = KNOWLEDGE.strip().split("\n")
|
|
172
|
+
matches = []
|
|
173
|
+
for line in lines:
|
|
174
|
+
line = line.strip()
|
|
175
|
+
if not line:
|
|
176
|
+
continue
|
|
177
|
+
words = q.split()
|
|
178
|
+
score = sum(1 for w in words if len(w) > 2 and w in line.lower())
|
|
179
|
+
if score >= 1:
|
|
180
|
+
matches.append((score, line))
|
|
181
|
+
|
|
182
|
+
matches.sort(key=lambda x: -x[0])
|
|
183
|
+
if matches:
|
|
184
|
+
top = [m[1] for m in matches[:8]]
|
|
185
|
+
return "\n".join(top)
|
|
186
|
+
return "I don't have that specific detail about Lee."
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
if __name__ == "__main__":
|
|
190
|
+
question = " ".join(sys.argv[1:]) if len(sys.argv) > 1 else sys.stdin.read().strip()
|
|
191
|
+
if not question:
|
|
192
|
+
print("Usage: python knowledge.py <question>")
|
|
193
|
+
sys.exit(1)
|
|
194
|
+
|
|
195
|
+
key = os.environ.get("OPENAI_API_KEY", "")
|
|
196
|
+
answer = ask(question, key)
|
|
197
|
+
print(answer)
|
package/package.json
CHANGED