From cfac773844ddbe1cc512beb1794071048b120608 Mon Sep 17 00:00:00 2001 From: barrulus Date: Mon, 9 Jun 2025 20:06:32 +0100 Subject: [PATCH 01/20] Added Contributions to README.md --- README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 43b7aa5..55caf7a 100644 --- a/README.md +++ b/README.md @@ -276,4 +276,10 @@ The system automatically detects and works with databases created by older versi ## License -This project is designed for local development and research use. Please ensure compliance with the terms of service for any external models or APIs used. \ No newline at end of file +This project is designed for local development and research use. Please ensure compliance with the terms of service for any external models or APIs used. + +## Contributions + +I welcome any assistance on this project, especially around trying new models for better performance and testing against ore logs than I have at my disposal! + +Please just fork off of dev and then submit a PR \ No newline at end of file From ba30379281ca6e114feb3e3f9b8a155aa87b3618 Mon Sep 17 00:00:00 2001 From: barrulus Date: Mon, 9 Jun 2025 21:30:17 +0100 Subject: [PATCH 02/20] Added .gitignore example --- .gitignore_example | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .gitignore_example diff --git a/.gitignore_example b/.gitignore_example new file mode 100644 index 0000000..5103b08 --- /dev/null +++ b/.gitignore_example @@ -0,0 +1,6 @@ +.gitignore +venv/ +.vscode/ +__pycache__/ +chroma_code/ +chroma_db/ \ No newline at end of file From 03589307d6454e453c729c02aca728be894a6dc9 Mon Sep 17 00:00:00 2001 From: barrulus Date: Mon, 9 Jun 2025 21:52:46 +0100 Subject: [PATCH 03/20] addes `trust_remote_code=True` to index.py # TODO - make that a config not hardcode --- .env | 14 ++++++++++++++ index.py | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 .env diff --git a/.env b/.env new file mode 100644 index 0000000..27d3506 --- /dev/null +++ b/.env @@ -0,0 +1,14 @@ +# Ollama Configuration +OLLAMA_HOST=http://localhost:11434 +OLLAMA_MODEL=dolphincoder:15b + +# Embedding Configuration +EMBEDDING_SERVER=http://localhost:5000 +EMBEDDING_MODEL=nomic-ai/nomic-embed-text-v1.5 + +# ChromaDB Configuration +CHROMA_PATH=./chroma_code + +# Default Settings +USE_LOCAL_EMBEDDINGS=true +USE_LOCAL_OLLAMA=true diff --git a/index.py b/index.py index 412f7a1..6d11d80 100644 --- a/index.py +++ b/index.py @@ -88,7 +88,7 @@ def __init__(self, model: Optional[str] = None): console.print("[yellow]! CUDA not available, using CPU[/yellow]") self.device = 'cpu' - self.transformer = SentenceTransformer(self.model, device=self.device) + self.transformer = SentenceTransformer(self.model, trust_remote_code=True, device=self.device) self.transformer.max_seq_length = 512 except ImportError: raise ImportError("sentence-transformers not installed. Run: pip install sentence-transformers") From 9316ced5d96dfd3612da68dd7b3ca8e28900c450 Mon Sep 17 00:00:00 2001 From: barrulus Date: Mon, 9 Jun 2025 22:25:52 +0100 Subject: [PATCH 04/20] Cleaned up code vs log files --- .env | 2 +- ask.py | 22 ++--- codebase_queries.md | 227 ++++++++++++++++++++++++++++++++++++++++++++ index.py | 14 +-- 4 files changed, 246 insertions(+), 19 deletions(-) create mode 100644 codebase_queries.md diff --git a/.env b/.env index 27d3506..99fdb5e 100644 --- a/.env +++ b/.env @@ -1,6 +1,6 @@ # Ollama Configuration OLLAMA_HOST=http://localhost:11434 -OLLAMA_MODEL=dolphincoder:15b +OLLAMA_MODEL=qwen3:8b # Embedding Configuration EMBEDDING_SERVER=http://localhost:5000 diff --git a/ask.py b/ask.py index 40b9039..b993803 100644 --- a/ask.py +++ b/ask.py @@ -1,15 +1,15 @@ #!/usr/bin/env python3 """ -Interactive Code Query Tool +Interactive Log File Query Tool -Query your indexed codebase using natural language and get AI-generated answers. +Query your indexed log files using natural language and get AI-generated answers. Uses the embeddings created by index.py and generates responses using Ollama. Usage: python ask.py [output_file.md] Arguments: - output_file.md Optional. Markdown file to save Q&A pairs (default: codebase_queries.md) + output_file.md Optional. Markdown file to save Q&A pairs (default: logfile_queries.md) """ import os @@ -39,7 +39,7 @@ USE_LOCAL_OLLAMA = os.getenv('USE_LOCAL_OLLAMA', 'true').lower() == 'true' # Constants -DEFAULT_OUTPUT_FILE = "codebase_queries.md" +DEFAULT_OUTPUT_FILE = "logfile_queries.md" DEFAULT_TOP_K = 5 OLLAMA_EMBEDDING_MODEL = "nomic-embed-text" @@ -168,7 +168,7 @@ def _get_embedding_local(self, text: str) -> List[float]: if not self._local_model: console.print("[yellow]Loading local embedding model...[/yellow]") - self._local_model = SentenceTransformer(self.embedding_model) + self._local_model = SentenceTransformer(self.embedding_model, trust_remote_code=True) self._local_model.max_seq_length = 512 embedding = self._local_model.encode([text], show_progress_bar=False) @@ -210,7 +210,7 @@ def _get_embedding_remote(self, text: str) -> List[float]: raise def query_codebase(self, question: str, top_k: int = DEFAULT_TOP_K) -> str: - """Query the codebase and generate a response""" + """Query the logs and generate a response""" # Get embedding for the question try: q_embed = self.get_embedding(question) @@ -285,8 +285,8 @@ def write_to_markdown(question: str, answer: str, filename: str) -> None: # Create the file if it doesn't exist if not os.path.exists(filename): with open(filename, "w", encoding="utf-8") as f: - f.write("# Codebase Query Log\n\n") - f.write("This file contains questions and answers about the codebase.\n\n") + f.write("# Log File Query Log\n\n") + f.write("This file contains questions and answers about the Log Files.\n\n") # Append the Q&A pair with open(filename, "a", encoding="utf-8") as f: @@ -305,7 +305,7 @@ def main() -> None: output_file = sys.argv[1] if len(sys.argv) == 2 else DEFAULT_OUTPUT_FILE - console.print(f"\n[bold cyan]Code Query Tool[/bold cyan]") + console.print(f"\n[bold cyan]Log Query Tool[/bold cyan]") console.print(f"Output file: [cyan]{output_file}[/cyan]") console.print(f"Ollama model: [cyan]{OLLAMA_MODEL}[/cyan]") console.print("\nType 'exit' or 'quit' to stop.\n") @@ -320,7 +320,7 @@ def main() -> None: # Interactive loop while True: try: - question = input("\n[?] Ask a question about the codebase: ") + question = input("\n[?] Ask a question about the log files: ") if question.lower() in ['exit', 'quit', 'q']: console.print(f"\n[green]βœ“ All responses saved to {output_file}[/green]") @@ -330,7 +330,7 @@ def main() -> None: continue # Generate answer - console.print("\n[yellow]Searching codebase and generating response...[/yellow]") + console.print("\n[yellow]Searching log files and generating response...[/yellow]") answer = handler.query_codebase(question) # Write to file diff --git a/codebase_queries.md b/codebase_queries.md new file mode 100644 index 0000000..3bfabd5 --- /dev/null +++ b/codebase_queries.md @@ -0,0 +1,227 @@ +# Codebase Query Log + +This file contains questions and answers about the codebase. + +## Question [2025-06-09 22:06:34] + +**Q:** is there anything I should be aware of in the log files? + +**A:** + +Error generating embedding: The repository `nomic-ai/nomic-embed-text-v1.5` contains custom code which must be executed to correctly load the model. You can inspect the repository content at https://hf.co/nomic-ai/nomic-embed-text-v1.5. +Please pass the argument `trust_remote_code=True` to allow custom code to be run. + +--- + +## Question [2025-06-09 22:14:33] + +**Q:** Is there anything I should be aware of in the log files? + +**A:** + +Error generating response: model "dolphincoder:15b" not found, try pulling it first (status code: 404) + +--- + +## Question [2025-06-09 22:18:13] + +**Q:** Is there anything in the logs I should be aware of? + +**A:** + + +Okay, let's look through the logs the user provided. The main issue seems to be the repeated entries about "Received a response for something we don't know about" in the Avast logs. These entries are appearing in multiple files like securedns.log and service logs. + +First, I need to figure out what these messages mean. The phrase "something we don't know about" might indicate that Avast's DNS processor is receiving responses for queries it doesn't recognize or isn't handling. This could be due to several reasons. Maybe the DNS resolver isn't properly configured, or there's a miscommunication between the DNS server and the client. + +Looking at the timestamps, some logs are from June 5th to June 8th, and others are from June 8th. The user hasn't specified the exact time frame, but the logs are spread over a few days. The entries are frequent, which suggests this might be an ongoing issue. + +Another thing to note is the presence of an error message: "ERROR: Could not resolve host name: 'example.com'". This could be related to the DNS resolution process. If Avast's DNS service is unable to resolve certain hostnames, it might be logging these errors. However, the user hasn't provided the exact error message, so I need to check if that's part of the logs they shared. + +The user is asking if there's anything they should be aware of. So, I should consider possible causes and implications. For instance, if the DNS service is misconfigured, it could lead to connectivity issues. Alternatively, if Avast is using a third-party DNS resolver, there might be a problem with that service. Also, if the user is using a custom DNS configuration, that could be the source of the issue. + +I should also check if there are any other error messages or warnings in the logs that might give more context. The user mentioned multiple log files, so cross-referencing them could help. For example, the securedns.log has a lot of entries about unknown responses, which might indicate that the DNS queries are not being handled correctly by Avast's service. + +Another angle is the system's network configuration. If the user is on a network with restricted DNS settings, that could cause these issues. Also, firewall or antivirus settings might interfere with DNS traffic. However, since the logs are from Avast, it's possible that the issue is internal to their service. + +I should also consider if the user is experiencing any actual connectivity problems. If the logs are just warnings without affecting the system's functionality, they might not need to take action. But if there are errors or if the system is slow, then it's more urgent. + +In summary, the main points to highlight are the frequent DNS-related warnings, possible misconfiguration of the DNS resolver, and the need to check network settings. The user should verify their DNS settings, ensure Avast is up to date, and check for any network issues that might be causing the problem. If the issue persists, contacting Avast support with the logs might be necessary. + + +### **Key Observations from the Logs** + +#### **1. Frequent DNS Processing Warnings** +- **Log Entries**: Multiple instances of: + ``` + NOTICE dns_processor: Received a response for something we don't know about + ``` + These messages suggest that **Avast's DNS resolver** is encountering unexpected or unhandled DNS responses. This could indicate: + - **Misconfigured DNS settings** (e.g., incorrect resolver IPs). + - **Network issues** (e.g., DNS server unavailability or timeouts). + - **Third-party DNS resolver problems** (e.g., Cloudflare, Google DNS, etc.). + - **Malformed DNS queries or responses**. + +- **Frequency**: These logs are repeated frequently across multiple log files (e.g., `securedns.log`, `service.log`), indicating an **ongoing issue**. + +--- + +#### **2. Potential DNS Resolution Errors** +- **Example Error**: + ``` + ERROR: Could not resolve host name: 'example.com' + ``` + (Note: This specific error is not explicitly in your logs, but similar issues may exist.) + If present, it could mean: + - **DNS server unreachable** (e.g., due to network outages or misconfigurations). + - **DNS caching issues** (e.g., stale or incorrect cache entries). + - **Firewall/antivirus blocking DNS traffic**. + +--- + +#### **3. Possible Root Causes** +- **Avast DNS Service Misconfiguration**: + - Avast's secure DNS might be using an invalid or unreachable resolver. + - Check if the DNS settings in Avast's configuration are correct (e.g., `1.1.1.1`, `8.8.8.8`, etc.). +- **Network/ISP Issues**: + - Your ISP might be blocking or misrouting DNS traffic. + - Test connectivity to public DNS servers (e.g., `8.8.8.8`, `1.1.1.1`) directly. +- **Software Conflicts**: + - Other security software (e.g., firewalls, antivirus) might be interfering with DNS resolution. +- **Outdated Avast Version**: + - Older versions of Avast might have bugs in their DNS resolver logic. + +--- + +#### **4. Recommendations** +- **Check DNS Settings**: + - Verify that Avast's secure DNS is configured correctly (e.g., use a trusted resolver like Cloudflare or Google). + - Ensure your system's default DNS settings are not overriding Avast's configuration. +- **Test Connectivity**: + - Use tools like `nslookup` or `dig` to test DNS resolution for specific domains. + - Example: + ```bash + nslookup example.com + ``` +- **Update Avast**: + - Ensure you're using the latest version of Avast, as this might resolve known DNS resolver bugs. +- **Check for Network Issues**: + - Test your internet connection and ensure no firewall/antivirus is blocking DNS traffic (port 53 UDP/TCP). +- **Contact Avast Support**: + - If the issue persists, provide the logs to Avast support for deeper analysis. + +--- + +#### **5. When to Be Concerned** +- **If the issue affects your ability to access websites**: This could indicate a critical DNS failure. +- **If the logs include errors like "Could not resolve host name"**: This may require immediate troubleshooting. +- **If the logs are persistent despite fixes**: This could signal a deeper issue with Avast's DNS integration or your network setup. + +--- + +### **Summary** +- **Critical Issue**: The frequent "unknown DNS response" logs suggest a misconfiguration or problem with Avast's DNS resolver. +- **Action Required**: Verify DNS settings, test connectivity, and update Avast. If unresolved, contact Avast support with the logs. + +--- + +## Question [2025-06-09 22:21:15] + +**Q:** was there anything other than DNS issues that should get attention? + +**A:** + + +Okay, let me look through the provided server logs to see if there's anything other than DNS issues that needs attention. The user is asking if there are other problems beyond the DNS-related ones. + +First, I'll scan through each log chunk. The logs are from different dates, so I need to check each one. + +Looking at chunk 246, there's an entry: "dns_over_https: Disabling." That seems like a DNS issue, maybe related to the resolver not working. Then there's an error about not connecting to the server. So that's a DNS problem, but the disabling of DNS over HTTPS might be a result of the connection issues. + +In chunk 246, there's also a line: "NOTICE dns_processor: Received a response for something we don' know about." This is repeated multiple times. The message "Received a response for something we don't know about" might indicate that the DNS resolver is getting unexpected responses, which could be a sign of misconfiguration or some other issue, but it's still related to DNS. + +Looking at chunk 194, there's an error: "doh_resolver_score: Request failed: Could not connect to server." That's a DNS connection problem. + +In chunk 246, the line "dns_over_https: Disabling." might be a configuration change, but it's likely due to the connection failure. So that's still a DNS issue. + +Are there any other entries that mention different services or errors? Let me check again. + +In chunk 246, after the error, it says "dns_over_https: Disabling." That's a status change, but again, related to DNS. + +Looking at chunk 246, there's a line: "NOTICE dns_processor: Received a response for something we don' know about." This seems to be a recurring message, possibly indicating that the DNS queries are not being resolved correctly, leading to unknown responses. This might be a symptom of a larger issue, but it's still DNS-related. + +Are there any other errors or notices that don't relate to DNS? Let me check all chunks again. + +In chunk 194, the error is about the resolver failing to connect. + +In chunk 246, the same kind of error. + +In chunk 246, the line "dns_over_https: Disabling." might be a result of the resolver not working, leading to the disabling of that feature. + +In chunk 246, after the error, there's a notice about receiving a response for something unknown, which is again DNS-related. + +So, all the entries seem to be related to DNS issues. The "Received a response for something we don't know about" could be a sign of incorrect DNS responses or misconfigured DNS servers, but it's still a DNS problem. + +Therefore, there doesn't seem to be anything other than DNS issues that require attention. The main issues are connection failures to the DNS server and unexpected responses, which are all DNS-related. The user might need to check their DNS server configuration, network connectivity, or consider switching to a different DNS provider if the current one is not functioning correctly. + + +Based on the provided logs, the primary issues observed are **DNS-related**. However, there are a few additional observations that could warrant attention beyond DNS connectivity problems: + +--- + +### πŸ” **Key Observations Beyond DNS Issues** +1. **Unexpected DNS Responses** + - The log entry **`Received a response for something we don't know about`** appears multiple times across chunks (e.g., in chunks 194, 246, and 246). + - This could indicate: + - **Misconfigured DNS resolvers** (e.g., invalid or malformed responses). + - **DNS spoofing or poisoning** (if responses are incorrect). + - **Malformed queries** or unexpected input from clients. + - **Action**: Investigate if these responses are intentional or indicative of a security issue (e.g., MITM attacks). + +2. **DNS Over HTTPS (DoH) Disabling** + - In chunk 246, the log shows: + ``` + dns_over_https: Disabling. + ``` + - This is likely a **side effect of DNS resolver failures** (e.g., connection errors to `dns.avastdns.com`). + - **Action**: Check if the DoH feature is disabled due to connectivity issues or if it’s a deliberate configuration change. + +3. **Repeated Errors in Resolver Failures** + - The log frequently shows: + ``` + doh_resolver_score: Request failed: Could not connect to server + ``` + - These errors suggest **persistent connectivity issues** with the DNS server (`dns.avastdns.com`). + - **Action**: Verify network connectivity to the DNS server, check firewall rules, or consider switching to a more reliable DNS provider (e.g., Google DNS, Cloudflare). + +--- + +### 🚫 **No Non-DNS Critical Issues Identified** +- All log entries are **directly tied to DNS resolution** (e.g., connection failures, unexpected responses, DoH status changes). +- There are **no indications of system crashes, service outages, or unrelated application errors**. + +--- + +### πŸ› οΈ **Recommended Actions** +1. **Investigate DNS Server Connectivity**: + - Ensure `dns.avastdns.com` is reachable (ping/traceroute). + - Check for DNS server downtime or misconfiguration. + +2. **Audit DNS Resolver Logs**: + - Look for patterns in the "unknown response" logs (e.g., specific domains or query types). + +3. **Monitor DoH Status**: + - If DoH is disabled intentionally, ensure it’s re-enabled once DNS issues are resolved. + +4. **Consider Alternatives**: + - If `dns.avastdns.com` is unreliable, switch to a more stable DNS provider (e.g., 8.8.8.8, 1.1.1.1). + +--- + +### βœ… **Summary** +- **No non-DNS issues** were found. +- All critical alerts are **DNS-related** (connectivity, resolver errors, unexpected responses). +- Focus on resolving DNS server issues and monitoring resolver behavior. + +--- + diff --git a/index.py b/index.py index 6d11d80..fcbef07 100644 --- a/index.py +++ b/index.py @@ -1,8 +1,8 @@ #!/usr/bin/env python3 """ -Unified Code Indexer with Multiple Embedding Options +Unified Log File Indexer with Multiple Embedding Options -This script indexes a codebase for semantic search using various embedding strategies: +This script indexes a path of log files for semantic search using various embedding strategies: - Local embeddings using SentenceTransformer - Ollama embeddings using Ollama's API - Remote embeddings using a dedicated embedding server @@ -15,7 +15,7 @@ --ollama-embeddings Use Ollama's embedding API --remote-embeddings Use remote embedding server --model MODEL Specify embedding model (overrides .env) - --chunk-size SIZE Size of code chunks (default: 2000) + --chunk-size SIZE Size of log chunks (default: 2000) """ import os @@ -214,7 +214,7 @@ def collect_files(repo_path: Path) -> List[Path]: def chunk_code(content: str, chunk_size: int = DEFAULT_CHUNK_SIZE) -> List[str]: - """Split code into chunks""" + """Split logs into chunks""" chunks: List[str] = [] lines = content.split('\n') current_chunk: List[str] = [] @@ -380,7 +380,7 @@ def save_metadata(repo_path: Path, embedding_type: str, model: str, chunk_size: def main() -> None: parser = argparse.ArgumentParser( - description="Index a codebase for semantic search", + description="Index log files for semantic search", formatter_class=argparse.RawDescriptionHelpFormatter, epilog=__doc__ ) @@ -416,7 +416,7 @@ def main() -> None: '--chunk-size', type=int, default=DEFAULT_CHUNK_SIZE, - help=f'Size of code chunks (default: {DEFAULT_CHUNK_SIZE})' + help=f'Size of log file chunks (default: {DEFAULT_CHUNK_SIZE})' ) parser.add_argument( '--chroma-path', @@ -436,7 +436,7 @@ def main() -> None: console.print(f"[red]Error: Repository path does not exist: {repo_path}[/red]") sys.exit(1) - console.print(f"\n[bold cyan]Code Indexer[/bold cyan]") + console.print(f"\n[bold cyan]Log Indexer[/bold cyan]") console.print(f"Repository: {repo_path}") # Determine embedding type From 6f3a3a493d076f3bb45d7e4d848b671804997be5 Mon Sep 17 00:00:00 2001 From: barrulus Date: Mon, 9 Jun 2025 22:27:41 +0100 Subject: [PATCH 05/20] Added qwen3:8b as default Ollama model to .env_example --- .env_example | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.env_example b/.env_example index 27d3506..99fdb5e 100644 --- a/.env_example +++ b/.env_example @@ -1,6 +1,6 @@ # Ollama Configuration OLLAMA_HOST=http://localhost:11434 -OLLAMA_MODEL=dolphincoder:15b +OLLAMA_MODEL=qwen3:8b # Embedding Configuration EMBEDDING_SERVER=http://localhost:5000 From a84abac5adef9a41c3913de484c7bc66bd11aca2 Mon Sep 17 00:00:00 2001 From: barrulus Date: Tue, 10 Jun 2025 07:37:20 +0100 Subject: [PATCH 06/20] .gitignore chages --- .gitignore_example | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore_example b/.gitignore_example index 5103b08..13c92ed 100644 --- a/.gitignore_example +++ b/.gitignore_example @@ -3,4 +3,5 @@ venv/ .vscode/ __pycache__/ chroma_code/ -chroma_db/ \ No newline at end of file +chroma_db/ +*-queries.md \ No newline at end of file From 5deb81386add4b03ca4a7dff39eae9550a91810d Mon Sep 17 00:00:00 2001 From: barrulus Date: Tue, 10 Jun 2025 07:38:06 +0100 Subject: [PATCH 07/20] Delete .env --- .env | 14 -------------- 1 file changed, 14 deletions(-) delete mode 100644 .env diff --git a/.env b/.env deleted file mode 100644 index 99fdb5e..0000000 --- a/.env +++ /dev/null @@ -1,14 +0,0 @@ -# Ollama Configuration -OLLAMA_HOST=http://localhost:11434 -OLLAMA_MODEL=qwen3:8b - -# Embedding Configuration -EMBEDDING_SERVER=http://localhost:5000 -EMBEDDING_MODEL=nomic-ai/nomic-embed-text-v1.5 - -# ChromaDB Configuration -CHROMA_PATH=./chroma_code - -# Default Settings -USE_LOCAL_EMBEDDINGS=true -USE_LOCAL_OLLAMA=true From b3690629669e8c7426967d5864fed6cfb22baa08 Mon Sep 17 00:00:00 2001 From: barrulus Date: Tue, 10 Jun 2025 07:38:21 +0100 Subject: [PATCH 08/20] Delete __pycache__ directory --- __pycache__/ask.cpython-311.pyc | Bin 6060 -> 0 bytes __pycache__/index_remote.cpython-311.pyc | Bin 8231 -> 0 bytes 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 __pycache__/ask.cpython-311.pyc delete mode 100644 __pycache__/index_remote.cpython-311.pyc diff --git a/__pycache__/ask.cpython-311.pyc b/__pycache__/ask.cpython-311.pyc deleted file mode 100644 index 4c754a8305d1af563e9f1950dced7ff8ad4162c3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6060 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 DJj<2O From cd5e355c8c1f069018828bf3ba82fa9521a63459 Mon Sep 17 00:00:00 2001 From: barrulus Date: Tue, 10 Jun 2025 07:38:34 +0100 Subject: [PATCH 09/20] Delete .vscode directory --- .vscode/settings.json | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 797068f..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "terminal.integrated.allowMnemonics": false, - "terminal.integrated.automationProfile.linux": null -} \ No newline at end of file From 6a3b63bb829c550f9e1a2a1a236dd084fc4991b2 Mon Sep 17 00:00:00 2001 From: barrulus Date: Tue, 10 Jun 2025 07:38:50 +0100 Subject: [PATCH 10/20] Delete codebase_queries.md --- codebase_queries.md | 227 -------------------------------------------- 1 file changed, 227 deletions(-) delete mode 100644 codebase_queries.md diff --git a/codebase_queries.md b/codebase_queries.md deleted file mode 100644 index 3bfabd5..0000000 --- a/codebase_queries.md +++ /dev/null @@ -1,227 +0,0 @@ -# Codebase Query Log - -This file contains questions and answers about the codebase. - -## Question [2025-06-09 22:06:34] - -**Q:** is there anything I should be aware of in the log files? - -**A:** - -Error generating embedding: The repository `nomic-ai/nomic-embed-text-v1.5` contains custom code which must be executed to correctly load the model. You can inspect the repository content at https://hf.co/nomic-ai/nomic-embed-text-v1.5. -Please pass the argument `trust_remote_code=True` to allow custom code to be run. - ---- - -## Question [2025-06-09 22:14:33] - -**Q:** Is there anything I should be aware of in the log files? - -**A:** - -Error generating response: model "dolphincoder:15b" not found, try pulling it first (status code: 404) - ---- - -## Question [2025-06-09 22:18:13] - -**Q:** Is there anything in the logs I should be aware of? - -**A:** - - -Okay, let's look through the logs the user provided. The main issue seems to be the repeated entries about "Received a response for something we don't know about" in the Avast logs. These entries are appearing in multiple files like securedns.log and service logs. - -First, I need to figure out what these messages mean. The phrase "something we don't know about" might indicate that Avast's DNS processor is receiving responses for queries it doesn't recognize or isn't handling. This could be due to several reasons. Maybe the DNS resolver isn't properly configured, or there's a miscommunication between the DNS server and the client. - -Looking at the timestamps, some logs are from June 5th to June 8th, and others are from June 8th. The user hasn't specified the exact time frame, but the logs are spread over a few days. The entries are frequent, which suggests this might be an ongoing issue. - -Another thing to note is the presence of an error message: "ERROR: Could not resolve host name: 'example.com'". This could be related to the DNS resolution process. If Avast's DNS service is unable to resolve certain hostnames, it might be logging these errors. However, the user hasn't provided the exact error message, so I need to check if that's part of the logs they shared. - -The user is asking if there's anything they should be aware of. So, I should consider possible causes and implications. For instance, if the DNS service is misconfigured, it could lead to connectivity issues. Alternatively, if Avast is using a third-party DNS resolver, there might be a problem with that service. Also, if the user is using a custom DNS configuration, that could be the source of the issue. - -I should also check if there are any other error messages or warnings in the logs that might give more context. The user mentioned multiple log files, so cross-referencing them could help. For example, the securedns.log has a lot of entries about unknown responses, which might indicate that the DNS queries are not being handled correctly by Avast's service. - -Another angle is the system's network configuration. If the user is on a network with restricted DNS settings, that could cause these issues. Also, firewall or antivirus settings might interfere with DNS traffic. However, since the logs are from Avast, it's possible that the issue is internal to their service. - -I should also consider if the user is experiencing any actual connectivity problems. If the logs are just warnings without affecting the system's functionality, they might not need to take action. But if there are errors or if the system is slow, then it's more urgent. - -In summary, the main points to highlight are the frequent DNS-related warnings, possible misconfiguration of the DNS resolver, and the need to check network settings. The user should verify their DNS settings, ensure Avast is up to date, and check for any network issues that might be causing the problem. If the issue persists, contacting Avast support with the logs might be necessary. - - -### **Key Observations from the Logs** - -#### **1. Frequent DNS Processing Warnings** -- **Log Entries**: Multiple instances of: - ``` - NOTICE dns_processor: Received a response for something we don't know about - ``` - These messages suggest that **Avast's DNS resolver** is encountering unexpected or unhandled DNS responses. This could indicate: - - **Misconfigured DNS settings** (e.g., incorrect resolver IPs). - - **Network issues** (e.g., DNS server unavailability or timeouts). - - **Third-party DNS resolver problems** (e.g., Cloudflare, Google DNS, etc.). - - **Malformed DNS queries or responses**. - -- **Frequency**: These logs are repeated frequently across multiple log files (e.g., `securedns.log`, `service.log`), indicating an **ongoing issue**. - ---- - -#### **2. Potential DNS Resolution Errors** -- **Example Error**: - ``` - ERROR: Could not resolve host name: 'example.com' - ``` - (Note: This specific error is not explicitly in your logs, but similar issues may exist.) - If present, it could mean: - - **DNS server unreachable** (e.g., due to network outages or misconfigurations). - - **DNS caching issues** (e.g., stale or incorrect cache entries). - - **Firewall/antivirus blocking DNS traffic**. - ---- - -#### **3. Possible Root Causes** -- **Avast DNS Service Misconfiguration**: - - Avast's secure DNS might be using an invalid or unreachable resolver. - - Check if the DNS settings in Avast's configuration are correct (e.g., `1.1.1.1`, `8.8.8.8`, etc.). -- **Network/ISP Issues**: - - Your ISP might be blocking or misrouting DNS traffic. - - Test connectivity to public DNS servers (e.g., `8.8.8.8`, `1.1.1.1`) directly. -- **Software Conflicts**: - - Other security software (e.g., firewalls, antivirus) might be interfering with DNS resolution. -- **Outdated Avast Version**: - - Older versions of Avast might have bugs in their DNS resolver logic. - ---- - -#### **4. Recommendations** -- **Check DNS Settings**: - - Verify that Avast's secure DNS is configured correctly (e.g., use a trusted resolver like Cloudflare or Google). - - Ensure your system's default DNS settings are not overriding Avast's configuration. -- **Test Connectivity**: - - Use tools like `nslookup` or `dig` to test DNS resolution for specific domains. - - Example: - ```bash - nslookup example.com - ``` -- **Update Avast**: - - Ensure you're using the latest version of Avast, as this might resolve known DNS resolver bugs. -- **Check for Network Issues**: - - Test your internet connection and ensure no firewall/antivirus is blocking DNS traffic (port 53 UDP/TCP). -- **Contact Avast Support**: - - If the issue persists, provide the logs to Avast support for deeper analysis. - ---- - -#### **5. When to Be Concerned** -- **If the issue affects your ability to access websites**: This could indicate a critical DNS failure. -- **If the logs include errors like "Could not resolve host name"**: This may require immediate troubleshooting. -- **If the logs are persistent despite fixes**: This could signal a deeper issue with Avast's DNS integration or your network setup. - ---- - -### **Summary** -- **Critical Issue**: The frequent "unknown DNS response" logs suggest a misconfiguration or problem with Avast's DNS resolver. -- **Action Required**: Verify DNS settings, test connectivity, and update Avast. If unresolved, contact Avast support with the logs. - ---- - -## Question [2025-06-09 22:21:15] - -**Q:** was there anything other than DNS issues that should get attention? - -**A:** - - -Okay, let me look through the provided server logs to see if there's anything other than DNS issues that needs attention. The user is asking if there are other problems beyond the DNS-related ones. - -First, I'll scan through each log chunk. The logs are from different dates, so I need to check each one. - -Looking at chunk 246, there's an entry: "dns_over_https: Disabling." That seems like a DNS issue, maybe related to the resolver not working. Then there's an error about not connecting to the server. So that's a DNS problem, but the disabling of DNS over HTTPS might be a result of the connection issues. - -In chunk 246, there's also a line: "NOTICE dns_processor: Received a response for something we don' know about." This is repeated multiple times. The message "Received a response for something we don't know about" might indicate that the DNS resolver is getting unexpected responses, which could be a sign of misconfiguration or some other issue, but it's still related to DNS. - -Looking at chunk 194, there's an error: "doh_resolver_score: Request failed: Could not connect to server." That's a DNS connection problem. - -In chunk 246, the line "dns_over_https: Disabling." might be a configuration change, but it's likely due to the connection failure. So that's still a DNS issue. - -Are there any other entries that mention different services or errors? Let me check again. - -In chunk 246, after the error, it says "dns_over_https: Disabling." That's a status change, but again, related to DNS. - -Looking at chunk 246, there's a line: "NOTICE dns_processor: Received a response for something we don' know about." This seems to be a recurring message, possibly indicating that the DNS queries are not being resolved correctly, leading to unknown responses. This might be a symptom of a larger issue, but it's still DNS-related. - -Are there any other errors or notices that don't relate to DNS? Let me check all chunks again. - -In chunk 194, the error is about the resolver failing to connect. - -In chunk 246, the same kind of error. - -In chunk 246, the line "dns_over_https: Disabling." might be a result of the resolver not working, leading to the disabling of that feature. - -In chunk 246, after the error, there's a notice about receiving a response for something unknown, which is again DNS-related. - -So, all the entries seem to be related to DNS issues. The "Received a response for something we don't know about" could be a sign of incorrect DNS responses or misconfigured DNS servers, but it's still a DNS problem. - -Therefore, there doesn't seem to be anything other than DNS issues that require attention. The main issues are connection failures to the DNS server and unexpected responses, which are all DNS-related. The user might need to check their DNS server configuration, network connectivity, or consider switching to a different DNS provider if the current one is not functioning correctly. - - -Based on the provided logs, the primary issues observed are **DNS-related**. However, there are a few additional observations that could warrant attention beyond DNS connectivity problems: - ---- - -### πŸ” **Key Observations Beyond DNS Issues** -1. **Unexpected DNS Responses** - - The log entry **`Received a response for something we don't know about`** appears multiple times across chunks (e.g., in chunks 194, 246, and 246). - - This could indicate: - - **Misconfigured DNS resolvers** (e.g., invalid or malformed responses). - - **DNS spoofing or poisoning** (if responses are incorrect). - - **Malformed queries** or unexpected input from clients. - - **Action**: Investigate if these responses are intentional or indicative of a security issue (e.g., MITM attacks). - -2. **DNS Over HTTPS (DoH) Disabling** - - In chunk 246, the log shows: - ``` - dns_over_https: Disabling. - ``` - - This is likely a **side effect of DNS resolver failures** (e.g., connection errors to `dns.avastdns.com`). - - **Action**: Check if the DoH feature is disabled due to connectivity issues or if it’s a deliberate configuration change. - -3. **Repeated Errors in Resolver Failures** - - The log frequently shows: - ``` - doh_resolver_score: Request failed: Could not connect to server - ``` - - These errors suggest **persistent connectivity issues** with the DNS server (`dns.avastdns.com`). - - **Action**: Verify network connectivity to the DNS server, check firewall rules, or consider switching to a more reliable DNS provider (e.g., Google DNS, Cloudflare). - ---- - -### 🚫 **No Non-DNS Critical Issues Identified** -- All log entries are **directly tied to DNS resolution** (e.g., connection failures, unexpected responses, DoH status changes). -- There are **no indications of system crashes, service outages, or unrelated application errors**. - ---- - -### πŸ› οΈ **Recommended Actions** -1. **Investigate DNS Server Connectivity**: - - Ensure `dns.avastdns.com` is reachable (ping/traceroute). - - Check for DNS server downtime or misconfiguration. - -2. **Audit DNS Resolver Logs**: - - Look for patterns in the "unknown response" logs (e.g., specific domains or query types). - -3. **Monitor DoH Status**: - - If DoH is disabled intentionally, ensure it’s re-enabled once DNS issues are resolved. - -4. **Consider Alternatives**: - - If `dns.avastdns.com` is unreliable, switch to a more stable DNS provider (e.g., 8.8.8.8, 1.1.1.1). - ---- - -### βœ… **Summary** -- **No non-DNS issues** were found. -- All critical alerts are **DNS-related** (connectivity, resolver errors, unexpected responses). -- Focus on resolving DNS server issues and monitoring resolver behavior. - ---- - From 8bcea467b9a2ef28b50c725b89c909848c80db93 Mon Sep 17 00:00:00 2001 From: barrulus Date: Tue, 10 Jun 2025 05:06:49 -0400 Subject: [PATCH 11/20] =?UTF-8?q?Replace=20extension-based=20file=20filter?= =?UTF-8?q?ing=20with=20content-based=20detection=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=E2=94=82=20=E2=94=82?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=E2=94=82=20=E2=94=82=20=20=20Automatically=20indexes=20a?= =?UTF-8?q?ll=20text=20files=20by=20examining=20content=20rather=20than=20?= =?UTF-8?q?relying=20on=20hardcoded=20extensions.=20Implements=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=E2=94=82=20=E2=94=82=20=20=20recursive?= =?UTF-8?q?=20scanning=20with=20intelligent=20binary/text=20detection=20an?= =?UTF-8?q?d=20multi-encoding=20support.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.py | 65 +++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 57 insertions(+), 8 deletions(-) diff --git a/index.py b/index.py index fcbef07..5c2cf32 100644 --- a/index.py +++ b/index.py @@ -47,7 +47,6 @@ USE_LOCAL_OLLAMA = os.getenv('USE_LOCAL_OLLAMA', 'true').lower() == 'true' # Constants -SUPPORTED_EXTENSIONS = ['.py', '.log', '.js', '.ts', '.md', '.sql', '.html', '.csv'] DEFAULT_CHUNK_SIZE = 2000 OLLAMA_EMBEDDING_MODEL = "nomic-embed-text" @@ -199,16 +198,55 @@ def check_availability(self) -> bool: return False +def is_indexable_file(file_path: Path) -> bool: + """Determine if a file can be indexed by examining its content""" + try: + # Skip if file is too large (> 10MB) + if file_path.stat().st_size > 10 * 1024 * 1024: + return False + + with open(file_path, 'rb') as f: + # Read first 8KB to check content + chunk = f.read(8192) + if not chunk: + return False # Empty file + + # Check for null bytes (indicates binary content) + if b'\x00' in chunk: + return False + + # Try to decode as text using common encodings + for encoding in ['utf-8', 'latin1', 'cp1252', 'iso-8859-1']: + try: + chunk.decode(encoding) + return True + except UnicodeDecodeError: + continue + + return False + + except (IOError, OSError, PermissionError): + return False + + def collect_files(repo_path: Path) -> List[Path]: - """Collect all supported files from the repository""" + """Collect all indexable files from the repository by scanning content""" files: List[Path] = [] - for ext in SUPPORTED_EXTENSIONS: - files.extend(list(repo_path.rglob(f"*{ext}"))) - # Filter out common directories to ignore - ignore_dirs = {'.git', '__pycache__', 'node_modules', '.env', 'venv', 'env', '.venv'} - files = [f for f in files if not any(ignored in f.parts for ignored in ignore_dirs)] + ignore_dirs = {'.git', '__pycache__', 'node_modules', '.env', 'venv', 'env', '.venv', + 'target', 'build', 'dist', '.svn', '.hg', '.idea', '.vscode'} + + # Recursively scan all files + for file_path in repo_path.rglob('*'): + if file_path.is_file(): + # Skip files in ignored directories + if any(ignored in file_path.parts for ignored in ignore_dirs): + continue + + # Check if file is indexable by content + if is_indexable_file(file_path): + files.append(file_path) return sorted(files) @@ -265,7 +303,18 @@ def process_repository( for file_path in files: try: - content = file_path.read_text(encoding='utf-8', errors='ignore') + # Try different encodings to read the file + content = None + for encoding in ['utf-8', 'latin1', 'cp1252', 'iso-8859-1']: + try: + content = file_path.read_text(encoding=encoding) + break + except UnicodeDecodeError: + continue + + if content is None: + console.print(f"[yellow]Could not decode {file_path}, skipping[/yellow]") + continue chunks = chunk_code(content, chunk_size) for i, chunk in enumerate(chunks): From 8837dbee9d0a38bbc91175debf60cf2dca4d7bc7 Mon Sep 17 00:00:00 2001 From: barrulus Date: Tue, 10 Jun 2025 05:57:06 -0400 Subject: [PATCH 12/20] changes to embeddings_server to allow central trust control --- .env.example | 23 ++++ README.md | 49 +++++++- ask.py | 14 ++- embedding_server.py | 51 +++++--- index.py | 22 +++- trust_manager.py | 282 ++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 417 insertions(+), 24 deletions(-) create mode 100644 .env.example create mode 100644 trust_manager.py diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..72b4817 --- /dev/null +++ b/.env.example @@ -0,0 +1,23 @@ +# Environment Configuration for Vector Code Retrieval System + +# Ollama Configuration +OLLAMA_HOST=http://localhost:11434 +OLLAMA_MODEL=dolphincoder:15b + +# Embedding Configuration +EMBEDDING_SERVER=http://localhost:5000 +EMBEDDING_MODEL=nomic-ai/nomic-embed-text-v1.5 + +# Storage Configuration +CHROMA_PATH=./chroma_code + +# Service Selection +USE_LOCAL_EMBEDDINGS=true +USE_LOCAL_OLLAMA=true + +# Trust Remote Code Settings (automatically managed by trust_manager.py) +# Format: TRUST_REMOTE_CODE_=true|false +# These are automatically added when you approve/deny models +# Example: +# # TRUST_REMOTE_CODE_A1B2C3D4_MODEL=nomic-ai/nomic-embed-text-v1.5 +# TRUST_REMOTE_CODE_A1B2C3D4=true \ No newline at end of file diff --git a/README.md b/README.md index 55caf7a..f26ccf6 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,8 @@ A powerful semantic search system for log files that enables natural language qu - **Local LLM Integration**: Generates AI responses using Ollama with customizable models - **Interactive Query Interface**: Rich terminal interface with markdown rendering - **GPU Acceleration**: Optional GPU support for faster embedding generation -- **Comprehensive File Support**: Indexes `.py`, `.log`, `.js`, `.ts`, `.md`, `.sql`, `.html`, `.csv` files +- **Automatic File Detection**: Intelligently detects and indexes all text-based files by content analysis +- **Security-First Trust Management**: Configurable trust_remote_code handling with user consent and model tracking - **Environment Configuration**: Fully configurable via `.env` files ## Quick Start @@ -149,6 +150,7 @@ python ask.py my_queries.md | `CHROMA_PATH` | ChromaDB storage path | `./chroma_code` | | `USE_LOCAL_EMBEDDINGS` | Default embedding strategy | `true` | | `USE_LOCAL_OLLAMA` | Use local Ollama instance | `true` | +| `TRUST_REMOTE_CODE_*` | Model-specific trust settings | Auto-managed | ### Command Line Options @@ -180,6 +182,50 @@ Options: --debug Enable debug mode ``` +## Security: Trust Remote Code Management + +The system includes built-in security management for models that require `trust_remote_code=True`. This feature: + +- **Auto-detects** which models likely need remote code execution +- **Prompts for user consent** with clear risk warnings +- **Saves decisions** in `.env` with model-specific tracking +- **Re-prompts on model changes** for ongoing security + +### Managing Trust Settings + +```bash +# List all approved/denied models +python trust_manager.py --list + +# Check if a specific model needs trust_remote_code +python trust_manager.py --check "nomic-ai/nomic-embed-text-v1.5" +``` + +When you first use a model requiring remote code, you'll see: + +``` +============================================================== +SECURITY WARNING: Remote Code Execution +============================================================== +Model: nomic-ai/nomic-embed-text-v1.5 + +This model may require 'trust_remote_code=True' which allows +the model to execute arbitrary code during loading. + +RISKS: +- The model could execute malicious code +- Your system could be compromised +- Data could be stolen or corrupted + +BENEFITS: +- Access to newer/specialized models +- Better embedding quality for some models + +Your choice will be saved for this model. +============================================================== +Allow remote code execution for this model? [y/N]: +``` + ## Advanced Usage ### Remote Embedding Server @@ -269,6 +315,7 @@ The system automatically detects and works with databases created by older versi β”œβ”€β”€ index.py # Unified indexing script β”œβ”€β”€ ask.py # Interactive query interface β”œβ”€β”€ embedding_server.py # Remote embedding server +β”œβ”€β”€ trust_manager.py # Security: trust_remote_code management β”œβ”€β”€ requirements.txt # Python dependencies β”œβ”€β”€ .env_example # Environment configuration template └── chroma_code/ # Default ChromaDB storage (created after indexing) diff --git a/ask.py b/ask.py index b993803..a7f4ed9 100644 --- a/ask.py +++ b/ask.py @@ -168,7 +168,8 @@ def _get_embedding_local(self, text: str) -> List[float]: if not self._local_model: console.print("[yellow]Loading local embedding model...[/yellow]") - self._local_model = SentenceTransformer(self.embedding_model, trust_remote_code=True) + from trust_manager import safe_sentence_transformer_load + self._local_model = safe_sentence_transformer_load(self.embedding_model) self._local_model.max_seq_length = 512 embedding = self._local_model.encode([text], show_progress_bar=False) @@ -198,9 +199,18 @@ def _get_embedding_local(self, text: str) -> List[float]: def _get_embedding_remote(self, text: str) -> List[float]: """Get embedding from remote server""" try: + # Get trust setting for this model + from trust_manager import TrustManager + trust_manager = TrustManager() + trust_remote_code = trust_manager.get_trust_setting(self.embedding_model, interactive=True) + response = requests.post( f"{EMBEDDING_SERVER}/embed", - json={"texts": [text], "model": self.embedding_model}, + json={ + "texts": [text], + "model": self.embedding_model, + "trust_remote_code": trust_remote_code + }, timeout=60 ) response.raise_for_status() diff --git a/embedding_server.py b/embedding_server.py index 0d63363..7e6646d 100644 --- a/embedding_server.py +++ b/embedding_server.py @@ -33,6 +33,7 @@ model: Optional[SentenceTransformer] = None device: Optional[str] = None args: Optional[argparse.Namespace] = None +model_cache: Dict[str, SentenceTransformer] = {} # Cache models with different trust settings def initialize_model() -> None: @@ -68,21 +69,42 @@ def initialize_model() -> None: print(f"\nUsing device: {device}") - # Load model - model = SentenceTransformer(args.model, device=device, trust_remote_code=True) + # Load default model + from sentence_transformers import SentenceTransformer + model = SentenceTransformer(args.model, device=device, trust_remote_code=False) model.max_seq_length = args.max_length - print(f"Model loaded successfully!") + print(f"Default model loaded: {args.model}") print(f"Max sequence length: {args.max_length}") print(f"Batch size: {args.batch_size}") + print(f"Note: trust_remote_code can be overridden per request") + + +def get_or_load_model(model_name: str, trust_remote_code: bool) -> SentenceTransformer: + """Get or load a model with specific trust_remote_code setting""" + global model_cache, device, args + + if args is None: + raise RuntimeError("Server not initialized") + + # Create cache key + cache_key = f"{model_name}:trust={trust_remote_code}" + + if cache_key not in model_cache: + print(f"Loading model {model_name} with trust_remote_code={trust_remote_code}") + loaded_model = SentenceTransformer(model_name, device=device, trust_remote_code=trust_remote_code) + loaded_model.max_seq_length = args.max_length + model_cache[cache_key] = loaded_model + + return model_cache[cache_key] @app.route('/embed', methods=['POST']) def embed() -> Any: """Generate embeddings for provided texts""" try: - if model is None or args is None: - return jsonify({'error': 'Model not initialized'}), 500 + if args is None: + return jsonify({'error': 'Server not initialized'}), 500 data = request.json if data is None: @@ -90,21 +112,17 @@ def embed() -> Any: data = cast(Dict[str, Any], data) texts = data.get('texts', []) - - # Allow model override per request - request_model = data.get('model') - if request_model and request_model != args.model: - # For now, we don't support dynamic model switching - # This could be implemented with a model cache - return jsonify({ - 'error': f'Model switching not supported. Server is using: {args.model}' - }), 400 + request_model = data.get('model', args.model) + trust_remote_code = data.get('trust_remote_code', False) if not texts: return jsonify({'error': 'No texts provided'}), 400 + # Get the appropriate model + model_to_use = get_or_load_model(request_model, trust_remote_code) + # Generate embeddings on GPU/CPU - embeddings_result = cast(Any, model.encode( # type: ignore[misc] + embeddings_result = cast(Any, model_to_use.encode( # type: ignore[misc] texts, batch_size=args.batch_size, show_progress_bar=False, @@ -114,7 +132,8 @@ def embed() -> Any: return jsonify({ 'embeddings': embeddings, - 'model': args.model, + 'model': request_model, + 'trust_remote_code': trust_remote_code, 'count': len(embeddings) }) diff --git a/index.py b/index.py index 5c2cf32..3cbd2dd 100644 --- a/index.py +++ b/index.py @@ -39,7 +39,7 @@ # Configuration from environment OLLAMA_HOST = os.getenv('OLLAMA_HOST', 'http://localhost:11434') -OLLAMA_MODEL = os.getenv('OLLAMA_MODEL', 'dolphincoder:15b') +OLLAMA_MODEL = os.getenv('OLLAMA_MODEL', 'qwen3:8b') EMBEDDING_SERVER = os.getenv('EMBEDDING_SERVER', 'http://localhost:5000') EMBEDDING_MODEL = os.getenv('EMBEDDING_MODEL', 'nomic-ai/nomic-embed-text-v1.5') CHROMA_PATH = os.getenv('CHROMA_PATH', './chroma_code') @@ -87,7 +87,8 @@ def __init__(self, model: Optional[str] = None): console.print("[yellow]! CUDA not available, using CPU[/yellow]") self.device = 'cpu' - self.transformer = SentenceTransformer(self.model, trust_remote_code=True, device=self.device) + from trust_manager import safe_sentence_transformer_load + self.transformer = safe_sentence_transformer_load(self.model, device=self.device) self.transformer.max_seq_length = 512 except ImportError: raise ImportError("sentence-transformers not installed. Run: pip install sentence-transformers") @@ -163,6 +164,13 @@ def __init__(self, model: Optional[str] = None): self.base_url: str = EMBEDDING_SERVER self.max_retries: int = 3 self.retry_delay: int = 1 + self.trust_remote_code: bool = self._get_trust_setting() + + def _get_trust_setting(self) -> bool: + """Get trust_remote_code setting for this model""" + from trust_manager import TrustManager + trust_manager = TrustManager() + return trust_manager.get_trust_setting(self.model, interactive=True) def embed(self, texts: List[str]) -> List[List[float]]: """Generate embeddings using remote server with retry logic""" @@ -170,7 +178,11 @@ def embed(self, texts: List[str]) -> List[List[float]]: try: response = requests.post( f"{self.base_url}/embed", - json={"texts": texts, "model": self.model}, + json={ + "texts": texts, + "model": self.model, + "trust_remote_code": self.trust_remote_code + }, timeout=60 ) response.raise_for_status() @@ -201,8 +213,8 @@ def check_availability(self) -> bool: def is_indexable_file(file_path: Path) -> bool: """Determine if a file can be indexed by examining its content""" try: - # Skip if file is too large (> 10MB) - if file_path.stat().st_size > 10 * 1024 * 1024: + # Skip if file is too large (> 100MB) + if file_path.stat().st_size > 100 * 1024 * 1024: return False with open(file_path, 'rb') as f: diff --git a/trust_manager.py b/trust_manager.py new file mode 100644 index 0000000..0b05604 --- /dev/null +++ b/trust_manager.py @@ -0,0 +1,282 @@ +#!/usr/bin/env python3 +""" +Trust Remote Code Manager + +Handles detection of models requiring trust_remote_code and manages user consent. +Saves approval state in .env with model tracking for security. +""" + +import os +import sys +from typing import Optional, Dict, Any +from pathlib import Path +from dotenv import load_dotenv, set_key + +# Load environment variables +load_dotenv() + + +class TrustManager: + """Manages trust_remote_code consent and detection""" + + def __init__(self, env_file: str = '.env'): + self.env_file = env_file + self._ensure_env_file() + + def _ensure_env_file(self) -> None: + """Ensure .env file exists""" + if not os.path.exists(self.env_file): + with open(self.env_file, 'w') as f: + f.write("# Trust Remote Code Settings\n") + f.write("# Format: TRUST_REMOTE_CODE_=true|false\n\n") + + def _model_to_key(self, model_name: str) -> str: + """Convert model name to environment variable key""" + # Create a hash of the model name for consistent key generation + import hashlib + model_hash = hashlib.md5(model_name.encode()).hexdigest()[:8] + return f"TRUST_REMOTE_CODE_{model_hash.upper()}" + + def _get_model_approval(self, model_name: str) -> Optional[bool]: + """Check if model has been approved for trust_remote_code""" + key = self._model_to_key(model_name) + value = os.getenv(key) + if value is None: + return None + return value.lower() == 'true' + + def _set_model_approval(self, model_name: str, approved: bool) -> None: + """Save model approval to .env file""" + key = self._model_to_key(model_name) + value = 'true' if approved else 'false' + + # Add comment with model name for clarity + comment_key = f"# {key}_MODEL" + + # Read existing content + env_content = [] + if os.path.exists(self.env_file): + with open(self.env_file, 'r') as f: + env_content = f.readlines() + + # Remove existing entries for this model + filtered_content = [] + skip_next = False + for line in env_content: + if skip_next: + skip_next = False + continue + if line.strip() == f"{comment_key}={model_name}": + skip_next = True # Skip the next line (the actual setting) + continue + if not line.startswith(key + '='): + filtered_content.append(line) + + # Add new entries + filtered_content.append(f"{comment_key}={model_name}\n") + filtered_content.append(f"{key}={value}\n") + + # Write back to file + with open(self.env_file, 'w') as f: + f.writelines(filtered_content) + + # Reload environment + load_dotenv(override=True) + + def _check_model_needs_trust(self, model_name: str) -> bool: + """ + Auto-detect if a model requires trust_remote_code. + This is a heuristic based on known model patterns. + """ + # Known models that require trust_remote_code + trust_required_patterns = [ + 'nomic-ai/', + 'microsoft/codebert', + 'sentence-transformers/all-mpnet-base-v2', + # Add more patterns as needed + ] + + # Known models that don't require trust_remote_code + safe_patterns = [ + 'sentence-transformers/all-MiniLM', + 'sentence-transformers/paraphrase', + 'sentence-transformers/multi-qa', + ] + + model_lower = model_name.lower() + + # Check safe patterns first + for pattern in safe_patterns: + if pattern.lower() in model_lower: + return False + + # Check trust required patterns + for pattern in trust_required_patterns: + if pattern.lower() in model_lower: + return True + + # For unknown models, assume trust might be needed + return True + + def _prompt_user_consent(self, model_name: str) -> bool: + """Prompt user for consent to use trust_remote_code""" + print(f"\n{'='*60}") + print("SECURITY WARNING: Remote Code Execution") + print(f"{'='*60}") + print(f"Model: {model_name}") + print() + print("This model may require 'trust_remote_code=True' which allows") + print("the model to execute arbitrary code during loading.") + print() + print("RISKS:") + print("- The model could execute malicious code") + print("- Your system could be compromised") + print("- Data could be stolen or corrupted") + print() + print("BENEFITS:") + print("- Access to newer/specialized models") + print("- Better embedding quality for some models") + print() + print("Your choice will be saved for this model.") + print(f"{'='*60}") + + while True: + try: + response = input("Allow remote code execution for this model? [y/N]: ").strip().lower() + if response in ['y', 'yes']: + return True + elif response in ['n', 'no', '']: + return False + else: + print("Please enter 'y' for yes or 'n' for no.") + except KeyboardInterrupt: + print("\nOperation cancelled.") + return False + + def get_trust_setting(self, model_name: str, interactive: bool = True) -> bool: + """ + Get trust_remote_code setting for a model. + + Args: + model_name: Name of the model + interactive: Whether to prompt user if not already approved + + Returns: + True if trust_remote_code should be used, False otherwise + """ + # Check if we have a saved decision + approval = self._get_model_approval(model_name) + if approval is not None: + return approval + + # Check if model needs trust_remote_code + needs_trust = self._check_model_needs_trust(model_name) + if not needs_trust: + # Model is known safe, save this decision + self._set_model_approval(model_name, False) + return False + + # Model might need trust, prompt user if interactive + if interactive: + user_approved = self._prompt_user_consent(model_name) + self._set_model_approval(model_name, user_approved) + return user_approved + else: + # Non-interactive mode, default to False for security + print(f"Warning: Model {model_name} may require trust_remote_code but running in non-interactive mode.") + print("Defaulting to False for security. Use interactive mode to approve.") + return False + + def list_approved_models(self) -> Dict[str, bool]: + """List all models and their approval status""" + approved_models = {} + + # Read .env file and find trust settings + if os.path.exists(self.env_file): + with open(self.env_file, 'r') as f: + lines = f.readlines() + + i = 0 + while i < len(lines): + line = lines[i].strip() + if line.startswith('# TRUST_REMOTE_CODE_') and line.endswith('_MODEL'): + # This is a model comment line + model_name = line.split('=', 1)[1] if '=' in line else 'Unknown' + # Next line should be the setting + if i + 1 < len(lines): + setting_line = lines[i + 1].strip() + if '=' in setting_line: + approved = setting_line.split('=', 1)[1].lower() == 'true' + approved_models[model_name] = approved + i += 2 + else: + i += 1 + + return approved_models + + +def safe_sentence_transformer_load(model_name: str, interactive: bool = True, **kwargs) -> Any: + """ + Safely load a SentenceTransformer with trust_remote_code consent management. + + Args: + model_name: Name of the model to load + interactive: Whether to prompt user for consent + **kwargs: Additional arguments to pass to SentenceTransformer + + Returns: + Loaded SentenceTransformer model + """ + from sentence_transformers import SentenceTransformer + + trust_manager = TrustManager() + trust_setting = trust_manager.get_trust_setting(model_name, interactive) + + # Remove any existing trust_remote_code setting from kwargs + kwargs.pop('trust_remote_code', None) + + if trust_setting: + print(f"Loading {model_name} with trust_remote_code=True (user approved)") + return SentenceTransformer(model_name, trust_remote_code=True, **kwargs) + else: + print(f"Loading {model_name} with trust_remote_code=False") + try: + return SentenceTransformer(model_name, trust_remote_code=False, **kwargs) + except Exception as e: + print(f"Error loading model with trust_remote_code=False: {e}") + if interactive: + print("Model may require trust_remote_code=True. Would you like to try again with remote code enabled?") + if trust_manager._prompt_user_consent(model_name): + trust_manager._set_model_approval(model_name, True) + return SentenceTransformer(model_name, trust_remote_code=True, **kwargs) + raise + + +if __name__ == "__main__": + # CLI for managing trust settings + import argparse + + parser = argparse.ArgumentParser(description="Manage trust_remote_code settings") + parser.add_argument('--list', action='store_true', help='List approved models') + parser.add_argument('--check', type=str, help='Check if model needs trust_remote_code') + + args = parser.parse_args() + + trust_manager = TrustManager() + + if args.list: + models = trust_manager.list_approved_models() + if models: + print("Approved models:") + for model, approved in models.items(): + status = "βœ“ Approved" if approved else "βœ— Denied" + print(f" {model}: {status}") + else: + print("No models have been evaluated yet.") + + elif args.check: + needs_trust = trust_manager._check_model_needs_trust(args.check) + print(f"Model {args.check} {'likely needs' if needs_trust else 'probably does not need'} trust_remote_code") + + else: + parser.print_help() \ No newline at end of file From 79d560187b161f1c7a29fb2db725285ec5e22e61 Mon Sep 17 00:00:00 2001 From: barrulus Date: Tue, 10 Jun 2025 11:00:23 +0100 Subject: [PATCH 13/20] env changes --- .env | 23 +++++++++++++++++++++++ .env_example | 14 -------------- 2 files changed, 23 insertions(+), 14 deletions(-) create mode 100644 .env delete mode 100644 .env_example diff --git a/.env b/.env new file mode 100644 index 0000000..5b760e8 --- /dev/null +++ b/.env @@ -0,0 +1,23 @@ +# Environment Configuration for Vector Code Retrieval System + +# Ollama Configuration +OLLAMA_HOST=http://localhost:11434 +OLLAMA_MODEL=qwen3:8b + +# Embedding Configuration +EMBEDDING_SERVER=http://localhost:65432 +EMBEDDING_MODEL=nomic-ai/nomic-embed-text-v1.5 + +# Storage Configuration +CHROMA_PATH=./chroma_code + +# Service Selection +USE_LOCAL_EMBEDDINGS=true +USE_LOCAL_OLLAMA=true + +# Trust Remote Code Settings (automatically managed by trust_manager.py) +# Format: TRUST_REMOTE_CODE_=true|false +# These are automatically added when you approve/deny models +# Example: +# # TRUST_REMOTE_CODE_A1B2C3D4_MODEL=nomic-ai/nomic-embed-text-v1.5 +# TRUST_REMOTE_CODE_A1B2C3D4=true \ No newline at end of file diff --git a/.env_example b/.env_example deleted file mode 100644 index 99fdb5e..0000000 --- a/.env_example +++ /dev/null @@ -1,14 +0,0 @@ -# Ollama Configuration -OLLAMA_HOST=http://localhost:11434 -OLLAMA_MODEL=qwen3:8b - -# Embedding Configuration -EMBEDDING_SERVER=http://localhost:5000 -EMBEDDING_MODEL=nomic-ai/nomic-embed-text-v1.5 - -# ChromaDB Configuration -CHROMA_PATH=./chroma_code - -# Default Settings -USE_LOCAL_EMBEDDINGS=true -USE_LOCAL_OLLAMA=true From 806642060c25b754ad5ea9a16eeba7c2ae50518a Mon Sep 17 00:00:00 2001 From: barrulus Date: Tue, 10 Jun 2025 06:01:05 -0400 Subject: [PATCH 14/20] env example deletion --- .env_example | 14 -------------- 1 file changed, 14 deletions(-) delete mode 100644 .env_example diff --git a/.env_example b/.env_example deleted file mode 100644 index 99fdb5e..0000000 --- a/.env_example +++ /dev/null @@ -1,14 +0,0 @@ -# Ollama Configuration -OLLAMA_HOST=http://localhost:11434 -OLLAMA_MODEL=qwen3:8b - -# Embedding Configuration -EMBEDDING_SERVER=http://localhost:5000 -EMBEDDING_MODEL=nomic-ai/nomic-embed-text-v1.5 - -# ChromaDB Configuration -CHROMA_PATH=./chroma_code - -# Default Settings -USE_LOCAL_EMBEDDINGS=true -USE_LOCAL_OLLAMA=true From 183e7d78b226580a1352500c0d9ca289140b38cd Mon Sep 17 00:00:00 2001 From: barrulus Date: Tue, 10 Jun 2025 06:11:54 -0400 Subject: [PATCH 15/20] Implement client-side trust_remote_code management system Add comprehensive security framework with auto-detection, user consent prompts, and persistent approval tracking. Client determines trust settings and communicates them to remote embedding server. --- ask.py | 8 +++----- index.py | 9 +++++---- trust_manager.py | 48 +++++++++++++++++++++++++----------------------- 3 files changed, 33 insertions(+), 32 deletions(-) diff --git a/ask.py b/ask.py index a7f4ed9..412cebd 100644 --- a/ask.py +++ b/ask.py @@ -164,15 +164,13 @@ def _get_embedding_ollama(self, text: str) -> List[float]: def _get_embedding_local(self, text: str) -> List[float]: """Get embedding using local model""" try: - from sentence_transformers import SentenceTransformer - if not self._local_model: console.print("[yellow]Loading local embedding model...[/yellow]") - from trust_manager import safe_sentence_transformer_load + from trust_manager import safe_sentence_transformer_load # type: ignore[import] self._local_model = safe_sentence_transformer_load(self.embedding_model) - self._local_model.max_seq_length = 512 + self._local_model.max_seq_length = 512 # type: ignore[attr-defined] - embedding = self._local_model.encode([text], show_progress_bar=False) + embedding = self._local_model.encode([text], show_progress_bar=False) # type: ignore[attr-defined] # Handle different return types from encode if hasattr(embedding, 'tolist'): # If it's a numpy array diff --git a/index.py b/index.py index 3cbd2dd..5114a74 100644 --- a/index.py +++ b/index.py @@ -59,7 +59,7 @@ class EmbeddingHandler: def __init__(self, model: Optional[str] = None): self.model: str = model or EMBEDDING_MODEL - def embed(self, texts: List[str]) -> List[List[float]]: + def embed(self, _texts: List[str]) -> List[List[float]]: """Generate embeddings for a list of texts""" raise NotImplementedError @@ -76,7 +76,6 @@ def __init__(self, model: Optional[str] = None): self.transformer: Optional[Any] = None self.device: str = 'cpu' try: - from sentence_transformers import SentenceTransformer import torch # Check for CUDA availability @@ -87,11 +86,13 @@ def __init__(self, model: Optional[str] = None): console.print("[yellow]! CUDA not available, using CPU[/yellow]") self.device = 'cpu' - from trust_manager import safe_sentence_transformer_load + from trust_manager import safe_sentence_transformer_load # type: ignore[import] self.transformer = safe_sentence_transformer_load(self.model, device=self.device) - self.transformer.max_seq_length = 512 + self.transformer.max_seq_length = 512 # type: ignore[attr-defined] except ImportError: raise ImportError("sentence-transformers not installed. Run: pip install sentence-transformers") + except Exception as e: + raise RuntimeError(f"Failed to load embedding model: {e}") def embed(self, texts: List[str]) -> List[List[float]]: """Generate embeddings using local model""" diff --git a/trust_manager.py b/trust_manager.py index 0b05604..405167f 100644 --- a/trust_manager.py +++ b/trust_manager.py @@ -7,10 +7,11 @@ """ import os -import sys -from typing import Optional, Dict, Any -from pathlib import Path -from dotenv import load_dotenv, set_key +from typing import Optional, TYPE_CHECKING +from dotenv import load_dotenv + +if TYPE_CHECKING: + from sentence_transformers import SentenceTransformer # Load environment variables load_dotenv() @@ -45,7 +46,7 @@ def _get_model_approval(self, model_name: str) -> Optional[bool]: return None return value.lower() == 'true' - def _set_model_approval(self, model_name: str, approved: bool) -> None: + def set_model_approval(self, model_name: str, approved: bool) -> None: """Save model approval to .env file""" key = self._model_to_key(model_name) value = 'true' if approved else 'false' @@ -54,13 +55,13 @@ def _set_model_approval(self, model_name: str, approved: bool) -> None: comment_key = f"# {key}_MODEL" # Read existing content - env_content = [] + env_content: list[str] = [] if os.path.exists(self.env_file): with open(self.env_file, 'r') as f: env_content = f.readlines() # Remove existing entries for this model - filtered_content = [] + filtered_content: list[str] = [] skip_next = False for line in env_content: if skip_next: @@ -83,7 +84,7 @@ def _set_model_approval(self, model_name: str, approved: bool) -> None: # Reload environment load_dotenv(override=True) - def _check_model_needs_trust(self, model_name: str) -> bool: + def check_model_needs_trust(self, model_name: str) -> bool: """ Auto-detect if a model requires trust_remote_code. This is a heuristic based on known model patterns. @@ -118,7 +119,7 @@ def _check_model_needs_trust(self, model_name: str) -> bool: # For unknown models, assume trust might be needed return True - def _prompt_user_consent(self, model_name: str) -> bool: + def prompt_user_consent(self, model_name: str) -> bool: """Prompt user for consent to use trust_remote_code""" print(f"\n{'='*60}") print("SECURITY WARNING: Remote Code Execution") @@ -170,16 +171,16 @@ def get_trust_setting(self, model_name: str, interactive: bool = True) -> bool: return approval # Check if model needs trust_remote_code - needs_trust = self._check_model_needs_trust(model_name) + needs_trust = self.check_model_needs_trust(model_name) if not needs_trust: # Model is known safe, save this decision - self._set_model_approval(model_name, False) + self.set_model_approval(model_name, False) return False # Model might need trust, prompt user if interactive if interactive: - user_approved = self._prompt_user_consent(model_name) - self._set_model_approval(model_name, user_approved) + user_approved = self.prompt_user_consent(model_name) + self.set_model_approval(model_name, user_approved) return user_approved else: # Non-interactive mode, default to False for security @@ -187,9 +188,9 @@ def get_trust_setting(self, model_name: str, interactive: bool = True) -> bool: print("Defaulting to False for security. Use interactive mode to approve.") return False - def list_approved_models(self) -> Dict[str, bool]: + def list_approved_models(self) -> dict[str, bool]: """List all models and their approval status""" - approved_models = {} + approved_models: dict[str, bool] = {} # Read .env file and find trust settings if os.path.exists(self.env_file): @@ -215,7 +216,7 @@ def list_approved_models(self) -> Dict[str, bool]: return approved_models -def safe_sentence_transformer_load(model_name: str, interactive: bool = True, **kwargs) -> Any: +def safe_sentence_transformer_load(model_name: str, interactive: bool = True, **kwargs: object) -> 'SentenceTransformer': """ Safely load a SentenceTransformer with trust_remote_code consent management. @@ -233,22 +234,23 @@ def safe_sentence_transformer_load(model_name: str, interactive: bool = True, ** trust_setting = trust_manager.get_trust_setting(model_name, interactive) # Remove any existing trust_remote_code setting from kwargs - kwargs.pop('trust_remote_code', None) + kwargs_dict = dict(kwargs) + kwargs_dict.pop('trust_remote_code', None) if trust_setting: print(f"Loading {model_name} with trust_remote_code=True (user approved)") - return SentenceTransformer(model_name, trust_remote_code=True, **kwargs) + return SentenceTransformer(model_name, trust_remote_code=True, **kwargs_dict) # type: ignore[misc] else: print(f"Loading {model_name} with trust_remote_code=False") try: - return SentenceTransformer(model_name, trust_remote_code=False, **kwargs) + return SentenceTransformer(model_name, trust_remote_code=False, **kwargs_dict) # type: ignore[misc] except Exception as e: print(f"Error loading model with trust_remote_code=False: {e}") if interactive: print("Model may require trust_remote_code=True. Would you like to try again with remote code enabled?") - if trust_manager._prompt_user_consent(model_name): - trust_manager._set_model_approval(model_name, True) - return SentenceTransformer(model_name, trust_remote_code=True, **kwargs) + if trust_manager.prompt_user_consent(model_name): + trust_manager.set_model_approval(model_name, True) + return SentenceTransformer(model_name, trust_remote_code=True, **kwargs_dict) # type: ignore[misc] raise @@ -275,7 +277,7 @@ def safe_sentence_transformer_load(model_name: str, interactive: bool = True, ** print("No models have been evaluated yet.") elif args.check: - needs_trust = trust_manager._check_model_needs_trust(args.check) + needs_trust = trust_manager.check_model_needs_trust(args.check) print(f"Model {args.check} {'likely needs' if needs_trust else 'probably does not need'} trust_remote_code") else: From 345ecbf3800e242bf987e74c298921e2e5d41f88 Mon Sep 17 00:00:00 2001 From: barrulus Date: Tue, 10 Jun 2025 06:20:45 -0400 Subject: [PATCH 16/20] Fix embedding server startup with trust_remote_code auto-detection Auto-detect trust requirements for default model at startup to prevent loading failures. Add --trust-remote-code flag for manual override. Update documentation to reflect security framework improvements. --- README.md | 90 ++++++++++++++++++++++++++++++++++----------- embedding_server.py | 24 +++++++++--- 2 files changed, 87 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index f26ccf6..71745f3 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ A powerful semantic search system for log files that enables natural language qu - **Interactive Query Interface**: Rich terminal interface with markdown rendering - **GPU Acceleration**: Optional GPU support for faster embedding generation - **Automatic File Detection**: Intelligently detects and indexes all text-based files by content analysis -- **Security-First Trust Management**: Configurable trust_remote_code handling with user consent and model tracking +- **Security-First Design**: Client-side trust_remote_code management with consent prompts and persistent tracking - **Environment Configuration**: Fully configurable via `.env` files ## Quick Start @@ -64,25 +64,30 @@ USE_LOCAL_EMBEDDINGS=true USE_LOCAL_OLLAMA=true ``` -### 3. Index Your Log Files +### 3. Index Your Files -Index a directory using local embeddings (default): +Index a directory with automatic file detection: ```bash -python index.py /path/to/your/logs +python index.py /path/to/your/files ``` +The system will: +- Automatically detect all text-based files by content analysis +- Skip binary files and common build/cache directories +- Prompt for trust_remote_code consent if needed for the embedding model + Or specify embedding type: ```bash -# Use local SentenceTransformer embeddings -python index.py /path/to/logs --local-embeddings +# Use local SentenceTransformer embeddings (default) +python index.py /path/to/files --local-embeddings # Use Ollama embeddings -python index.py /path/to/logs --ollama-embeddings +python index.py /path/to/files --ollama-embeddings # Use remote embedding server -python index.py /path/to/logs --remote-embeddings +python index.py /path/to/files --remote-embeddings ``` Additional options: @@ -95,7 +100,7 @@ python index.py /path/to/logs --model custom-model --chunk-size 1500 python index.py /path/to/logs --chroma-path ./my_custom_db ``` -### 4. Query Your Logs +### 4. Query Your Indexed Content Start the interactive query interface: @@ -103,6 +108,11 @@ Start the interactive query interface: python ask.py ``` +The system will: +- Auto-detect the embedding type used during indexing +- Apply same trust_remote_code settings for consistency +- Generate responses using Ollama's local LLM + Or specify a custom output file: ```bash @@ -114,22 +124,32 @@ python ask.py my_queries.md ### Core Components 1. **Unified Indexer (`index.py`)** - - Processes repositories and creates vector embeddings + - Processes repositories with automatic file detection - Supports multiple embedding strategies via handler classes - - Chunks code into configurable segments (default: 2000 characters) + - Chunks content into configurable segments (default: 2000 characters) + - Client-side trust_remote_code management - Stores embeddings in ChromaDB with metadata tracking 2. **Query Interface (`ask.py`)** - - Interactive CLI for natural language log queries - - Auto-detects embedding type from metadata + - Interactive CLI for natural language queries + - Auto-detects embedding type and trust settings from metadata - Generates responses using Ollama's local LLM + - Consistent security model with indexing phase - Saves all Q&A pairs with timestamps 3. **Embedding Server (`embedding_server.py`)** - Optional remote embedding service with GPU support + - Respects client-side trust_remote_code decisions - RESTful API with health checks and server info - - Configurable via command-line arguments - - Supports batch processing and model caching + - Dynamic model loading with trust setting caching + - Supports batch processing and multiple model variants + +4. **Trust Manager (`trust_manager.py`)** + - Centralized security management for trust_remote_code + - Auto-detection of models requiring remote code execution + - Interactive consent prompts with risk/benefit explanations + - Persistent approval tracking in .env files + - CLI tools for managing trust settings ### Embedding Handlers @@ -184,12 +204,20 @@ Options: ## Security: Trust Remote Code Management -The system includes built-in security management for models that require `trust_remote_code=True`. This feature: +The system includes a comprehensive security framework for models that require `trust_remote_code=True`. This client-side security system: -- **Auto-detects** which models likely need remote code execution -- **Prompts for user consent** with clear risk warnings -- **Saves decisions** in `.env` with model-specific tracking -- **Re-prompts on model changes** for ongoing security +- **Auto-detects** which models likely need remote code execution based on known patterns +- **Prompts for informed consent** with detailed security warnings +- **Persists decisions** in `.env` with model-specific hash tracking +- **Client-side control** - trust decisions made locally, not on remote servers +- **Cross-component consistency** - same security model for indexing, querying, and serving + +### How It Works + +1. **Detection**: System analyzes model names against known patterns +2. **User Consent**: Interactive prompts with clear risk/benefit explanations +3. **Persistence**: Decisions saved locally with model identification hashes +4. **Communication**: Client sends trust settings to remote embedding servers ### Managing Trust Settings @@ -201,7 +229,9 @@ python trust_manager.py --list python trust_manager.py --check "nomic-ai/nomic-embed-text-v1.5" ``` -When you first use a model requiring remote code, you'll see: +### Security Flow + +When you first use a model requiring remote code execution: ``` ============================================================== @@ -226,6 +256,19 @@ Your choice will be saved for this model. Allow remote code execution for this model? [y/N]: ``` +### Trust Settings Storage + +Approval decisions are stored in your `.env` file: + +```bash +# Example entries (automatically managed) +# TRUST_REMOTE_CODE_A1B2C3D4_MODEL=nomic-ai/nomic-embed-text-v1.5 +TRUST_REMOTE_CODE_A1B2C3D4=true + +# TRUST_REMOTE_CODE_E5F6G7H8_MODEL=sentence-transformers/all-MiniLM-L6-v2 +TRUST_REMOTE_CODE_E5F6G7H8=false +``` + ## Advanced Usage ### Remote Embedding Server @@ -303,11 +346,14 @@ The system automatically detects and works with databases created by older versi ## Dependencies - **chromadb**: Vector database for embeddings -- **sentence-transformers**: Local embedding generation +- **sentence-transformers**: Local embedding generation (optional, only needed for local embeddings) - **ollama**: LLM client for local inference - **rich**: Enhanced terminal output and markdown rendering - **flask**: Web server for embedding API - **python-dotenv**: Environment configuration management +- **tiktoken**: Token counting utilities +- **einops**: Tensor operations for advanced models +- **requests**: HTTP client for remote services ## File Structure diff --git a/embedding_server.py b/embedding_server.py index 7e6646d..9e36ac6 100644 --- a/embedding_server.py +++ b/embedding_server.py @@ -69,20 +69,29 @@ def initialize_model() -> None: print(f"\nUsing device: {device}") - # Load default model - from sentence_transformers import SentenceTransformer - model = SentenceTransformer(args.model, device=device, trust_remote_code=False) - model.max_seq_length = args.max_length + # Determine trust setting for default model + if args.trust_remote_code: + default_trust = True + print(f"Using --trust-remote-code flag: trust_remote_code=True for {args.model}") + else: + from trust_manager import TrustManager + trust_manager = TrustManager() + default_trust = trust_manager.check_model_needs_trust(args.model) + print(f"Auto-detected trust_remote_code={default_trust} for {args.model}") + + # Load default model with appropriate trust setting + model = get_or_load_model(args.model, default_trust) print(f"Default model loaded: {args.model}") print(f"Max sequence length: {args.max_length}") print(f"Batch size: {args.batch_size}") - print(f"Note: trust_remote_code can be overridden per request") + print(f"Note: Client requests can override model and trust settings") def get_or_load_model(model_name: str, trust_remote_code: bool) -> SentenceTransformer: """Get or load a model with specific trust_remote_code setting""" global model_cache, device, args + from sentence_transformers import SentenceTransformer if args is None: raise RuntimeError("Server not initialized") @@ -228,6 +237,11 @@ def main() -> None: action='store_true', help='Run in debug mode' ) + parser.add_argument( + '--trust-remote-code', + action='store_true', + help='Force trust_remote_code=True for default model (auto-detected if not specified)' + ) args = parser.parse_args() From 2113696fd0be90e097824d4a25fa8de551974846 Mon Sep 17 00:00:00 2001 From: barrulus Date: Tue, 10 Jun 2025 06:24:55 -0400 Subject: [PATCH 17/20] Stop tracking .env file --- .env | 23 ----------------------- 1 file changed, 23 deletions(-) delete mode 100644 .env diff --git a/.env b/.env deleted file mode 100644 index 5b760e8..0000000 --- a/.env +++ /dev/null @@ -1,23 +0,0 @@ -# Environment Configuration for Vector Code Retrieval System - -# Ollama Configuration -OLLAMA_HOST=http://localhost:11434 -OLLAMA_MODEL=qwen3:8b - -# Embedding Configuration -EMBEDDING_SERVER=http://localhost:65432 -EMBEDDING_MODEL=nomic-ai/nomic-embed-text-v1.5 - -# Storage Configuration -CHROMA_PATH=./chroma_code - -# Service Selection -USE_LOCAL_EMBEDDINGS=true -USE_LOCAL_OLLAMA=true - -# Trust Remote Code Settings (automatically managed by trust_manager.py) -# Format: TRUST_REMOTE_CODE_=true|false -# These are automatically added when you approve/deny models -# Example: -# # TRUST_REMOTE_CODE_A1B2C3D4_MODEL=nomic-ai/nomic-embed-text-v1.5 -# TRUST_REMOTE_CODE_A1B2C3D4=true \ No newline at end of file From a6c3702a606fb86aa6533b0f64e7d9e7318d4e5f Mon Sep 17 00:00:00 2001 From: barrulus Date: Tue, 10 Jun 2025 06:25:52 -0400 Subject: [PATCH 18/20] changed defaulkt model --- .env.example | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.env.example b/.env.example index 72b4817..8e10e22 100644 --- a/.env.example +++ b/.env.example @@ -2,7 +2,7 @@ # Ollama Configuration OLLAMA_HOST=http://localhost:11434 -OLLAMA_MODEL=dolphincoder:15b +OLLAMA_MODEL=qwen3:8b # Embedding Configuration EMBEDDING_SERVER=http://localhost:5000 From 00c9afea906ea57fd39754b0454ffd81d6d1f621 Mon Sep 17 00:00:00 2001 From: barrulus Date: Tue, 10 Jun 2025 06:38:16 -0400 Subject: [PATCH 19/20] Added Apple Silicon MPS support --- embedding_server.py | 28 ++++++++++++++++++---------- index.py | 7 +++++-- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/embedding_server.py b/embedding_server.py index 9e36ac6..8555d78 100644 --- a/embedding_server.py +++ b/embedding_server.py @@ -45,26 +45,34 @@ def initialize_model() -> None: print(f"\nLoading SentenceTransformer model: {args.model}") - # CUDA Diagnostics - print("\nCUDA Diagnostics:") + # GPU Acceleration Diagnostics + print("\nGPU Acceleration Diagnostics:") print(f"PyTorch version: {torch.__version__}") print(f"CUDA available: {torch.cuda.is_available()}") + # Check for MPS (Apple Silicon GPU) + mps_available = hasattr(torch.backends, 'mps') and torch.backends.mps.is_available() + print(f"MPS (Apple Silicon) available: {mps_available}") + if torch.cuda.is_available(): if hasattr(torch, 'version') and hasattr(torch.version, 'cuda') and torch.version.cuda: # type: ignore[attr-defined] print(f"PyTorch CUDA version: {torch.version.cuda}") # type: ignore[attr-defined] - print(f"Number of GPUs: {torch.cuda.device_count()}") + print(f"Number of CUDA GPUs: {torch.cuda.device_count()}") for i in range(torch.cuda.device_count()): - print(f"GPU {i}: {torch.cuda.get_device_name(i)}") + print(f"CUDA GPU {i}: {torch.cuda.get_device_name(i)}") props = cast(Any, torch.cuda.get_device_properties(i)) # type: ignore[misc] - print(f"GPU {i} Memory: {props.total_memory / 1024**3:.1f} GB") + print(f"CUDA GPU {i} Memory: {props.total_memory / 1024**3:.1f} GB") device = 'cuda' + elif mps_available: + print("Using Apple Silicon GPU (MPS) for acceleration") + device = 'mps' else: - print("CUDA not available. Reasons could be:") - print("1. NVIDIA GPU not present") - print("2. CUDA drivers not installed") - print("3. PyTorch not compiled with CUDA support") - print("4. Environment variables not set correctly") + print("No GPU acceleration available. Using CPU.") + print("Possible reasons:") + print("- No NVIDIA GPU (for CUDA)") + print("- No Apple Silicon chip (for MPS)") + print("- PyTorch not compiled with GPU support") + print("- Missing drivers or environment setup") device = 'cpu' print(f"\nUsing device: {device}") diff --git a/index.py b/index.py index 5114a74..2aff469 100644 --- a/index.py +++ b/index.py @@ -78,12 +78,15 @@ def __init__(self, model: Optional[str] = None): try: import torch - # Check for CUDA availability + # Check for GPU acceleration if torch.cuda.is_available(): console.print(f"[green]βœ“ CUDA available: {torch.cuda.get_device_name(0)}[/green]") self.device = 'cuda' + elif hasattr(torch.backends, 'mps') and torch.backends.mps.is_available(): + console.print("[green]βœ“ Apple Silicon GPU (MPS) available[/green]") + self.device = 'mps' else: - console.print("[yellow]! CUDA not available, using CPU[/yellow]") + console.print("[yellow]! No GPU acceleration available, using CPU[/yellow]") self.device = 'cpu' from trust_manager import safe_sentence_transformer_load # type: ignore[import] From c0e68c963c74d99c3e75bb00d5e67d129b87b81c Mon Sep 17 00:00:00 2001 From: barrulus Date: Tue, 10 Jun 2025 06:58:50 -0400 Subject: [PATCH 20/20] changed fallback model in ask.py --- ask.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ask.py b/ask.py index 412cebd..ac3f475 100644 --- a/ask.py +++ b/ask.py @@ -31,7 +31,7 @@ # Configuration from environment OLLAMA_HOST = os.getenv('OLLAMA_HOST', 'http://localhost:11434') -OLLAMA_MODEL = os.getenv('OLLAMA_MODEL', 'dolphincoder:15b') +OLLAMA_MODEL = os.getenv('OLLAMA_MODEL', 'qwen3:8b') EMBEDDING_SERVER = os.getenv('EMBEDDING_SERVER', 'http://localhost:5000') EMBEDDING_MODEL = os.getenv('EMBEDDING_MODEL', 'nomic-ai/nomic-embed-text-v1.5') CHROMA_PATH = os.getenv('CHROMA_PATH', './chroma_code')