Hacker News new | ask | show | jobs
by bclavie 1233 days ago
Hi HN! I'm the other person working on this with Ankly.

This came up as a pet project as we were eager to put some LLM work into production. Currently piggy-backing off APIs, though the results with certain self-hosted models could be worse (but could be better), as he mentioned, we've ran some experiments with Flan-T5.

We have a bunch of current plans as to where to keep building on this, beyond improving the model/engine/prompting/etc... We're very keen to integrate more libs that we use (FastAPI and Pandas come to mind, in terms of sprawling doc), and adding a "Search through StackOverflow Answers" button, though testing how well our similarity look-up works on that front.

On the non-code/technical aspects, everything we've tried has been pretty encouraging, but has a bunch of different challenges. For documentation questions, we're trying to "ground" the model knowledge -- it probably knows a lot of react, but can't quite reference this exact bit of the documentation, or will use an outdated something, or this, or that... So we're trying to re-center and improve the knowledge of the original model and the way it serves it.

When we test the approach on in-house documentation (such as Notion), the problem is a bit different: in a lot of cases, _all_ the relevant information should be in the context, and we very much don't want the model to rely on whatever latent knowledge it has of "What was agreed with Joe about the framework swap?". We're not seeing much of it anymore, but even with synthetic data, we had some interesting situations where the relevant context wasn't found and some safeguards failed, so an entirely made-up Joe was purported as having approved to swap to Angular.

Happy to answer questions and discuss more about this -- LLM as the "logic" layer of document retrieval is definitely fascinating.

2 comments

I've noticed when prompting ChatGPT for code that it occasionally invents libraries that don't exist at all, or adds it own input if something about a prompt is strongly connected to its latent knowledge. For example, I asked it to write a program that would select one of my favourite dinner ideas at random, providing a list of options in my prompt. It added 4 more recipes I'd never heard of and some playful commentary about Ruby in the comments (and a working program).

As I'm a complete novice when it comes to LLMs, I'm really curious how you go about building these safeguards/constraints around knowledge you want the model to prioritize?

Is it simply a matter of fine-tuning the model with explicit instructions on how to handle certain topics? Can you simply train it with assertions like "Ignore everything you know about comparing the Angular and React javascript frameworks. Read this document we wrote to compare them instead."?

It's kind of like that. You always have the option of fine-tuning, although that quickly gets pricey if you aren't self hosting (e.g. OpenAI bills an order of magnitude higher for serving fine-tuned models)

The constraints can be put in place through a bunch of different things. The prompt engineering is a big thing, instruction-tuned models can be pretty good at following very restrictive instructions. You do end up sacrificing some creativity in your answers by adding a lot of restrictions but it generally works quite well as a safeguard layer. A lot of the cool LLM applications are, first and foremost, proper prompting. Setting a low temperature is also key, as the higher likelihood suggestions _generally_ (but not always) are less made-up. ChatGPT makes this a bit harder as you have no control over the model parameters (temperature is OpenAI-set) and cannot control the original prompt, meaning you can't fully be in charge of the instructions it gets, so any mitigation to avoid hallucinations will have its limits.

After that yeah, the context documents you provide are pretty important in grounding it. It ties back in with the prompt, but you can more or less drill it into a low-temperature instruction-fine tuned model that if it can't find the answer within a set of documents you provide it, it should simply not answer. Again, you lose out in some contexts (it's a bad feeling on the user's end to not get an answer) but you also ensure that your model isn't live-freewheeling about a new framework called Reagular...

https://platform.openai.com/docs/guides/fine-tuning

You create a series of prompts and their responses and then that tuned model is used with that implicit knowledge already stored in it.

For example a notebook for "lets train GPT on the information about the olympics - https://github.com/openai/openai-cookbook/blob/main/examples... and https://github.com/openai/openai-cookbook/blob/main/examples... and https://github.com/openai/openai-cookbook/blob/main/examples... )

The gotcha for this is that while regular Davinci is $0.02/1k tokens, training is $0.03/1k tokens and use is $0.12/1k tokens.

The other thing to consider is that Chat GPT has a session and history for that session. You can use GPT stateless which doesn't have the "it gets confused about what you were talking about before."

    curl https://api.openai.com/v1/completions \
      -H "Content-Type: application/json" \
      -H "Authorization: Bearer $OPENAI_API_KEY" \
      -d '{
      "model": "text-davinci-003",
      "prompt": "Write a recipe based on these ingredients and instructions:\n\nFrito Pie\n\nIngredients:\nFritos\nChili\nShredded cheddar cheese\nSweet white or red onions, diced small\nSour cream\n\nInstructions:",
      "temperature": 0.3,
      "max_tokens": 120,
      "top_p": 1,
      "frequency_penalty": 0,
      "presence_penalty": 0
    }'
And thus asking it about one and only one thing with no additional chat context around it.
How do you decide where to break up the chunks for embedding? On mine I am currently just doing something like X words per chunk. It's seems like ideally I could parse out all source code and avoiding breaking up functions but not sure how to do that for arbitrary languages.
I've experimented with a few approaches and to be honest, kind of gone with what "felt best" as we're quite artisanal with our testing approach at the moment.

We try to always go for logical breakpoints (e.g. never in the middle of a sentence or explanation). Some docs are cut into smaller chunks because the way they're written works quite well for segmentation, and smaller chunks have the advantage of allowing more to be looked-up, so your semantic search is allowed to mess up as long as it finds 1-2 relevant context elements. For some, we felt like cutting into chunk was losing too much information, so we've added them as quite huge chunks. It feels suboptimal in some ways, especially in terms of performance and modularity, but we've also found that the model is very good at parsing a ±2k token length sample and getting the right info from it in most cases.

Ultimately there's no right answer and it's a case-by-case tradeoff.