-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcontroller.js
More file actions
156 lines (138 loc) · 4.24 KB
/
controller.js
File metadata and controls
156 lines (138 loc) · 4.24 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
const dotenv = require('dotenv');
const OpenAI = require('openai');
const { chromium } = require('playwright');
const { wrap, configure } = require('agentql');
const { pruneUndefined } = require('./utils');
const { addDocument, getCollection, getQuery } = require('./embedding');
const { SystemMessage, HumanMessage } = require('langchain');
const { ChatOllama } = require('@langchain/ollama');
dotenv.config();
configure({
apiKey: process.env.AGENTQL_KEY,
});
const fetchFormFields = async (href, browser, additionalFields={}) => {
const page = await wrap(await browser.newPage());
await page.goto(href);
const formQuery = `{
first_name,
last_name,
name,
email,
gender,
date_of_birth,
address,
city,
state,
zip_code,
graduation_year,
school,
degree,
current_role,
current_company,
current_compensation,
applying_for_position,
years_of_experience,
expected_salary,
when_can_I_start,
end_date_of_latest_role,
start_date_of_latest_role,
phone_number,
area_code,
cover_letter,
about,
website,
submit_btn,
}`;
const response = await page.queryElements(formQuery);
return response;
}
const askLLM = async (question) => {
const llm = new ChatOllama({
model: 'llama3.2',
baseUrl: 'http://localhost:11434'
});
const system = `You are a very helpful assistant and expert in filling application form. You have to answer to the form questions based on context provided. Only provide the answer to the question and nothing else I repeat nothing else. strictly provide 'null' if you do not the know the exact answer to the question or have any doubt about the question.`;
const ragDocuments = await getQuery(question, process.env.CHROMA_COLLECTION);
const query = ragDocuments.documents[0].join(', ');
try{
const messages = [
new SystemMessage(system),
new HumanMessage(`Context: ${query} \n Answer the form field : ${question} for me`),
]
const response = await llm.invoke(messages);
return response.content;
}
catch(error){
console.log(error);
}
}
const queryController = async (req, res, next) => {
const body = req.body;
if(!body){
res.status(400).json({
message: 'no body'
});
return;
}
const href = body.href;
if(!href){
res.status(400).json({
message: 'no href'
});
return;
}
const browser = await chromium.launch({ headless: false, args: ['--start-maximized'] });
const context = await browser.newContext({
viewport: null, // Allow the browser to set its own viewport size
});
const fields = await fetchFormFields(href, context);
const data = await fields.toData();
// Ask from LLM with retrieved data
const questions = pruneUndefined(data);
for(const key in questions){
const answer = await askLLM(key);
// Fill the form
if(answer && answer.length && answer != 'null'){
await fields[key].type(answer);
}
else{
await fields[key].type('NA');
}
}
await fields.submit_btn.click();
// await browser.close();
return res.status(200).json({
message: 'query completed'
});
}
const createEmbedding = async (req, res, next) => {
const body = req.body;
if(!body){
res.status(400).json({
message: 'no body'
});
return;
}
const documents = body.documents;
if(!documents){
res.status(400).json({
message: 'no document'
});
return;
}
try{
const collection = await getCollection(process.env.CHROMA_COLLECTION);
await addDocument(documents, collection);
return res.status(200).json({
message: 'document added succesfully'
});
}
catch(err){
console.log(err);
return res.status(500).json({
message: 'server error'
});
}
}
module.exports = { queryController, createEmbedding };
// "href": "https://templates-demo.formbold.com/html-application-form",