From 715dd21637b2c441ce7bd523941d6adf4da7bbca Mon Sep 17 00:00:00 2001 From: zhangdahai <631871336@qq.com> Date: Thu, 13 Mar 2025 17:21:26 +0800 Subject: [PATCH 01/15] adapt to newer ollama version --- .gitignore | 3 ++- src/llm/llm.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index fec312fd..4388b995 100644 --- a/.gitignore +++ b/.gitignore @@ -160,4 +160,5 @@ cython_debug/ .idea/ notes.md -data/ \ No newline at end of file +data/ +.vscode \ No newline at end of file diff --git a/src/llm/llm.py b/src/llm/llm.py index 24f20d59..9bad470a 100644 --- a/src/llm/llm.py +++ b/src/llm/llm.py @@ -68,7 +68,7 @@ def __init__(self, model_id: str = None): } if ollama.client: - self.models["OLLAMA"] = [(model["name"], model["name"]) for model in ollama.models] + self.models["OLLAMA"] = [(model["model"], model["model"]) for model in ollama.models] def list_models(self) -> dict: return self.models From 0c2c1c4ea711ae5688f2fb0b3125faab1594240e Mon Sep 17 00:00:00 2001 From: zhangdahai <631871336@qq.com> Date: Fri, 14 Mar 2025 20:46:00 +0800 Subject: [PATCH 02/15] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- devika.py | 2 +- src/browser/search.py | 90 +++++++++++++++++++++++++++++++------------ 2 files changed, 66 insertions(+), 26 deletions(-) diff --git a/devika.py b/devika.py index 961b792a..d239b8f7 100644 --- a/devika.py +++ b/devika.py @@ -206,4 +206,4 @@ def status(): if __name__ == "__main__": logger.info("Devika is up and running!") - socketio.run(app, debug=False, port=1337, host="0.0.0.0") + socketio.run(app, debug=True, port=1337, host="0.0.0.0") diff --git a/src/browser/search.py b/src/browser/search.py index 030fa5fe..7c0eb9be 100644 --- a/src/browser/search.py +++ b/src/browser/search.py @@ -1,3 +1,6 @@ +from lxml import etree + +from duckduckgo_search import DDGS import requests from src.config import Config @@ -62,6 +65,7 @@ def get_first_link(self): print(error) return "" + # class DuckDuckGoSearch: # def __init__(self): # self.query_result = None @@ -90,6 +94,7 @@ class DuckDuckGoSearch: currently, the package is not working with our current setup. """ + def __init__(self): from curl_cffi import requests as curl_requests self.query_result = None @@ -98,37 +103,24 @@ def __init__(self): def _get_url(self, method, url, data): try: - resp = self.asession.request(method, url, data=data) - if resp.status_code == 200: - return resp.content - if resp.status_code == (202, 301, 403): - raise Exception(f"Error: {resp.status_code} rate limit error") - if not resp: - return None + return None except Exception as error: if "timeout" in str(error).lower(): raise TimeoutError("Duckduckgo timed out error") def duck(self, query): - resp = self._get_url("POST", "https://duckduckgo.com/", data={"q": query}) - vqd = self.extract_vqd(resp) - - params = {"q": query, "kl": 'en-us', "p": "1", "s": "0", "df": "", "vqd": vqd, "ex": ""} - resp = self._get_url("GET", "https://links.duckduckgo.com/d.js", params) - page_data = self.text_extract_json(resp) - results = [] - for row in page_data: - href = row.get("u") - if href and href != f"http://www.google.com/search?q={query}": - body = self.normalize(row["a"]) - if body: - result = { - "title": self.normalize(row["t"]), - "href": self.normalize_url(href), - "body": self.normalize(row["a"]), - } - results.append(result) + with DDGS(timeout=20, proxies=None) as ddgs: + for r in ddgs.text(keywords=query, max_results=3, backend="html"): + # print(r) + if r is not None: + r['content'] = get_html_content(r['href']) + if r['content']: + results.append({ + "title": self.normalize(r['title']), + "href": self.normalize_url(r['href']), + "body": r['content'], + }) self.query_result = results @@ -165,3 +157,51 @@ def normalize_url(url: str) -> str: @staticmethod def normalize(raw_html: str) -> str: return unescape(re.sub("<.*?>", "", raw_html)) if raw_html else "" + + +def get_html_content(url): + # 发送HTTP请求获取网页源代码 + if url is None: + return "url为空!" + try: + header = { + 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36', + 'cookie': '__yjs_duid=1_b1ac9fc87dce4de5552d7cf0924fb4981686228951567; u=b0281776fd75d3eefeb3562b2a5e6534; ' + '__bid_n=1889b14047a51b2b754207; ' + 'FPTOKEN=qU+ieOMqkW6y6DlsOZ+D/T' + '+SCY6yS3dYvGXKibFoGBijKuUuSbc3ACFDzjlcC18wuDjNLENrw4ktAFAqnl3Akg492Lr4fbvNrkdJ' + '/ZQrluIdklkNDAKYnPrpcbe2H9y7AtX+/b+FCTkSTNv5+qB3OtQQ3BXXsEen72oEoAfK+H6' + '/u6ltZPdyHttJBJiXEDDS3EiUVt+S2w+8ozXENWbNt/AHeCgNUMmdeDinAKCR+nQSGK/twOoTLOU/nxBeSAazg' + '+wu5K8ooRmW00Bk6XAqC4Cb829XR3UinZHRsJxt7q9biKzYQh' + '+Yu5s6EHypKwpA6RPtVAC1axxbxza0l5LJ5hX8IxJXDaQ6srFoEzQ92jM0rmDynp+gT' + '+3qNfEtB2PjkURvmRghGUn8wOcUUKPOqg==|mfg5DyAulnBuIm/fNO5JCrEm9g5yXrV1etiaV0jqQEw=|10' + '|dcfdbf664758c47995de31b90def5ca5; PHPSESSID=18397defd82b1b3ef009662dc77fe210; ' + 'Hm_lvt_de3f6fd28ec4ac19170f18e2a8777593=1686322028,1686360205; ' + 'history=cid%3A2455%2Ccid%3A2476%2Ccid%3A5474%2Ccid%3A5475%2Ccid%3A2814%2Cbid%3A3667; ' + 'Hm_lpvt_de3f6fd28ec4ac19170f18e2a8777593=1686360427'} + response = requests.get(url, header) + response.encoding = response.apparent_encoding + html_content = response.text + + # 使用lxml解析网页源代码 + tree = etree.HTML(html_content) + + # 使用XPath选择器提取纯文本内容 + # 这里假设要提取的内容位于
标签内,你可以根据实际情况调整XPath表达式
+ content = get_text(tree, url, '//p/text()')
+
+ if (len(content) == 0):
+ content = get_text(tree, url, '//body/text()')
+ return content
+ except BaseException as e:
+ print(e)
+ return None
+
+
+def get_text(tree, url, regex):
+ paragraphs = tree.xpath(regex)
+ content = []
+ # 打印提取的文本内容
+ for paragraph in paragraphs:
+ content.append(paragraph)
+ return content
From 92dfb2cd88725e2bf3f2c010fea8781255e0d140 Mon Sep 17 00:00:00 2001
From: zhangdahai <631871336@qq.com>
Date: Sat, 15 Mar 2025 21:11:08 +0800
Subject: [PATCH 03/15] =?UTF-8?q?=E9=80=82=E9=85=8D=E5=9B=BD=E4=BA=A7?=
=?UTF-8?q?=E6=A8=A1=E5=9E=8B\?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
sample.config.toml | 2 +-
src/agents/coder/prompt.jinja2 | 10 ++---
src/agents/planner/planner.py | 2 +-
src/browser/search.py | 4 +-
src/config.py | 2 +-
src/init.py | 1 +
src/llm/china_client.py | 19 +++++++++
src/llm/llm.py | 71 +++++++++++++++++++---------------
src/llm/ollama_client.py | 2 +
9 files changed, 73 insertions(+), 40 deletions(-)
create mode 100644 src/llm/china_client.py
diff --git a/sample.config.toml b/sample.config.toml
index 62cde107..b9d7e594 100644
--- a/sample.config.toml
+++ b/sample.config.toml
@@ -31,4 +31,4 @@ LOG_REST_API = "true"
LOG_PROMPTS = "false"
[TIMEOUT]
-INFERENCE = 60
\ No newline at end of file
+INFERENCE = 6000000
\ No newline at end of file
diff --git a/src/agents/coder/prompt.jinja2 b/src/agents/coder/prompt.jinja2
index c6336a03..4a7191c6 100644
--- a/src/agents/coder/prompt.jinja2
+++ b/src/agents/coder/prompt.jinja2
@@ -28,24 +28,24 @@ Read the step-by-step plan carefully. Think step-by-step. Learn relevant informa
Your response should only be in the following Markdown format:
~~~
-File: `main.py`:
-```py
+File: main.html:
+```html
print("Example")
```
-File: `src/main.rs`:
+File: src/main.rs:
```rs
fn main() {
println!("Example");
}
```
-File: `nested/directory/example/code.py`:
+File: nested/directory/example/code.py:
```py
print("Example")
```
-File: `README.md`
+File: README.md
```md
# Example
diff --git a/src/agents/planner/planner.py b/src/agents/planner/planner.py
index 3f241773..5234ba28 100644
--- a/src/agents/planner/planner.py
+++ b/src/agents/planner/planner.py
@@ -50,7 +50,7 @@ def parse_response(self, response: str):
elif current_section == "focus":
result["focus"] += " " + line
elif current_section == "plans":
- if line.startswith("- [ ] Step"):
+ if line.find('Step') != -1:
current_step = line.split(":")[0].strip().split(" ")[-1]
result["plans"][int(current_step)] = line.split(":", 1)[1].strip()
elif current_step:
diff --git a/src/browser/search.py b/src/browser/search.py
index 7c0eb9be..e56d6fb2 100644
--- a/src/browser/search.py
+++ b/src/browser/search.py
@@ -128,7 +128,9 @@ def search(self, query):
self.duck(query)
def get_first_link(self):
- return self.query_result[0]["href"]
+ if len(self.query_result) > 0:
+ return self.query_result[0]["href"]
+ return ""
@staticmethod
def extract_vqd(html_bytes: bytes) -> str:
diff --git a/src/config.py b/src/config.py
index a3303118..2336807e 100644
--- a/src/config.py
+++ b/src/config.py
@@ -109,7 +109,7 @@ def get_logging_prompts(self):
return self.config["LOGGING"]["LOG_PROMPTS"] == "true"
def get_timeout_inference(self):
- return self.config["TIMEOUT"]["INFERENCE"]
+ return 6000000000
def set_bing_api_key(self, key):
self.config["API_KEYS"]["BING"] = key
diff --git a/src/init.py b/src/init.py
index abb8b95b..89953982 100644
--- a/src/init.py
+++ b/src/init.py
@@ -26,6 +26,7 @@ def init_devika():
from src.bert.sentence import SentenceBert
+ # using llm instead
logger.info("Loading sentence-transformer BERT models...")
prompt = "Light-weight keyword extraction exercise for BERT model loading.".strip()
SentenceBert(prompt).extract_keywords()
diff --git a/src/llm/china_client.py b/src/llm/china_client.py
new file mode 100644
index 00000000..82a54b23
--- /dev/null
+++ b/src/llm/china_client.py
@@ -0,0 +1,19 @@
+from openai import OpenAI
+
+
+class China:
+ def __init__(self):
+ pass
+
+ def inference(self, model_id: str, prompt: str) -> str:
+ completion = OpenAI(
+ api_key="sk-lHKZ5qJaGU3axOPVnCJSGMdiYep04VRSwCMB311rnCE9Fh19",
+ base_url="https://api.moonshot.cn/v1",
+ )
+ result = completion.chat.completions.create(
+ model=model_id,
+ # model="moonshot-v1-128k",
+ messages=[{"role": "user", "content": prompt}],
+ temperature=0.3,
+ )
+ return result.choices[0].message.content
diff --git a/src/llm/llm.py b/src/llm/llm.py
index 9bad470a..d6656b8a 100644
--- a/src/llm/llm.py
+++ b/src/llm/llm.py
@@ -3,6 +3,7 @@
import tiktoken
from typing import List, Tuple
+from .china_client import China
from src.socket_instance import emit_agent
from .ollama_client import Ollama
from .claude_client import Claude
@@ -31,37 +32,44 @@ def __init__(self, model_id: str = None):
self.log_prompts = config.get_logging_prompts()
self.timeout_inference = config.get_timeout_inference()
self.models = {
- "CLAUDE": [
- ("Claude 3 Opus", "claude-3-opus-20240229"),
- ("Claude 3 Sonnet", "claude-3-sonnet-20240229"),
- ("Claude 3 Haiku", "claude-3-haiku-20240307"),
- ],
- "OPENAI": [
- ("GPT-4o-mini", "gpt-4o-mini"),
- ("GPT-4o", "gpt-4o"),
- ("GPT-4 Turbo", "gpt-4-turbo"),
- ("GPT-3.5 Turbo", "gpt-3.5-turbo-0125"),
- ],
- "GOOGLE": [
- ("Gemini 1.0 Pro", "gemini-pro"),
- ("Gemini 1.5 Flash", "gemini-1.5-flash"),
- ("Gemini 1.5 Pro", "gemini-1.5-pro"),
- ],
- "MISTRAL": [
- ("Mistral 7b", "open-mistral-7b"),
- ("Mistral 8x7b", "open-mixtral-8x7b"),
- ("Mistral Medium", "mistral-medium-latest"),
- ("Mistral Small", "mistral-small-latest"),
- ("Mistral Large", "mistral-large-latest"),
- ],
- "GROQ": [
- ("LLAMA3 8B", "llama3-8b-8192"),
- ("LLAMA3 70B", "llama3-70b-8192"),
- ("LLAMA2 70B", "llama2-70b-4096"),
- ("Mixtral", "mixtral-8x7b-32768"),
- ("GEMMA 7B", "gemma-7b-it"),
- ],
+ # "CLAUDE": [
+ # ("Claude 3 Opus", "claude-3-opus-20240229"),
+ # ("Claude 3 Sonnet", "claude-3-sonnet-20240229"),
+ # ("Claude 3 Haiku", "claude-3-haiku-20240307"),
+ # ],
+ # "OPENAI": [
+ # ("GPT-4o-mini", "gpt-4o-mini"),
+ # ("GPT-4o", "gpt-4o"),
+ # ("GPT-4 Turbo", "gpt-4-turbo"),
+ # ("GPT-3.5 Turbo", "gpt-3.5-turbo-0125"),
+ # ],
+ # "GOOGLE": [
+ # ("Gemini 1.0 Pro", "gemini-pro"),
+ # ("Gemini 1.5 Flash", "gemini-1.5-flash"),
+ # ("Gemini 1.5 Pro", "gemini-1.5-pro"),
+ # ],
+ # "MISTRAL": [
+ # ("Mistral 7b", "open-mistral-7b"),
+ # ("Mistral 8x7b", "open-mixtral-8x7b"),
+ # ("Mistral Medium", "mistral-medium-latest"),
+ # ("Mistral Small", "mistral-small-latest"),
+ # ("Mistral Large", "mistral-large-latest"),
+ # ],
+ # "GROQ": [
+ # ("LLAMA3 8B", "llama3-8b-8192"),
+ # ("LLAMA3 70B", "llama3-70b-8192"),
+ # ("LLAMA2 70B", "llama2-70b-4096"),
+ # ("Mixtral", "mixtral-8x7b-32768"),
+ # ("GEMMA 7B", "gemma-7b-it"),
+ # ],
"OLLAMA": [],
+ "国内大模型": [
+ ("kimi moonshot-v1-8k", "moonshot-v1-8k"),
+ ("kimi moonshot-v1-32k", "moonshot-v1-32k"),
+ # ("kimi kimi-latest-8k", "kimi-latest-8k"),
+ # ("kimi kimi-latest-32k", "kimi-latest-32k"),
+ # ("kimi kimi-latest-128k", "kimi-latest-128k"),
+ ],
"LM_STUDIO": [
("LM Studio", "local-model"),
],
@@ -100,6 +108,7 @@ def inference(self, prompt: str, project_name: str) -> str:
model_mapping = {
"OLLAMA": ollama,
+ "国内大模型": China(),
"CLAUDE": Claude(),
"OPENAI": OpenAi(),
"GOOGLE": Gemini(),
@@ -123,7 +132,7 @@ def inference(self, prompt: str, project_name: str) -> str:
elapsed_seconds = format(elapsed_time, ".2f")
emit_agent("inference", {"type": "time", "elapsed_time": elapsed_seconds})
if int(elapsed_time) == 5:
- emit_agent("inference", {"type": "warning", "message": "Inference is taking longer than expected"})
+ emit_agent("inference", {"type": "warning", "message": "Inference is taking longer than expected"}, False)
if elapsed_time > self.timeout_inference:
raise concurrent.futures.TimeoutError
if future.done():
diff --git a/src/llm/ollama_client.py b/src/llm/ollama_client.py
index 95b1e365..0412550a 100644
--- a/src/llm/ollama_client.py
+++ b/src/llm/ollama_client.py
@@ -22,4 +22,6 @@ def inference(self, model_id: str, prompt: str) -> str:
prompt=prompt.strip(),
options={"temperature": 0}
)
+ if "deepseek" in model_id:
+ response['response'] = response['response'][response['response'].find('') + 8:]
return response['response']
From b612771689edc335c37fbd84015305506e781570 Mon Sep 17 00:00:00 2001
From: zhangdahai <631871336@qq.com>
Date: Sat, 15 Mar 2025 21:49:02 +0800
Subject: [PATCH 04/15] =?UTF-8?q?kimi=E6=A8=A1=E5=9E=8B?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
sample.config.toml | 1 +
src/config.py | 4 ++++
src/llm/china_client.py | 16 +++++++++-------
3 files changed, 14 insertions(+), 7 deletions(-)
diff --git a/sample.config.toml b/sample.config.toml
index b9d7e594..878dc736 100644
--- a/sample.config.toml
+++ b/sample.config.toml
@@ -16,6 +16,7 @@ GEMINI = "