chore: first commit

This commit is contained in:
Han Xiao
2025-01-27 21:36:14 +08:00
parent 597d32b46e
commit 4fd7f41e85
3 changed files with 33 additions and 16 deletions

View File

@@ -7,7 +7,7 @@ import {SafeSearchType, search} from "duck-duck-scrape";
import {rewriteQuery} from "./tools/query-rewriter"; import {rewriteQuery} from "./tools/query-rewriter";
import {dedupQueries} from "./tools/dedup"; import {dedupQueries} from "./tools/dedup";
import {evaluateAnswer} from "./tools/evaluator"; import {evaluateAnswer} from "./tools/evaluator";
import {buildURLMap} from "./tools/getURLIndex"; import {buildURLMap, StepData} from "./tools/getURLIndex";
// Proxy setup remains the same // Proxy setup remains the same
if (process.env.https_proxy) { if (process.env.https_proxy) {
@@ -111,7 +111,7 @@ function getSchema(allowReflect: boolean, allowRead: boolean): ResponseSchema {
actions.push("reflect"); actions.push("reflect");
} }
if (allowRead) { if (allowRead) {
actions.push("read"); actions.push("visit");
} }
return { return {
type: SchemaType.OBJECT, type: SchemaType.OBJECT,
@@ -213,13 +213,13 @@ ${JSON.stringify(context, null, 2)}
When uncertain or needing additional information, select one of these actions: When uncertain or needing additional information, select one of these actions:
${allURLs ? ` ${allURLs ? `
**read**: **visit**:
- Access any URLs from below to gather external knowledge - Visit any URLs from below to gather external knowledge
${JSON.stringify(allURLs, null, 2)} ${JSON.stringify(allURLs, null, 2)}
- When you have enough search result in the context and want to deep dive into specific URLs - When you have enough search result in the context and want to deep dive into specific URLs
- It allows you access the full content behind any URLs - It allows you to access the full content behind any URLs
` : ''} ` : ''}
**search**: **search**:
@@ -269,9 +269,16 @@ Critical Requirements:
- Maintain strict JSON syntax`.trim(); - Maintain strict JSON syntax`.trim();
} }
async function getResponse(question: string, tokenBudget: number = 30000000) { let context: StepData[] = []; // successful steps in the current session
let allContext: StepData[] = []; // all steps in the current session, including those leads to wrong results
function updateContext(step: any) {
context.push(step);
allContext.push(step)
}
async function getResponse(question: string, tokenBudget: number = 1000000) {
let totalTokens = 0; let totalTokens = 0;
let context = [];
let step = 0; let step = 0;
let gaps: string[] = [question]; // All questions to be answered including the orginal question let gaps: string[] = [question]; // All questions to be answered including the orginal question
let allQuestions = [question]; let allQuestions = [question];
@@ -288,7 +295,7 @@ async function getResponse(question: string, tokenBudget: number = 30000000) {
const allowReflect = gaps.length <= 1; const allowReflect = gaps.length <= 1;
const currentQuestion = gaps.length > 0 ? gaps.shift()! : question; const currentQuestion = gaps.length > 0 ? gaps.shift()! : question;
// update all urls with buildURLMap // update all urls with buildURLMap
allURLs = {...allURLs, ...buildURLMap(context)}; allURLs = buildURLMap(allContext);
const allowRead = Object.keys(allURLs).length > 0; const allowRead = Object.keys(allURLs).length > 0;
const prompt = getPrompt( const prompt = getPrompt(
currentQuestion, currentQuestion,
@@ -320,15 +327,18 @@ async function getResponse(question: string, tokenBudget: number = 30000000) {
console.log('Question-Action:', currentQuestion, action); console.log('Question-Action:', currentQuestion, action);
if (action.action === 'answer') { if (action.action === 'answer') {
context.push({ updateContext({
step, step,
question: currentQuestion, question: currentQuestion,
...action, ...action,
}); });
const evaluation = await evaluateAnswer(currentQuestion, action.answer); const evaluation = await evaluateAnswer(currentQuestion, action.answer);
if (currentQuestion === question) { if (currentQuestion === question) {
if (evaluation.is_valid_answer) { if (evaluation.is_valid_answer) {
// EXIT POINT
await storeContext(prompt, [allContext, allKeywords, allQuestions, allKnowledge], step);
return action; return action;
} else { } else {
badContext.push({ badContext.push({
@@ -354,7 +364,7 @@ async function getResponse(question: string, tokenBudget: number = 30000000) {
gaps.push(question); // always keep the original question in the gaps gaps.push(question); // always keep the original question in the gaps
} else { } else {
console.log('No new questions to ask'); console.log('No new questions to ask');
context.push({ updateContext({
step, step,
...action, ...action,
result: 'I have tried all possible questions and found no useful information. I must think out of the box or different angle!!!' result: 'I have tried all possible questions and found no useful information. I must think out of the box or different angle!!!'
@@ -388,7 +398,7 @@ async function getResponse(question: string, tokenBudget: number = 30000000) {
await sleep(5000); await sleep(5000);
} }
context.push({ updateContext({
step, step,
question: currentQuestion, question: currentQuestion,
...action, ...action,
@@ -396,20 +406,20 @@ async function getResponse(question: string, tokenBudget: number = 30000000) {
}); });
} else { } else {
console.log('No new queries to search'); console.log('No new queries to search');
context.push({ updateContext({
step, step,
...action, ...action,
result: 'I have tried all possible queries and found no new information. I must think out of the box or different angle!!!' result: 'I have tried all possible queries and found no new information. I must think out of the box or different angle!!!'
}); });
} }
} else if (action.action === 'read' && action.URLTargets?.length) { } else if (action.action === 'visit' && action.URLTargets?.length) {
const urlResults = await Promise.all( const urlResults = await Promise.all(
action.URLTargets.map(async (url: string) => { action.URLTargets.map(async (url: string) => {
const response = await readUrl(url, jinaToken); const response = await readUrl(url, jinaToken);
return {url, result: response}; return {url, result: response};
}) })
); );
context.push({ updateContext({
step, step,
question: currentQuestion, question: currentQuestion,
...action, ...action,
@@ -420,7 +430,7 @@ async function getResponse(question: string, tokenBudget: number = 30000000) {
} catch (error) { } catch (error) {
console.error('Error fetching data:', error); console.error('Error fetching data:', error);
} }
await storeContext(prompt, [context, allKeywords, allQuestions, allKnowledge], step); await storeContext(prompt, [allContext, allKeywords, allQuestions, allKnowledge], step);
} }
} }

View File

@@ -86,6 +86,13 @@ Evaluation: {
"reasoning": "The answer is not definitive and fails to provide the requested information. Don't know, can't derive, lack of information is unacceptable," "reasoning": "The answer is not definitive and fails to provide the requested information. Don't know, can't derive, lack of information is unacceptable,"
} }
Question: "who owns jina ai?"
Answer: "The ownership structure of Jina AI is not publicly disclosed."
Evaluation: {
"is_valid_answer": false,
"reasoning": "The answer is not definitive and fails to provide the requested information. Lack of information is unacceptable, more search and deep reasoning is needed."
}
Now evaluate this pair: Now evaluate this pair:
Question: ${JSON.stringify(question)} Question: ${JSON.stringify(question)}
Answer: ${JSON.stringify(answer)}`; Answer: ${JSON.stringify(answer)}`;

View File

@@ -9,7 +9,7 @@ interface QueryResult {
results: SearchResult[]; results: SearchResult[];
} }
interface StepData { export interface StepData {
step: number; step: number;
question: string; question: string;
action: string; action: string;