Spaces:
Sleeping
Sleeping
TahaFawzyElshrif commited on
Commit ·
32a7233
1
Parent(s): 1327b4d
uploaded files
Browse files- .gitignore +0 -0
- Dockerfile +14 -0
- Server.py +73 -0
- __pycache__/Server.cpython-312.pyc +0 -0
- agent/agent_graph/Graph_Nodes.py +174 -0
- agent/agent_graph/Graph_Routes.py +19 -0
- agent/agent_graph/Graph_Utils.py +25 -0
- agent/agent_graph/StateTasks.py +49 -0
- agent/agent_graph/__pycache__/Finalize_Nodes.cpython-312.pyc +0 -0
- agent/agent_graph/__pycache__/Graph_Nodes.cpython-312.pyc +0 -0
- agent/agent_graph/__pycache__/Graph_Routes.cpython-312.pyc +0 -0
- agent/agent_graph/__pycache__/Graph_Utils.cpython-312.pyc +0 -0
- agent/agent_graph/__pycache__/StateTasks.cpython-312.pyc +0 -0
- agent/agent_graph/__pycache__/graph.cpython-312.pyc +0 -0
- agent/agent_graph/graph.py +32 -0
- agent/llm/__pycache__/prompts.cpython-312.pyc +0 -0
- agent/llm/prompts.py +413 -0
- agent/rag/__pycache__/rag.cpython-312.pyc +0 -0
- agent/rag/rag.py +47 -0
- agent/rag/rag.xlsx +0 -0
- agent/tools/PDF.py +36 -0
- agent/tools/__pycache__/PDF.cpython-312.pyc +0 -0
- agent/tools/__pycache__/email.cpython-312.pyc +0 -0
- agent/tools/email.py +39 -0
- app.py +28 -0
- requirements.txt +14 -0
.gitignore
ADDED
|
File without changes
|
Dockerfile
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
FROM python:3.11-slim
|
| 2 |
+
|
| 3 |
+
ENV PYTHONDONTWRITEBYTECODE=1
|
| 4 |
+
ENV PYTHONUNBUFFERED=1
|
| 5 |
+
|
| 6 |
+
WORKDIR /app
|
| 7 |
+
|
| 8 |
+
COPY requirements.txt ./
|
| 9 |
+
RUN pip install --no-cache-dir --upgrade pip && \
|
| 10 |
+
pip install --no-cache-dir -r requirements.txt
|
| 11 |
+
|
| 12 |
+
COPY . .
|
| 13 |
+
|
| 14 |
+
CMD ["python", "Server.py"]
|
Server.py
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from langchain_huggingface import HuggingFaceEndpoint,ChatHuggingFace
|
| 2 |
+
from langchain_core.messages import HumanMessage,SystemMessage
|
| 3 |
+
import os
|
| 4 |
+
import pandas as pd
|
| 5 |
+
from agent.agent_graph.graph import compiled_graph
|
| 6 |
+
from agent.rag.rag import rag_text_chooser
|
| 7 |
+
import sys
|
| 8 |
+
import os
|
| 9 |
+
from agent.agent_graph.StateTasks import Available_Tasks
|
| 10 |
+
from agent.tools.PDF import PDF_generator_Node
|
| 11 |
+
from agent.tools.email import EMAIL_sender_Node
|
| 12 |
+
from agent.agent_graph.Graph_Nodes import get_llm_answer
|
| 13 |
+
from agent.llm.prompts import NODES_Prompts
|
| 14 |
+
import dotenv
|
| 15 |
+
|
| 16 |
+
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..')))
|
| 17 |
+
dotenv.load_dotenv("/content/drive/MyDrive/study/Projects/keys.env")
|
| 18 |
+
def get_response(prompt,memory,hf_key,state,user_email,user_name):
|
| 19 |
+
# Setting up models
|
| 20 |
+
os.environ["HF_TOKEN"] = hf_key
|
| 21 |
+
llm_gpt = HuggingFaceEndpoint(
|
| 22 |
+
repo_id="openai/gpt-oss-20b",#"deepseek-ai/DeepSeek-V3.2-Exp",#"openai/gpt-oss-20b",
|
| 23 |
+
task='conversational',
|
| 24 |
+
provider="auto",
|
| 25 |
+
max_new_tokens=2048
|
| 26 |
+
)
|
| 27 |
+
llm_gpt = ChatHuggingFace(llm=llm_gpt)
|
| 28 |
+
|
| 29 |
+
rag_model = rag_text_chooser(os.path.join(os.path.dirname(__file__), 'agent' ,'rag', 'rag.xlsx'))
|
| 30 |
+
|
| 31 |
+
# update state
|
| 32 |
+
state["question"] = prompt
|
| 33 |
+
state["memory"] = memory
|
| 34 |
+
state["llm"] = llm_gpt
|
| 35 |
+
state["rag_model"] = rag_model
|
| 36 |
+
|
| 37 |
+
call = compiled_graph.invoke(state)
|
| 38 |
+
|
| 39 |
+
save_send_email(call,user_email,user_name)
|
| 40 |
+
os.environ["HF_TOKEN"] = "" # to prevent keep it in env for other calls and for security
|
| 41 |
+
|
| 42 |
+
return call
|
| 43 |
+
|
| 44 |
+
def save_send_email(call,user_email,user_name):
|
| 45 |
+
if ("all_ok" in call.keys()):
|
| 46 |
+
if (call['all_ok']== True):
|
| 47 |
+
if (call['question_type'] in [Available_Tasks.LAPTOP_CHOOSE.value ,
|
| 48 |
+
Available_Tasks.QUESTION.value ,
|
| 49 |
+
Available_Tasks.ROADMAP.value]):
|
| 50 |
+
email_txt = get_llm_answer(model_llm=call['llm'],messages=[HumanMessage(content=("اسم الزميل لتستخدمه هو : "+ user_name +"/n/n")+ NODES_Prompts.Email_text.value + call['question'] + str(call['memory']) + call['question_type'] + call['answer'])])
|
| 51 |
+
title = get_llm_answer(model_llm=call['llm'],messages=[HumanMessage(content=NODES_Prompts.Email_title.value + call['question'] + str(call['memory']) + call['question_type']+ call['answer'])])
|
| 52 |
+
|
| 53 |
+
import tempfile
|
| 54 |
+
path_pdf = ''
|
| 55 |
+
with tempfile.NamedTemporaryFile(suffix=".pdf", delete=False) as tmp_file:
|
| 56 |
+
path_pdf = tmp_file.name
|
| 57 |
+
# هنا تكتب الكود اللي بيولد الملف
|
| 58 |
+
print("PDF path:", path_pdf)
|
| 59 |
+
|
| 60 |
+
# بعد ما تخلص من الملف ممكن تحذفه
|
| 61 |
+
# import os
|
| 62 |
+
# os.remove(path_pdf)
|
| 63 |
+
|
| 64 |
+
|
| 65 |
+
#path_pdf ="/content/drive/MyDrive/study/Projects/CodeBuddyAI/tmp.pdf"
|
| 66 |
+
PDF_generator_Node(call['answer'],title,path_pdf)
|
| 67 |
+
EMAIL_sender_Node(user_email,email_txt,title,path_pdf)
|
| 68 |
+
import os
|
| 69 |
+
os.remove(path_pdf)
|
| 70 |
+
print("Done")
|
| 71 |
+
|
| 72 |
+
|
| 73 |
+
|
__pycache__/Server.cpython-312.pyc
ADDED
|
Binary file (4.28 kB). View file
|
|
|
agent/agent_graph/Graph_Nodes.py
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
from typing import TypedDict, List, Dict, Any, Optional
|
| 3 |
+
from langgraph.graph import StateGraph, START, END
|
| 4 |
+
from agent.agent_graph.StateTasks import *
|
| 5 |
+
from agent.llm.prompts import *
|
| 6 |
+
from typing import get_type_hints
|
| 7 |
+
import json
|
| 8 |
+
from langchain_core.messages import HumanMessage,SystemMessage
|
| 9 |
+
from agent.agent_graph.Graph_Utils import get_egp_to_usd
|
| 10 |
+
from agent.rag.rag import *
|
| 11 |
+
|
| 12 |
+
def answer_question(state:ProblemState):
|
| 13 |
+
print("Answering...")
|
| 14 |
+
question = state["question"]
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
if state["question_type"] == Available_Tasks.LAPTOP_CHOOSE.value:
|
| 18 |
+
guide_prompt = Tasks_prompts.LAPTOP_THINK.value
|
| 19 |
+
elif state["question_type"] == Available_Tasks.ROADMAP.value:
|
| 20 |
+
guide_prompt = Tasks_prompts.ROADMAP.value
|
| 21 |
+
elif ("node_output_article" in state.keys()):
|
| 22 |
+
guide_prompt = Tasks_prompts.ROADMAP.value +"<source>" + state["node_output_article"] +"</source>"
|
| 23 |
+
|
| 24 |
+
else:
|
| 25 |
+
guide_prompt = Tasks_prompts.RAG.value
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
answer_prompt = ((guide_prompt + "طلب المستخدم:\n" + question + "\nاهم معلومات المستخدم لاستخدامها ف الدلالة (بالنسبة للسعر هو نفس السعر لكن بالدولار فدائما ركز على السعر بالدولار\n)"+ str(state) + Route_prompts.FINALIZER_PROMPT.value))
|
| 29 |
+
|
| 30 |
+
print("ANSWER-PROMPT",answer_prompt)
|
| 31 |
+
|
| 32 |
+
state["answer"] = get_llm_answer(model_llm=state["llm"],messages=state["memory"] + [HumanMessage(content=(guide_prompt + "طلب المستخدم:\n" + question + "\nاهم معلومات المستخدم لاستخدامها ف الدلالة (بالنسبة للسعر هو نفس السعر لكن بالدولار فدائما ركز على السعر بالدولار\n)"+ str(state) + Route_prompts.FINALIZER_PROMPT.value))])
|
| 33 |
+
|
| 34 |
+
print("Answer ",state["answer"])
|
| 35 |
+
print("STATE ",state)
|
| 36 |
+
print("----------------------------")
|
| 37 |
+
return state
|
| 38 |
+
|
| 39 |
+
|
| 40 |
+
def update_context(state:ProblemState):
|
| 41 |
+
# Control what keys can be modified to preven hullicination
|
| 42 |
+
keys = get_type_hints(ProblemState).keys()
|
| 43 |
+
keys_modifiable = [] # keep it inside the function to make sure append to it not affected by other calls
|
| 44 |
+
|
| 45 |
+
_is_rag=False
|
| 46 |
+
_rag_text_if_exist = ""
|
| 47 |
+
|
| 48 |
+
for i in list(keys):
|
| 49 |
+
|
| 50 |
+
# 1️⃣ استبعاد المفاتيح غير القابلة للتعديل نهائيًا
|
| 51 |
+
if i in ["question", "answer", "node_output_article", "memory"]:
|
| 52 |
+
continue
|
| 53 |
+
|
| 54 |
+
# 2️⃣ منع تعديل question_type بعد بداية الشات
|
| 55 |
+
# - question_type يُسمح به فقط في أول الشات
|
| 56 |
+
# - لو موجود بالفعل في state → يبقى الشات بدأ → ممنوع التعديل
|
| 57 |
+
# if exist question in data rag skip it
|
| 58 |
+
|
| 59 |
+
if i == "question_type":
|
| 60 |
+
if "question_type" in state.keys():
|
| 61 |
+
continue
|
| 62 |
+
|
| 63 |
+
rag_text = state["rag_model"].get_relevant_question(state["question"])
|
| 64 |
+
|
| 65 |
+
if bool(rag_text):
|
| 66 |
+
_is_rag = True
|
| 67 |
+
_rag_text_if_exist = rag_text # store text to prevent calling twice
|
| 68 |
+
continue
|
| 69 |
+
|
| 70 |
+
# 3️⃣ أي key وصل هنا يبقى مسموح للـ LLM يرجّعه
|
| 71 |
+
keys_modifiable.append(i)
|
| 72 |
+
|
| 73 |
+
# Make the prompt
|
| 74 |
+
prompt_llm_new_info = Route_prompts.Context_UPDATOR.value + "\n <KEYS> \n" +str(keys_modifiable) +"\n </KEYS> <Text>"+state["question"]+"</Text>"
|
| 75 |
+
|
| 76 |
+
print("UPDATE - PROMPT",prompt_llm_new_info)
|
| 77 |
+
|
| 78 |
+
|
| 79 |
+
llm_new_info = get_llm_answer(model_llm=state["llm"],messages = [HumanMessage(prompt_llm_new_info)])
|
| 80 |
+
print("ANSWER ", llm_new_info)
|
| 81 |
+
|
| 82 |
+
|
| 83 |
+
# Save and Process the returned json to prevent hallucination
|
| 84 |
+
try:
|
| 85 |
+
llm_new_info = json.loads(llm_new_info)
|
| 86 |
+
for key in llm_new_info.keys():
|
| 87 |
+
if key in keys_modifiable:
|
| 88 |
+
state[key] = llm_new_info[key]
|
| 89 |
+
|
| 90 |
+
# check if rag
|
| 91 |
+
if _is_rag:
|
| 92 |
+
state["question_type"] = Available_Tasks.QUESTION.value
|
| 93 |
+
state["node_output_article"] = _rag_text_if_exist
|
| 94 |
+
|
| 95 |
+
# Check if all_ok can be answered now
|
| 96 |
+
last_question = state.get("answer", "")
|
| 97 |
+
check_finalized_prompt = (
|
| 98 |
+
"عندك ده اخر سوال واجابة"+
|
| 99 |
+
last_question +
|
| 100 |
+
state["question"] +
|
| 101 |
+
"هل معنى ذلك ان المستخدم اكد على الفهم الصحيح؟" +
|
| 102 |
+
"رجع فقط BOOL (True/False)"
|
| 103 |
+
)
|
| 104 |
+
|
| 105 |
+
print("UPDATE 2 - PROMPT ",check_finalized_prompt)
|
| 106 |
+
check_finalized = get_llm_answer(model_llm=state["llm"], messages = [HumanMessage(
|
| 107 |
+
check_finalized_prompt
|
| 108 |
+
)])
|
| 109 |
+
print("ANSWER ", check_finalized)
|
| 110 |
+
state['all_ok'] = check_finalized.strip().lower() == "true" # If wrong parsed it's false
|
| 111 |
+
print("Context updated")
|
| 112 |
+
|
| 113 |
+
|
| 114 |
+
|
| 115 |
+
except Exception as e:
|
| 116 |
+
print("Context was not updated due to error : ",e)
|
| 117 |
+
|
| 118 |
+
print("STATE ",state)
|
| 119 |
+
print("----------------------------")
|
| 120 |
+
|
| 121 |
+
return state
|
| 122 |
+
|
| 123 |
+
|
| 124 |
+
|
| 125 |
+
def convertPriceToDollar(state:ProblemState):
|
| 126 |
+
print("Converting price to dollar...")
|
| 127 |
+
if "price" in state.keys():
|
| 128 |
+
state["price"] = get_egp_to_usd(state["price"])
|
| 129 |
+
print("STATE ",state)
|
| 130 |
+
print("----------------------------")
|
| 131 |
+
|
| 132 |
+
return state
|
| 133 |
+
|
| 134 |
+
def step(state:ProblemState):
|
| 135 |
+
next_topic = None
|
| 136 |
+
|
| 137 |
+
if "question_type" not in state.keys():
|
| 138 |
+
next_topic = "question_type"
|
| 139 |
+
|
| 140 |
+
|
| 141 |
+
else:
|
| 142 |
+
for i in task_steps[state.get("question_type")]:
|
| 143 |
+
if i not in state.keys():
|
| 144 |
+
next_topic = i
|
| 145 |
+
print("Next topic ",next_topic)
|
| 146 |
+
break
|
| 147 |
+
# Only after finishing the to do list of the question type we can ask for all_ok to confirm
|
| 148 |
+
if (not next_topic) and ("all_ok" not in state.keys() or (state["all_ok"]==False)) and "question_type" in state.keys():
|
| 149 |
+
|
| 150 |
+
next_topic = "all_ok"
|
| 151 |
+
print("Next topic ",next_topic)
|
| 152 |
+
|
| 153 |
+
|
| 154 |
+
|
| 155 |
+
step_prompt = (System_prompts.STATE_DESCRIBE.value + f"<order>{next_topic} </order> <state>{state}</state>" + Route_prompts.FINALIZER_PROMPT_STEP.value)
|
| 156 |
+
print("STEP PROMPT",step_prompt)
|
| 157 |
+
state['answer'] = get_llm_answer(model_llm=state["llm"],messages = [HumanMessage(step_prompt)])
|
| 158 |
+
print("ANSWER ", state['answer'])
|
| 159 |
+
print("STATE ",state)
|
| 160 |
+
print("----------------------------")
|
| 161 |
+
|
| 162 |
+
return state
|
| 163 |
+
|
| 164 |
+
def search_knowledgebase(state:ProblemState):
|
| 165 |
+
"""
|
| 166 |
+
Search the vector database for relevant contexts.
|
| 167 |
+
"""
|
| 168 |
+
# fetch top 3 relevant docs
|
| 169 |
+
state["node_output_article"] = state["rag_model"].get_relevant_question(state["question"])
|
| 170 |
+
|
| 171 |
+
return state
|
| 172 |
+
|
| 173 |
+
def get_llm_answer(model_llm=None,messages=[HumanMessage(content="hi")]):
|
| 174 |
+
return model_llm.invoke(messages).content
|
agent/agent_graph/Graph_Routes.py
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from agent.agent_graph.StateTasks import *
|
| 2 |
+
|
| 3 |
+
def is_question_clear(state:ProblemState): # not check type , only check to do list
|
| 4 |
+
is_clear = True # as used with and later
|
| 5 |
+
|
| 6 |
+
is_clear = is_clear and ("question" in state.keys())
|
| 7 |
+
|
| 8 |
+
is_clear = is_clear and ("question_type" in state.keys()) and (state.get("question_type") in task_steps.keys())
|
| 9 |
+
|
| 10 |
+
if "question_type" in state.keys():
|
| 11 |
+
for step in task_steps[state.get("question_type")]:
|
| 12 |
+
|
| 13 |
+
is_clear = is_clear and (step in state.keys())
|
| 14 |
+
|
| 15 |
+
is_clear = is_clear and (state["all_ok"]==True)
|
| 16 |
+
|
| 17 |
+
return is_clear
|
| 18 |
+
|
| 19 |
+
|
agent/agent_graph/Graph_Utils.py
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import requests
|
| 2 |
+
USD_url = "https://open.er-api.com/v6/latest/EGP"
|
| 3 |
+
|
| 4 |
+
def get_egp_to_usd(egp_amount):
|
| 5 |
+
|
| 6 |
+
try:
|
| 7 |
+
response = requests.get(USD_url, timeout=8)
|
| 8 |
+
response.raise_for_status() # raise error for bad status
|
| 9 |
+
data = response.json()
|
| 10 |
+
|
| 11 |
+
if data.get("result") != "success":
|
| 12 |
+
print("API error:", data)
|
| 13 |
+
return None
|
| 14 |
+
|
| 15 |
+
rate = data["rates"]["USD"]
|
| 16 |
+
usd_amount = egp_amount * rate
|
| 17 |
+
|
| 18 |
+
return usd_amount
|
| 19 |
+
|
| 20 |
+
except Exception as e:
|
| 21 |
+
print("Error:", e)
|
| 22 |
+
return None
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
get_egp_to_usd(1)
|
agent/agent_graph/StateTasks.py
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
from typing import TypedDict, List, Dict, Any, Optional
|
| 3 |
+
from enum import Enum
|
| 4 |
+
|
| 5 |
+
# 1) Core Tasks
|
| 6 |
+
class Available_Tasks(Enum):
|
| 7 |
+
LAPTOP_CHOOSE = "LAPTOP_CHOOSE"
|
| 8 |
+
QUESTION = "QUESTION" # EAG of well known
|
| 9 |
+
ROADMAP = "ROADMAP"
|
| 10 |
+
PROGRAMMING = "PROGRAMMING"
|
| 11 |
+
GENERAL = "GENERAL" # last option with notice
|
| 12 |
+
HELLO = "HELLO" # this is to generally detect hello , but in use update_context prompt control to not classify it as core type
|
| 13 |
+
|
| 14 |
+
# 2) Task Steps
|
| 15 |
+
task_steps = {
|
| 16 |
+
Available_Tasks.GENERAL.value : [],
|
| 17 |
+
Available_Tasks.LAPTOP_CHOOSE.value : ["price","usage","other_concern"],
|
| 18 |
+
Available_Tasks.QUESTION.value : [],
|
| 19 |
+
Available_Tasks.PROGRAMMING.value : [],
|
| 20 |
+
Available_Tasks.ROADMAP.value : ["career","level","experience","skills"],
|
| 21 |
+
Available_Tasks.HELLO.value : []
|
| 22 |
+
}
|
| 23 |
+
|
| 24 |
+
# 3) Tasks State
|
| 25 |
+
class ProblemState(TypedDict):
|
| 26 |
+
# main
|
| 27 |
+
question: str
|
| 28 |
+
answer: Optional[str]
|
| 29 |
+
node_output_article : Optional[str]
|
| 30 |
+
memory: List[Dict[str, Any]] # filled by list of Human/Sytem messages ... as in gui
|
| 31 |
+
|
| 32 |
+
# to do lists
|
| 33 |
+
# same as defined in task_Steps
|
| 34 |
+
question_type : Optional[str] # --> must be of Available_Tasks values
|
| 35 |
+
price : Optional[str]
|
| 36 |
+
usage : Optional[str]
|
| 37 |
+
other_concern : Optional[str]
|
| 38 |
+
career : Optional[str]
|
| 39 |
+
level : Optional[str]
|
| 40 |
+
experience : Optional[List[str]]
|
| 41 |
+
skills : Optional[List[str]]
|
| 42 |
+
all_ok : Optional[bool]
|
| 43 |
+
|
| 44 |
+
# Models
|
| 45 |
+
llm: Optional[Any]
|
| 46 |
+
rag_model: Optional[Any]
|
| 47 |
+
|
| 48 |
+
|
| 49 |
+
|
agent/agent_graph/__pycache__/Finalize_Nodes.cpython-312.pyc
ADDED
|
Binary file (2.6 kB). View file
|
|
|
agent/agent_graph/__pycache__/Graph_Nodes.cpython-312.pyc
ADDED
|
Binary file (7.46 kB). View file
|
|
|
agent/agent_graph/__pycache__/Graph_Routes.cpython-312.pyc
ADDED
|
Binary file (943 Bytes). View file
|
|
|
agent/agent_graph/__pycache__/Graph_Utils.cpython-312.pyc
ADDED
|
Binary file (1.01 kB). View file
|
|
|
agent/agent_graph/__pycache__/StateTasks.cpython-312.pyc
ADDED
|
Binary file (1.92 kB). View file
|
|
|
agent/agent_graph/__pycache__/graph.cpython-312.pyc
ADDED
|
Binary file (1.09 kB). View file
|
|
|
agent/agent_graph/graph.py
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from IPython.display import Image, display
|
| 2 |
+
from langgraph.graph import StateGraph, START, END
|
| 3 |
+
from agent.agent_graph.Graph_Nodes import *
|
| 4 |
+
from agent.agent_graph.Graph_Routes import *
|
| 5 |
+
|
| 6 |
+
problem_graph = StateGraph(ProblemState)
|
| 7 |
+
|
| 8 |
+
# Add nodes
|
| 9 |
+
problem_graph.add_node("answer_question",answer_question)
|
| 10 |
+
problem_graph.add_node("update_context",update_context)
|
| 11 |
+
problem_graph.add_node("convertPriceToDollar",convertPriceToDollar)
|
| 12 |
+
problem_graph.add_node("step",step)
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
# Routes
|
| 16 |
+
problem_graph.add_conditional_edges(
|
| 17 |
+
"update_context",
|
| 18 |
+
is_question_clear,
|
| 19 |
+
{
|
| 20 |
+
True: "convertPriceToDollar",
|
| 21 |
+
False: "step"
|
| 22 |
+
}
|
| 23 |
+
)
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
# Edges
|
| 27 |
+
problem_graph.add_edge(START,"update_context")
|
| 28 |
+
problem_graph.add_edge("convertPriceToDollar","answer_question")
|
| 29 |
+
|
| 30 |
+
# Finalize
|
| 31 |
+
compiled_graph = problem_graph.compile()
|
| 32 |
+
#display(Image(compiled_graph.get_graph().draw_mermaid_png()))
|
agent/llm/__pycache__/prompts.cpython-312.pyc
ADDED
|
Binary file (20.9 kB). View file
|
|
|
agent/llm/prompts.py
ADDED
|
@@ -0,0 +1,413 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from enum import Enum
|
| 2 |
+
from agent.agent_graph.StateTasks import Available_Tasks
|
| 3 |
+
|
| 4 |
+
class System_prompts(Enum):
|
| 5 |
+
STATE_DESCRIBE = """
|
| 6 |
+
بيانات الحالة (state) مقسمة كالآتي:
|
| 7 |
+
|
| 8 |
+
1. البيانات الأساسية
|
| 9 |
+
|
| 10 |
+
question: str → هذا هو السؤال الذي أدخله المستخدم.
|
| 11 |
+
|
| 12 |
+
answer: Optional[str] → هذا الحقل مخصص لإجابتك، لكن لا تكتب فيه مباشرة، كود آخر سيملأه لاحقًا.
|
| 13 |
+
|
| 14 |
+
node_output_article: Optional[str] → هذا النص يُستخدم لإرسال معلومات إلى نود آخر، مثل نص سيتم إرساله عبر البريد، فقط عند الحاجة.
|
| 15 |
+
|
| 16 |
+
memory: List[Dict[str, Any]] → سجل المحادثة السابقة (الرسائل من المستخدم والنظام)، لا تملأه، كود آخر سيستخدمه.
|
| 17 |
+
|
| 18 |
+
2. قائمة المهام (To-Do / Question Type)
|
| 19 |
+
|
| 20 |
+
question_type: Optional[str] → يحدد نوع السؤال، ويجب أن يكون أحد القيم التالية من Enum Available_Tasks:
|
| 21 |
+
|
| 22 |
+
LAPTOP_CHOOSE → أي سؤال عن لابتوب أو كمبيوتر أو جهاز شغل.
|
| 23 |
+
|
| 24 |
+
ROADMAP → لو السؤال عن خارطة تعلم أو مسار دراسة (رودماب).
|
| 25 |
+
|
| 26 |
+
QUESTION → أسئلة مشهورة أو RAG.
|
| 27 |
+
|
| 28 |
+
PROGRAMMING → أي سؤال تقني أو برمجة دقيق.
|
| 29 |
+
|
| 30 |
+
GENERAL → أي سؤال آخر.
|
| 31 |
+
|
| 32 |
+
3. بيانات خاصة بالسؤال عن لابتوب
|
| 33 |
+
|
| 34 |
+
price: Optional[str] → الميزانية بالدولار.
|
| 35 |
+
|
| 36 |
+
usage: Optional[str] →
|
| 37 |
+
→ الغرض الأساسي اللي الجهاز معمول عشانه
|
| 38 |
+
→ الحاجة اللي لو الجهاز مش هيشغلها كويس يبقى فاشل
|
| 39 |
+
→ اختر حاجة واحدة فقط
|
| 40 |
+
"تعرفها ازاى؟ لو قال "استخدامى الاساسى
|
| 41 |
+
|
| 42 |
+
other_concern: Optional[str] →
|
| 43 |
+
→ أي استخدام إضافي أو ثانوي
|
| 44 |
+
→ حاجات "لطيفة لو موجودة" بس مش سبب الشراء الأساسي
|
| 45 |
+
→ ممكن يكون أكتر من حاجة
|
| 46 |
+
"تعرفها ازاى؟ لو قال "استخدام اخر
|
| 47 |
+
|
| 48 |
+
4. بيانات خاصة بالسؤال عن رودماب
|
| 49 |
+
|
| 50 |
+
career: Optional[str] → المجال الذي يود المستخدم العمل فيه.
|
| 51 |
+
→ المجال أو الوظيفة اللي عايز يشتغل فيها
|
| 52 |
+
→ اسم مجال واحد واضح
|
| 53 |
+
→ "عايز أبقى إيه؟"
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
level: Optional[str] → مستواه الحالي (مبتدئ، متوسط، متقدم).
|
| 57 |
+
→ مستواه الحالي في المجال ده
|
| 58 |
+
→ قيمة واحدة فقط: مبتدئ / متوسط / متقدم
|
| 59 |
+
→ إحساس عام مش تفاصيل
|
| 60 |
+
|
| 61 |
+
|
| 62 |
+
experience: Optional[List[str]] → خبراته السابقة.
|
| 63 |
+
→ حاجات اشتغل عليها قبل كده فعلًا
|
| 64 |
+
→ مشاريع، شغل، دراسة عملية
|
| 65 |
+
→ إجابة سؤال: "عملت إيه قبل كده؟"
|
| 66 |
+
|
| 67 |
+
|
| 68 |
+
|
| 69 |
+
skills: Optional[List[str]] → المهارات التي يمتلكها.
|
| 70 |
+
→ مهارات أو أدوات بيعرف يستخدمها
|
| 71 |
+
→ لغات، تقنيات، فريموركس
|
| 72 |
+
→ إجابة سؤال: "بتعرف تعمل بإيه؟"
|
| 73 |
+
|
| 74 |
+
|
| 75 |
+
5. بيانات عامة
|
| 76 |
+
|
| 77 |
+
all_ok: Optional[bool] → للتأكد من صحة التحليل؛ ستسأل المستخدم "هل هذه المعلومات صحيحة؟" ويجيب بنعم أو لا.
|
| 78 |
+
"""
|
| 79 |
+
SYSTEM_PROMPT = """
|
| 80 |
+
انت نظام CodeBuddy نظام مخصص للمبرمجين الجداد
|
| 81 |
+
تجب عن الاسئلة المشهورة كمبتدا وتصنع خرائط roadmaps وترشح لابتوب وغيره
|
| 82 |
+
|
| 83 |
+
- يجب ان تكون ودودا
|
| 84 |
+
- فكر قبل الاجابة
|
| 85 |
+
- اذا كنت غير متاكد ف الاجابة لديك الحرية ان تقول
|
| 86 |
+
"بص هو غالبا ......على اساس ان ...سبب .. ممكن تحاول تدور فيها اكتر او هتوضح مع الخبرة"
|
| 87 |
+
-حاول بردوا تفهم شعور الطالب لو مرتبك تكون تقوله بالراحة كدة ولو حزين قله فاهمك يخويك متزعلش ....
|
| 88 |
+
- اذا اعطيتك خيارات لارجاع منها اياك ابدا ابدا ان تخرج عنها او ترجع قيمة فارغة بل فكر واختار الاقرب حسب المعنى
|
| 89 |
+
- مش لازم تطول وتزود كتير خليك مركز
|
| 90 |
+
- - لا تتوقف قبل إكمال الفكرة
|
| 91 |
+
|
| 92 |
+
|
| 93 |
+
|
| 94 |
+
ستستلم معلومات ال state كالاتى:
|
| 95 |
+
|
| 96 |
+
""" + STATE_DESCRIBE
|
| 97 |
+
|
| 98 |
+
class Tasks_prompts(Enum):
|
| 99 |
+
|
| 100 |
+
ROADMAP = f"""
|
| 101 |
+
أنت الآن دورك مستشار تعلم ودود. مهمتك مساعدة الشخص على وضع **خطة تعلم شخصية منظمة** بناءً على معلوماته:
|
| 102 |
+
|
| 103 |
+
- career: المجال أو الوظيفة اللي عايز يشتغل فيها
|
| 104 |
+
- level: مستواه الحالي أو كم سنة شغال
|
| 105 |
+
- experience: خبراته العملية الحالية
|
| 106 |
+
- skills: المهارات اللي عنده
|
| 107 |
+
|
| 108 |
+
مطلوب منك:
|
| 109 |
+
1) تبني له خطة منظمة خطوة بخطوة
|
| 110 |
+
2) تشمل تأسيس قوي للمبادئ الأساسية
|
| 111 |
+
3) تخليه يواكب العصر والتقنيات الحديثة
|
| 112 |
+
4) شرحها بطريقة بسيطة ومريحة، بحيث ميتعقدش أو يحس بالضغط
|
| 113 |
+
5) تخليه يطلع مشروع أو نتيجة قريبة ممكن يعملها، حتى لو بسيطة، لو أمكن
|
| 114 |
+
|
| 115 |
+
قواعد أثناء الكتابة:
|
| 116 |
+
- ركز على **الأساسيات أولاً ثم التدرج للمستوى المتقدم**
|
| 117 |
+
- قدم أمثلة عملية بسيطة، بدون غرق في تفاصيل دقيقة جداً
|
| 118 |
+
- وضّح أدوات أو موارد ممكن تساعده، سواء أونلاين أو برامج بسيطة
|
| 119 |
+
- أخيراً، شجّعه على البدء الآن:
|
| 120 |
+
> "خد خطوة دلوقتي، والباقي هييجي مع الوقت، وكلنا بنحتار الأول، المهم تبدأ."
|
| 121 |
+
|
| 122 |
+
"""
|
| 123 |
+
|
| 124 |
+
RAG = f"""
|
| 125 |
+
انت المصدر الاخير للمعلومات. لا تستخدم أي معلومة غير موجودة في <source>.
|
| 126 |
+
إذا لم يكن هناك إجابة واضحة في <source>، أجب: "لا تتوفر معلومات كافية".
|
| 127 |
+
صغ الرد بأسلوب ودود ومرتب، لا تضف أمثلة أو أرقام من خبرتك الشخصية.
|
| 128 |
+
إذا كان المصدر يشير إلى موقع فقط، فاشرح للمستخدم أن البيانات يمكن الاطلاع عليها في هذا الموقع.
|
| 129 |
+
استعمل مصدر المعلومات الاتى
|
| 130 |
+
"""
|
| 131 |
+
LAPTOP_THINK = f"""
|
| 132 |
+
أنت الآن في دور مستشار تقني ودود.
|
| 133 |
+
مهمتك مساعدة المستخدم يفكّر إزاي يختار لابتوب، وليس ماذا يشتري.
|
| 134 |
+
ممنوع تمامًا ذكر أي اسم جهاز أو موديل أو شركة.
|
| 135 |
+
|
| 136 |
+
====================
|
| 137 |
+
قواعد صارمة قبل الإجابة
|
| 138 |
+
====================
|
| 139 |
+
|
| 140 |
+
1) لا افتراض:
|
| 141 |
+
ممنوع افتراض وجود مواصفات غير منطقية للسعر.
|
| 142 |
+
لو المواصفة غير متاحة اقتصاديًا → صرّح بأنها غير ممكنة.
|
| 143 |
+
|
| 144 |
+
2) السعر هو الحاكم:
|
| 145 |
+
إذا تعارض الاستخدام مع السعر → السعر يكسب.
|
| 146 |
+
ممنوع رفع المواصفات لإرضاء الاستخدام.
|
| 147 |
+
|
| 148 |
+
3) لا دقة زائفة:
|
| 149 |
+
❌ ممنوع الجداول
|
| 150 |
+
❌ ممنوع ذكر أجيال حديثة مع أسعار رخيصة
|
| 151 |
+
❌ ممنوع ذكر كروت شاشة قوية أو حديثة إلا إذا السعر يسمح منطقيًا
|
| 152 |
+
|
| 153 |
+
4) نبرة الإجابة:
|
| 154 |
+
لا تتحدث بثقة مطلقة.
|
| 155 |
+
استخدم دائمًا:
|
| 156 |
+
"في الغالب"
|
| 157 |
+
"المتوقع"
|
| 158 |
+
"المنطقي في الرينج ده"
|
| 159 |
+
لو في شك → قل إنه حد أدنى أو توقع، وليس ضمانًا.
|
| 160 |
+
|
| 161 |
+
5) حجم الإجابة:
|
| 162 |
+
لو السؤال بسيط → الإجابة لا تتجاوز 8–10 سطور.
|
| 163 |
+
ممنوع التقارير الطويلة.
|
| 164 |
+
|
| 165 |
+
====================
|
| 166 |
+
الخطوة 1: تحديد الاستخدام (الأهم)
|
| 167 |
+
====================
|
| 168 |
+
|
| 169 |
+
ابدأ دائمًا بتحديد الاستخدام الأساسي فقط.
|
| 170 |
+
❌ ممنوع شرح كل الاستخدامات
|
| 171 |
+
❌ ممنوع فتح أقسام لم يُسأل عنها
|
| 172 |
+
✅ مسموح فقط ذكر نوع المعالج / الجيل / الرام / التخزين / الكارت بشكل عام
|
| 173 |
+
✅لو في تعارض بين السعر والمواصفات، وضّح التعارض بدل ما تحاول تلفّق حل.
|
| 174 |
+
ردودك تكون خطوط عريضة بدون تشعب.
|
| 175 |
+
|
| 176 |
+
خريطة الاستخدام → المتطلبات العامة:
|
| 177 |
+
|
| 178 |
+
- دراسة فقط:
|
| 179 |
+
→ أي جهاز حديث نسبيًا ينفع
|
| 180 |
+
|
| 181 |
+
- برمجة ويب / موبايل:
|
| 182 |
+
→ Core i3 أو i5 قديم نسبيًا
|
| 183 |
+
→ التركيز على RAM و SSD
|
| 184 |
+
|
| 185 |
+
- ألعاب:
|
| 186 |
+
→ التركيز على كارت الشاشة
|
| 187 |
+
→ لو السعر قليل جدًا، صرّح أن الأداء سيكون محدود جدًا
|
| 188 |
+
→ لو الألعاب اهتمام جانبي: سطر تحذيري واحد فقط بدون ذكر كروت أو VRAM
|
| 189 |
+
|
| 190 |
+
- مونتاج / جرافيكس:
|
| 191 |
+
→ كارت مخصص للمونتاج + بروسيسور أقوى نسبيًا
|
| 192 |
+
|
| 193 |
+
- ذكاء اصطناعي:
|
| 194 |
+
→ الكارت + البروسيسور أهم شيء
|
| 195 |
+
→ أفضل أداء ممكن داخل الفئة السعرية فقط
|
| 196 |
+
|
| 197 |
+
- استخدام غير محدد:
|
| 198 |
+
→ جهاز متوازن داخل الفئة السعرية
|
| 199 |
+
|
| 200 |
+
أساسيات في كل الحالات:
|
| 201 |
+
- SSD
|
| 202 |
+
- RAM لا تقل عن 8GB
|
| 203 |
+
- Windows 10/11 أو Linux حديث أو macOS
|
| 204 |
+
|
| 205 |
+
====================
|
| 206 |
+
الخطوة 2: تقريب المواصفات
|
| 207 |
+
====================
|
| 208 |
+
|
| 209 |
+
قرّب المواصفات الواقعية فقط.
|
| 210 |
+
اذكر "أفضل ما يمكن استهدافه" داخل نفس الفئة السعرية في 2025.
|
| 211 |
+
ممنوع ذكر مواصفات تعلم أنها نادرة أو غير متاحة في هذا السعر.
|
| 212 |
+
|
| 213 |
+
====================
|
| 214 |
+
الخطوة 3: البرامج
|
| 215 |
+
====================
|
| 216 |
+
|
| 217 |
+
لو المستخدم ذكر برنامج:
|
| 218 |
+
قل له يرجع للموقع الرسمي ويشوف المتطلبات.
|
| 219 |
+
اذكر أمثلة أسماء فقط بدون شرح:
|
| 220 |
+
Android Studio – Blender – AutoCAD
|
| 221 |
+
|
| 222 |
+
====================
|
| 223 |
+
الخطوة 4: Other Concern
|
| 224 |
+
====================
|
| 225 |
+
|
| 226 |
+
لخّص أي احتياج إضافي في سطر واحد.
|
| 227 |
+
لو خارج نطاق السعر → صرّح بذلك بوضوح.
|
| 228 |
+
|
| 229 |
+
====================
|
| 230 |
+
الخطوة 5: السعر
|
| 231 |
+
====================
|
| 232 |
+
|
| 233 |
+
- قيّم السعر: رخيص / متوسط / غالي (حسب 2025)
|
| 234 |
+
- لو بالجنيه: حوّله تقديريًا للدولار
|
| 235 |
+
- قل: "أعلى مواصفات منطقية في الرينج ده غالبًا هي…"
|
| 236 |
+
|
| 237 |
+
لو السعر غير كافٍ:
|
| 238 |
+
صرّح بذلك بوضوح.
|
| 239 |
+
اقترح بدائل أونلاين مناسبة فقط للاستخدام الأساسي:
|
| 240 |
+
Google Colab – Firebase – Android IDX – VS Code Web
|
| 241 |
+
|
| 242 |
+
====================
|
| 243 |
+
الخطوة 6: الخاتمة
|
| 244 |
+
====================
|
| 245 |
+
|
| 246 |
+
أكّد أن التعلم والتفكير أهم من قوة اللابتوب.
|
| 247 |
+
شجّع المستخدم يبدأ دلوقتي.
|
| 248 |
+
|
| 249 |
+
====================
|
| 250 |
+
اكتب الإجابة الآن بأسلوب ودود وبسيط.
|
| 251 |
+
أنهِي الرد بجملة واضحة ولا تتوقف في منتصف جملة.
|
| 252 |
+
|
| 253 |
+
"""
|
| 254 |
+
|
| 255 |
+
|
| 256 |
+
|
| 257 |
+
GENERAL_QUESTION = f"""
|
| 258 |
+
انت المصدر الاخير للمعلومات
|
| 259 |
+
فقله فيما معناه ان لا تتوفر اجابة والاجابة مصدرها اجتهاد وقد تكون غير محدثة
|
| 260 |
+
-ثم اجب
|
| 261 |
+
"""
|
| 262 |
+
|
| 263 |
+
class Route_prompts(Enum):
|
| 264 |
+
Context_UPDATOR = """
|
| 265 |
+
ساعطيك نصا ف <text>
|
| 266 |
+
المطلوب حلل النص ورجع المعلومات ال فيه بصورة dictionary json
|
| 267 |
+
- only onlys dict no other words like "json"...
|
| 268 |
+
- keys of the json to be returned must be only from <Keys> only not </keys>
|
| 269 |
+
- يعنى ال مطلوب منك ببساطة حلل ال ف text لو ف معلومة من اللمرفقين ف keys
|
| 270 |
+
موجود ف النص ام لا
|
| 271 |
+
❗ بخصوص المفتاح all_ok:
|
| 272 |
+
- لا تحاول تخمينه أو استنتاجه بأي شكل.
|
| 273 |
+
- لا تُرجِع all_ok إلا إذا صرّح المستخدم صراحة أنه موافق / تمام / كده تمام / مفهوم / كله واضح.
|
| 274 |
+
- إذا لم يوجد تأكيد صريح من المستخدم → لا تُرجِع all_ok نهائيًا.
|
| 275 |
+
- إذا قال المستخدم "لا معنديش استخدامات تانية" او ذكر اى كلمة استخدام فرعى فحدث other_concern
|
| 276 |
+
ولا تضعها في usage
|
| 277 |
+
- اياك اياك ابدا ان ترجع فى question_type
|
| 278 |
+
اى شى غير موجود فى
|
| 279 |
+
"""+str([i.value for i in Available_Tasks if i.name!="QUESTION"])+"""}
|
| 280 |
+
ex
|
| 281 |
+
→ ارجع {"other_concern": "لا يوجد"}
|
| 282 |
+
❗ ممنوع الدمج أو التعميم:
|
| 283 |
+
- لا تدمج مجالات.
|
| 284 |
+
- لا تفترض نية المستخدم.
|
| 285 |
+
- لا تكمّل الناقص من عندك.
|
| 286 |
+
|
| 287 |
+
|
| 288 |
+
1-USER: عاوز لابتوب ف رينج 5000
|
| 289 |
+
System: {"price":5000,"question_type":"LAPTOP_CHOOSE"}
|
| 290 |
+
|
| 291 |
+
2- USER: عاوز اتعلم برمجة موبايل
|
| 292 |
+
System: {"question_type":"ROADMAP","career":"برمجة موبايل"}
|
| 293 |
+
|
| 294 |
+
3- USER :مشعارف
|
| 295 |
+
System: {}
|
| 296 |
+
|
| 297 |
+
4- USER: معاى نص مليون جنيه
|
| 298 |
+
System: {"price":1000000}
|
| 299 |
+
5- USER : السلام عليكم اى الاخبار
|
| 300 |
+
System: {}
|
| 301 |
+
"""
|
| 302 |
+
|
| 303 |
+
|
| 304 |
+
FINALIZER_PROMPT = """
|
| 305 |
+
صوغ الكل��م ف صيغة ودودة ومرتبه كانك بتشرح مش بتتكلم
|
| 306 |
+
الآن اكتب الإجابة النهائية للمستخدم. أنهِي الرد بجملة واضحة ولا تتوقف ابدا في منتصف جملة.
|
| 307 |
+
"""
|
| 308 |
+
|
| 309 |
+
FINALIZER_PROMPT_STEP = """
|
| 310 |
+
أنت في خطوة الـ Finalizer.
|
| 311 |
+
مهمتك سؤال واحد فقط بناءً على قيمة <order>، ولا شيء غيره.
|
| 312 |
+
|
| 313 |
+
قواعد صارمة:
|
| 314 |
+
1) اسأل سؤال واحد فقط متعلق بـ <order>.
|
| 315 |
+
2) لا تضف أي معلومات أو نصائح أو استنتاجات.
|
| 316 |
+
3) لا تنتقل لمرحلة التأكيد (all_ok) إلا إذا كانت بياناتها مكتملة.
|
| 317 |
+
4) لا تسأل "هل هذه المعلومات صحيحة" إلا إذا كان <order> == all_ok.
|
| 318 |
+
5 ) لو الإدخال تحية أو كلام عام، لا تذهب إلى all_ok.
|
| 319 |
+
رد التحية اولا ثم اساله عاوز اى
|
| 320 |
+
اياك تشرح التحية
|
| 321 |
+
6) قدم ملخصًا واضحًا لما فهمته في جملة واحدة
|
| 322 |
+
(من معطى ال <state> قدم ملخص اى ال فهمته مطلوب اذا فقط وجد معلومات)
|
| 323 |
+
- يجب الا تكون غبيا اذا فقط السوال هو تحية فرد التحية مطولش
|
| 324 |
+
ومتقولش فهمت انك بتحيي
|
| 325 |
+
7)اى حاجة غير is_ok وضحها بظبط بطريقة بسيطة ومثال
|
| 326 |
+
كما ف الامثلة
|
| 327 |
+
|
| 328 |
+
8)يجب ان:
|
| 329 |
+
- توضيح بسيط للمقصود
|
| 330 |
+
- مثال واحد أو أكثر
|
| 331 |
+
حتى لو كان السؤال مباشر.
|
| 332 |
+
|
| 333 |
+
|
| 334 |
+
❗ تحذير:
|
| 335 |
+
يُمنع منعًا باتًا سؤال أي شيء غير <order>.
|
| 336 |
+
حتى لو كانت معلومة ناقصة أو مذكورة سابقًا.
|
| 337 |
+
|
| 338 |
+
|
| 339 |
+
|
| 340 |
+
النبرة المطلوبة:
|
| 341 |
+
- ودودة وبسيطة.
|
| 342 |
+
- كأنك زميل بتتكلم، مش بوت.
|
| 343 |
+
- بدون كلمات رسمية زي "بالرجاء".
|
| 344 |
+
وبردود مشجعة
|
| 345 |
+
ومودبة مش كلمة عاوز
|
| 346 |
+
|
| 347 |
+
التصرف حسب <order>:
|
| 348 |
+
- إذا <order> == usage:
|
| 349 |
+
اسأل: "طيب استخدامك الأساسي إيه؟"
|
| 350 |
+
- إذا <order> == price:
|
| 351 |
+
اسأل: "طيب بادجتك كام تقريبًا؟"
|
| 352 |
+
- إذا <order> == all_ok:
|
| 353 |
+
قدم ملخصًا واضحًا لما فهمته في جملة واحدة،
|
| 354 |
+
ثم اسأل: "هل فهمي كده صح؟"
|
| 355 |
+
|
| 356 |
+
|
| 357 |
+
مثال:
|
| 358 |
+
<order>usage</order>
|
| 359 |
+
الرد: طيب استخدامك الأساسي إيه؟
|
| 360 |
+
اقصد اهم استخدام → الحاجة اللي لو الجهاز مش هيشغلها كويس يبقى فاشل
|
| 361 |
+
|
| 362 |
+
مثال:
|
| 363 |
+
<order>other_concern </order>
|
| 364 |
+
الرد : عندك اى استخدام تانى؟
|
| 365 |
+
→ حاجات "لطيفة لو موجودة" بس مش سبب الشراء الأساسي
|
| 366 |
+
|
| 367 |
+
مثال:
|
| 368 |
+
<order>price</order>
|
| 369 |
+
الرد: طيب بادجتك كام تقريبًا؟
|
| 370 |
+
نطاق السعر ال تقدر تدفعه
|
| 371 |
+
(ادخل رقم واحد للمتوسط)
|
| 372 |
+
|
| 373 |
+
|
| 374 |
+
مثال:
|
| 375 |
+
<order>all_ok</order>
|
| 376 |
+
الرد: تمام، فهمت إنك عايز لابتوب بسعر X لاستخدام Y، هل فهمي كده صح؟
|
| 377 |
+
|
| 378 |
+
|
| 379 |
+
"""
|
| 380 |
+
|
| 381 |
+
class NODES_Prompts(Enum):
|
| 382 |
+
Email_text = """
|
| 383 |
+
سأعطيك نصًا يحتوي على محادثة كاملة،
|
| 384 |
+
وفي النهاية توجد الإجابة أو النتيجة النهائية.
|
| 385 |
+
|
| 386 |
+
لا تهتم بالتفاصيل الدقيقة داخل الحوار.
|
| 387 |
+
المطلوب هو فهم السياق العام فقط.
|
| 388 |
+
|
| 389 |
+
اكتب ملخصًا قصيرًا مناسبًا ليكون نص بريد إلكتروني
|
| 390 |
+
مرسل إلى زميل عمل، يوضح خلاصة ما تم الاتفاق عليه.
|
| 391 |
+
|
| 392 |
+
يجب أن يكون الأسلوب مهنيًا وبسيطًا.
|
| 393 |
+
يمكنك الإشارة إلى أن التفاصيل موجودة في الملف إذا احتاجها.
|
| 394 |
+
|
| 395 |
+
المطلوب:
|
| 396 |
+
- إخراج نص الإيميل فقط. بالعامية المصرى
|
| 397 |
+
- بدون أي مقدمات أو شروحات إضافية.
|
| 398 |
+
"""
|
| 399 |
+
|
| 400 |
+
Email_title = """
|
| 401 |
+
سأعطيك نصًا يحتوي على محادثة كاملة،
|
| 402 |
+
وفي النهاية توجد الإجابة أو النتيجة النهائية.
|
| 403 |
+
|
| 404 |
+
لا تهتم بالتفاصيل.
|
| 405 |
+
المطلوب هو فهم موضوع المحادثة فقط.
|
| 406 |
+
|
| 407 |
+
اكتب عنوانًا قصيرًا وواضحًا يلخص موضوع المحادثة
|
| 408 |
+
كما لو كان عنوان بريد إلكتروني.
|
| 409 |
+
|
| 410 |
+
المطلوب:
|
| 411 |
+
- إخراج العنوان فقط.
|
| 412 |
+
- بدون أي نص إضافي.
|
| 413 |
+
"""
|
agent/rag/__pycache__/rag.cpython-312.pyc
ADDED
|
Binary file (2.46 kB). View file
|
|
|
agent/rag/rag.py
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from langchain_text_splitters import CharacterTextSplitter
|
| 2 |
+
from langchain_core.documents import Document # Added import for Document
|
| 3 |
+
from sentence_transformers import SentenceTransformer, util
|
| 4 |
+
import pandas as pd
|
| 5 |
+
|
| 6 |
+
class rag_text_chooser:
|
| 7 |
+
def __init__(self,data_rag):
|
| 8 |
+
self.data_rag = pd.read_excel(data_rag)
|
| 9 |
+
|
| 10 |
+
self.corpus, self.answers = self.get_questions_Answers()
|
| 11 |
+
self.model = SentenceTransformer('sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2')
|
| 12 |
+
self.corpus_embeddings = self.model.encode(self.corpus)
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
def get_questions_Answers(self):
|
| 17 |
+
|
| 18 |
+
questions = []
|
| 19 |
+
answers = []
|
| 20 |
+
|
| 21 |
+
for _, row in self.data_rag.iterrows():
|
| 22 |
+
questions.append(row[0])
|
| 23 |
+
answers.append(row[1])
|
| 24 |
+
|
| 25 |
+
return questions, answers
|
| 26 |
+
|
| 27 |
+
def get_relevant_question(self, query):
|
| 28 |
+
# 4) Encode the Arabic query
|
| 29 |
+
query_embedding = self.model.encode(query)
|
| 30 |
+
|
| 31 |
+
# 5) Compute cosine similarity
|
| 32 |
+
cos_scores = util.cos_sim(query_embedding, self.corpus_embeddings)[0]
|
| 33 |
+
|
| 34 |
+
# 6) Rank results
|
| 35 |
+
top_results = cos_scores.argsort(descending=True)
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
matched_result = None
|
| 39 |
+
for idx in top_results:
|
| 40 |
+
if (cos_scores[idx] < .7): # Mostly not relate to her:
|
| 41 |
+
matched_result = None
|
| 42 |
+
else:
|
| 43 |
+
matched_result = (f"Questions {self.corpus[idx]} \n Answer {self.answers[idx]} \n (score: {cos_scores[idx]:.4f})")
|
| 44 |
+
|
| 45 |
+
break
|
| 46 |
+
|
| 47 |
+
return matched_result
|
agent/rag/rag.xlsx
ADDED
|
Binary file (10.1 kB). View file
|
|
|
agent/tools/PDF.py
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from markdown_pdf import MarkdownPdf, Section
|
| 2 |
+
import os
|
| 3 |
+
|
| 4 |
+
#### For this version the nodes used directly not by graph
|
| 5 |
+
|
| 6 |
+
format_css = """
|
| 7 |
+
body {
|
| 8 |
+
font-family: 'Amiri', 'Arial', sans-serif; /* خط يدعم عربي وانجليزي */
|
| 9 |
+
font-size: 12pt;
|
| 10 |
+
line-height: 1.6;
|
| 11 |
+
direction: rtl; /* لجعل النص من اليمين لليسار */
|
| 12 |
+
margin: 20px;
|
| 13 |
+
}
|
| 14 |
+
h1, h2, h3 {
|
| 15 |
+
color: #2E86C1;
|
| 16 |
+
margin-bottom: 10px;
|
| 17 |
+
}
|
| 18 |
+
table {
|
| 19 |
+
border-collapse: collapse;
|
| 20 |
+
width: 100%;
|
| 21 |
+
margin-bottom: 10px;
|
| 22 |
+
}
|
| 23 |
+
table, th, td {
|
| 24 |
+
border: 1px solid #555;
|
| 25 |
+
padding: 6px;
|
| 26 |
+
}
|
| 27 |
+
th {
|
| 28 |
+
background-color: #f0f0f0;
|
| 29 |
+
}
|
| 30 |
+
"""
|
| 31 |
+
|
| 32 |
+
def PDF_generator_Node(text_md,text_title,path_pdf):
|
| 33 |
+
pdf = MarkdownPdf(toc_level=2)
|
| 34 |
+
pdf.add_section(Section("# "+text_title), user_css=format_css)
|
| 35 |
+
pdf.add_section(Section(text_md), user_css=format_css)
|
| 36 |
+
pdf.save(path_pdf)
|
agent/tools/__pycache__/PDF.cpython-312.pyc
ADDED
|
Binary file (1.24 kB). View file
|
|
|
agent/tools/__pycache__/email.cpython-312.pyc
ADDED
|
Binary file (1.6 kB). View file
|
|
|
agent/tools/email.py
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import smtplib
|
| 2 |
+
from email.message import EmailMessage
|
| 3 |
+
import os
|
| 4 |
+
|
| 5 |
+
#### For this version the nodes used directly not by graph
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
smtp_server = "smtp.gmail.com" # SMTP is protcol for sending mail, use this server
|
| 9 |
+
smtp_port = 587
|
| 10 |
+
# for large scale / send many message you should use other server
|
| 11 |
+
|
| 12 |
+
def EMAIL_sender_Node(user_email,email_txt,subject,path_pdf):
|
| 13 |
+
APP_email = os.environ["APP_email"]
|
| 14 |
+
APP_password = os.environ["APP_password"]
|
| 15 |
+
|
| 16 |
+
msg = EmailMessage()
|
| 17 |
+
msg["Subject"] = subject
|
| 18 |
+
msg["From"] = APP_email
|
| 19 |
+
msg["To"] = user_email
|
| 20 |
+
|
| 21 |
+
msg.set_content(email_txt)
|
| 22 |
+
|
| 23 |
+
with open(path_pdf, "rb") as f:
|
| 24 |
+
file_data = f.read()
|
| 25 |
+
msg.add_attachment(file_data,
|
| 26 |
+
maintype="application",
|
| 27 |
+
subtype="pdf",
|
| 28 |
+
filename=path_pdf)
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
with smtplib.SMTP(smtp_server, smtp_port) as server:
|
| 32 |
+
server.ehlo() # know server / get info
|
| 33 |
+
server.starttls() # start the tls (securing protocol)
|
| 34 |
+
server.ehlo()
|
| 35 |
+
server.login(APP_email, APP_password)
|
| 36 |
+
server.send_message(msg)
|
| 37 |
+
print("Email sent!")
|
| 38 |
+
|
| 39 |
+
|
app.py
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from fastapi import FastAPI
|
| 2 |
+
import sys
|
| 3 |
+
import os
|
| 4 |
+
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..')))
|
| 5 |
+
from Server import get_response
|
| 6 |
+
from pydantic import BaseModel
|
| 7 |
+
|
| 8 |
+
# Create app instance
|
| 9 |
+
app = FastAPI()
|
| 10 |
+
|
| 11 |
+
class RequestModel(BaseModel):
|
| 12 |
+
prompt: str
|
| 13 |
+
ht_token : str
|
| 14 |
+
user_email : str
|
| 15 |
+
user_name : str
|
| 16 |
+
memory: list[str]
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
@app.get("/")
|
| 20 |
+
def read_root():
|
| 21 |
+
return {"message": "Hello From CodeBuddyAI!"}
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
@app.post("/call/")
|
| 25 |
+
def call(request: RequestModel):
|
| 26 |
+
answer = get_response(request.prompt, request.memory,request.ht_token,request.user_email,request.user_name)
|
| 27 |
+
|
| 28 |
+
return {"answer": answer}
|
requirements.txt
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
langchain-huggingface
|
| 2 |
+
langchain-core
|
| 3 |
+
langchain-text-splitters
|
| 4 |
+
langgraph
|
| 5 |
+
python-dotenv
|
| 6 |
+
pandas
|
| 7 |
+
openpyxl
|
| 8 |
+
sentence-transformers
|
| 9 |
+
requests
|
| 10 |
+
ipython
|
| 11 |
+
fastapi
|
| 12 |
+
uvicorn
|
| 13 |
+
markdown_pdf
|
| 14 |
+
smtplib
|