Spaces:
Running on Zero
Running on Zero
| import requests | |
| from typing import Dict, Any | |
| import xml.etree.ElementTree as ET | |
| import database | |
| def search_arxiv_papers(query:str, max_results:int=10) -> Dict[str, Any]: | |
| """ | |
| Arxiv üzerinden kullanıcı sorgusunu arar ve başlık, yazar, özet ve PDF linklerini döner. | |
| Inputs: | |
| query: Kullanıcı sorgusu (Örneğin kullanıcı son 2 yılda çıkan Machine Learning makalelerini ara diyebilir.) | |
| max_results: Dönen sonuçlar içerisinden seçilecek maksimum makale miktarı | |
| Outputs: | |
| Dict : {status: "success" or "error", count: int, papers: List[Dict] | None, message: str | None} | |
| """ | |
| try: | |
| url = f"http://export.arxiv.org/api/query?search_query=all:{query}&start=0&max_results={max_results}" | |
| response = requests.get(url, timeout=10) | |
| root = ET.fromstring(response.text) | |
| ns = { | |
| "atom": "http://www.w3.org/2005/Atom" | |
| } | |
| papers = [] | |
| for entry in root.findall("atom:entry", ns): | |
| arxiv_id_elem = entry.find('atom:id', ns) | |
| raw_id = arxiv_id_elem.text if arxiv_id_elem is not None else "" | |
| paper_id = raw_id.split('/abs/')[-1] if '/abs/' in raw_id else raw_id | |
| title = entry.find("atom:title", ns).text.strip() | |
| summary = entry.find("atom:summary", ns).text.strip() | |
| authors = [author.find("atom:name", ns).text for author in entry.findall("atom:author", ns)] | |
| pdf = None | |
| for link in entry.findall("atom:link", ns): | |
| if link.attrib.get("title") == "pdf": | |
| pdf = link.attrib["href"] | |
| published_elem = entry.find('atom:published', ns) | |
| published = published_elem.text[:10] if published_elem is not None else "" | |
| year = published[:4] if published else "" | |
| authors = [] | |
| for author in entry.findall('atom:author', ns): | |
| name_elem = author.find('atom:name', ns) | |
| if name_elem is not None and name_elem.text: | |
| authors.append(name_elem.text) | |
| authors_str = ", ".join(authors) | |
| paper_url = f"https://arxiv.org/abs/{paper_id}" | |
| papers.append({ | |
| "paper_id": f"arxiv_{paper_id}", | |
| "title": title, | |
| "authors": authors_str, | |
| "summary": summary[:350] + "..." if len(summary) > 350 else summary, | |
| "url": paper_url, | |
| "published_year": year, | |
| "source": "ArXiv" | |
| }) | |
| return {"status": "success", "count": len(papers), "papers": papers} | |
| except Exception as e: | |
| return {"status": "error", "message": str(e)} | |
| def search_openalex(query: str, limit: int = 5) -> Dict[str, Any]: | |
| """OpenAlex üzerinden atıf sayıları (citations) ile zenginleştirilmiş akademik makaleleri getirir. | |
| Inputs: | |
| query: Kullanıcı sorgusu (Örneğin kullanıcı son 2 yılda çıkan Machine Learning makalelerini ara diyebilir.) | |
| limit: Dönen sonuçlar içerisinden seçilecek maksimum makale miktarı | |
| Outputs: | |
| Dict : {status: "success" or "error", count: int, papers: List[Dict] | None, message: str | None} | |
| """ | |
| url = "https://api.openalex.org/works" | |
| params = { | |
| "search": query, | |
| "per_page": limit, | |
| "select": "id,title,publication_year,cited_by_count,authorships,doi,primary_location" | |
| } | |
| response = requests.get(url, params=params, timeout=10) | |
| if response.status_code != 200: | |
| print("OpenAlex API rate limit hatası oluştu, Arxiv API kullanılıyor...") | |
| return search_arxiv_papers(query=query, max_results=limit) | |
| data = response.json() | |
| papers = [] | |
| for item in data.get("results", []): | |
| paper_id = item.get("id", "").split("/")[-1] | |
| title = item.get("title", "") | |
| authors = [ | |
| author["author"]["display_name"] | |
| for author in item.get("authorships", []) | |
| ] | |
| authors_str = ", ".join(authors) | |
| summary = "" | |
| if "abstract" in item: | |
| summary = item["abstract"] | |
| year = item.get("publication_year", "") | |
| citation_count = item.get("cited_by_count", 0) | |
| location = item.get("primary_location", {}) | |
| paper_url = ( | |
| location.get("landing_page_url") | |
| or item.get("doi") | |
| or item.get("id") | |
| ) | |
| papers.append({ | |
| "paper_id": f"openalex_{paper_id}", | |
| "title": title, | |
| "authors": authors_str, | |
| "summary": summary[:350] + "..." if len(summary) > 350 else summary, | |
| "citation_count": citation_count, | |
| "published_year": year, | |
| "url": paper_url, | |
| "source": "OpenAlex" | |
| }) | |
| return { | |
| "status": "success", | |
| "count": len(papers), | |
| "papers": papers | |
| } | |
| def save_paper_to_library(paper_id: str, title: str, authors: str = "", | |
| summary: str = "", url: str = "", source: str = "ArXiv", citation_count: int = 0, | |
| published_year: str = "", tags: str = "") -> Dict[str, Any]: | |
| """Seçilen makaleyi SQLite kişisel veritabanına kaydeder. | |
| Inputs: | |
| paper_id: Makalenin benzersiz ID'si | |
| title: Makalenin başlığı | |
| authors: Makalenin yazarları | |
| summary: Makalenin özeti | |
| url: Makalenin URL'si | |
| source: Makalenin kaynağı | |
| citation_count: Makalenin atıf sayısı | |
| published_year: Makalenin yayınlanma yılı | |
| tags: Makalenin etiketleri | |
| Outputs: | |
| Dict : {status: "success" or "error", message: str} | |
| """ | |
| return database.save_paper( | |
| paper_id=paper_id, | |
| title=title, | |
| authors=authors, | |
| summary=summary, | |
| url=url, | |
| source=source, | |
| citation_count=citation_count, | |
| published_year=published_year, | |
| tags=tags | |
| ) | |
| def get_saved_library(status_filter: str = "hepsi", tag_filter: str = "", query: str = "") -> Dict[str, Any]: | |
| """Kayıtlı makale kütüphanesini okur ve listeler. | |
| Inputs: | |
| status_filter: Durum | |
| tag_filter: Etiket | |
| query: Arama sorgusu | |
| Outputs: | |
| Dict : {status: "success" or "error", count: int, papers: List[Dict] | None, message: str | None} | |
| """ | |
| papers = database.get_saved_papers(status_filter=status_filter, tag_filter=tag_filter, query=query) | |
| return { | |
| "status": "success", | |
| "saved_count": len(papers), | |
| "library": papers | |
| } | |
| def update_paper_status_or_note(paper_id: str, status: str = "", notes: str = "", tags: str = "") -> Dict[str, Any]: | |
| """Kayıtlı bir makalenin okuma durumunu ('unread', 'reading', 'completed') veya kişisel notlarını günceller. | |
| Inputs: | |
| paper_id: Makalenin benzersiz ID'si | |
| status: Makalenin okuma durumu | |
| notes: Makalenin kişisel notları | |
| tags: Makalenin etiketleri | |
| Outputs: | |
| Dict : {status: "success" or "error", message: str} | |
| """ | |
| return database.update_paper_status_or_note(paper_id=paper_id, status=status if status else None, notes=notes if notes else None, tags=tags if tags else None) | |
| def execute_tool(tool_name: str, arguments: Dict[str, Any]) -> Dict[str, Any]: | |
| """LLM tarafından çağrılan fonksiyonu eşleştirir ve çalıştırır. | |
| Inputs: | |
| tool_name: Fonksiyonun adı | |
| arguments: Fonksiyonun argümanları | |
| Outputs: | |
| Dict : {status: "success" or "error", message: str} | |
| """ | |
| if not isinstance(arguments, dict): | |
| arguments = {} | |
| cleaned_args = {k: v for k, v in arguments.items() if v is not None} | |
| if tool_name == "search_arxiv_papers": | |
| return search_arxiv_papers(**cleaned_args) | |
| elif tool_name == "search_openalex": | |
| return search_openalex(**cleaned_args) | |
| elif tool_name == "save_paper_to_library": | |
| return save_paper_to_library(**cleaned_args) | |
| elif tool_name == "get_saved_library": | |
| return get_saved_library(**cleaned_args) | |
| elif tool_name == "update_paper_status_or_note": | |
| return update_paper_status_or_note(**cleaned_args) | |
| elif tool_name in ["delete_paper", "delete_paper_from_library"]: | |
| return delete_paper(**cleaned_args) | |
| elif tool_name in ["clear_library", "clear_entire_library"]: | |
| return clear_library() | |
| else: | |
| return {"status": "error", "message": f"Bilinmeyen fonksiyon: {tool_name}"} | |
| def delete_paper(paper_id:str) -> Dict[str, Any]: | |
| """Kayıtlı bir makaleyi veritabanından siler. | |
| Inputs: | |
| paper_id: Makalenin benzersiz ID'si | |
| Outputs: | |
| Dict : {status: "success" or "error", message: str} | |
| """ | |
| return database.delete_paper(paper_id=paper_id) | |
| def clear_library() -> Dict[str, Any]: | |
| """Kütüphanedeki TÜM makaleleri veritabanından tamamen siler ve temizler. | |
| Inputs: | |
| None | |
| Outputs: | |
| Dict : {status: "success" or "error", message: str} | |
| """ | |
| return database.clear_library() | |
| TOOLS_SCHEMA = [ | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "search_arxiv_papers", | |
| "description": "ArXiv akademik platformundan verilen konu veya kelimelere göre en güncel makaleleri arar ve getirir.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "query": { | |
| "type": "string", | |
| "description": "Aranacak akademik konu veya anahtar kelimeler (örn: 'quantum machine learning', 'LLM tool calling')" | |
| }, | |
| "max_results": { | |
| "type": "integer", | |
| "description": "Getirilecek maksimum makale sayısı (Varsayılan 10)", | |
| "default": 10 | |
| } | |
| }, | |
| "required": ["query"] | |
| } | |
| } | |
| }, | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "search_openalex", | |
| "description": "OpenAlex platformundan makaleleri atıf sayıları (citations) ve yayın yılı bilgisi ile getirir.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "query": { | |
| "type": "string", | |
| "description": "Aranacak makale konusu" | |
| }, | |
| "limit": { | |
| "type": "integer", | |
| "description": "Getirilecek makale sayısı", | |
| "default": 5 | |
| } | |
| }, | |
| "required": ["query"] | |
| } | |
| } | |
| }, | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "save_paper_to_library", | |
| "description": "Arama sonuçlarında bulunan bir makaleyi veritabanındaki kişisel kütüphaneye kaydeder.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "paper_id": {"type": "string", "description": "Makalenin benzersiz kimliği (örn: arxiv_2303.08774)"}, | |
| "title": {"type": "string", "description": "Makale başlığı"}, | |
| "authors": {"type": "string", "description": "Yazarlar", "default": ""}, | |
| "summary": {"type": "string", "description": "Makale özeti", "default": ""}, | |
| "url": {"type": "string", "description": "Makale web/PDF bağlantısı", "default": ""}, | |
| "source": {"type": "string", "description": "Kaynak platform (ArXiv, OpenAlex)", "default": "ArXiv"}, | |
| "citation_count": {"type": "integer", "description": "Atıf sayısı", "default": 0}, | |
| "published_year": {"type": "string", "description": "Yayın yılı", "default": ""}, | |
| "tags": {"type": "string", "description": "Kullanıcı etiketleri", "default": ""} | |
| }, | |
| "required": ["paper_id", "title"] | |
| } | |
| } | |
| }, | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "get_saved_library", | |
| "description": "Veritabanına önceden kaydedilmiş makaleleri ve okuma listesini getirir. Filtre kullanılmayacaksa query ve tag_filter parametrelerine boş metin '' verilmeli veya dahil edilmemelidir.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "status_filter": { | |
| "type": "string", | |
| "description": "Filtreleme durumu: 'hepsi', 'unread', 'reading', 'completed'", | |
| "default": "hepsi" | |
| }, | |
| "tag_filter": { | |
| "type": "string", | |
| "description": "Etikete göre filtreleme. Özel filtre yoksa '' (boş metin) kullanın.", | |
| "default": "" | |
| }, | |
| "query": { | |
| "type": "string", | |
| "description": "Başlık veya özet içinde kelime araması. Özel filtre yoksa '' (boş metin) kullanın.", | |
| "default": "" | |
| } | |
| } | |
| } | |
| } | |
| }, | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "update_paper_status_or_note", | |
| "description": "Kütüphanede kayıtlı bir makalenin okuma durumunu ('unread', 'reading', 'completed') günceller veya kişisel not/etiket ekler.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "paper_id": {"type": "string", "description": "Güncellenecek makalenin kimliği veya ID'si"}, | |
| "status": {"type": "string", "description": "Yeni okuma durumu: 'unread', 'reading', 'completed'", "default": ""}, | |
| "notes": {"type": "string", "description": "Kullanıcının makaleye eklemek istediği özel not", "default": ""}, | |
| "tags": {"type": "string", "description": "Güncellenecek etiketler", "default": ""} | |
| }, | |
| "required": ["paper_id"] | |
| } | |
| } | |
| }, | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "delete_paper", | |
| "description": "Kütüphanede kayıtlı bir makaleyi veritabanından siler.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "paper_id": {"type": "string", "description": "Silinecek makalenin kimliği veya ID'si"} | |
| }, | |
| "required": ["paper_id"] | |
| } | |
| } | |
| }, | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "clear_library", | |
| "description": "Kütüphanedeki TÜM makaleleri veritabanından tamamen siler ve temizler.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": {}, | |
| "required": [] | |
| } | |
| } | |
| } | |
| ] | |