Skip to content

Commit be78632

Browse files
committed
feat: enhance HTML processing and context handling
- Add concatenation option for small chunks in context settings - Update system and chunk processing prompts for better HTML handling - Improve selected content detection and processing - Fix CSS overflow in controls component
1 parent 3559f0c commit be78632

File tree

5 files changed

+189
-57
lines changed

5 files changed

+189
-57
lines changed

Diff for: chrome-extension/side_panel/js/context.js

+19-17
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@ const contextConfigs = {
22
'text/html': [
33
{ backend_id: 'use_tag_attributes', id: 'useTagAttributes', label: 'Tag Attributes' },
44
{ backend_id: 'use_only_text', id: 'useOnlyText', label: 'Only text' },
5+
{ backend_id: 'concatenate_small_chunks', id: 'concatenateSmallChunks', label: 'Concatenate small chunks' },
56
{ backend_id: 'body', id: 'useBodyTag', label: 'Body' },
67
{ backend_id: 'head', id: 'useHeadTag', label: 'Head' },
7-
{ backend_id: 'script', id: 'useScriptTag', label: 'Scripts' }
8+
{ backend_id: 'script', id: 'useScriptTag', label: 'Scripts' },
9+
810
],
9-
};
11+
};
1012

1113

1214
export class Context {
@@ -35,7 +37,7 @@ export class Context {
3537
this.updateContextOptions().catch(console.error);
3638
});
3739
});
38-
40+
3941
chrome.tabs.onUpdated.addListener((tabId, changeInfo) => {
4042
if (changeInfo.status === 'complete') {
4143
this.updateContextOptions().catch(console.error);
@@ -50,22 +52,22 @@ export class Context {
5052

5153
async getPageContentType() {
5254
return new Promise((resolve) => {
53-
chrome.tabs.query({active: true, currentWindow: true}, async function(tabs) {
55+
chrome.tabs.query({ active: true, currentWindow: true }, async function (tabs) {
5456
let currentTab = tabs[0];
55-
57+
5658
if (currentTab.url.startsWith('chrome://')) {
5759
resolve("");
5860
return;
5961
}
6062

6163
try {
62-
64+
6365
let response = await fetch(currentTab.url);
6466
let contentType = response.headers.get('Content-Type');
6567
contentType = contentType.split(';')[0];
6668
console.log('Content Type:', contentType);
6769
resolve(contentType);
68-
} catch(error) {
70+
} catch (error) {
6971
resolve("");
7072
}
7173
});
@@ -77,29 +79,29 @@ export class Context {
7779
console.log('Generating options for content type:', contentType);
7880
const options = contextConfigs[contentType] || [];
7981
console.log('Available options:', options);
80-
82+
8183
options.forEach(option => {
8284
const label = document.createElement('label');
8385
const input = document.createElement('input');
84-
86+
8587
input.type = 'checkbox';
8688
input.id = option.id;
87-
89+
8890
label.appendChild(input);
8991
label.appendChild(document.createTextNode(option.label));
90-
92+
9193
this.contextOptions.appendChild(label);
9294
});
9395
}
9496

9597
async toggleContext() {
9698
this.contextOptions.style.display = this.usePageContext.checked ? 'block' : 'none';
9799
this.useContext = this.usePageContext.checked;
98-
100+
99101
await this.updateContextOptions();
100-
102+
101103
this.generateContextOptions(this.contentType);
102-
104+
103105
this.onContextChange(this.getContextParams());
104106
}
105107

@@ -108,15 +110,15 @@ export class Context {
108110
const options = contextConfigs[this.contentType] || [];
109111

110112
let contextParams = {};
111-
113+
112114
options.forEach(option => {
113-
115+
114116
const element = document.getElementById(option.id);
115117
contextParams[option.backend_id] = element.checked
116118
});
117119

118120
console.log(contextParams)
119121

120-
return {use_page_context: this.usePageContext.checked, content_type: this.contentType, processing_settings: contextParams};
122+
return { use_page_context: this.usePageContext.checked, content_type: this.contentType, processing_settings: contextParams };
121123
}
122124
}

Diff for: chrome-extension/side_panel/styles/components/controls.css

-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
padding: 5px;
66
background-color: rgb(53, 53, 53);
77
align-items: flex-start;
8-
overflow-y: auto;
98
}
109

1110
.buttons-column {

Diff for: server/agent/html_agent.py

+87-16
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,55 @@
88
from server.partition.html_processor import HTMLProcessingSettings
99

1010

11-
SYSTEM_PROMPT = """Твоя задача быть ассистентом для помощи мне в работе над документами в формате html в браузере, который я вижу, я буду упоминать тебя о том, на какой странице я сейчас нахожусь, это как дополнительная информация тебе, а также передать контекстный документ в формате html.
11+
SYSTEM_PROMPT = """You are an intelligent browser assistant that helps users analyze and work with content from the currently active browser tab. Your main tasks are:
1212
13-
HTML-контент может быть сложным, там могут быть блокирующие факторы в виде графических меню, рекламных материалов, старайся найти необходимую мне информацию среди всего этого и сам по себе, рассуждая над тем, что из информации в формате html тебе понадобится.
13+
1. Understand and process content only from the current active tab (HTML, PDF, plain text)
14+
2. Provide relevant information and answers based on the given context
15+
3. Help users find specific information within the current page
16+
4. Generate summaries, explanations, or analyses as requested
1417
15-
Ты можешь дать ответ только на одной странице за раз, если тебе нужно еще раз увидеть прошлую страницу, чтобы дать ответ, скажи мне об этом."""
18+
Important rules:
19+
- Always respond in the same language the user's question is asked in
20+
- Base your answers strictly on the provided context from the current tab
21+
- If information needed is on another page, politely ask the user to navigate to that page first
22+
- If something is unclear or missing from the context, acknowledge this
23+
- Keep responses clear, concise, and well-structured
24+
- When appropriate, use formatting (bullet points, paragraphs) for better readability
25+
- Never make assumptions about content that isn't visible in the current tab
26+
- If user asks about information from another page, remind them that you can only work with the current tab's content
27+
"""
28+
29+
30+
CHUNK_PROCESSING_PROMPT = """You are processing a part of a webpage. Your task is to:
31+
32+
1. Extract only relevant information from this chunk that relates to the user's question
33+
2. Provide a focused, self-contained response about this specific part
34+
3. Consider previous findings when analyzing new information
35+
4. Keep the response concise and factual
36+
5. Format the response so it can be easily combined with other parts
37+
38+
Remember:
39+
- This is part of an iterative analysis process
40+
- Focus on new relevant information in this chunk
41+
- Avoid repeating information already found in previous parts
42+
- Maintain the user's original language in the response
43+
- If you find information that complements or contradicts previous findings, note this
44+
45+
The final response will be assembled from multiple parts, so keep your answer focused and relevant to this specific chunk.
46+
"""
47+
48+
49+
class AnswerGeneratorWithRelevanceScore(BaseModel):
50+
reflection: str
51+
answer: str
52+
answer_relevance_score_to_question: float = Field(
53+
default=None, description="Relevance to the question (0-1)"
54+
)
55+
56+
57+
class AnswerGenerator(BaseModel):
58+
reflection: str
59+
answer: str
1660

1761

1862
class HTMLAgent:
@@ -31,7 +75,8 @@ def get_relevant_info(
3175
):
3276
processing_settings = HTMLProcessingSettings(**processing_settings)
3377

34-
messages = [
78+
messages = [{"role": "system", "content": SYSTEM_PROMPT}]
79+
messages += [
3580
{
3681
"role": "user" if conv.role == "user" else "assistant",
3782
"content": conv.message,
@@ -42,13 +87,23 @@ def get_relevant_info(
4287
print(f"page_url: {url}")
4388

4489
self.content_processor = get_processor(page_type="text/html")
90+
91+
is_full_page = self.content_processor.is_full_page(context)
92+
print(is_full_page)
93+
selected_content = (
94+
"Full web page"
95+
if is_full_page
96+
else "This is not the entire web page, it is the selected content on the page"
97+
)
98+
4599
documents = self.content_processor.process_page(
46100
context,
47101
url,
48102
split=False,
49103
processing_settings=processing_settings,
50104
context_len_checker=self.client.check_context_len,
51105
)
106+
print(documents)
52107

53108
if not self.client.check_context_len(text=str(documents)):
54109
documents = self.content_processor.process_page(
@@ -64,35 +119,51 @@ def get_relevant_info(
64119
)
65120
relevant_chunks = []
66121
for i, doc in tqdm(enumerate(documents), total=len(documents)):
67-
doc = self.content_processor.make_page(documents, i, relevant_chunks, processing_settings)
68-
messages_parting = messages + [
122+
doc = f"""{i} part of the webpage, the webpage is divided into {len(documents)} parts in total\n```{doc}```\n"""
123+
124+
messages_parting = [
125+
{"role": "system", "content": CHUNK_PROCESSING_PROMPT}
126+
]
127+
messages_parting += messages[1:]
128+
messages_parting += [
69129
{
70130
"role": "user",
71-
"content": f"{question} Не повторяй информацию что была в прошлых ответах, они помеченны ты увидишь \n\n Page Url: ```{url}``` \n\nPart of web page \n\n ```{doc}```",
131+
"content": f"{question} \n\n Page Url: ```{url}``` \n\nPart of web page \n\n {doc} \n\nYour response format: {AnswerGeneratorWithRelevanceScore.model_json_schema()}",
72132
},
73133
]
74134

75-
response = self.client.generate(messages_parting, stream=False)
76-
relevant_chunks.append(response)
135+
response = self.client.generate(
136+
messages_parting,
137+
stream=False,
138+
schema=AnswerGeneratorWithRelevanceScore.model_json_schema(),
139+
)
140+
print(response)
77141
print(doc)
78-
messages = messages + [
142+
relevant_chunks.append(response)
143+
144+
messages += [
79145
{
80146
"role": "user",
81-
"content": f"Составь единый ответы из нескольких User query: ```{question}``` \n\n Ответы по разным частям одной web страницы: ```{self.content_processor.make_page(documents, len(documents)-1, relevant_chunks, processing_settings)}```",
147+
"content": f"My question: {question} \n\n {selected_content}. The content has already been submitted part by part here are the answers to my question in parts with reflection: \n\n```{self.content_processor.make_page(documents, relevant_chunks, processing_settings)}```",
82148
},
83149
]
84150
response_from_model = self.client.generate(messages, stream=True)
85151
else:
86-
print("\n\nGOOOODYYYY\n\n")
87-
messages = [{"role": "system", "content": SYSTEM_PROMPT}] + messages
152+
print("\n\nSINGLE RUN\n\n")
153+
print(str(documents))
154+
88155
messages += [
89-
# {"role": "system", "content": CITATION_SYSTEM_PROMPT},
90156
{
91157
"role": "user",
92-
"content": f"{question} \n\n Page url: ```{url}```\n\n Web page \n\n ```{str(documents)}```",
158+
"content": f"{question} \n\n Page url: ```{url}```\n\n {selected_content} \n\n ```{str(documents)}```",
159+
# Your response format: {AnswerGenerator.model_json_schema()}",
93160
},
94161
]
95-
response_from_model = self.client.generate(messages, stream=True)
162+
response_from_model = self.client.generate(
163+
messages,
164+
stream=True,
165+
# schema=AnswerGenerator.model_json_schema()
166+
)
96167
return response_from_model
97168

98169
def generate_chat_response(self, dialog_history):

Diff for: server/dialogue_manager.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@
1616
class DialogManager:
1717
def __init__(
1818
self,
19-
temperature=0.0,
20-
max_new_tokens=2048,
19+
temperature=0.3,
20+
max_new_tokens=4048,
2121
max_context_size=15000,
22-
max_prompt_size=2000,
22+
max_prompt_size=3000,
2323
repeat_penalty=1.1,
2424
top_k=30,
2525
top_p=1.0,
@@ -61,7 +61,7 @@ def add_chat_query(
6161
message=user_query,
6262
model_name="",
6363
service_comments=str(processing_settings.json()),
64-
version="0.3.5.1",
64+
version="0.3.5.5",
6565
)
6666

6767
print("\n".join([f"{d.role} - {d.message}" for d in chat_history]))
@@ -102,7 +102,7 @@ def add_chat_query(
102102
message=complete_response,
103103
model_name=self.model_name,
104104
service_comments=str(params),
105-
version="0.3.5.1",
105+
version="0.3.5.5",
106106
)
107107

108108
def from_chat_to_llm_tempalte(self, dialog_history):

0 commit comments

Comments
 (0)